Merge changes from topic "DisableEcbmInUmtsGsm" into main

* changes:
  (APDS) Don't enter ECBM when ECC ends in GSM/UMTS networks
  Add flag not to enter ECBM in GSM and UMTS networks
diff --git a/flags/carrier.aconfig b/flags/carrier.aconfig
index 14aedc6..19d2145 100644
--- a/flags/carrier.aconfig
+++ b/flags/carrier.aconfig
@@ -30,3 +30,14 @@
     description: "Enable temporary failures in CarrierMessagingService"
     bug:"326610112"
 }
+
+# OWNER=melhuishj TARGET=25Q3
+flag {
+    name: "disable_carrier_network_change_on_carrier_app_lost"
+    namespace: "telephony"
+    description: "Set carrier network change status to false whenever the carrier app is lost"
+    bug:"333571417"
+    metadata {
+      purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/flags/misc.aconfig b/flags/misc.aconfig
index 574cd63..42d9f4b 100644
--- a/flags/misc.aconfig
+++ b/flags/misc.aconfig
@@ -52,14 +52,6 @@
     bug:"271921464"
 }
 
-# OWNER=joonhunshin TARGET=24Q3
-flag {
-    name: "enforce_telephony_feature_mapping_for_public_apis"
-    namespace: "telephony"
-    description: "This flag controls telephony feature flags mapping for public APIs and CTS."
-    bug:"297989574"
-}
-
 # OWNER=stevestatia TARGET=24Q3
 flag {
     name: "prevent_system_server_and_phone_deadlock"
@@ -78,14 +70,6 @@
 
 # OWNER=jackyu TARGET=24Q3
 flag {
-    name: "minimal_telephony_cdm_check"
-    namespace: "telephony"
-    description: "This flag disables Calling/Data/Messaging features if their respective feature is missing"
-    bug: "310710841"
-}
-
-# OWNER=jackyu TARGET=24Q3
-flag {
     name: "minimal_telephony_managers_conditional_on_features"
     namespace: "telephony"
     description: "This flag enables checking for telephony features before initializing corresponding managers"
diff --git a/flags/satellite.aconfig b/flags/satellite.aconfig
index 3ea7a51..b433030 100644
--- a/flags/satellite.aconfig
+++ b/flags/satellite.aconfig
@@ -91,3 +91,15 @@
   bug: "393966687"
   is_exported: true
 }
+
+# OWNER=amallampati TARGET=25Q3
+flag {
+    name: "satellite_exit_p2p_session_outside_geofence"
+    is_exported: true
+    namespace: "telephony"
+    description: "Exit P2P satellite session outside geofence"
+    bug:"391926447"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/jarjar-rules-shared.txt b/jarjar-rules-shared.txt
index 2353507..01bdb75 100644
--- a/jarjar-rules-shared.txt
+++ b/jarjar-rules-shared.txt
@@ -18,6 +18,7 @@
 rule com.android.internal.util.State* com.android.internal.telephony.State@1
 rule com.android.internal.util.StateMachine* com.android.internal.telephony.StateMachine@1
 rule com.android.internal.util.UserIcons* com.android.internal.telephony.UserIcons@1
+rule com.android.server.updates.ConfigUpdateInstallReceiver* com.android.internal.telephony.server.updates.ConfigUpdateInstallReceiver@1
 rule com.google.i18n.phonenumbers.** com.android.internal.telephony.phonenumbers.@1
 
 # Module library in frameworks/libs/net
diff --git a/proto/src/persist_atoms.proto b/proto/src/persist_atoms.proto
index 37a61b2..34424c1 100644
--- a/proto/src/persist_atoms.proto
+++ b/proto/src/persist_atoms.proto
@@ -822,6 +822,9 @@
     optional int32 count_of_outgoing_sms = 14;
     optional int32 count_of_incoming_mms = 15;
     optional int32 count_of_outgoing_mms = 16;
+    repeated int32 supported_satellite_services = 17;
+    optional int32 service_data_policy = 18;
+    optional int64 satellite_data_consumed_bytes = 19;
 }
 
 message CarrierRoamingSatelliteControllerStats {
@@ -842,6 +845,9 @@
     optional int32 entitlement_status = 3;
     optional bool is_retry = 4;
     optional int32 count = 5;
+    optional bool is_allowed_service_entitlement = 6;
+    repeated int32 entitlement_service_type = 7;
+    optional int32 entitlement_data_policy = 8;
 }
 
 message SatelliteConfigUpdater {
diff --git a/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java b/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
index ffefce3..2b426b8 100644
--- a/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
+++ b/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
@@ -559,6 +559,9 @@
     private void handleSimStateChanged(int slotId, int simState) {
         if (slotId != mPhone.getPhoneId()) return;
 
+        // TODO(b/398737967): remove or silence down when diagnosed
+        Rlog.d(TAG, "handleSimStateChanged: slotId=" + slotId + " simState=" + simState);
+
         List<UiccAccessRule> updatedUiccRules = Collections.EMPTY_LIST;
 
         mPrivilegedPackageInfoLock.writeLock().lock();
@@ -570,7 +573,7 @@
 
         // Only include the UICC rules if the SIM is fully loaded
         if (simState == SIM_STATE_LOADED) {
-            mLocalLog.log("SIM fully loaded, handleUiccAccessRulesLoaded.");
+            Rlog.d(TAG, "handleSimStateChanged: SIM fully loaded.");
             handleUiccAccessRulesLoaded();
         } else {
             if (!mUiccRules.isEmpty()
@@ -579,12 +582,13 @@
                         SystemClock.uptimeMillis() + CLEAR_UICC_RULES_DELAY_MILLIS;
                 mCurrentHandler.sendMessageAtTime(obtainMessage(ACTION_CLEAR_UICC_RULES),
                         mClearUiccRulesUptimeMillis);
-                mLocalLog.log("SIM is gone, simState=" + TelephonyManager.simStateToString(simState)
+                Rlog.d(TAG, "handleSimStateChanged: SIM is gone, simState="
+                        + TelephonyManager.simStateToString(simState)
                         + ". Delay " + TimeUnit.MILLISECONDS.toSeconds(
                         CLEAR_UICC_RULES_DELAY_MILLIS) + " seconds to clear UICC rules.");
             } else {
-                mLocalLog.log(
-                        "Ignore SIM gone event while UiccRules is empty or waiting to be emptied.");
+                Rlog.d(TAG, "handleSimStateChanged: Ignore SIM gone event while"
+                        + " UiccRules is empty or waiting to be emptied.");
             }
         }
     }
diff --git a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
index 4f9d84d..300ebdf 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
@@ -40,6 +40,7 @@
 import android.service.carrier.CarrierService;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
 import android.text.TextUtils;
 import android.util.LocalLog;
 import android.util.Log;
@@ -335,7 +336,7 @@
             bindCount++;
             lastBindStartMillis = System.currentTimeMillis();
 
-            connection = new CarrierServiceConnection();
+            connection = new CarrierServiceConnection(getPhoneId());
 
             String error;
             try {
@@ -431,6 +432,11 @@
 
     private class CarrierServiceConnection implements ServiceConnection {
         private boolean connected;
+        private final int mPhoneId;
+
+        CarrierServiceConnection(int phoneId) {
+            mPhoneId = phoneId;
+        }
 
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
@@ -438,16 +444,38 @@
             connected = true;
         }
 
+        private void maybeDisableCarrierNetworkChangeNotification() {
+            int subscriptionId = SubscriptionManager.getSubscriptionId(mPhoneId);
+            // TODO(b/117525047): switch to phoneId-based solution when available in
+            // TelephonyRegistryManager to address SIM remove/disable case.
+            if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+                logdWithLocalLog(
+                        "No valid subscription found when trying to disable carrierNetworkChange"
+                                + " for phoneId: "
+                                + mPhoneId);
+                return;
+            }
+            TelephonyRegistryManager telephonyRegistryManager =
+                    mContext.getSystemService(TelephonyRegistryManager.class);
+            telephonyRegistryManager.notifyCarrierNetworkChange(subscriptionId, false);
+        }
+
         @Override
         public void onServiceDisconnected(ComponentName name) {
             logdWithLocalLog("Disconnected from carrier app: " + name.flattenToString());
             connected = false;
+            if (Flags.disableCarrierNetworkChangeOnCarrierAppLost()) {
+                maybeDisableCarrierNetworkChangeNotification();
+            }
         }
 
         @Override
         public void onBindingDied(ComponentName name) {
             logdWithLocalLog("Binding from carrier app died: " + name.flattenToString());
             connected = false;
+            if (Flags.disableCarrierNetworkChangeOnCarrierAppLost()) {
+                maybeDisableCarrierNetworkChangeNotification();
+            }
         }
 
         @Override
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 8451bed..edcc51e 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -101,6 +101,7 @@
 import com.android.internal.telephony.imsphone.ImsPhoneCall;
 import com.android.internal.telephony.metrics.SmsStats;
 import com.android.internal.telephony.metrics.VoiceCallSessionStats;
+import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.internal.telephony.test.SimulatedRadioControl;
@@ -1065,20 +1066,13 @@
     public void notifySmsSent(String destinationAddress) {
         TelephonyManager m = (TelephonyManager) getContext().getSystemService(
                 Context.TELEPHONY_SERVICE);
-        if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()) {
+        if (mContext.getPackageManager() != null
+                && mContext.getPackageManager().hasSystemFeature(
+                        PackageManager.FEATURE_TELEPHONY_CALLING)) {
             if (m != null && m.isEmergencyNumber(destinationAddress)) {
                 mLocalLog.log("Emergency SMS detected, recording time.");
                 mTimeLastEmergencySmsSentMs = SystemClock.elapsedRealtime();
             }
-        } else {
-            if (mContext.getPackageManager() != null
-                    && mContext.getPackageManager().hasSystemFeature(
-                            PackageManager.FEATURE_TELEPHONY_CALLING)) {
-                if (m != null && m.isEmergencyNumber(destinationAddress)) {
-                    mLocalLog.log("Emergency SMS detected, recording time.");
-                    mTimeLastEmergencySmsSentMs = SystemClock.elapsedRealtime();
-                }
-            }
         }
     }
 
@@ -5405,6 +5399,7 @@
     public void notifyCarrierRoamingNtnEligibleStateChanged(boolean eligible) {
         logd("notifyCarrierRoamingNtnEligibleStateChanged eligible:" + eligible);
         mNotifier.notifyCarrierRoamingNtnEligibleStateChanged(this, eligible);
+        ControllerMetricsStats.getInstance().reportP2PSmsEligibilityNotificationsCount(eligible);
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/PhoneSubInfoController.java b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
index 9801542..c8cd242 100644
--- a/src/java/com/android/internal/telephony/PhoneSubInfoController.java
+++ b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
@@ -861,8 +861,7 @@
             return;
         }
 
-        if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
-                || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+        if (!CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
                 Binder.getCallingUserHandle())
                 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
             // Skip to check associated telephony feature,
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 2b7557c..f994fe6 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -3802,7 +3802,11 @@
         mNewSS.setOutOfService(false);
 
         mCellIdentity = primaryCellIdentity;
-        if (mSS.getState() == ServiceState.STATE_IN_SERVICE && primaryCellIdentity != null) {
+        boolean isCsRegistered = mSS.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_CS,
+                AccessNetworkConstants.TRANSPORT_TYPE_WWAN).isNetworkRegistered();
+        boolean isPsRegistered = mSS.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
+                AccessNetworkConstants.TRANSPORT_TYPE_WWAN).isNetworkRegistered();
+        if (isCsRegistered || isPsRegistered) {
             mLastKnownCellIdentity = mCellIdentity;
             removeMessages(EVENT_RESET_LAST_KNOWN_CELL_IDENTITY);
         }
diff --git a/src/java/com/android/internal/telephony/SmsController.java b/src/java/com/android/internal/telephony/SmsController.java
index 051fbbd..ab1eb31 100644
--- a/src/java/com/android/internal/telephony/SmsController.java
+++ b/src/java/com/android/internal/telephony/SmsController.java
@@ -1254,8 +1254,7 @@
             return;
         }
 
-        if (!mFlags.enforceTelephonyFeatureMappingForPublicApis()
-                || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+        if (!CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
                 Binder.getCallingUserHandle())
                 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
             // Skip to check associated telephony feature,
diff --git a/src/java/com/android/internal/telephony/TelephonyCapabilities.java b/src/java/com/android/internal/telephony/TelephonyCapabilities.java
index b650b43..c5bfe79 100644
--- a/src/java/com/android/internal/telephony/TelephonyCapabilities.java
+++ b/src/java/com/android/internal/telephony/TelephonyCapabilities.java
@@ -207,9 +207,7 @@
         // Check SDK version of the vendor partition.
         final int vendorApiLevel = SystemProperties.getInt(
                 "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT);
-        if (vendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) return false;
-
-        return featureFlags.minimalTelephonyCdmCheck();
+        return vendorApiLevel >= Build.VERSION_CODES.VANILLA_ICE_CREAM;
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java b/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
index 04f2c4f..b299411 100644
--- a/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
+++ b/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
@@ -34,6 +34,7 @@
 
 import libcore.io.IoUtils;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.util.Iterator;
@@ -293,4 +294,37 @@
         Log.d(TAG, "source file is not exist, no file to copy");
         return false;
     }
+
+    /**
+     * This API should be used by only CTS/unit tests to reset the telephony configs set through
+     * config updater
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public boolean cleanUpTelephonyConfigs() {
+        Log.d(TAG, "cleanTelephonyConfigs: resetting the telephony configs");
+        try {
+            // metadata/version
+            File updateMetadataDir = new File(updateDir, UPDATE_METADATA_PATH);
+            writeUpdate(
+                    updateMetadataDir,
+                    updateVersion,
+                    new ByteArrayInputStream(Integer.toString(-1).getBytes()));
+
+            // new_telephony_config.pb
+            writeUpdate(updateDir, updateContent, new ByteArrayInputStream(new byte[] {}));
+
+            // valid_telephony_config.pb
+            File validConfigContentPath = new File(updateDir, VALID_CONFIG_CONTENT_PATH);
+            writeUpdate(updateDir, validConfigContentPath, new ByteArrayInputStream(new byte[] {}));
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to clean telephony config files: " + e);
+            return false;
+        }
+
+        Log.d(TAG, "cleanTelephonyConfigs: resetting the config parser");
+        synchronized (getInstance().mConfigParserLock) {
+            getInstance().mConfigParser = null;
+        }
+        return true;
+    }
 }
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index 392b996..86cfbba 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -697,13 +697,6 @@
         public void onDataServiceBound(@TransportType int transport) {}
 
         /**
-         * Called when SIM load state changed.
-         *
-         * @param simState The current SIM state
-         */
-        public void onSimStateChanged(@SimState int simState) {}
-
-        /**
          * Called when QosBearerSessions changed.
          *
          * @param qosBearerSessions The latest QOS bearer sessions.
@@ -3605,8 +3598,6 @@
                 sendMessage(obtainMessage(EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS,
                         DataEvaluationReason.SIM_LOADED));
             }
-            mDataNetworkControllerCallbacks.forEach(callback -> callback.invokeFromExecutor(
-                    () -> callback.onSimStateChanged(mSimState)));
         }
     }
 
diff --git a/src/java/com/android/internal/telephony/data/DataProfileManager.java b/src/java/com/android/internal/telephony/data/DataProfileManager.java
index f9f78ea..0138aa0 100644
--- a/src/java/com/android/internal/telephony/data/DataProfileManager.java
+++ b/src/java/com/android/internal/telephony/data/DataProfileManager.java
@@ -37,7 +37,6 @@
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.TelephonyManager.SimState;
 import android.telephony.data.ApnSetting;
 import android.telephony.data.DataProfile;
 import android.telephony.data.TrafficDescriptor;
@@ -47,6 +46,7 @@
 import android.util.LocalLog;
 import android.util.LruCache;
 
+import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback;
 import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback;
@@ -120,10 +120,6 @@
     @NonNull
     private final Set<DataProfileManagerCallback> mDataProfileManagerCallbacks = new ArraySet<>();
 
-    /** SIM state. */
-    @SimState
-    private int mSimState = TelephonyManager.SIM_STATE_UNKNOWN;
-
     /** Feature flags controlling which feature is enabled. */
     @NonNull
     private final FeatureFlags mFeatureFlags;
@@ -186,11 +182,6 @@
                         if (internetNetworks.isEmpty()) return;
                         DataProfileManager.this.onInternetDataNetworkConnected(internetNetworks);
                     }
-
-                    @Override
-                    public void onSimStateChanged(@SimState int simState) {
-                        DataProfileManager.this.mSimState = simState;
-                    }
                 });
         mDataConfigManager.registerCallback(new DataConfigManagerCallback(this::post) {
             @Override
@@ -315,7 +306,7 @@
 
         DataProfile dataProfile;
 
-        if (mSimState == TelephonyManager.SIM_STATE_LOADED) {
+        if (IccCardConstants.State.LOADED.equals(mPhone.getIccCard().getState())) {
             // Check if any of the profile already supports IMS, if not, add the default one.
             dataProfile = profiles.stream()
                     .filter(dp -> dp.canSatisfy(NetworkCapabilities.NET_CAPABILITY_IMS))
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccCardController.java b/src/java/com/android/internal/telephony/euicc/EuiccCardController.java
index e511e8f..96107a2 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccCardController.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccCardController.java
@@ -1544,8 +1544,7 @@
             return;
         }
 
-        if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
-                || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+        if (!CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
                 Binder.getCallingUserHandle())
                 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
             // Skip to check associated telephony feature,
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccConnector.java b/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
index c5cc769..b919bdd 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
@@ -749,12 +749,12 @@
         @Override
         public boolean processMessage(Message message) {
             if (message.what == CMD_SERVICE_DISCONNECTED) {
-                EuiccSession.get().endAllSessions();
+                EuiccSession.get(mContext).endAllSessions();
                 mEuiccService = null;
                 transitionTo(mDisconnectedState);
                 return HANDLED;
             } else if (message.what == CMD_LINGER_TIMEOUT) {
-                EuiccSession.get().endAllSessions();
+                EuiccSession.get(mContext).endAllSessions();
                 unbind();
                 transitionTo(mAvailableState);
                 return HANDLED;
@@ -833,7 +833,7 @@
                         }
                         case CMD_DOWNLOAD_SUBSCRIPTION: {
                             DownloadRequest request = (DownloadRequest) message.obj;
-                            EuiccSession.get().startSession(EuiccSession.DOWNLOAD);
+                            EuiccSession.get(mContext).startSession(EuiccSession.DOWNLOAD);
                             mEuiccService.downloadSubscription(slotId,
                                     request.mPortIndex,
                                     request.mSubscription,
@@ -848,7 +848,8 @@
                                                     .onDownloadComplete(result);
                                                 onCommandEnd(callback);
                                             });
-                                            EuiccSession.get().endSession(EuiccSession.DOWNLOAD);
+                                            EuiccSession.get(mContext)
+                                                    .endSession(EuiccSession.DOWNLOAD);
                                         }
                                     });
                             break;
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccController.java b/src/java/com/android/internal/telephony/euicc/EuiccController.java
index cc9d793..58eb4f2 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccController.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccController.java
@@ -2377,8 +2377,7 @@
             return;
         }
 
-        if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
-                || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+        if (!CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
                 Binder.getCallingUserHandle())
                 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
             // Skip to check associated telephony feature,
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccSession.java b/src/java/com/android/internal/telephony/euicc/EuiccSession.java
index f17789f..790ca89 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccSession.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccSession.java
@@ -16,6 +16,7 @@
 package com.android.internal.telephony.euicc;
 
 import android.annotation.Nullable;
+import android.content.Context;
 import android.util.ArraySet;
 
 import com.android.internal.annotations.GuardedBy;
@@ -41,9 +42,9 @@
     @GuardedBy("EuiccSession.class")
     private static EuiccSession sInstance;
 
-    public static synchronized EuiccSession get() {
+    public static synchronized EuiccSession get(Context context) {
         if (sInstance == null) {
-            sInstance = new EuiccSession();
+            sInstance = new EuiccSession(context);
         }
         return sInstance;
     }
@@ -53,6 +54,18 @@
 
     @GuardedBy("this")
     private final Set<ApduSender> mApduSenders = new ArraySet<>();
+    private final Context mContext;
+
+    /**
+     * Returns true if the ApduSender optimization is enabled i.e. a logical channel is opened
+     * and kept open for multiple APDU commands within one session.
+     *
+     * This is gated by both an aconfig flag and a device-specific flag.
+     */
+    private boolean optimizeApduSender() {
+        return Flags.optimizationApduSender() && mContext.getResources().getBoolean(
+                com.android.internal.R.bool.euicc_optimize_apdu_sender);
+    }
 
     /**
      * Marks the start of a eUICC transaction session.
@@ -72,7 +85,7 @@
      * @param sessionId The session ID.
      */
     public void startSession(String sessionId) {
-        if (!Flags.optimizationApduSender()) {
+        if (!optimizeApduSender()) {
             // Other methods in this class is no-op if no session started.
             // Do not add flag to other methods, so if the flag gets turned off,
             // the session can be ended properly.
@@ -179,5 +192,7 @@
     }
 
     @VisibleForTesting
-    public EuiccSession() {}
+    public EuiccSession(Context context) {
+        mContext = context;
+    }
 }
diff --git a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
index e925e1a..e8db550 100644
--- a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+++ b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
@@ -1593,7 +1593,10 @@
                 stats.countOfIncomingSms,
                 stats.countOfOutgoingSms,
                 stats.countOfIncomingMms,
-                stats.countOfOutgoingMms);
+                stats.countOfOutgoingMms,
+                stats.supportedSatelliteServices,
+                stats.serviceDataPolicy,
+                stats.satelliteDataConsumedBytes);
     }
 
     private static StatsEvent buildStatsEvent(CarrierRoamingSatelliteControllerStats stats) {
@@ -1617,7 +1620,10 @@
                 stats.result,
                 stats.entitlementStatus,
                 stats.isRetry,
-                stats.count);
+                stats.count,
+                stats.isAllowedServiceEntitlement,
+                stats.entitlementServiceType,
+                stats.entitlementDataPolicy);
     }
 
     private static StatsEvent buildStatsEvent(SatelliteConfigUpdater stats) {
diff --git a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
index 0cd1d77..0a0e961 100644
--- a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
+++ b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
@@ -1634,6 +1634,7 @@
                     mAtoms.carrierRoamingSatelliteControllerStats;
             mAtoms.carrierRoamingSatelliteControllerStats =
                     new CarrierRoamingSatelliteControllerStats[0];
+            SatelliteStats.getInstance().resetCarrierRoamingSatelliteControllerStats();
             saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS);
             return statsArray;
         } else {
diff --git a/src/java/com/android/internal/telephony/metrics/SatelliteStats.java b/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
index 6ae86f3..47b877e 100644
--- a/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
+++ b/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
@@ -16,8 +16,8 @@
 
 package com.android.internal.telephony.metrics;
 
-import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
 import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
+import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
 
 import static com.android.internal.telephony.satellite.SatelliteConstants.TRIGGERING_EVENT_UNKNOWN;
 
@@ -1762,6 +1762,9 @@
         private final int mCountOfOutgoingSms;
         private final int mCountOfIncomingMms;
         private final int mCountOfOutgoingMms;
+        private final int[] mSupportedSatelliteServices;
+        private final int mServiceDataPolicy;
+        private final long mSatelliteDataConsumedBytes;
 
         private CarrierRoamingSatelliteSessionParams(Builder builder) {
             this.mCarrierId = builder.mCarrierId;
@@ -1781,6 +1784,10 @@
             this.mCountOfOutgoingSms = builder.mCountOfOutgoingSms;
             this.mCountOfIncomingMms = builder.mCountOfIncomingMms;
             this.mCountOfOutgoingMms = builder.mCountOfOutgoingMms;
+            this.mSupportedSatelliteServices = builder.mSupportedSatelliteServices;
+            this.mServiceDataPolicy = builder.mServiceDataPolicy;
+            this.mSatelliteDataConsumedBytes =
+                    builder.mSatelliteDataConsumedBytes;
         }
 
         public int getCarrierId() {
@@ -1847,6 +1854,19 @@
             return mCountOfOutgoingMms;
         }
 
+        public int[] getSupportedSatelliteServices() {
+            return mSupportedSatelliteServices;
+        }
+
+
+        public int getServiceDataPolicy() {
+            return mServiceDataPolicy;
+        }
+
+        public long getSatelliteDataConsumedBytes() {
+            return mSatelliteDataConsumedBytes;
+        }
+
         /**
          * A builder class to create {@link CarrierRoamingSatelliteSessionParams} data structure
          * class
@@ -1868,6 +1888,10 @@
             private int mCountOfOutgoingSms = 0;
             private int mCountOfIncomingMms = 0;
             private int mCountOfOutgoingMms = 0;
+            private int[] mSupportedSatelliteServices = new int[0];
+            int mServiceDataPolicy =
+                    SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN;
+            long mSatelliteDataConsumedBytes = 0L;
 
             /**
              * Sets carrierId value of {@link CarrierRoamingSatelliteSession} atom
@@ -2017,6 +2041,34 @@
             }
 
             /**
+             * Sets supportedSatelliteServices value of {@link CarrierRoamingSatelliteSession}
+             * atom then returns Builder class
+             */
+            public Builder setSupportedSatelliteServices(int[] supportedSatelliteServices) {
+                this.mSupportedSatelliteServices = supportedSatelliteServices;
+                return this;
+            }
+
+            /**
+             * Sets serviceDataPolicy value of {@link CarrierRoamingSatelliteSession}
+             * atom then returns Builder class
+             */
+            public Builder setServiceDataPolicy(int serviceDataPolicy) {
+                this.mServiceDataPolicy = serviceDataPolicy;
+                return this;
+            }
+
+            /**
+             * Sets satelliteDataConsumedPerSessionBytes value of
+             * {@link CarrierRoamingSatelliteSession} atom then returns Builder class
+             */
+            public Builder setSatelliteDataConsumedBytes(
+                    long satelliteDataConsumedPerSessionBytes) {
+                this.mSatelliteDataConsumedBytes = satelliteDataConsumedPerSessionBytes;
+                return this;
+            }
+
+            /**
              * Returns CarrierRoamingSatelliteSessionParams, which contains whole component of
              * {@link CarrierRoamingSatelliteSession} atom
              */
@@ -2046,6 +2098,9 @@
                     + ", countOfOutgoingSms=" + mCountOfOutgoingSms
                     + ", countOfIncomingMms=" + mCountOfIncomingMms
                     + ", countOfOutgoingMms=" + mCountOfOutgoingMms
+                    + ", supportedSatelliteServices=" + Arrays.toString(mSupportedSatelliteServices)
+                    + ", serviceDataPolicy=" + mServiceDataPolicy
+                    + ", SatelliteDataConsumedBytes=" + mSatelliteDataConsumedBytes
                     + ")";
         }
     }
@@ -2060,9 +2115,9 @@
         private final int mCountOfEntitlementStatusQueryRequest;
         private final int mCountOfSatelliteConfigUpdateRequest;
         private final int mCountOfSatelliteNotificationDisplayed;
-        private final int mSatelliteSessionGapMinSec;
-        private final int mSatelliteSessionGapAvgSec;
-        private final int mSatelliteSessionGapMaxSec;
+        private static int sSatelliteSessionGapMinSec;
+        private static int sSatelliteSessionGapAvgSec;
+        private static int sSatelliteSessionGapMaxSec;
         private static int sCarrierId;
         private static boolean sIsDeviceEntitled;
 
@@ -2074,9 +2129,17 @@
                     builder.mCountOfSatelliteConfigUpdateRequest;
             this.mCountOfSatelliteNotificationDisplayed =
                     builder.mCountOfSatelliteNotificationDisplayed;
-            this.mSatelliteSessionGapMinSec = builder.mSatelliteSessionGapMinSec;
-            this.mSatelliteSessionGapAvgSec = builder.mSatelliteSessionGapAvgSec;
-            this.mSatelliteSessionGapMaxSec = builder.mSatelliteSessionGapMaxSec;
+
+            // Update session gap params only when they are explicitly provided
+            if (builder.mSatelliteSessionGapMinSec.isPresent()) {
+                this.sSatelliteSessionGapMinSec = builder.mSatelliteSessionGapMinSec.get();
+            }
+            if (builder.mSatelliteSessionGapAvgSec.isPresent()) {
+                this.sSatelliteSessionGapAvgSec = builder.mSatelliteSessionGapAvgSec.get();
+            }
+            if (builder.mSatelliteSessionGapMaxSec.isPresent()) {
+                this.sSatelliteSessionGapMaxSec = builder.mSatelliteSessionGapMaxSec.get();
+            }
 
             // Carrier ID value should be updated only when it is meaningful.
             if (builder.mCarrierId.isPresent()) {
@@ -2107,15 +2170,15 @@
         }
 
         public int getSatelliteSessionGapMinSec() {
-            return mSatelliteSessionGapMinSec;
+            return sSatelliteSessionGapMinSec;
         }
 
         public int getSatelliteSessionGapAvgSec() {
-            return mSatelliteSessionGapAvgSec;
+            return sSatelliteSessionGapAvgSec;
         }
 
         public int getSatelliteSessionGapMaxSec() {
-            return mSatelliteSessionGapMaxSec;
+            return sSatelliteSessionGapMaxSec;
         }
 
         public int getCarrierId() {
@@ -2135,9 +2198,9 @@
             private int mCountOfEntitlementStatusQueryRequest = 0;
             private int mCountOfSatelliteConfigUpdateRequest = 0;
             private int mCountOfSatelliteNotificationDisplayed = 0;
-            private int mSatelliteSessionGapMinSec = 0;
-            private int mSatelliteSessionGapAvgSec = 0;
-            private int mSatelliteSessionGapMaxSec = 0;
+            private Optional<Integer> mSatelliteSessionGapMinSec = Optional.empty();
+            private Optional<Integer> mSatelliteSessionGapAvgSec = Optional.empty();
+            private Optional<Integer> mSatelliteSessionGapMaxSec = Optional.empty();
             private Optional<Integer> mCarrierId = Optional.empty();
             private Optional<Boolean> mIsDeviceEntitled = Optional.empty();
 
@@ -2185,7 +2248,7 @@
              * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class
              */
             public Builder setSatelliteSessionGapMinSec(int satelliteSessionGapMinSec) {
-                this.mSatelliteSessionGapMinSec = satelliteSessionGapMinSec;
+                this.mSatelliteSessionGapMinSec = Optional.of(satelliteSessionGapMinSec);
                 return this;
             }
 
@@ -2194,7 +2257,7 @@
              * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class
              */
             public Builder setSatelliteSessionGapAvgSec(int satelliteSessionGapAvgSec) {
-                this.mSatelliteSessionGapAvgSec = satelliteSessionGapAvgSec;
+                this.mSatelliteSessionGapAvgSec = Optional.of(satelliteSessionGapAvgSec);
                 return this;
             }
 
@@ -2203,7 +2266,7 @@
              * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class
              */
             public Builder setSatelliteSessionGapMaxSec(int satelliteSessionGapMaxSec) {
-                this.mSatelliteSessionGapMaxSec = satelliteSessionGapMaxSec;
+                this.mSatelliteSessionGapMaxSec = Optional.of(satelliteSessionGapMaxSec);
                 return this;
             }
 
@@ -2239,9 +2302,9 @@
                     + mCountOfSatelliteConfigUpdateRequest
                     + ", countOfSatelliteNotificationDisplayed="
                     + mCountOfSatelliteNotificationDisplayed
-                    + ", satelliteSessionGapMinSec=" + mSatelliteSessionGapMinSec
-                    + ", satelliteSessionGapAvgSec=" + mSatelliteSessionGapAvgSec
-                    + ", satelliteSessionGapMaxSec=" + mSatelliteSessionGapMaxSec
+                    + ", satelliteSessionGapMinSec=" + sSatelliteSessionGapMinSec
+                    + ", satelliteSessionGapAvgSec=" + sSatelliteSessionGapAvgSec
+                    + ", satelliteSessionGapMaxSec=" + sSatelliteSessionGapMaxSec
                     + ", carrierId=" + sCarrierId
                     + ", isDeviceEntitled=" + sIsDeviceEntitled
                     + ")";
@@ -2258,6 +2321,9 @@
         private final int mEntitlementStatus;
         private final boolean mIsRetry;
         private final int mCount;
+        private final boolean mIsAllowedServiceEntitlement;
+        private final int[] mEntitlementServiceType;
+        private final int mEntitlementDataPolicy;
 
         private SatelliteEntitlementParams(Builder builder) {
             this.mCarrierId = builder.mCarrierId;
@@ -2265,6 +2331,9 @@
             this.mEntitlementStatus = builder.mEntitlementStatus;
             this.mIsRetry = builder.mIsRetry;
             this.mCount = builder.mCount;
+            this.mIsAllowedServiceEntitlement = builder.mIsAllowedServiceEntitlement;
+            this.mEntitlementServiceType = builder.mEntitlementServiceType;
+            this.mEntitlementDataPolicy = builder.mEntitlementDataPolicy;
         }
 
         public int getCarrierId() {
@@ -2287,6 +2356,18 @@
             return mCount;
         }
 
+        public boolean getIsAllowedServiceEntitlement() {
+            return mIsAllowedServiceEntitlement;
+        }
+
+        public int[] getEntitlementServiceType() {
+            return mEntitlementServiceType;
+        }
+
+        public int getEntitlementDataPolicy() {
+            return mEntitlementDataPolicy;
+        }
+
         /**
          * A builder class to create {@link SatelliteEntitlementParams} data structure class
          */
@@ -2296,6 +2377,10 @@
             private int mEntitlementStatus = -1;
             private boolean mIsRetry = false;
             private int mCount = -1;
+            private boolean mIsAllowedServiceEntitlement = false;
+            private int[] mEntitlementServiceType = new int[0];
+            private int mEntitlementDataPolicy =
+                    SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN;
 
             /**
              * Sets carrierId value of {@link SatelliteEntitlement} atom
@@ -2343,6 +2428,33 @@
             }
 
             /**
+             * Sets isAllowedServiceEntitlement value of {@link SatelliteEntitlement} atom
+             * then returns Builder class
+             */
+            public Builder setIsAllowedServiceEntitlement(boolean isAllowedServiceEntitlement) {
+                this.mIsAllowedServiceEntitlement = isAllowedServiceEntitlement;
+                return this;
+            }
+
+            /**
+             * Sets entitlementServiceType value of {@link SatelliteEntitlement} atom
+             * then returns Builder class
+             */
+            public Builder setEntitlementServiceType(int[] entitlementServiceType) {
+                this.mEntitlementServiceType = entitlementServiceType;
+                return this;
+            }
+
+            /**
+             * Sets entitlementDataPolicy value of {@link SatelliteEntitlement} atom
+             * then returns Builder class
+             */
+            public Builder setEntitlementDataPolicy(int entitlementDataPolicy) {
+                this.mEntitlementDataPolicy = entitlementDataPolicy;
+                return this;
+            }
+
+            /**
              * Returns SatelliteEntitlementParams, which contains whole component of
              * {@link SatelliteEntitlement} atom
              */
@@ -2359,7 +2471,10 @@
                     + ", result=" + mResult
                     + ", entitlementStatus=" + mEntitlementStatus
                     + ", isRetry=" + mIsRetry
-                    + ", count=" + mCount + ")";
+                    + ", count=" + mCount
+                    + ",isAllowedServiceEntitlement=" + mIsAllowedServiceEntitlement
+                    + ",entitlementServiceType=" + Arrays.toString(mEntitlementServiceType)
+                    + ",entitlementServicePolicy=" + mEntitlementDataPolicy + ")";
         }
     }
 
@@ -2831,6 +2946,9 @@
         proto.countOfOutgoingSms = param.mCountOfOutgoingSms;
         proto.countOfIncomingMms = param.mCountOfIncomingMms;
         proto.countOfOutgoingMms = param.mCountOfOutgoingMms;
+        proto.supportedSatelliteServices = param.mSupportedSatelliteServices;
+        proto.serviceDataPolicy = param.mServiceDataPolicy;
+        proto.satelliteDataConsumedBytes = param.mSatelliteDataConsumedBytes;
         mAtomsStorage.addCarrierRoamingSatelliteSessionStats(proto);
     }
 
@@ -2842,14 +2960,21 @@
         proto.countOfEntitlementStatusQueryRequest = param.mCountOfEntitlementStatusQueryRequest;
         proto.countOfSatelliteConfigUpdateRequest = param.mCountOfSatelliteConfigUpdateRequest;
         proto.countOfSatelliteNotificationDisplayed = param.mCountOfSatelliteNotificationDisplayed;
-        proto.satelliteSessionGapMinSec = param.mSatelliteSessionGapMinSec;
-        proto.satelliteSessionGapAvgSec = param.mSatelliteSessionGapAvgSec;
-        proto.satelliteSessionGapMaxSec = param.mSatelliteSessionGapMaxSec;
+        proto.satelliteSessionGapMinSec = param.getSatelliteSessionGapMinSec();
+        proto.satelliteSessionGapAvgSec = param.getSatelliteSessionGapAvgSec();
+        proto.satelliteSessionGapMaxSec = param.getSatelliteSessionGapMaxSec();
         proto.carrierId = param.getCarrierId();
         proto.isDeviceEntitled = param.isDeviceEntitled();
         mAtomsStorage.addCarrierRoamingSatelliteControllerStats(proto);
     }
 
+    /** Reset carrier roaming satellite controller stats after atom is pulled. */
+    public synchronized void resetCarrierRoamingSatelliteControllerStats() {
+        com.android.internal.telephony.satellite.metrics
+                .CarrierRoamingSatelliteControllerStats.getOrCreateInstance()
+                .resetSessionGapLists();
+    }
+
     /**  Create a new atom for SatelliteEntitlement metrics */
     public synchronized  void onSatelliteEntitlementMetrics(SatelliteEntitlementParams param) {
         SatelliteEntitlement proto = new SatelliteEntitlement();
@@ -2858,6 +2983,9 @@
         proto.entitlementStatus = param.getEntitlementStatus();
         proto.isRetry = param.getIsRetry();
         proto.count = param.getCount();
+        proto.isAllowedServiceEntitlement = param.getIsAllowedServiceEntitlement();
+        proto.entitlementServiceType = param.getEntitlementServiceType();
+        proto.entitlementDataPolicy = param.getEntitlementDataPolicy();
         mAtomsStorage.addSatelliteEntitlementStats(proto);
     }
 
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index a6b4efb..bb509be 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -1374,7 +1374,14 @@
     private boolean allowMtSmsPolling() {
         if (!mFeatureFlags.carrierRoamingNbIotNtn()) return false;
 
-        if (mIsMtSmsPollingThrottled) return false;
+        SatelliteController satelliteController = SatelliteController.getInstance();
+        int subId = satelliteController.getSelectedSatelliteSubId();
+        boolean isP2PSmsDisallowed =
+                satelliteController.isP2PSmsDisallowedOnCarrierRoamingNtn(subId);
+        if (isP2PSmsDisallowed) {
+            plogd("allowMtSmsPolling: P2P SMS disallowed, subId = " + subId);
+            return false;
+        }
 
         if (!mIsAligned) return false;
 
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java b/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
index bde3975..cfade30 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.os.FileUtils;
 import android.util.ArraySet;
 import android.util.Log;
 
@@ -288,6 +289,33 @@
     }
 
     /**
+     * This method cleans the Satellite Config OTA resources and it should be used only in CTS/Unit
+     * tests
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public void cleanOtaResources(@Nullable Context context) {
+        if (context == null) {
+            Log.d(TAG, "cleanOtaResources : context is null");
+            return;
+        }
+        try {
+            File satelliteFileDir = context.getDir(SATELLITE_DIR_NAME, Context.MODE_PRIVATE);
+            if (!satelliteFileDir.exists()) {
+                Log.d(
+                        TAG,
+                        "cleanOtaResources: "
+                                + SATELLITE_DIR_NAME
+                                + " does not exist. No need to clean.");
+                return;
+            }
+            Log.d(TAG, "cleanOtaResources: Deleting contents under " + SATELLITE_DIR_NAME);
+            FileUtils.deleteContents(satelliteFileDir);
+        } catch (Exception e) {
+            Log.e(TAG, "cleanOtaResources error : " + e);
+        }
+    }
+
+    /**
      * @return {@code true} if the SatS2File is already existed and {@code false} otherwise.
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java b/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java
index e81a708..866969f 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java
@@ -124,4 +124,18 @@
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface TriggeringEvent {}
+
+    public static final int SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN = 0;
+    public static final int SATELLITE_ENTITLEMENT_SERVICE_POLICY_RESTRICTED = 1;
+    public static final int SATELLITE_ENTITLEMENT_SERVICE_POLICY_CONSTRAINED = 2;
+    public static final int SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNCONSTRAINED = 3;
+
+    @IntDef(prefix = {"SATELLITE_ENTITLEMENT_SERVICE_POLICY_"}, value = {
+            SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN,
+            SATELLITE_ENTITLEMENT_SERVICE_POLICY_RESTRICTED,
+            SATELLITE_ENTITLEMENT_SERVICE_POLICY_CONSTRAINED,
+            SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNCONSTRAINED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SatelliteEntitlementServicePolicy {}
 }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index f0822a9..89c3c95 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -68,6 +68,7 @@
 import static com.android.internal.telephony.configupdate.ConfigProviderAdaptor.DOMAIN_SATELLITE;
 
 import android.annotation.ArrayRes;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AlertDialog;
@@ -91,6 +92,7 @@
 import android.database.ContentObserver;
 import android.hardware.devicestate.DeviceState;
 import android.hardware.devicestate.DeviceStateManager;
+import android.location.LocationManager;
 import android.net.Uri;
 import android.net.wifi.WifiManager;
 import android.nfc.NfcAdapter;
@@ -183,6 +185,8 @@
 import com.android.internal.telephony.util.WorkerThread;
 import com.android.internal.util.FunctionalUtils;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -312,6 +316,9 @@
     private static final int EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE = 59;
     private static final int EVENT_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_CHANGED = 60;
     private static final int CMD_EVALUATE_CARRIER_ROAMING_NTN_ELIGIBILITY_CHANGE = 61;
+    private static final int CMD_LOCATION_SERVICE_STATE_CHANGED = 62;
+    protected static final int
+        EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT = 63;
 
     @NonNull private static SatelliteController sInstance;
     @NonNull private final Context mContext;
@@ -601,6 +608,7 @@
     SparseArray<Map<String, Integer>> mEntitlementVoiceServicePolicyMapPerCarrier =
             new SparseArray<>();
     private static AtomicLong sNextSatelliteEnableRequestId = new AtomicLong(0);
+    private static AtomicLong sNextSystemSelectionChannelsUpdateRequestId = new AtomicLong(0);
     // key : subscriberId, value : provisioned or not.
     @GuardedBy("mSatelliteTokenProvisionedLock")
     private Map<String, Boolean> mProvisionedSubscriberId = new HashMap<>();
@@ -653,6 +661,7 @@
     private final RegistrantList mSatelliteSubIdChangedRegistrants = new RegistrantList();
     private final BTWifiNFCStateReceiver mBTWifiNFCSateReceiver;
     private final UwbAdapterStateCallback mUwbAdapterStateCallback;
+    private final List<Integer> mCtsSatelliteAccessAllowedSubIds = new ArrayList<>();
 
     private long mSessionStartTimeStamp;
     private long mSessionProcessingTimeStamp;
@@ -693,6 +702,12 @@
     // Data Plan types at entitlement for the plmn allowed
     public static final int SATELLITE_DATA_PLAN_METERED = 0;
     public static final int SATELLITE_DATA_PLAN_UNMETERED = 1;
+    @IntDef(prefix = {"SATELLITE_DATA_PLAN_"}, value = {
+            SATELLITE_DATA_PLAN_METERED,
+            SATELLITE_DATA_PLAN_UNMETERED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SatelliteDataPlan {}
     private BroadcastReceiver
             mDefaultSmsSubscriptionChangedBroadcastReceiver = new BroadcastReceiver() {
                 @Override
@@ -731,6 +746,17 @@
         }
     };
 
+    protected BroadcastReceiver mLocationServiceStateChangedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // Check whether user has turned on/off location manager from settings menu
+            if (intent.getAction().equals(LocationManager.MODE_CHANGED_ACTION)) {
+                plogd("mLocationServiceStateChangedReceiver");
+                sendRequestAsync(CMD_LOCATION_SERVICE_STATE_CHANGED, null, null);
+            }
+        }
+    };
+
     // List of device states returned from DeviceStateManager to determine if running on a foldable
     // device.
     private List<DeviceState> mDeviceStates = new ArrayList();
@@ -927,6 +953,7 @@
 
         mSatellitePlmnListFromOverlayConfig = readSatellitePlmnsFromOverlayConfig();
         registerApplicationStateChanged();
+        registerLocationServiceStateChanged();
         updateSupportedSatelliteServicesForActiveSubscriptions();
         mCarrierConfigChangeListener =
                 (slotIndex, subId, carrierId, specificCarrierId) ->
@@ -1051,6 +1078,15 @@
     }
 
     /**
+     * This API should be used by only CTS/unit tests to reset the telephony configs set through
+     * config updater
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public void cleanUpTelephonyConfigs() {
+        TelephonyConfigUpdateInstallReceiver.getInstance().cleanUpTelephonyConfigs();
+    }
+
+    /**
      * Get SatelliteConfigParser from TelephonyConfigUpdateInstallReceiver
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@@ -1311,14 +1347,17 @@
     }
 
     private static final class UpdateSystemSelectionChannelsArgument {
-        @NonNull List<SystemSelectionSpecifier> mSystemSelectionSpecifiers;
-        @NonNull ResultReceiver mResult;
+        public @NonNull List<SystemSelectionSpecifier> systemSelectionSpecifiers;
+        public @NonNull ResultReceiver result;
+        public long requestId;
 
         UpdateSystemSelectionChannelsArgument(
                 @NonNull List<SystemSelectionSpecifier> systemSelectionSpecifiers,
                 @NonNull ResultReceiver result) {
-            this.mSystemSelectionSpecifiers = systemSelectionSpecifiers;
-            this.mResult = result;
+            this.systemSelectionSpecifiers = systemSelectionSpecifiers;
+            this.result = result;
+            this.requestId = sNextSystemSelectionChannelsUpdateRequestId.getAndUpdate(
+                    n -> ((n + 1) % Long.MAX_VALUE));
         }
     }
 
@@ -2147,11 +2186,13 @@
             case CMD_UPDATE_SYSTEM_SELECTION_CHANNELS: {
                 plogd("CMD_UPDATE_SYSTEM_SELECTION_CHANNELS");
                 request = (SatelliteControllerHandlerRequest) msg.obj;
-                onCompleted = obtainMessage(EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE, request);
+                onCompleted =
+                    obtainMessage(EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE, request);
+                UpdateSystemSelectionChannelsArgument argument =
+                        (UpdateSystemSelectionChannelsArgument) request.argument;
                 mSatelliteModemInterface.updateSystemSelectionChannels(
-                        ((UpdateSystemSelectionChannelsArgument) (request.argument))
-                                .mSystemSelectionSpecifiers,
-                        onCompleted);
+                        argument.systemSelectionSpecifiers, onCompleted);
+                startWaitForUpdateSystemSelectionChannelsResponseTimer(argument);
                 break;
             }
 
@@ -2161,8 +2202,25 @@
                 int error =  SatelliteServiceUtils.getSatelliteError(
                         ar, "updateSystemSelectionChannel");
                 plogd("EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE = " + error);
-                ((UpdateSystemSelectionChannelsArgument) (request.argument)).mResult.send(error,
-                        null);
+                UpdateSystemSelectionChannelsArgument argument =
+                        (UpdateSystemSelectionChannelsArgument) request.argument;
+                if (shouldProcessEventUpdateSystemSelectionChannelsDone(argument)) {
+                    argument.result.send(error, null);
+                    stopWaitForUpdateSystemSelectionChannelsResponseTimer(argument);
+                } else {
+                    plogd("EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE: the timer of "
+                              + "the request ID " + argument.requestId
+                              + " has already expired.");
+                }
+                break;
+            }
+
+            case EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT: {
+                UpdateSystemSelectionChannelsArgument argument =
+                        (UpdateSystemSelectionChannelsArgument) msg.obj;
+                argument.result.send(SATELLITE_RESULT_MODEM_TIMEOUT, null);
+                plogd("Timed out to wait for response of the system selection channels"
+                          + " update request ID " + argument.requestId);
                 break;
             }
 
@@ -2176,6 +2234,9 @@
                 break;
             }
 
+            case CMD_LOCATION_SERVICE_STATE_CHANGED:
+                plogd("CMD_LOCATION_SERVICE_STATE_CHANGED");
+                // Fall through
             case CMD_EVALUATE_CARRIER_ROAMING_NTN_ELIGIBILITY_CHANGE: {
                 plogd("CMD_EVALUATE_CARRIER_ROAMING_NTN_ELIGIBILITY_CHANGE");
                 evaluateCarrierRoamingNtnEligibilityChange();
@@ -3402,12 +3463,6 @@
         synchronized (mIsSatelliteSupportedLock) {
             mIsSatelliteSupported = null;
         }
-        synchronized (mDeviceProvisionLock) {
-            mIsDeviceProvisioned = Optional.ofNullable(provisioned)
-                    .filter(s -> s.equalsIgnoreCase("true") || s.equalsIgnoreCase("false"))
-                    .map(s -> s.equalsIgnoreCase("true"))
-                    .orElse(null);
-        }
         synchronized (mIsSatelliteEnabledLock) {
             mIsSatelliteEnabled = null;
         }
@@ -3435,6 +3490,25 @@
     }
 
     /**
+     * This API can be used by only CTS to override TN scanning support.
+     *
+     * @param concurrentTnScanningSupported Whether concurrent TN scanning is supported.
+     * @param tnScanningDuringSatelliteSessionAllowed Whether TN scanning is allowed during
+     * a satellite session.
+     * @return {@code true} if the TN scanning support is set successfully,
+     * {@code false} otherwise.
+     */
+    public boolean setTnScanningSupport(boolean reset, boolean concurrentTnScanningSupported,
+        boolean tnScanningDuringSatelliteSessionAllowed) {
+        if (mSatelliteSessionController == null) {
+            ploge("setTnScanningSupport: mSatelliteSessionController is not initialized yet");
+            return false;
+        }
+        return mSatelliteSessionController.setTnScanningSupport(reset,
+                concurrentTnScanningSupported, tnScanningDuringSatelliteSessionAllowed);
+    }
+
+    /**
      * This API can be used by only CTS to control ingoring cellular service state event.
      *
      * @param enabled Whether to enable boolean config.
@@ -4190,19 +4264,27 @@
     }
 
     /**
-     * To use the satellite service, update the EntitlementStatus and the PlmnAllowedList after
-     * receiving the satellite configuration from the entitlement server. If satellite
-     * entitlement is enabled, enable satellite for the carrier. Otherwise, disable satellite.
+     * To use the satellite service, update the EntitlementStatus, PlmnAllowedList, barred plmn list
+     * data plan, service type, data service policy and voice service policy after receiving the
+     * satellite configuration from the entitlement server. If satellite entitlement is enabled,
+     * enable satellite for the carrier. Otherwise, disable satellite.
      *
      * @param subId              subId
      * @param entitlementEnabled {@code true} Satellite service enabled
      * @param allowedPlmnList    plmn allowed list to use the satellite service
      * @param barredPlmnList    plmn barred list to pass the modem
-     * @param plmnDataPlanMap   data plan map for the plmn
-     * @param plmnServiceTypeMap available services map for the plmn
-     * @param plmnDataServicePolicyMap data service policy map for the plmn
-     * @param plmnVoiceServicePolicyMap voice service policy map for the plmn
-     * @param callback           callback for accept
+     * @param plmnDataPlanMap   data plan map for the plmn with key as plmn and data plan as value
+     *        with possible values {@link SatelliteDataPlan}
+     * @param plmnServiceTypeMap available services map for the plmn with key as plmn and service
+     *        type as list of integer values with possible values
+     *        {@link NetworkRegistrationInfo#ServiceType}
+     * @param plmnDataServicePolicyMap data service policy map for the plmn with key as plmn and
+     *        data service policy as integer value with possible values
+     *        {@link CarrierConfigManager#SATELLITE_DATA_SUPPORT_MODE}
+     * @param plmnVoiceServicePolicyMap voice service policy map for the plmn with key as plmn and
+     *        voice service policy as integer value with possible values
+     *        @link CarrierConfigManager#SATELLITE_DATA_SUPPORT_MODE}
+     * @param callback callback for accept
      */
     public void onSatelliteEntitlementStatusUpdated(int subId, boolean entitlementEnabled,
             @Nullable List<String> allowedPlmnList, @Nullable List<String> barredPlmnList,
@@ -4358,11 +4440,8 @@
         if (result == SATELLITE_RESULT_SUCCESS
                 || result == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
             persistOemEnabledSatelliteProvisionStatus(true);
-            synchronized (mDeviceProvisionLock) {
-                mIsDeviceProvisioned = true;
-            }
             callback.accept(SATELLITE_RESULT_SUCCESS);
-            handleEventSatelliteProvisionStateChanged(true);
+            updateCachedDeviceProvisionStatus();
         } else {
             callback.accept(result);
         }
@@ -4387,13 +4466,10 @@
         if (result == SATELLITE_RESULT_SUCCESS
                 || result == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
             persistOemEnabledSatelliteProvisionStatus(false);
-            synchronized (mDeviceProvisionLock) {
-                mIsDeviceProvisioned = false;
-            }
             if (arg.callback != null) {
                 arg.callback.accept(SATELLITE_RESULT_SUCCESS);
             }
-            handleEventSatelliteProvisionStateChanged(false);
+            updateCachedDeviceProvisionStatus();
         } else if (arg.callback != null) {
             arg.callback.accept(result);
         }
@@ -4687,23 +4763,13 @@
         }
     }
 
-    private void handleEventSatelliteProvisionStateChanged(boolean provisioned) {
-        plogd("handleSatelliteProvisionStateChangedEvent: provisioned=" + provisioned);
-
-        synchronized (mDeviceProvisionLock) {
-            persistOemEnabledSatelliteProvisionStatus(provisioned);
-            mIsDeviceProvisioned = provisioned;
-        }
-        notifyDeviceProvisionStateChanged(provisioned);
-    }
-
     private void notifyDeviceProvisionStateChanged(boolean provisioned) {
         List<ISatelliteProvisionStateCallback> deadCallersList = new ArrayList<>();
         mSatelliteProvisionStateChangedListeners.values().forEach(listener -> {
             try {
                 listener.onSatelliteProvisionStateChanged(provisioned);
             } catch (RemoteException e) {
-                plogd("handleSatelliteProvisionStateChangedEvent RemoteException: " + e);
+                plogd("notifyDeviceProvisionStateChanged RemoteException: " + e);
                 deadCallersList.add(listener);
             }
         });
@@ -4763,7 +4829,7 @@
                 getPrioritizedSatelliteSubscriberProvisionStatusList();
         plogd("handleEventSatelliteSubscriptionProvisionStateChanged: " + informList);
         notifySatelliteSubscriptionProvisionStateChanged(informList);
-        updateDeviceProvisionStatus();
+        updateCachedDeviceProvisionStatus();
         // Report updated provisioned status to metrics.
         synchronized (mSatelliteTokenProvisionedLock) {
             boolean isProvisioned = !mProvisionedSubscriberId.isEmpty()
@@ -4774,9 +4840,9 @@
         evaluateCarrierRoamingNtnEligibilityChange();
     }
 
-    private void updateDeviceProvisionStatus() {
+    private void updateCachedDeviceProvisionStatus() {
         boolean isProvisioned = getPersistedDeviceProvisionStatus();
-        plogd("updateDeviceProvisionStatus: isProvisioned=" + isProvisioned);
+        plogd("updateCachedDeviceProvisionStatus: isProvisioned=" + isProvisioned);
         synchronized (mDeviceProvisionLock) {
             if (mIsDeviceProvisioned == null || mIsDeviceProvisioned != isProvisioned) {
                 mIsDeviceProvisioned = isProvisioned;
@@ -5133,6 +5199,10 @@
                             mSatelliteEnableAttributesUpdateRequest, null);
                 }
                 updateLastNotifiedNtnModeAndNotify(getSatellitePhone());
+
+                if (mFeatureFlags.satelliteExitP2pSessionOutsideGeofence()) {
+                    evaluateDisablingP2pSession();
+                }
             }
         }
     }
@@ -5531,7 +5601,7 @@
             }
         }
         // Need to update the provision status of the device
-        updateDeviceProvisionStatus();
+        updateCachedDeviceProvisionStatus();
     }
 
     @NonNull
@@ -6026,6 +6096,36 @@
         }
     }
 
+    /**
+     * map data policy to support unknown case at metrics
+     * @param dataPolicy data support mode for the service type
+     * @return corresponding value from {@link SatelliteConstants.SatelliteEntitlementServicePolicy}
+     *
+     */
+    @SatelliteConstants.SatelliteEntitlementServicePolicy
+    public int mapDataPolicyForMetrics(int dataPolicy) {
+        switch (dataPolicy) {
+            case CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED -> {
+                return SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_RESTRICTED;
+            }
+            case CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED -> {
+                return SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_CONSTRAINED;
+            }
+            case CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL -> {
+                return SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNCONSTRAINED;
+            }
+        }
+        return SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN;
+    }
+
+    private int[] getSupportedSatelliteServicesOnSessionStart(List<Integer> supportedServices) {
+        if (supportedServices == null || supportedServices.isEmpty()) {
+            return new int[0];
+        }
+
+        return supportedServices.stream().mapToInt(Integer::intValue).toArray();
+    }
+
     private void logCarrierRoamingSatelliteSessionStats(@NonNull Phone phone,
             boolean lastNotifiedNtnMode, boolean currNtnMode) {
         synchronized (mSatelliteConnectedLock) {
@@ -6034,14 +6134,24 @@
                 // Log satellite session start
                 CarrierRoamingSatelliteSessionStats sessionStats =
                         CarrierRoamingSatelliteSessionStats.getInstance(subId);
-                sessionStats.onSessionStart(phone.getCarrierId(), phone);
+                int[] supported_satellite_services =
+                        getSupportedSatelliteServicesOnSessionStart(
+                                getSupportedSatelliteServicesForPlmn(subId,
+                        phone.getServiceState().getOperatorNumeric()));
+                int dataPolicy = mapDataPolicyForMetrics(getSatelliteDataServicePolicyForPlmn(subId,
+                        phone.getServiceState().getOperatorNumeric()));
+
+                sessionStats.onSessionStart(phone.getCarrierId(), phone,
+                        supported_satellite_services, dataPolicy);
                 mCarrierRoamingSatelliteSessionStatsMap.put(subId, sessionStats);
+                mCarrierRoamingSatelliteControllerStats.onSessionStart();
             } else if (lastNotifiedNtnMode && !currNtnMode) {
                 // Log satellite session end
                 CarrierRoamingSatelliteSessionStats sessionStats =
                         mCarrierRoamingSatelliteSessionStatsMap.get(subId);
                 sessionStats.onSessionEnd();
                 mCarrierRoamingSatelliteSessionStatsMap.remove(subId);
+                mCarrierRoamingSatelliteControllerStats.onSessionEnd();
             }
         }
     }
@@ -6130,8 +6240,6 @@
 
         if (mOverrideNtnEligibility != null) {
             satellitePhone.notifyCarrierRoamingNtnEligibleStateChanged(currentNtnEligibility);
-            mControllerMetricsStats.reportP2PSmsEligibilityNotificationsCount(
-                    currentNtnEligibility);
             return;
         }
 
@@ -6346,6 +6454,45 @@
         }
     }
 
+    private void startWaitForUpdateSystemSelectionChannelsResponseTimer(
+            @NonNull UpdateSystemSelectionChannelsArgument argument) {
+        synchronized (mSatelliteEnabledRequestLock) {
+            if (hasMessages(
+                    EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT, argument)) {
+                plogd("WaitForUpdateSystemSelectionChannelsResponseTimer of request ID "
+                        + argument.requestId + " was already started");
+                return;
+            }
+            plogd("Start timer to wait for response of the system selection channels update request"
+                    + " ID=" + argument.requestId + ", mWaitTimeForSatelliteEnablingResponse="
+                    + mWaitTimeForSatelliteEnablingResponse);
+            sendMessageDelayed(
+                obtainMessage(EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT,
+                    argument), mWaitTimeForSatelliteEnablingResponse);
+        }
+    }
+
+    private void stopWaitForUpdateSystemSelectionChannelsResponseTimer(
+            @NonNull UpdateSystemSelectionChannelsArgument argument) {
+        synchronized (mSatelliteEnabledRequestLock) {
+            plogd("Stop timer to wait for response of the system selection channels"
+                      + " update request ID=" + argument.requestId);
+            removeMessages(
+                EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT, argument);
+        }
+    }
+
+    private boolean shouldProcessEventUpdateSystemSelectionChannelsDone(
+            @NonNull UpdateSystemSelectionChannelsArgument argument) {
+        synchronized (mSatelliteEnabledRequestLock) {
+            if (hasMessages(
+                    EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT, argument)) {
+                return true;
+            }
+            return false;
+        }
+    }
+
     private void startWaitForUpdateSatelliteEnableAttributesResponseTimer(
             @NonNull RequestSatelliteEnabledArgument argument) {
         synchronized (mSatelliteEnabledRequestLock) {
@@ -7471,6 +7618,11 @@
             plogd("isSatelliteAvailableAtCurrentLocation: subscriptionInfo is null");
             return false;
         }
+        if (mCtsSatelliteAccessAllowedSubIds.contains(info.getSubscriptionId())) {
+            plogd("isSatelliteAvailableAtCurrentLocation: subscriptionId="
+                      + info.getSubscriptionId() + " is allowed for CTS testing");
+            return true;
+        }
         if (!isSatelliteAccessAllowedAtCurrentLocation()) {
             plogd("isSatelliteAvailableAtCurrentLocation: satellite access is not allowed at " +
                     "current location");
@@ -7778,6 +7930,13 @@
             return false;
         }
 
+        // Even if Location service is off, isSatelliteAccessAllowed can be true
+        // when the device is in emergency call and the allowed cache is valid.
+        if (!isLocationServiceEnabled()) {
+            plogd("isCarrierRoamingNtnEligible: Location service is off");
+            return false;
+        }
+
         if (phone == null) {
             plogd("isCarrierRoamingNtnEligible: phone is null");
             return false;
@@ -7896,14 +8055,17 @@
             new SatelliteCommunicationAccessStateCallback() {
                 @Override
                 public void onAccessAllowedStateChanged(boolean isAllowed) {
-                    plogd("onAccessStateChanged: isAllowed="
-                        + isAllowed);
-                    synchronized (mSatelliteAccessConfigLock) {
-                        mSatelliteAccessAllowed = isAllowed;
+                    plogd("onAccessStateChanged: isAllowed=" + isAllowed);
+                    if (mFeatureFlags.satelliteExitP2pSessionOutsideGeofence()) {
+                        handleSatelliteAccessAllowedStateChanged(isAllowed);
+                    } else{
+                        synchronized (mSatelliteAccessConfigLock) {
+                            mSatelliteAccessAllowed = isAllowed;
+                        }
+                        evaluateESOSProfilesPrioritization();
+                        evaluateCarrierRoamingNtnEligibilityChange();
+                        handleCarrierRoamingNtnAvailableServicesChanged();
                     }
-                    evaluateESOSProfilesPrioritization();
-                    evaluateCarrierRoamingNtnEligibilityChange();
-                    handleCarrierRoamingNtnAvailableServicesChanged();
                 }
 
                 @Override
@@ -7926,6 +8088,48 @@
         mRegisteredForSatelliteCommunicationAccessStateChanged.set(true);
     }
 
+    /** Handle access allowed state changes. */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public void handleSatelliteAccessAllowedStateChanged(boolean isAllowed) {
+        plogd("handleSatelliteAccessAllowedStateChanged: isAllowed=" + isAllowed);
+        synchronized (mSatelliteAccessConfigLock) {
+            mSatelliteAccessAllowed = isAllowed;
+        }
+
+        evaluateESOSProfilesPrioritization();
+        selectBindingSatelliteSubscription(false);
+        evaluateCarrierRoamingNtnEligibilityChange();
+        handleCarrierRoamingNtnAvailableServicesChanged();
+        evaluateDisablingP2pSession();
+    }
+
+    private void evaluateDisablingP2pSession() {
+        boolean isAllowed = isSatelliteAccessAllowedAtCurrentLocation();
+        boolean isSatelliteEnabled = isSatelliteEnabled();
+        boolean isEmergency = getRequestIsEmergency();
+
+        plogd("evaluateDisablingP2pSession: isAllowed=" + isAllowed
+                + " isEmergency=" + isEmergency
+                + " isSatelliteEnabled:" + isSatelliteEnabled);
+        if (!isAllowed && isSatelliteEnabled && !isEmergency) {
+            // Disable P2P session if satellite is not allowed in current location
+            disableSatelliteSession(isEmergency);
+        }
+    }
+
+    private void disableSatelliteSession(boolean isEmergency) {
+        plogd("disableSatelliteSession: isEmergency=" + isEmergency);
+        requestSatelliteEnabled(false /* enableSatellite */,
+                false /* enableDemoMode */, isEmergency,
+                new IIntegerConsumer.Stub() {
+                    @Override
+                    public void accept(int result) {
+                        plogd("disableSatelliteSession:"
+                                + " requestSatelliteEnabled result=" + result);
+                    }
+                });
+    }
+
     private void handleSatelliteAccessConfigUpdateResult(
         SatelliteAccessConfiguration satelliteAccessConfig) {
         if(satelliteAccessConfig != null) {
@@ -8047,6 +8251,41 @@
         return result;
     }
 
+    /**
+     * This API can be used by only CTS to override the satellite access allowed state for
+     * a list of subscription IDs.
+     *
+     * @param subIdListStr The string representation of the list of subscription IDs,
+     *                     which are numbers separated by comma.
+     * @return {@code true} if the satellite access allowed state is set successfully,
+     * {@code false} otherwise.
+     */
+    public boolean setSatelliteAccessAllowedForSubscriptions(@Nullable String subIdListStr) {
+        if (!isMockModemAllowed()) {
+            plogd("setSatelliteAccessAllowedForSubscriptions: mock modem not allowed");
+            return false;
+        }
+
+        plogd("setSatelliteAccessAllowedForSubscriptions: subIdListStr=" + subIdListStr);
+        if (subIdListStr == null) {
+            mCtsSatelliteAccessAllowedSubIds.clear();
+            return true;
+        }
+
+        List<Integer> subIdList = new ArrayList<>();
+        for (String subIdStr : subIdListStr.split(",")) {
+            try {
+                subIdList.add(Integer.parseInt(subIdStr));
+            } catch (NumberFormatException e) {
+                plogd("setSatelliteAccessAllowedForSubscriptions: invalid subIdStr=" + subIdStr);
+                return false;
+            }
+        }
+        mCtsSatelliteAccessAllowedSubIds.clear();
+        mCtsSatelliteAccessAllowedSubIds.addAll(subIdList);
+        return true;
+    }
+
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected String getConfigSatelliteGatewayServicePackage() {
         if (!mChangeIntentComponent) {
@@ -8335,7 +8574,6 @@
      * return {@code true} when the phone does not support P2P SMS over carrier roaming satellite
      *        {@code false} otherwise
      */
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     public boolean isP2PSmsDisallowedOnCarrierRoamingNtn(int subId) {
         int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId);
         if (carrierRoamingNtnConnectType == CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
@@ -8407,6 +8645,12 @@
                 mContext.RECEIVER_EXPORTED);
     }
 
+    private void registerLocationServiceStateChanged() {
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION);
+        mContext.registerReceiver(mLocationServiceStateChangedReceiver, intentFilter);
+    }
+
 
     private void notifyEnabledStateChanged(boolean isEnabled) {
         TelephonyRegistryManager trm = mContext.getSystemService(TelephonyRegistryManager.class);
@@ -8647,6 +8891,17 @@
                 == NetworkRegistrationInfo.SERVICE_TYPE_DATA);
     }
 
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    protected boolean isLocationServiceEnabled() {
+        LocationManager lm = mContext.createAttributionContext("telephony")
+                .getSystemService(LocationManager.class);
+        if (lm != null) {
+            return lm.isLocationEnabled();
+        }
+
+        return true;
+    }
+
     /**
      * Method to return the current satellite data service policy supported mode for the registered
      * plmn based on entitlement provisioning information. Note: If no information at
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteOptimizedApplicationsTracker.java b/src/java/com/android/internal/telephony/satellite/SatelliteOptimizedApplicationsTracker.java
index 0fdb653..636c04e 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteOptimizedApplicationsTracker.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteOptimizedApplicationsTracker.java
@@ -82,10 +82,10 @@
                                 handleInitializeTracker();
                             }
                             case ACTION_PACKAGE_ADDED,
-                                ACTION_PACKAGE_UPDATED,
-                                ACTION_PACKAGE_MODIFIED-> {
-                                    String packageName = (String) msg.obj;
-                                    handlePackageMonitor(packageName);
+                                    ACTION_PACKAGE_UPDATED,
+                                    ACTION_PACKAGE_MODIFIED -> {
+                                String packageName = (String) msg.obj;
+                                handlePackageMonitor(packageName);
                             }
                             case ACTION_PACKAGE_REMOVED -> {
                                 String packageName = (String) msg.obj;
@@ -161,10 +161,7 @@
     }
 
     private void handlePackageRemoved(String packageName) {
-        ApplicationInfo applicationInfo = getApplicationInfo(packageName);
-        if (applicationInfo != null && isOptimizedSatelliteApplication(applicationInfo)) {
-            removeCacheOptimizedSatelliteApplication(packageName);
-        }
+        removeCacheOptimizedSatelliteApplication(packageName);
     }
 
     private void handlePackageMonitor(String packageName) {
@@ -182,7 +179,7 @@
         List<UserInfo> users = mUserManager.getUsers();
         for (UserInfo user : users) {
             int userId = user.getUserHandle().getIdentifier();
-            mSatelliteApplications.put(userId, new HashSet<>());
+            mSatelliteApplications.putIfAbsent(userId, new HashSet<>());
         }
         // Get a list of installed packages
         List<PackageInfo> packages =
@@ -213,6 +210,7 @@
             try {
                 mPackageManager.getPackageUidAsUser(
                         packageName, PackageManager.GET_META_DATA, userId);
+                mSatelliteApplications.putIfAbsent(userId, new HashSet<>());
                 mSatelliteApplications.get(userId).add(packageName);
             } catch (java.lang.Exception e) {
                 // package is not present for current user
@@ -229,7 +227,8 @@
                         packageName, PackageManager.GET_META_DATA, userId);
             } catch (java.lang.Exception e) {
                 // package is not present for current user
-                if (mSatelliteApplications.get(userId).contains(packageName)) {
+                if (mSatelliteApplications.containsKey(userId)
+                        && mSatelliteApplications.get(userId).contains(packageName)) {
                     mSatelliteApplications.get(userId).remove(packageName);
                 }
             }
@@ -240,7 +239,6 @@
      * Get list of applications that are optimized for low bandwidth satellite data.
      *
      * @param userId is Identifier of user
-     *
      * @return List of applications package names with data optimized network property. {@link
      *     #PROPERTY_SATELLITE_DATA_OPTIMIZED}
      */
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
index 57e768c..5f23e09 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
@@ -176,6 +176,8 @@
     private long mSatelliteStayAtListeningFromReceivingMillis;
     private long mSatelliteNbIotInactivityTimeoutMillis;
     private boolean mIgnoreCellularServiceState = false;
+    private Boolean mIsConcurrentTnScanningSupportedForCtsTest = null;
+    private Boolean mIsTnScanningDuringSatelliteSessionAllowedForCtsTest = null;
     private final ConcurrentHashMap<IBinder, ISatelliteModemStateCallback> mListeners;
     @SatelliteManager.SatelliteModemState private int mCurrentState;
     @SatelliteManager.SatelliteModemState private int mPreviousState;
@@ -542,6 +544,37 @@
     }
 
     /**
+     * This API can be used by only CTS to override TN scanning support.
+     *
+     * @param concurrentTnScanningSupported Whether concurrent TN scanning is supported.
+     * @param tnScanningDuringSatelliteSessionAllowed Whether TN scanning is allowed during
+     * a satellite session.
+     * @return {@code true} if the TN scanning support is set successfully,
+     * {@code false} otherwise.
+     */
+    boolean setTnScanningSupport(boolean reset, boolean concurrentTnScanningSupported,
+        boolean tnScanningDuringSatelliteSessionAllowed) {
+        if (!isMockModemAllowed()) {
+            ploge("setTnScanningSupport: modifying TN scanning support is not allowed");
+            return false;
+        }
+
+        plogd("setTnScanningSupport: reset=" + reset
+                  + ", concurrentTnScanningSupported=" + concurrentTnScanningSupported
+                  + ", tnScanningDuringSatelliteSessionAllowed="
+                  + tnScanningDuringSatelliteSessionAllowed);
+        if (reset) {
+            mIsConcurrentTnScanningSupportedForCtsTest = null;
+            mIsTnScanningDuringSatelliteSessionAllowedForCtsTest = null;
+        } else {
+            mIsConcurrentTnScanningSupportedForCtsTest = concurrentTnScanningSupported;
+            mIsTnScanningDuringSatelliteSessionAllowedForCtsTest =
+                    tnScanningDuringSatelliteSessionAllowed;
+        }
+        return true;
+    }
+
+    /**
      * Adjusts listening timeout duration when demo mode is on
      *
      * @param isDemoMode {@code true} : The listening timeout durations will be set to
@@ -2023,6 +2056,11 @@
     }
 
     private boolean isConcurrentTnScanningSupported() {
+        if (mIsConcurrentTnScanningSupportedForCtsTest != null) {
+            plogd("isConcurrentTnScanningSupported: mIsConcurrentTnScanningSupportedForCtsTest="
+                    + mIsConcurrentTnScanningSupportedForCtsTest);
+            return mIsConcurrentTnScanningSupportedForCtsTest;
+        }
         try {
             return mContext.getResources().getBoolean(
                 R.bool.config_satellite_modem_support_concurrent_tn_scanning);
@@ -2033,6 +2071,12 @@
     }
 
     private boolean isTnScanningAllowedDuringSatelliteSession() {
+        if (mIsTnScanningDuringSatelliteSessionAllowedForCtsTest != null) {
+            plogd("isTnScanningAllowedDuringSatelliteSession: "
+                    + "mIsTnScanningDuringSatelliteSessionAllowedForCtsTest="
+                    + mIsTnScanningDuringSatelliteSessionAllowedForCtsTest);
+            return mIsTnScanningDuringSatelliteSessionAllowedForCtsTest;
+        }
         try {
             return mContext.getResources().getBoolean(
                     R.bool.config_satellite_allow_tn_scanning_during_satellite_session);
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java
index e97d234..1db2361 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java
@@ -22,15 +22,22 @@
 import com.android.internal.telephony.metrics.SatelliteStats;
 import com.android.internal.telephony.satellite.SatelliteConstants;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 public class CarrierRoamingSatelliteControllerStats {
     private static final String TAG = CarrierRoamingSatelliteControllerStats.class.getSimpleName();
     private static CarrierRoamingSatelliteControllerStats sInstance = null;
     private static final int ADD_COUNT = 1;
 
     private SatelliteStats mSatelliteStats;
+    private List<Long> mSessionStartTimeList;
+    private List<Long> mSessionEndTimeList;
 
     private CarrierRoamingSatelliteControllerStats() {
         mSatelliteStats = SatelliteStats.getInstance();
+        resetSessionGapLists();
     }
 
     /**
@@ -96,6 +103,76 @@
                         .build());
     }
 
+    /** Log carrier roaming satellite session start */
+    public void onSessionStart() {
+        mSessionStartTimeList.add(getCurrentTime());
+    }
+
+    /** Log carrier roaming satellite session end */
+    public void onSessionEnd() {
+        mSessionEndTimeList.add(getCurrentTime());
+
+        int numberOfSatelliteSessions = getNumberOfSatelliteSessions();
+        List<Integer> sessionGapList = getSatelliteSessionGapList(numberOfSatelliteSessions);
+        int satelliteSessionGapMinSec = 0;
+        int satelliteSessionGapMaxSec = 0;
+        if (!sessionGapList.isEmpty()) {
+            satelliteSessionGapMinSec = Collections.min(sessionGapList);
+            satelliteSessionGapMaxSec = Collections.max(sessionGapList);
+        }
+
+        mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
+                new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+                        .setSatelliteSessionGapMinSec(satelliteSessionGapMinSec)
+                        .setSatelliteSessionGapAvgSec(getAvg(sessionGapList))
+                        .setSatelliteSessionGapMaxSec(satelliteSessionGapMaxSec)
+                        .build());
+    }
+
+    /** Atom is pulled once per day. Reset session gap lists after the atom is pulled. */
+    public void resetSessionGapLists() {
+        mSessionStartTimeList = new ArrayList<>();
+        mSessionEndTimeList = new ArrayList<>();
+    }
+
+    private int getNumberOfSatelliteSessions() {
+        return Math.min(mSessionStartTimeList.size(), mSessionEndTimeList.size());
+    }
+
+    private List<Integer> getSatelliteSessionGapList(int numberOfSatelliteSessions) {
+        if (numberOfSatelliteSessions == 0) {
+            return new ArrayList<>();
+        }
+
+        List<Integer> sessionGapList = new ArrayList<>();
+        for (int i = 1; i < numberOfSatelliteSessions; i++) {
+            long prevSessionEndTime = mSessionEndTimeList.get(i - 1);
+            long currentSessionStartTime = mSessionStartTimeList.get(i);
+            if (currentSessionStartTime > prevSessionEndTime && prevSessionEndTime > 0) {
+                sessionGapList.add((int) (
+                        (currentSessionStartTime - prevSessionEndTime) / 1000));
+            }
+        }
+        return sessionGapList;
+    }
+
+    private int getAvg(@NonNull List<Integer> list) {
+        if (list.isEmpty()) {
+            return 0;
+        }
+
+        int total = 0;
+        for (int num : list) {
+            total += num;
+        }
+
+        return total / list.size();
+    }
+
+    private long getCurrentTime() {
+        return System.currentTimeMillis();
+    }
+
     private static void logd(@NonNull String log) {
         Log.d(TAG, log);
     }
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
index 3138b16..b55e485 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
@@ -17,6 +17,10 @@
 package com.android.internal.telephony.satellite.metrics;
 
 import android.annotation.NonNull;
+import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStatsManager;
+import android.content.Context;
+import android.net.NetworkTemplate;
 import android.telephony.CellInfo;
 import android.telephony.CellSignalStrength;
 import android.telephony.CellSignalStrengthLte;
@@ -24,18 +28,22 @@
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.SparseArray;
 
 import com.android.internal.telephony.MccTable;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.metrics.SatelliteStats;
+import com.android.internal.telephony.satellite.SatelliteConstants;
 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 public class CarrierRoamingSatelliteSessionStats {
     private static final String TAG = CarrierRoamingSatelliteSessionStats.class.getSimpleName();
@@ -49,12 +57,17 @@
     private int mCountOfIncomingMms;
     private int mCountOfOutgoingMms;
     private long mIncomingMessageId;
-
     private int mSessionStartTimeSec;
     private List<Long> mConnectionStartTimeList;
     private List<Long> mConnectionEndTimeList;
     private List<Integer> mRsrpList;
     private List<Integer> mRssnrList;
+    private int[] mSupportedSatelliteServices;
+    private int mServiceDataPolicy;
+    private Phone mPhone;
+    private Context mContext;
+    private long mSatelliteDataConsumedBytes = 0L;
+    private long mDataUsageOnSessionStartBytes = 0L;
 
     public CarrierRoamingSatelliteSessionStats(int subId) {
         logd("Create new CarrierRoamingSatelliteSessionStats. subId=" + subId);
@@ -74,11 +87,18 @@
     }
 
     /** Log carrier roaming satellite session start */
-    public void onSessionStart(int carrierId, Phone phone) {
+    public void onSessionStart(int carrierId, Phone phone, int[] supportedServices,
+            int serviceDataPolicy) {
+        mPhone = phone;
+        mContext = mPhone.getContext();
         mCarrierId = carrierId;
+        mSupportedSatelliteServices = supportedServices;
+        mServiceDataPolicy = serviceDataPolicy;
         mSessionStartTimeSec = getCurrentTimeInSec();
         mIsNtnRoamingInHomeCountry = false;
-        onConnectionStart(phone);
+        onConnectionStart(mPhone);
+        mDataUsageOnSessionStartBytes = getDataUsage();
+        logd("current data consumed: " + mDataUsageOnSessionStartBytes);
     }
 
     /** Log carrier roaming satellite connection start */
@@ -87,11 +107,51 @@
         updateNtnRoamingInHomeCountry(phone);
     }
 
+    /** calculate total satellite data consumed at the session */
+    private long getDataUsage() {
+        if (mContext == null) {
+            return 0L;
+        }
+
+        NetworkStatsManager networkStatsManager =
+                mContext.getSystemService(NetworkStatsManager.class);
+
+        if (networkStatsManager != null) {
+            final NetworkTemplate.Builder builder =
+                    new NetworkTemplate.Builder(NetworkTemplate.MATCH_MOBILE);
+            final String subscriberId = mPhone.getSubscriberId();
+            logd("subscriber id for data consumed:" + subscriberId);
+
+            if (!TextUtils.isEmpty(subscriberId)) {
+                builder.setSubscriberIds(Set.of(subscriberId));
+                // Consider data usage calculation of only metered capabilities / data network
+                builder.setMeteredness(android.net.NetworkStats.METERED_YES);
+                NetworkTemplate template = builder.build();
+                final NetworkStats.Bucket ret = networkStatsManager
+                        .querySummaryForDevice(template, 0L, System.currentTimeMillis());
+                return ret.getRxBytes() + ret.getTxBytes();
+            }
+        }
+        return 0L;
+    }
+
     /** Log carrier roaming satellite session end */
     public void onSessionEnd() {
         onConnectionEnd();
+        long dataUsageOnSessionEndBytes = getDataUsage();
+        logd("update data consumed: " + dataUsageOnSessionEndBytes);
+        if (dataUsageOnSessionEndBytes > 0L
+                && dataUsageOnSessionEndBytes > mDataUsageOnSessionStartBytes) {
+            mSatelliteDataConsumedBytes =
+                    dataUsageOnSessionEndBytes - mDataUsageOnSessionStartBytes;
+        }
+        logd("satellite data consumed at session: " + mSatelliteDataConsumedBytes);
         reportMetrics();
         mIsNtnRoamingInHomeCountry = false;
+        mSupportedSatelliteServices = new int[0];
+        mServiceDataPolicy = SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN;
+        mSatelliteDataConsumedBytes = 0L;
+        mDataUsageOnSessionStartBytes = 0L;
     }
 
     /** Log carrier roaming satellite connection end */
@@ -189,8 +249,12 @@
                         .setCountOfOutgoingSms(mCountOfOutgoingSms)
                         .setCountOfIncomingMms(mCountOfIncomingMms)
                         .setCountOfOutgoingMms(mCountOfOutgoingMms)
+                        .setSupportedSatelliteServices(mSupportedSatelliteServices)
+                        .setServiceDataPolicy(mServiceDataPolicy)
+                        .setSatelliteDataConsumedBytes(mSatelliteDataConsumedBytes)
                         .build();
         SatelliteStats.getInstance().onCarrierRoamingSatelliteSessionMetrics(params);
+        logd("Supported satellite services: " + Arrays.toString(mSupportedSatelliteServices));
         logd("reportMetrics: " + params);
         initializeParams();
     }
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/EntitlementMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/EntitlementMetricsStats.java
index 4862188..828642c 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/EntitlementMetricsStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/EntitlementMetricsStats.java
@@ -35,6 +35,9 @@
     private int mResult;
     private int mEntitlementStatus;
     private boolean mIsRetry;
+    private boolean mIsAllowedServiceEntitlement;
+    private int[] mEntitlementServiceType;
+    private int mEntitlementDataPolicy;
 
     private EntitlementMetricsStats() {}
 
@@ -56,11 +59,14 @@
     /** Report metrics on entitlement query request success */
     public void reportSuccess(int subId,
             @SatelliteConstants.SatelliteEntitlementStatus int entitlementStatus,
-            boolean isRetry) {
+            boolean isRetry, boolean isAllowedServiceInfo, int[] serviceType, int dataPolicy) {
         mSubId = subId;
         mResult = RESULT_SUCCESS;
         mEntitlementStatus = entitlementStatus;
         mIsRetry = isRetry;
+        mIsAllowedServiceEntitlement = isAllowedServiceInfo;
+        mEntitlementServiceType = serviceType;
+        mEntitlementDataPolicy = dataPolicy;
         reportEntitlementMetrics();
     }
 
@@ -70,6 +76,9 @@
         mResult = result;
         mIsRetry = isRetry;
         mEntitlementStatus = SatelliteConstants.SATELLITE_ENTITLEMENT_STATUS_UNKNOWN;
+        mIsAllowedServiceEntitlement = false;
+        mEntitlementServiceType = new int[0];
+        mEntitlementDataPolicy = SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN;
         reportEntitlementMetrics();
     }
 
@@ -82,6 +91,9 @@
                         .setEntitlementStatus(mEntitlementStatus)
                         .setIsRetry(mIsRetry)
                         .setCount(1)
+                        .setIsAllowedServiceEntitlement(mIsAllowedServiceEntitlement)
+                        .setEntitlementServiceType(mEntitlementServiceType)
+                        .setEntitlementDataPolicy(mEntitlementDataPolicy)
                         .build();
         SatelliteStats.getInstance().onSatelliteEntitlementMetrics(entitlementParams);
         logd("reportEntitlementMetrics: " + entitlementParams);
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
index 5017f0a..8cb1ebe 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -4751,8 +4751,7 @@
             return;
         }
 
-        if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
-                || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+        if (!CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
                 Binder.getCallingUserHandle())
                 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
             // Skip to check associated telephony feature,
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java b/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
index 5eac4b1..5a63179 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
@@ -134,7 +134,7 @@
             return;
         }
 
-        boolean euiccSession = EuiccSession.get().hasSession();
+        boolean euiccSession = EuiccSession.get(mContext).hasSession();
         // Case 1, channel was already opened AND EuiccSession is ongoing.
         // sendCommand directly. Do not immediately close channel after sendCommand.
         // Case 2, channel was already opened AND EuiccSession is not ongoing. This means
@@ -147,7 +147,7 @@
         // before sendCommand. Close channel immediately after sendCommand.
         if (mChannelOpened) {  // Case 1 or 2
             if (euiccSession) {
-                EuiccSession.get().noteChannelOpen(this);
+                EuiccSession.get(mContext).noteChannelOpen(this);
             }
             RequestBuilder builder = getRequestBuilderWithOpenedChannel(requestProvider,
                     !euiccSession /* closeChannelImmediately */, resultCallback, handler);
@@ -158,7 +158,7 @@
                     !euiccSession /* closeChannelImmediately */, resultCallback, handler);
         } else {  // Case 3 or 4
             if (euiccSession) {
-                EuiccSession.get().noteChannelOpen(this);
+                EuiccSession.get(mContext).noteChannelOpen(this);
             }
             openChannel(requestProvider,
                     !euiccSession /* closeChannelImmediately */, resultCallback, handler);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
index 331fcba..ae43b2f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doReturn;
@@ -25,18 +26,30 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.Bundle;
 import android.os.Message;
+import android.service.carrier.CarrierService;
+import android.service.carrier.ICarrierService;
 import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.telephony.flags.Flags;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
 
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
@@ -101,6 +114,16 @@
                         new Integer(0)));
     }
 
+    // Verify a CarrierPrivilegesCallback is registered and return the callback object. May return
+    // null if no callback is captured.
+    private CarrierPrivilegesCallback expectRegisterCarrierPrivilegesCallback(int phoneId) {
+        ArgumentCaptor<CarrierPrivilegesCallback> callbackCaptor =
+                ArgumentCaptor.forClass(CarrierPrivilegesCallback.class);
+        verify(mTelephonyManager)
+                .registerCarrierPrivilegesCallback(eq(phoneId), any(), callbackCaptor.capture());
+        return callbackCaptor.getAllValues().get(0);
+    }
+
     @Test
     public void testCarrierPrivilegesCallbackRegistration() {
         // Device starts with DSDS mode
@@ -110,18 +133,11 @@
 
         // Verify that CarrierPrivilegesCallbacks are registered on both phones.
         // Capture the callbacks for further verification
-        ArgumentCaptor<CarrierPrivilegesCallback> phone0CallbackCaptor = ArgumentCaptor.forClass(
-                CarrierPrivilegesCallback.class);
-        verify(mTelephonyManager).registerCarrierPrivilegesCallback(eq(PHONE_ID_0), any(),
-                phone0CallbackCaptor.capture());
-        CarrierPrivilegesCallback phone0Callback = phone0CallbackCaptor.getAllValues().get(0);
+        CarrierPrivilegesCallback phone0Callback =
+                expectRegisterCarrierPrivilegesCallback(PHONE_ID_0);
         assertNotNull(phone0Callback);
-
-        ArgumentCaptor<CarrierPrivilegesCallback> phone1CallbackCaptor = ArgumentCaptor.forClass(
-                CarrierPrivilegesCallback.class);
-        verify(mTelephonyManager).registerCarrierPrivilegesCallback(eq(PHONE_ID_1), any(),
-                phone1CallbackCaptor.capture());
-        CarrierPrivilegesCallback phone1Callback = phone1CallbackCaptor.getAllValues().get(0);
+        CarrierPrivilegesCallback phone1Callback =
+                expectRegisterCarrierPrivilegesCallback(PHONE_ID_1);
         assertNotNull(phone1Callback);
 
         // Switch back to single SIM.
@@ -133,5 +149,115 @@
         verify(mTelephonyManager).unregisterCarrierPrivilegesCallback(eq(phone1Callback));
         verify(mTelephonyManager, never()).unregisterCarrierPrivilegesCallback(eq(phone0Callback));
     }
+
+    @Test
+    public void testCarrierAppConnectionLost_resetsCarrierNetworkChange() {
+        if (!Flags.disableCarrierNetworkChangeOnCarrierAppLost()) {
+            return;
+        }
+        // Static test data
+        String carrierServicePackageName = "android.test.package.carrier";
+        ComponentName carrierServiceComponentName =
+                new ComponentName("android.test.package", "carrier");
+        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
+                ArgumentCaptor.forClass(ServiceConnection.class);
+        ResolveInfo resolveInfo = new ResolveInfo();
+        ServiceInfo serviceInfo = new ServiceInfo();
+        serviceInfo.packageName = carrierServicePackageName;
+        serviceInfo.name = "carrier";
+        serviceInfo.metaData = new Bundle();
+        serviceInfo.metaData.putBoolean("android.service.carrier.LONG_LIVED_BINDING", true);
+        resolveInfo.serviceInfo = serviceInfo;
+
+        // Set up expectations for construction/initialization.
+        doReturn(carrierServicePackageName)
+                .when(mTelephonyManager)
+                .getCarrierServicePackageNameForLogicalSlot(PHONE_ID_0);
+        doReturn(1).when(mTelephonyManager).getActiveModemCount();
+        doReturn(resolveInfo)
+                .when(mPackageManager)
+                .resolveService(any(), eq(PackageManager.GET_META_DATA));
+        ICarrierService carrierServiceInterface = Mockito.mock(ICarrierService.class);
+        mContextFixture.addService(
+                CarrierService.CARRIER_SERVICE_INTERFACE,
+                carrierServiceComponentName,
+                carrierServicePackageName,
+                carrierServiceInterface,
+                serviceInfo);
+
+        mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext);
+        processAllMessages();
+
+        CarrierPrivilegesCallback phoneCallback =
+                expectRegisterCarrierPrivilegesCallback(PHONE_ID_0);
+        assertNotNull(phoneCallback);
+        phoneCallback.onCarrierServiceChanged(null, 0);
+        processAllMessages();
+
+        // Grab the ServiceConnection for CarrierService
+        verify(mContext)
+                .bindService(any(Intent.class), anyInt(), any(), serviceConnectionCaptor.capture());
+        ServiceConnection serviceConnection = serviceConnectionCaptor.getAllValues().get(0);
+        assertNotNull(serviceConnection);
+
+        // Test CarrierService disconnection
+        serviceConnection.onServiceDisconnected(carrierServiceComponentName);
+        verify(mTelephonyRegistryManager).notifyCarrierNetworkChange(PHONE_ID_0, false);
+    }
+
+    @Test
+    public void testCarrierAppBindingLost_resetsCarrierNetworkChange() {
+        if (!Flags.disableCarrierNetworkChangeOnCarrierAppLost()) {
+            return;
+        }
+        // Static test data
+        String carrierServicePackageName = "android.test.package.carrier";
+        ComponentName carrierServiceComponentName =
+                new ComponentName("android.test.package", "carrier");
+        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
+                ArgumentCaptor.forClass(ServiceConnection.class);
+        ResolveInfo resolveInfo = new ResolveInfo();
+        ServiceInfo serviceInfo = new ServiceInfo();
+        serviceInfo.packageName = carrierServicePackageName;
+        serviceInfo.name = "carrier";
+        serviceInfo.metaData = new Bundle();
+        serviceInfo.metaData.putBoolean("android.service.carrier.LONG_LIVED_BINDING", true);
+        resolveInfo.serviceInfo = serviceInfo;
+
+        // Set up expectations for construction/initialization.
+        doReturn(carrierServicePackageName)
+                .when(mTelephonyManager)
+                .getCarrierServicePackageNameForLogicalSlot(PHONE_ID_0);
+        doReturn(1).when(mTelephonyManager).getActiveModemCount();
+        doReturn(resolveInfo)
+                .when(mPackageManager)
+                .resolveService(any(), eq(PackageManager.GET_META_DATA));
+        ICarrierService carrierServiceInterface = Mockito.mock(ICarrierService.class);
+        mContextFixture.addService(
+                CarrierService.CARRIER_SERVICE_INTERFACE,
+                carrierServiceComponentName,
+                carrierServicePackageName,
+                carrierServiceInterface,
+                serviceInfo);
+
+        mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext);
+        processAllMessages();
+
+        CarrierPrivilegesCallback phoneCallback =
+                expectRegisterCarrierPrivilegesCallback(PHONE_ID_0);
+        assertNotNull(phoneCallback);
+        phoneCallback.onCarrierServiceChanged(null, 0);
+        processAllMessages();
+
+        // Grab the ServiceConnection for CarrierService
+        verify(mContext)
+                .bindService(any(Intent.class), anyInt(), any(), serviceConnectionCaptor.capture());
+        ServiceConnection serviceConnection = serviceConnectionCaptor.getAllValues().get(0);
+        assertNotNull(serviceConnection);
+
+        // Test CarrierService disconnection
+        serviceConnection.onBindingDied(carrierServiceComponentName);
+        verify(mTelephonyRegistryManager).notifyCarrierNetworkChange(PHONE_ID_0, false);
+    }
     // TODO (b/232461097): Add UT cases to cover more scenarios (user unlock, SIM state change...)
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
index 9788320..39139bf 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
@@ -105,6 +105,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Executor;
 
 /**
  * Controls a test {@link Context} as would be provided by the Android framework to an
@@ -226,21 +227,37 @@
             if (mServiceByServiceConnection.containsKey(connection)) {
                 throw new RuntimeException("ServiceConnection already bound: " + connection);
             }
-            IInterface service = mServiceByComponentName.get(serviceIntent.getComponent());
+            IInterface service = null;
+            if (serviceIntent.getComponent() != null) {
+                service = mServiceByComponentName.get(serviceIntent.getComponent());
+            }
             if (service == null) {
                 service = mServiceByPackageName.get(serviceIntent.getPackage());
             }
             if (service == null) {
                 throw new RuntimeException(
-                        String.format("ServiceConnection not found for component: %s, package: %s",
+                        String.format(
+                                "ServiceConnection not found for component: %s, package: %s",
                                 serviceIntent.getComponent(), serviceIntent.getPackage()));
             }
             mServiceByServiceConnection.put(connection, service);
-            connection.onServiceConnected(serviceIntent.getComponent(), service.asBinder());
+            ComponentName componentName = null;
+            if (mComponentNameByService.containsKey(service)) {
+                componentName = mComponentNameByService.get(service);
+            } else {
+                componentName = serviceIntent.getComponent();
+            }
+            connection.onServiceConnected(componentName, service.asBinder());
             return true;
         }
 
         @Override
+        public boolean bindService(
+                Intent serviceIntent, int flags, Executor executor, ServiceConnection connection) {
+            return bindService(serviceIntent, connection, flags);
+        }
+
+        @Override
         public boolean bindServiceAsUser(
                 Intent serviceIntent,
                 ServiceConnection connection,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
index 6fb3083..9a9f11f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
@@ -749,7 +749,6 @@
 
         // Feature flag enabled
         // Device does not have FEATURE_TELEPHONY_CALLING
-        doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
         doReturn(false).when(mPackageManager).hasSystemFeature(
                 eq(PackageManager.FEATURE_TELEPHONY_CALLING));
         mPhoneUT.notifySmsSent(emergencyNumber);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
index 28d0318..cbcd89d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
@@ -119,7 +119,6 @@
 
         // In order not to affect the existing implementation, define a telephony features
         // and disabled enforce_telephony_feature_mapping_for_public_apis feature flag
-        doReturn(false).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
         doReturn(true).when(mPm).hasSystemFeature(anyString());
         doReturn(new String[] {TAG}).when(mPm).getPackagesForUid(anyInt());
     }
@@ -218,27 +217,14 @@
 
     @Test
     @SmallTest
-    public void testGetNai() {
-        doReturn("aaa@example.com").when(mPhone).getNai();
-        assertEquals("aaa@example.com",
-                mPhoneSubInfoControllerUT.getNaiForSubscriber(0, TAG, FEATURE_ID));
-
-        doReturn("bbb@example.com").when(mSecondPhone).getNai();
-        assertEquals("bbb@example.com",
-                mPhoneSubInfoControllerUT.getNaiForSubscriber(1, TAG, FEATURE_ID));
-    }
-
-    @Test
-    @SmallTest
     @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
-    public void testGetNai_EnabledEnforceTelephonyFeatureMappingForPublicApis() throws Exception {
+    public void testGetNai() throws Exception {
         // Replace field to set SDK version of vendor partition to Android V
         int vendorApiLevel = Build.VERSION_CODES.VANILLA_ICE_CREAM;
         replaceInstance(PhoneSubInfoController.class, "mVendorApiLevel",
                 mPhoneSubInfoControllerUT, vendorApiLevel);
 
         // FeatureFlags enabled, System has required feature
-        doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
         doReturn(true).when(mPm).hasSystemFeature(
                 eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
         doReturn("bbb@example.com").when(mSecondPhone).getNai();
@@ -465,7 +451,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSubscriberId() {
         //IMSI
         doReturn("310260426283121").when(mPhone).getSubscriberId();
@@ -478,7 +464,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSubscriberIdWithInactiveSubId() {
         //IMSI
         assertNull(mPhoneSubInfoControllerUT.getSubscriberIdForSubscriber(2, TAG, FEATURE_ID));
@@ -557,7 +543,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetIccSerialNumber() {
         //IccId
         doReturn("8991101200003204510").when(mPhone).getIccSerialNumber();
@@ -641,7 +627,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetLine1Number() {
         mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
         doReturn("+18051234567").when(mPhone).getLine1Number();
@@ -654,7 +640,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetLine1NumberWithOutPermissionTargetPreR() {
         mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
         doReturn("+18051234567").when(mPhone).getLine1Number();
@@ -695,7 +681,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetLine1NumberWithOutPermissionTargetR() {
         mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
         doReturn("+18051234567").when(mPhone).getLine1Number();
@@ -876,7 +862,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetVoiceMailNumber() {
         doReturn("+18051234567").when(mPhone).getVoiceMailNumber();
         assertEquals("+18051234567", mPhoneSubInfoControllerUT
@@ -888,7 +874,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetVoiceMailNumberWithOutPermission() {
         doReturn("+18051234567").when(mPhone).getVoiceMailNumber();
         doReturn("+18052345678").when(mSecondPhone).getVoiceMailNumber();
@@ -932,7 +918,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetVoiceMailAlphaTag() {
         doReturn("VM_SIM_0").when(mPhone).getVoiceMailAlphaTag();
         assertEquals("VM_SIM_0", mPhoneSubInfoControllerUT
@@ -944,7 +930,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetVoiceMailAlphaTagWithOutPermission() {
         doReturn("VM_SIM_0").when(mPhone).getVoiceMailAlphaTag();
         doReturn("VM_SIM_1").when(mSecondPhone).getVoiceMailAlphaTag();
@@ -1012,6 +998,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSmscIdentityForTelUri() {
         try {
             setUpInitials();
@@ -1029,6 +1016,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSmscIdentityForSipUri() {
         try {
             UiccPort uiccPort1 = Mockito.mock(UiccPort.class);
@@ -1067,6 +1055,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSmscIdentityWithOutPermissions() {
         setUpInitials();
 
@@ -1125,6 +1114,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSimServiceTable() throws RemoteException {
         String refSst = "1234567";
         doReturn(mUiccPort).when(mPhone).getUiccPort();
@@ -1139,6 +1129,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSimServiceTableEmpty() throws RemoteException {
         String refSst = null;
         doReturn(mUiccPort).when(mPhone).getUiccPort();
@@ -1153,6 +1144,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSstWhenNoUiccPort() throws RemoteException {
         String refSst = "1234567";
         doReturn(null).when(mPhone).getUiccPort();
@@ -1167,6 +1159,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSstWhenNoUiccProfile() throws RemoteException {
         String refSst = "1234567";
         doReturn(mUiccPort).when(mPhone).getUiccPort();
@@ -1181,6 +1174,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSstWhenNoUiccApplication() throws RemoteException {
         String refSst = "1234567";
         doReturn(mUiccPort).when(mPhone).getUiccPort();
@@ -1195,6 +1189,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSimServiceTableWithOutPermissions() throws RemoteException {
         String refSst = "1234567";
         doReturn(mUiccPort).when(mPhone).getUiccPort();
@@ -1262,6 +1257,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void getImsPublicUserIdentities() {
         String[] refImpuArray = new String[3];
         refImpuArray[0] = "012345678";
@@ -1280,6 +1276,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void getImsPublicUserIdentities_InvalidImpu() {
         String[] refImpuArray = new String[3];
         refImpuArray[0] = null;
@@ -1294,8 +1291,11 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void getImsPublicUserIdentities_IsimNotLoadedError() {
         doReturn(null).when(mPhone).getIsimRecords();
+        doReturn(true).when(mPackageManager).hasSystemFeature(
+                eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
 
         try {
             mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG);
@@ -1333,6 +1333,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void getImsPcscfAddresses() {
         String[] preDefinedPcscfs = new String[3];
         preDefinedPcscfs[0] = "127.0.0.1";
@@ -1352,6 +1353,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void getImsPcscfAddresses_InvalidPcscf() {
         String[] preDefinedPcscfs = new String[3];
         preDefinedPcscfs[0] = null;
@@ -1369,6 +1371,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void getImsPcscfAddresses_IsimNotLoadedError() {
         doReturn(true).when(mFeatureFlags).supportIsimRecord();
         doReturn(null).when(mPhone).getIsimRecords();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java
index 710f1ec..0f4f3d5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java
@@ -219,6 +219,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void sendsendTextForSubscriberTest() {
         int subId = 1;
         doReturn(true).when(mSubscriptionManager)
@@ -232,6 +233,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void sendTextForSubscriberTest_InteractAcrossUsers() {
         int subId = 1;
         // Sending text to subscriber should not fail when the caller has the
@@ -313,7 +315,6 @@
         replaceInstance(SmsController.class, "mVendorApiLevel", mSmsControllerUT, vendorApiLevel);
 
         // Feature enabled, device does not have required telephony feature.
-        doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
         doReturn(false).when(mPackageManager).hasSystemFeature(
                 PackageManager.FEATURE_TELEPHONY_MESSAGING);
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index 5c37cba..f0f7a1f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -580,7 +580,6 @@
         mDomainSelectionResolver = Mockito.mock(DomainSelectionResolver.class);
         mNullCipherNotifier = Mockito.mock(NullCipherNotifier.class);
 
-        doReturn(true).when(mFeatureFlags).minimalTelephonyCdmCheck();
         doReturn(true).when(mFeatureFlags).hsumBroadcast();
         doReturn(true).when(mFeatureFlags).hsumPackageManager();
         doReturn(true).when(mFeatureFlags).dataServiceCheck();
@@ -712,6 +711,7 @@
 
         //mPhone
         doReturn(mContext).when(mPhone).getContext();
+        doReturn(mContext).when(mPhone2).getContext();
         doReturn(mContext).when(mImsPhone).getContext();
         doReturn(true).when(mPhone).getUnitTestMode();
         doReturn(mUiccProfile).when(mPhone).getIccCard();
@@ -750,6 +750,7 @@
         doReturn(mDataRetryManager).when(mDataNetworkController).getDataRetryManager();
         doReturn(mCarrierPrivilegesTracker).when(mPhone).getCarrierPrivilegesTracker();
         doReturn(0).when(mPhone).getPhoneId();
+        doReturn(1).when(mPhone2).getPhoneId();
         doReturn(true).when(mPhone).hasCalling();
         doReturn(true).when(mPhone2).hasCalling();
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
index 854c871..aef2fcf 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
@@ -49,6 +49,7 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
+import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.TelephonyTest;
 import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback;
 import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback;
@@ -1353,7 +1354,7 @@
     }
 
     @Test
-    public void testSimInsertedAgain() throws Exception {
+    public void testSimInsertedAgain() {
         testSimRemoval();
         Mockito.clearInvocations(mDataProfileManagerCallback);
         Mockito.clearInvocations(mMockedWwanDataServiceManager);
@@ -1955,7 +1956,7 @@
 
     private void changeSimStateTo(@TelephonyManager.SimState int simState) {
         mSimInserted = simState == TelephonyManager.SIM_STATE_LOADED;
-        mDataNetworkControllerCallback.onSimStateChanged(simState);
+        doReturn(IccCardConstants.State.intToState(simState)).when(mIccCard).getState();
     }
 
     @Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyNumberTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyNumberTrackerTest.java
index 10dbfea..37042ee 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyNumberTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyNumberTrackerTest.java
@@ -26,15 +26,11 @@
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
-import android.content.ContextWrapper;
 import android.content.IntentFilter;
-import android.content.res.AssetManager;
-import android.content.res.Resources;
 import android.os.AsyncResult;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
@@ -129,31 +125,19 @@
 
     private File mLocalDownloadDirectory;
     private ShortNumberInfo mShortNumberInfo;
-    private Context mMockContext;
-    private Resources mResources;
 
     @Before
     public void setUp() throws Exception {
-        logd("EmergencyNumberTrackerTest +Setup!");
         super.setUp(getClass().getSimpleName());
         mShortNumberInfo = mock(ShortNumberInfo.class);
-        mCarrierConfigManagerMock = mock(CarrierConfigManager.class);
+        mCarrierConfigManagerMock = (CarrierConfigManager) mContext.getSystemService(
+                Context.CARRIER_CONFIG_SERVICE);
 
-        mContext = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
-        mMockContext = mock(Context.class);
-        mResources = mock(Resources.class);
+        doReturn(InstrumentationRegistry.getTargetContext().getAssets()).when(mContext).getAssets();
 
-        doReturn(mContext).when(mPhone).getContext();
-        doReturn(0).when(mPhone).getPhoneId();
         doReturn(SUB_ID_PHONE_1).when(mPhone).getSubId();
-
-        doReturn(mContext).when(mPhone2).getContext();
-        doReturn(1).when(mPhone2).getPhoneId();
         doReturn(SUB_ID_PHONE_2).when(mPhone2).getSubId();
 
-        doReturn(mPackageManager).when(mContext).getPackageManager();
-        doReturn(mPackageManager).when(mMockContext).getPackageManager();
-
         initializeEmergencyNumberListTestSamples();
         mEmergencyNumberTrackerMock = new EmergencyNumberTracker(mPhone, mSimulatedCommands,
                 mFeatureFlags);
@@ -165,11 +149,7 @@
         // Copy an OTA file to the test directory to similate the OTA mechanism
         simulateOtaEmergencyNumberDb(mPhone);
 
-        AssetManager am = new AssetManager.Builder().build();
-        doReturn(am).when(mMockContext).getAssets();
-
         processAllMessages();
-        logd("EmergencyNumberTrackerTest -Setup!");
     }
 
     @After
@@ -251,20 +231,16 @@
     }
 
     private void setOtaEmergencyNumberDbFileFolderForTesting(
-            EmergencyNumberTracker emergencyNumberTrackerMock, Phone phone) {
+            EmergencyNumberTracker emergencyNumberTrackerMock, Phone phone)
+            throws FileNotFoundException {
         // Override the OTA emergency number database file path for testing
         File file = new File(Environment.getExternalStorageDirectory(), LOCAL_DOWNLOAD_DIRECTORY
                 + "/" + EMERGENCY_NUMBER_DB_OTA_FILE);
-        try {
-            mOtaParcelFileDescriptor = ParcelFileDescriptor.open(
-                    file, ParcelFileDescriptor.MODE_READ_ONLY);
-            emergencyNumberTrackerMock.obtainMessage(
-                EmergencyNumberTracker.EVENT_OVERRIDE_OTA_EMERGENCY_NUMBER_DB_FILE_PATH,
-                    mOtaParcelFileDescriptor).sendToTarget();
-            logd("Changed emergency number db file folder for testing ");
-        } catch (FileNotFoundException e) {
-            logd("Failed to open emergency number db file folder for testing " + e.toString());
-        }
+        mOtaParcelFileDescriptor = ParcelFileDescriptor.open(
+                file, ParcelFileDescriptor.MODE_READ_ONLY);
+        emergencyNumberTrackerMock.obtainMessage(
+            EmergencyNumberTracker.EVENT_OVERRIDE_OTA_EMERGENCY_NUMBER_DB_FILE_PATH,
+                mOtaParcelFileDescriptor).sendToTarget();
         processAllMessages();
     }
 
@@ -544,11 +520,8 @@
      */
     @Test
     public void testUsingEmergencyNumberDatabaseWheneverHal_1_4() {
-        doReturn(mMockContext).when(mPhone).getContext();
-        doReturn(mContext.getAssets()).when(mMockContext).getAssets();
-        doReturn(mResources).when(mMockContext).getResources();
-        doReturn(true).when(mResources).getBoolean(
-                com.android.internal.R.bool.ignore_emergency_number_routing_from_db);
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.ignore_emergency_number_routing_from_db, true);
 
         EmergencyNumberTracker emergencyNumberTrackerMock = new EmergencyNumberTracker(
                 mPhone, mSimulatedCommands, mFeatureFlags);
@@ -616,12 +589,9 @@
 
     @Test
     public void testUsingEmergencyNumberDatabaseWithRouting() {
-        doReturn(mMockContext).when(mPhone).getContext();
-        doReturn(mContext.getAssets()).when(mMockContext).getAssets();
-        doReturn(mResources).when(mMockContext).getResources();
         doReturn("05").when(mCellIdentity).getMncString();
-        doReturn(false).when(mResources).getBoolean(
-                com.android.internal.R.bool.ignore_emergency_number_routing_from_db);
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.ignore_emergency_number_routing_from_db, false);
 
         EmergencyNumberTracker emergencyNumberTrackerMock = new EmergencyNumberTracker(
                 mPhone, mSimulatedCommands, mFeatureFlags);
@@ -721,11 +691,8 @@
 
     @Test
     public void testUsingEmergencyNumberDatabaseWithRoutingInOOS() {
-        doReturn(mMockContext).when(mPhone).getContext();
-        doReturn(mContext.getAssets()).when(mMockContext).getAssets();
-        doReturn(mResources).when(mMockContext).getResources();
-        doReturn(false).when(mResources).getBoolean(
-                com.android.internal.R.bool.ignore_emergency_number_routing_from_db);
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.ignore_emergency_number_routing_from_db, false);
 
         EmergencyNumberTracker emergencyNumberTrackerMock = new EmergencyNumberTracker(
                 mPhone, mSimulatedCommands, mFeatureFlags);
@@ -776,7 +743,7 @@
      * Test OTA Emergency Number Database Update Status.
      */
     @Test
-    public void testOtaEmergencyNumberDatabase() {
+    public void testOtaEmergencyNumberDatabase() throws Exception {
         sendEmergencyNumberPrefix(mEmergencyNumberTrackerMock);
         mEmergencyNumberTrackerMock.updateEmergencyCountryIsoAllPhones("");
         processAllMessages();
@@ -841,13 +808,7 @@
     @Test
     public void testOverridingEmergencyNumberPrefixCarrierConfig() throws Exception {
         // Capture CarrierConfigChangeListener to emulate the carrier config change notification
-        doReturn(mMockContext).when(mPhone).getContext();
-        doReturn(Context.CARRIER_CONFIG_SERVICE)
-                .when(mMockContext)
-                .getSystemService(CarrierConfigManager.class);
-        doReturn(mCarrierConfigManagerMock)
-                .when(mMockContext)
-                .getSystemService(eq(Context.CARRIER_CONFIG_SERVICE));
+        Mockito.clearInvocations(mCarrierConfigManagerMock);
         ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
                 ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
         EmergencyNumberTracker localEmergencyNumberTracker =
diff --git a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
index 569785b..4ff13de 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
@@ -1656,7 +1656,6 @@
                 vendorApiLevel);
 
         // Feature flag enabled, device has required telephony feature.
-        doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
         doReturn(true).when(mPackageManager).hasSystemFeature(
                 eq(PackageManager.FEATURE_TELEPHONY_EUICC));
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java
index 6e0d383..84dc4ba 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java
@@ -107,7 +107,8 @@
 
     @Before
     public void setUp() throws Exception {
-        mEuiccSession = new EuiccSession();
+        super.setUp(getClass().getSimpleName());
+        mEuiccSession = new EuiccSession(mContext);
     }
 
     @Test
@@ -128,7 +129,25 @@
 
     @Test
     @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
+    public void startOneSession_featureOverlayDisabled_noop() throws Exception {
+        mEuiccSession.startSession(SESSION_ID_1);
+        mEuiccSession.noteChannelOpen(mApduSender);
+        mEuiccSession.noteChannelOpen(mApduSender2);
+
+        assertThat(mEuiccSession.hasSession()).isFalse();
+
+        mEuiccSession.endSession(SESSION_ID_1);
+
+        assertThat(mEuiccSession.hasSession()).isFalse();
+        verify(mApduSender, never()).closeAnyOpenChannel();
+        verify(mApduSender2, never()).closeAnyOpenChannel();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
     public void startOneSession_endSession_hasSession() throws Exception {
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.euicc_optimize_apdu_sender, true);
         mEuiccSession.startSession(SESSION_ID_1);
         mEuiccSession.noteChannelOpen(mApduSender);
         mEuiccSession.noteChannelOpen(mApduSender2);
@@ -150,6 +169,8 @@
     @Test
     @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
     public void startTwoSession_endSession_hasSession() throws Exception {
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.euicc_optimize_apdu_sender, true);
         mEuiccSession.startSession(SESSION_ID_1);
         mEuiccSession.noteChannelOpen(mApduSender);
         mEuiccSession.startSession(SESSION_ID_2);
@@ -170,6 +191,8 @@
     @Test
     @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
     public void startTwoSessions_endAllSessions_hasSession() throws Exception {
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.euicc_optimize_apdu_sender, true);
         mEuiccSession.startSession(SESSION_ID_1);
         mEuiccSession.noteChannelOpen(mApduSender);
         mEuiccSession.startSession(SESSION_ID_2);
@@ -188,6 +211,8 @@
     @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
     public void noteChannelOpen_noSession_endSession_noop() throws Exception {
         // noteChannelOpen called without a session started
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.euicc_optimize_apdu_sender, true);
         mEuiccSession.noteChannelOpen(mApduSender);
 
         assertThat(mEuiccSession.hasSession()).isFalse();
@@ -202,6 +227,8 @@
     @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
     public void endAllSessions_noSession_endAllSessions_noOp() throws Exception {
         // noteChannelOpen called without a session started
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.euicc_optimize_apdu_sender, true);
         mEuiccSession.noteChannelOpen(mApduSender);
 
         assertThat(mEuiccSession.hasSession()).isFalse();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
index a6a4b0b..ba31203 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -1264,9 +1264,6 @@
         mContextFixture.putBooleanResource(
                 R.bool.config_satellite_allow_check_message_in_not_connected, true);
 
-        mDatagramDispatcherUT.onSatelliteModemStateChanged(
-                SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
-
         verify(mMockSmsDispatchersController, times(0)).sendMtSmsPollingMessage();
     }
 
@@ -1285,6 +1282,31 @@
         verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
     }
 
+    @Test
+    public void testSendsMtSmsPoll_P2PSmsAllowed() {
+        mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        mContextFixture.putBooleanResource(R.bool.config_enabled_mt_sms_polling, true);
+        when(mMockSatelliteController.shouldSendSmsToDatagramDispatcher(any(Phone.class)))
+                .thenReturn(true);
+
+        // Set P2P SMS disallowed
+        when(mMockSatelliteController.isP2PSmsDisallowedOnCarrierRoamingNtn(anyInt()))
+                .thenReturn(true);
+        mDatagramDispatcherUT.onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+
+        verify(mMockSmsDispatchersController, times(0)).sendMtSmsPollingMessage();
+
+        // Set P2P SMS allowed
+        when(mMockSatelliteController.isP2PSmsDisallowedOnCarrierRoamingNtn(anyInt()))
+                .thenReturn(false);
+        mDatagramDispatcherUT.onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+
+        verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
+    }
+
     private void setModemState(int state) {
         mDatagramDispatcherUT.onSatelliteModemStateChanged(state);
     }
@@ -1296,6 +1318,8 @@
         mContextFixture.putBooleanResource(R.bool.config_enabled_mt_sms_polling, true);
         when(mMockSatelliteController.shouldSendSmsToDatagramDispatcher(any(Phone.class)))
                 .thenReturn(true);
+        when(mMockSatelliteController.isP2PSmsDisallowedOnCarrierRoamingNtn(anyInt()))
+                .thenReturn(false);
         // This will trigger mShouldPollMtSms = shouldPollMtSms
         setModemState(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
     }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
index 831c15d..ded67d7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -124,6 +124,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.NotificationManager;
+import android.app.usage.NetworkStatsManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -133,6 +134,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.hardware.devicestate.DeviceState;
+import android.location.LocationManager;
 import android.net.Uri;
 import android.os.AsyncResult;
 import android.os.Bundle;
@@ -284,6 +286,7 @@
     @Mock private SubscriptionManager mSubscriptionManager;
     @Mock private SubscriptionInfo mSubscriptionInfo;
     @Mock private PackageManager mMockPManager;
+    @Mock private Intent mMockLocationIntent;
 
     private Semaphore mIIntegerConsumerSemaphore = new Semaphore(0);
     private IIntegerConsumer mIIntegerConsumer = new IIntegerConsumer.Stub() {
@@ -621,6 +624,14 @@
         when(mPhone2.getPhoneId()).thenReturn(1);
         when(mPhone2.getSignalStrengthController()).thenReturn(mSignalStrengthController);
 
+        doReturn(Context.NETWORK_STATS_SERVICE).when(mContext).getSystemServiceName(
+                NetworkStatsManager.class);
+        doReturn(mStatsManager).when(mContext).getSystemService(Context.NETWORK_STATS_SERVICE);
+        if (mContext.getSystemService(NetworkStatsManager.class) == null) {
+            // Test is using mockito-extended
+            doReturn(mStatsManager).when(mContext).getSystemService(NetworkStatsManager.class);
+        }
+
         mContextFixture.putStringArrayResource(
                 R.array.config_satellite_providers,
                 EMPTY_STRING_ARRAY);
@@ -998,6 +1009,7 @@
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         when(mFeatureFlags.satelliteStateChangeListener()).thenReturn(true);
         mIsSatelliteEnabledSemaphore.drainPermits();
+        mSatelliteControllerUT.handleSatelliteAccessAllowedStateChanged(true);
 
         // Fail to enable satellite when SatelliteController is not fully loaded yet.
         mIIntegerConsumerResults.clear();
@@ -3566,6 +3578,7 @@
         mIsSatelliteEnabledSemaphore.drainPermits();
         mIIntegerConsumerResults.clear();
         resetSatelliteControllerUT();
+        mSatelliteControllerUT.handleSatelliteAccessAllowedStateChanged(true);
 
         // Successfully provisioned
         reset(mMockSatelliteModemInterface);
@@ -5867,6 +5880,8 @@
         private boolean callOnlySuperMethod = false;
         public boolean isSatelliteEnabledOrBeingEnabled = false;
 
+        private boolean mLocationServiceEnabled = true;
+
         TestSatelliteController(
                 Context context, Looper looper, @NonNull FeatureFlags featureFlags) {
             super(context, looper, featureFlags);
@@ -5988,6 +6003,11 @@
             return selectedSatelliteSubId;
         }
 
+        @Override
+        protected boolean isLocationServiceEnabled() {
+            return mLocationServiceEnabled;
+        }
+
         void setSatelliteProvisioned(@Nullable Boolean isProvisioned) {
             synchronized (mDeviceProvisionLock) {
                 mIsDeviceProvisioned = isProvisioned;
@@ -6065,6 +6085,14 @@
         public void setCallOnlySuperMethod() {
             callOnlySuperMethod = true;
         }
+
+        public void  setLocationServiceEnabled(boolean locationServiceEnabled) {
+            mLocationServiceEnabled = locationServiceEnabled;
+        }
+
+        public BroadcastReceiver getLocationReceiver() {
+            return mLocationServiceStateChangedReceiver;
+        }
     }
 
     @Test
@@ -6781,4 +6809,148 @@
         processAllMessages();
         verify(mPhone, times(0)).notifyCarrierRoamingNtnEligibleStateChanged(anyBoolean());
     }
+
+    @Test
+    public void testExitOutOfP2pSessionIfSatelliteIsNotAllowed() throws Exception {
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        when(mFeatureFlags.satelliteExitP2pSessionOutsideGeofence()).thenReturn(true);
+
+        // Enable satellite P2P session
+        setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+        verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+        setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+        verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+        setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+        mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
+        processAllMessages();
+        assertTrue(waitForIIntegerConsumerResult(1));
+        assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+        verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+
+        ArgumentCaptor<SatelliteModemEnableRequestAttributes> enableSatelliteRequest =
+                ArgumentCaptor.forClass(SatelliteModemEnableRequestAttributes.class);
+        ArgumentCaptor<Message> enableSatelliteResponse = ArgumentCaptor.forClass(Message.class);
+
+        reset(mMockSatelliteModemInterface);
+        doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+        // Set access allowed to false
+        final int carrierSubId = SUB_ID;
+        final int oemSubId = SUB_ID1;
+        setSatelliteSubscriberTesting(false);
+        mSatelliteControllerUT.subsInfoListPerPriority().computeIfAbsent(
+                        getKeyPriority(testSubscriptionInfo), k -> new ArrayList<>())
+                .add(testSubscriptionInfo);
+        mSatelliteControllerUT.subsInfoListPerPriority().computeIfAbsent(
+                        getKeyPriority(testSubscriptionInfo2), k -> new ArrayList<>())
+                .add(testSubscriptionInfo2);
+        mSatelliteControllerUT.selectedSatelliteSubId = SUB_ID1;
+        mSatelliteControllerUT.handleSatelliteAccessAllowedStateChanged(false);
+        processAllMessages();
+        verify(mMockSatelliteModemInterface).requestSatelliteEnabled(
+                enableSatelliteRequest.capture(), enableSatelliteResponse.capture());
+
+        // Disable satellite request is sent to modem
+        SatelliteModemEnableRequestAttributes request = enableSatelliteRequest.getValue();
+        assertFalse(request.isEnabled());
+        assertFalse(request.isForDemoMode());
+        assertFalse(request.isForEmergencyMode());
+        // OEM satellite subscription should be selected as current location is not supported
+        assertEquals(oemSubId, mSatelliteControllerUT.getSelectedSatelliteSubId());
+
+        // As current location is allowed, carrier subscription should be selected
+        mSatelliteControllerUT.selectedSatelliteSubId = SUB_ID;
+        mSatelliteControllerUT.handleSatelliteAccessAllowedStateChanged(true);
+        processAllMessages();
+        assertEquals(carrierSubId, mSatelliteControllerUT.getSelectedSatelliteSubId());
+
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        mSatelliteControllerUT.mIsApplicationSupportsP2P = true;
+        mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 1);
+        mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL, true);
+        int[] supportedServices2 = {2};
+        int[] supportedServices3 = {1, 3};
+        PersistableBundle carrierSupportedSatelliteServicesPerProvider = new PersistableBundle();
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                "00102", supportedServices2);
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                "00103", supportedServices3);
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                carrierSupportedSatelliteServicesPerProvider);
+        for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+                : mCarrierConfigChangedListenerList) {
+            pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+                    /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+            );
+        }
+        mSatelliteControllerUT.setSatellitePhone(1);
+        mSatelliteControllerUT.setSelectedSatelliteSubId(SUB_ID);
+        mSatelliteControllerUT.isSatelliteProvisioned = true;
+        processAllMessages();
+
+        assertTrue(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
+    }
+
+    public void testNotifyNtnEligibilityLocationServiceStatusChanged() {
+        // Enable CarrierRoamingNtn
+        mContextFixture.putBooleanResource(
+                R.bool.config_satellite_should_notify_availability, true);
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        mSatelliteControllerUT.mIsApplicationSupportsP2P = true;
+        mSatelliteControllerUT.setIsSatelliteSupported(true);
+        mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
+                CARRIER_ROAMING_NTN_CONNECT_MANUAL);
+        mCarrierConfigBundle.putInt(
+                KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT, 1 * 60);
+        mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL, true);
+        int[] supportedServices2 = {2};
+        int[] supportedServices3 = {1, 3};
+        PersistableBundle carrierSupportedSatelliteServicesPerProvider = new PersistableBundle();
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                "00102", supportedServices2);
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                "00103", supportedServices3);
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                carrierSupportedSatelliteServicesPerProvider);
+        for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+                : mCarrierConfigChangedListenerList) {
+            pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+                    /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+            );
+        }
+        mSatelliteControllerUT.setSatellitePhone(1);
+        mSatelliteControllerUT.setSelectedSatelliteSubId(SUB_ID);
+        mSatelliteControllerUT.isSatelliteProvisioned = true;
+        mSatelliteControllerUT.isSatelliteAllowedCallback = null;
+        mSatelliteControllerUT.setIsSatelliteAllowedState(true);
+        processAllMessages();
+        clearInvocations(mPhone);
+
+        doReturn(LocationManager.MODE_CHANGED_ACTION).when(mMockLocationIntent).getAction();
+
+        // Location service off
+        mSatelliteControllerUT.setLocationServiceEnabled(false);
+        BroadcastReceiver receiver = mSatelliteControllerUT.getLocationReceiver();
+        receiver.onReceive(mContext, mMockLocationIntent);
+
+        processAllMessages();
+
+        verify(mPhone, times(1)).notifyCarrierRoamingNtnEligibleStateChanged(eq(false));
+        clearInvocations(mPhone);
+
+        // Location service off
+        mSatelliteControllerUT.setLocationServiceEnabled(true);
+        receiver.onReceive(mContext, mMockLocationIntent);
+
+        processAllMessages();
+
+        verify(mPhone, times(1)).notifyCarrierRoamingNtnEligibleStateChanged(eq(true));
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
index 4d4d160..4c2f6cc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
@@ -203,6 +203,8 @@
         doReturn(true).when(mUiccSlot).isActive();
         doReturn(FAKE_ICCID1).when(mUiccController).convertToCardString(eq(1));
         doReturn(FAKE_ICCID2).when(mUiccController).convertToCardString(eq(2));
+        doReturn(true).when(mPackageManager).hasSystemFeature(
+                eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
 
         mBinder = Mockito.mock(BinderWrapper.class);
         doReturn(FAKE_USER_HANDLE).when(mBinder).getCallingUserHandle();
@@ -242,8 +244,6 @@
         doReturn(true).when(mUserManager)
                 .isManagedProfile(eq(FAKE_MANAGED_PROFILE_USER_HANDLE.getIdentifier()));
 
-        doReturn(true).when(mPackageManager).hasSystemFeature(
-                eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
         logd("SubscriptionManagerServiceTest -Setup!");
     }
 
@@ -326,6 +326,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testBroadcastOnInitialization() {
         ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
         verify(mContext, times(3)).sendBroadcastAsUser(
@@ -337,6 +338,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testAddSubInfo() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1,
@@ -360,6 +362,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetMccMnc() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1,
@@ -380,6 +383,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetCountryIso() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1,
@@ -399,6 +403,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetCarrierId() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1,
@@ -418,6 +423,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetAdminOwned() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1, 0,
@@ -435,6 +441,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGroupOwner_callerMissingpPermission_throws() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1, 0,
@@ -467,8 +474,7 @@
         replaceInstance(SubscriptionManagerService.class, "mVendorApiLevel",
                 mSubscriptionManagerServiceUT, vendorApiLevel);
 
-        // Enabled FeatureFlags and ENABLE_FEATURE_MAPPING, telephony features are defined
-        doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
+        // Enabled ENABLE_FEATURE_MAPPING, telephony features are defined
         doReturn(true).when(mPackageManager).hasSystemFeature(
                 eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
         try {
@@ -489,6 +495,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetAllSubInfoList() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
@@ -619,6 +626,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetAvailableSubscriptionInfoList() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         SubscriptionInfoInternal anotherSubInfo =
@@ -654,6 +662,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetDefaultVoiceSubId() throws Exception {
         clearInvocations(mContext);
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
@@ -696,6 +705,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetDefaultDataSubId() throws Exception {
         clearInvocations(mContext);
         doReturn(false).when(mTelephonyManager).isVoiceCapable();
@@ -742,6 +752,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSingleSimSetDefaultDataSubId() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
@@ -762,6 +773,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetDefaultSmsSubId() throws Exception {
         clearInvocations(mContext);
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
@@ -793,6 +805,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testIsActiveSubId() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(new SubscriptionInfoInternal.Builder(FAKE_SUBSCRIPTION_INFO2)
@@ -811,6 +824,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetActiveSubscriptionInfoList() {
         // Grant MODIFY_PHONE_STATE permission for insertion.
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
@@ -849,6 +863,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetActiveSubscriptionInfoForSimSlotIndex() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -880,6 +895,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testUpdateEmbeddedSubscriptions() {
         EuiccProfileInfo profileInfo1 = new EuiccProfileInfo.Builder(FAKE_ICCID1)
                 .setIccid(FAKE_ICCID1)
@@ -955,6 +971,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testUpdateEmbeddedSubscriptionsNullResult() {
         // Grant READ_PHONE_STATE permission.
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE);
@@ -974,6 +991,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetActiveSubscriptionInfo() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1004,6 +1022,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetDisplayNameUsingSrc() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1031,6 +1050,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetActiveSubInfoCount() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -1045,6 +1065,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetIconTint() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1064,6 +1085,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetActiveSubscriptionInfoForIccId() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1078,6 +1100,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetAccessibleSubscriptionInfoList() {
         doReturn(true).when(mEuiccManager).isEnabled();
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -1116,6 +1139,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testIsSubscriptionEnabled() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1129,6 +1153,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetEnabledSubscriptionId() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1148,12 +1173,14 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetActiveDataSubscriptionId() {
         doReturn(12345).when(mPhoneSwitcher).getActiveDataSubId();
         assertThat(mSubscriptionManagerServiceUT.getActiveDataSubscriptionId()).isEqualTo(12345);
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetSubscriptionUserHandle() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1187,6 +1214,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSubscriptionUserHandleUnknownSubscription() {
         mContextFixture.addCallingOrSelfPermission(
                 Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
@@ -1200,6 +1228,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testIsSubscriptionAssociatedWithUser() {
         // Should fail without MANAGE_SUBSCRIPTION_USER_ASSOCIATION
         assertThrows(SecurityException.class, () -> mSubscriptionManagerServiceUT
@@ -1577,6 +1606,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetUsageSetting() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1601,6 +1631,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetDisplayNumber() {
         insertSubscription(new SubscriptionInfoInternal.Builder(FAKE_SUBSCRIPTION_INFO1)
                 .setNumberFromCarrier("")
@@ -1623,6 +1654,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetOpportunistic() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1642,6 +1674,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetOpportunisticSubscriptions() {
         testSetOpportunistic();
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -1669,6 +1702,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetPreferredDataSubscriptionId() {
         // Should fail without MODIFY_PHONE_STATE
         assertThrows(SecurityException.class, () -> mSubscriptionManagerServiceUT
@@ -1681,6 +1715,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetPreferredDataSubscriptionId() {
         // Should fail without READ_PRIVILEGED_PHONE_STATE
         assertThrows(SecurityException.class, () -> mSubscriptionManagerServiceUT
@@ -1693,6 +1728,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testAddSubscriptionsIntoGroup() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -1717,6 +1753,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetDeviceToDeviceStatusSharing() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1740,6 +1777,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetDeviceToDeviceStatusSharingContacts() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1760,6 +1798,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetPhoneNumberFromFirstAvailableSource() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1774,6 +1813,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetPhoneNumberSourcePriority() throws Exception {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_NUMBERS);
 
@@ -1813,6 +1853,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetUiccApplicationsEnabled() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1842,6 +1883,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testCanDisablePhysicalSubscription() {
         // Should fail without READ_PRIVILEGED_PHONE_STATE
         assertThrows(SecurityException.class, () -> mSubscriptionManagerServiceUT
@@ -1857,6 +1899,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetEnhanced4GModeEnabled() throws Exception {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1882,6 +1925,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetVideoTelephonyEnabled() throws Exception {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1907,6 +1951,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetWifiCallingEnabled() throws Exception {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1932,6 +1977,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetWifiCallingMode() throws Exception {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1957,6 +2003,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetWifiCallingModeForRoaming() throws Exception {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1982,6 +2029,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetEnabledMobileDataPolicies() throws Exception {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2008,6 +2056,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetRcsUceEnabled() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2036,6 +2085,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetCrossSimCallingEnabled() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2062,6 +2112,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetRcsConfig() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2088,6 +2139,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetDeviceToDeviceStatusSharingPreference() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2113,6 +2165,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetVoImsOptInEnabled() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2138,6 +2191,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetDeviceToDeviceStatusSharingContacts() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2165,6 +2219,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetNrAdvancedCallingEnabled() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2191,6 +2246,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetSubscriptionPropertyInvalidField() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
@@ -2200,6 +2256,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetNumberWithCarrierNumber() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2233,6 +2290,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetNonAccessibleFields() throws Exception {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2256,6 +2314,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSyncToGroup() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -2340,6 +2399,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testRemoveSubInfo() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -2361,6 +2421,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testUserUnlockUpdateEmbeddedSubscriptions() {
         doReturn(true).when(mUiccSlot).isEuicc();
         doReturn(1).when(mUiccController).convertToPublicCardId(FAKE_ICCID1);
@@ -2405,6 +2466,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testInsertNewSim() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
@@ -2466,6 +2528,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGroupDisable() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(new SubscriptionInfoInternal.Builder(FAKE_SUBSCRIPTION_INFO2)
@@ -2512,6 +2575,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetPhoneNumberFromInactiveSubscription() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         testInactiveSimRemoval();
@@ -2530,6 +2594,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetPhoneNumberFromDefaultSubscription() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
@@ -2561,6 +2626,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testEsimActivation() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
@@ -2642,6 +2708,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testDeleteEsim() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         // pSIM with ICCID2
@@ -2700,6 +2767,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testEsimSwitch() {
         setIdentifierAccess(true);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
@@ -2750,6 +2818,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testDump() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -2767,6 +2836,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testOnSubscriptionChanged() {
         CountDownLatch latch = new CountDownLatch(1);
         SubscriptionManagerServiceCallback callback =
@@ -2784,6 +2854,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testOnUiccApplicationsEnabled() {
         CountDownLatch latch = new CountDownLatch(1);
         Executor executor = Runnable::run;
@@ -2813,6 +2884,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testDeactivatePsim() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         testInsertNewSim();
@@ -2831,6 +2903,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testRemoteSim() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
@@ -2870,6 +2943,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testRemoveSubscriptionsFromGroup() {
         testAddSubscriptionsIntoGroup();
 
@@ -2898,6 +2972,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testUpdateSimStateForInactivePort() {
         testSetUiccApplicationsEnabled();
 
@@ -2911,6 +2986,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testInactiveSimInserted() {
         doReturn(0).when(mUiccSlot).getPortIndexFromIccId(eq(FAKE_ICCID1));
 
@@ -2928,6 +3004,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testRestoreAllSimSpecificSettingsFromBackup() throws Exception {
         assertThrows(SecurityException.class, ()
                 -> mSubscriptionManagerServiceUT.restoreAllSimSpecificSettingsFromBackup(
@@ -2965,6 +3042,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSubscriptionMap() {
         SubscriptionMap<Integer, Integer> map = new SubscriptionMap<>();
         map.put(1, 1);
@@ -2978,6 +3056,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSimNotReady() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         mSubscriptionManagerServiceUT.updateSimState(
@@ -2988,6 +3067,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSimNotReadyBySimDeactivate() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -3001,6 +3081,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testInactiveSimRemoval() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
 
@@ -3036,6 +3117,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testEmbeddedProfilesUpdateFailed() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -3079,6 +3161,7 @@
 
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testNonNullSubInfoBuilderFromEmbeddedProfile() {
         EuiccProfileInfo profileInfo1 = new EuiccProfileInfo.Builder(FAKE_ICCID1)
                 .setIccid(FAKE_ICCID1) //can't build profile with null iccid.
@@ -3136,6 +3219,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetActiveSubscriptionInfoListNoSecurityException() {
         // Grant MODIFY_PHONE_STATE permission for insertion.
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
@@ -3162,6 +3246,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testUpdateGroupDisabled() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(new SubscriptionInfoInternal
@@ -3175,6 +3260,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testIsSatelliteSpn() {
         mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
                 FAKE_CARRIER_NAME1);
@@ -3211,6 +3297,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testIsSatelliteSpnWithEmptySpn() {
         mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier, ""); // Empty
         System.setProperty("persist.radio.allow_mock_modem", "true");
@@ -3272,6 +3359,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testIsSatelliteSpnWithNullCarrierIdentifier() {
         mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
                 FAKE_CARRIER_NAME1);
@@ -3307,6 +3395,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testIsSatelliteSpnWithWrongSpn() {
         mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
                 FAKE_CARRIER_NAME1);
@@ -3343,6 +3432,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSatelliteEntitlementPlmnList() throws Exception {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
index d0dbe77..88e9142 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
@@ -33,6 +33,7 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
 import android.platform.test.flag.junit.SetFlagsRule;
@@ -106,18 +107,20 @@
     private ResponseCaptor mResponseCaptor;
     private byte[] mSelectResponse;
     private ApduSender mSender;
+    private Context mContext;
 
     @Before
     public void setUp() {
         mSetFlagsRule.enableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER);
 
+        mContext = InstrumentationRegistry.getContext();
         mMockCi = mock(CommandsInterface.class);
         mLooper = TestableLooper.get(this);
         mHandler = new Handler(mLooper.getLooper());
         mResponseCaptor = new ResponseCaptor();
         mSelectResponse = null;
 
-        mSender = new ApduSender(InstrumentationRegistry.getContext(), PHONE_ID,
+        mSender = new ApduSender(mContext, PHONE_ID,
                             mMockCi, ApduSender.ISD_R_AID, false /* supportExtendedApdu */);
     }
 
@@ -134,7 +137,7 @@
         mSelectResponse = null;
         mSender = null;
 
-        EuiccSession.get().endSession(SESSION_ID);
+        EuiccSession.get(mContext).endSession(SESSION_ID);
         clearSharedPreferences();
     }
 
@@ -458,7 +461,7 @@
         int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
         LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, "A1A1A19000");
         LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
-        EuiccSession.get().startSession(SESSION_ID);
+        EuiccSession.get(mContext).startSession(SESSION_ID);
 
         mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
                 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
@@ -469,7 +472,7 @@
         inOrder.verify(mMockCi).iccOpenLogicalChannel(eq(ApduSender.ISD_R_AID), anyInt(), any());
         inOrder.verify(mMockCi).iccTransmitApduLogicalChannel(eq(channel), eq(channel | 10),
                 eq(1), eq(2), eq(3), eq(0), eq("a"), anyBoolean(), any());
-        // No iccCloseLogicalChannel
+        inOrder.verify(mMockCi).iccCloseLogicalChannel(eq(channel), eq(true /*isEs10*/), any());
         inOrder.verifyNoMoreInteractions();
     }
 
@@ -480,7 +483,7 @@
         LogicalChannelMocker.mockSendToLogicalChannel(
                     mMockCi, channel, "A1A1A19000", "A1A1A19000");
         LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
-        EuiccSession.get().startSession(SESSION_ID);
+        EuiccSession.get(mContext).startSession(SESSION_ID);
 
         mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
                 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
@@ -496,7 +499,7 @@
         // iccTransmitApduLogicalChannel twice
         inOrder.verify(mMockCi, times(2)).iccTransmitApduLogicalChannel(eq(channel),
                  eq(channel | 10), eq(1), eq(2), eq(3), eq(0), eq("a"), anyBoolean(), any());
-        // No iccCloseLogicalChannel
+        inOrder.verify(mMockCi).iccCloseLogicalChannel(eq(channel), eq(true /*isEs10*/), any());
         inOrder.verifyNoMoreInteractions();
     }
 
@@ -506,7 +509,7 @@
         LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel,
                 "A1A1A19000", "A1A1A19000");
         LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
-        EuiccSession.get().startSession(SESSION_ID);
+        EuiccSession.get(mContext).startSession(SESSION_ID);
 
         mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
                 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
@@ -514,7 +517,7 @@
         mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
                 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
         mLooper.processAllMessages();
-        EuiccSession.get().endSession(SESSION_ID);
+        EuiccSession.get(mContext).endSession(SESSION_ID);
         mLooper.processAllMessages();
 
         assertEquals("A1A1A1", IccUtils.bytesToHexString(mResponseCaptor.response));