Merge "[Geofence] Update SatS2FileCreator, SatS2LocationLookup, and DumpSatS2File to support config ID" into main
diff --git a/assets/CarrierRestrictionOperatorDetails.json b/assets/CarrierRestrictionOperatorDetails.json
index 4f650a0..b3c8976 100644
--- a/assets/CarrierRestrictionOperatorDetails.json
+++ b/assets/CarrierRestrictionOperatorDetails.json
@@ -7,5 +7,8 @@
   "com.comcast.mobile.mxs":{"carrierIds": [2032,2532,2556],"callerSHA256Ids":["914C26403B57D2D482359FC235CC825AD00D52B0121C18EF2B2B9D4DDA4B8996"]},
   "com.xfinity.digitalhome": {"carrierIds": [2032,2532,2556],"callerSHA256Ids":["31b4c17315c2269040d535f7b6a79cf4d11517c664d9de8f1ddf4f8a785aad47"]},
   "com.xfinity.digitalhome.debug":{"carrierIds": [2032,2532,2556],"callerSHA256Ids":["c9133e8168f97573c8c567f46777dff74ade0c015ecf2c5e91be3e4e76ddcae2"]},
-  "com.xfinity.dh.xm.app": {"carrierIds": [2032,2532,2556],"callerSHA256Ids":["c9133e8168f97573c8c567f46777dff74ade0c015ecf2c5e91be3e4e76ddcae2"]}
+  "com.xfinity.dh.xm.app": {"carrierIds": [2032,2532,2556],"callerSHA256Ids":["c9133e8168f97573c8c567f46777dff74ade0c015ecf2c5e91be3e4e76ddcae2"]},
+  "com.tmobile.tmte": {"carrierIds": [1],"callerSHA256Ids":["3D:1A:4B:EF:6E:E7:AF:7D:34:D1:20:E7:B1:AA:C0:DD:24:55:85:DE:62:37:CF:10:0F:68:33:3A:FA:CF:F5:62"]},
+  "com.tmobile.tuesdays": {"carrierIds": [1],"callerSHA256Ids":["3D:1A:4B:EF:6E:E7:AF:7D:34:D1:20:E7:B1:AA:C0:DD:24:55:85:DE:62:37:CF:10:0F:68:33:3A:FA:CF:F5:62","92:B5:F8:11:7F:BD:9B:D5:73:8F:F1:68:A4:FA:12:CB:E2:84:BE:83:4E:DE:1A:7B:B4:4D:D8:45:5B:A1:59:20"]},
+  "com.tmobile.pr.mytmobile": {"carrierIds": [1],"callerSHA256Ids":["92:B5:F8:11:7F:BD:9B:D5:73:8F:F1:68:A4:FA:12:CB:E2:84:BE:83:4E:DE:1A:7B:B4:4D:D8:45:5B:A1:59:20"]}
 }
\ No newline at end of file
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 536c88a..440c39d 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -13725,6 +13725,29 @@
     }
 
     /**
+     * Request to get satellite access configuration for the current location.
+     *
+     * @param result The result receiver that returns the satellite access configuration
+     *               for the current location if the request is successful or an error code
+     *               if the request failed.
+     *
+     * @throws SecurityException if the caller doesn't have the required permission.
+     */
+    @Override
+    public void requestSatelliteAccessConfigurationForCurrentLocation(
+            @NonNull ResultReceiver result) {
+        enforceSatelliteCommunicationPermission(
+                "requestSatelliteAccessConfigurationForCurrentLocation");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mSatelliteAccessController
+                    .requestSatelliteAccessConfigurationForCurrentLocation(result);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
      * Request to get the time after which the satellite will be visible.
      *
      * @param result The result receiver that returns the time after which the satellite will
@@ -14727,6 +14750,24 @@
         }
     }
 
+
+    /**
+     * Inform whether application supports NTN SMS in satellite mode.
+     *
+     * This method is used by default messaging application to inform framework whether it supports
+     * NTN SMS or not.
+     *
+     * @param ntnSmsSupported {@code true} If application supports NTN SMS, else {@code false}.
+     *
+     * @throws SecurityException if the caller doesn't have required permission.
+     */
+    @Override
+    public void setNtnSmsSupported(boolean ntnSmsSupported) {
+        enforceSatelliteCommunicationPermission("setNtnSmsSupported");
+        enforceSendSmsPermission();
+        mSatelliteController.setNtnSmsSupportedByMessagesApp(ntnSmsSupported);
+    }
+
     /**
      * This API can be used by only CTS to override the cached value for the device overlay config
      * value :
diff --git a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
index be2e53b..5f60291 100644
--- a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
+++ b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
@@ -16,6 +16,7 @@
 
 package com.android.phone.satellite.accesscontrol;
 
+import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_ACCESS_CONFIGURATION;
 import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED;
 import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_PROVISIONED;
 import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_SUPPORTED;
@@ -24,6 +25,7 @@
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_NOT_IN_ALLOWED_REGION;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_UNSUPPORTED_DEFAULT_MSG_APP;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_LOCATION_DISABLED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_LOCATION_DISABLED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_LOCATION_NOT_AVAILABLE;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
@@ -78,6 +80,7 @@
 import android.telephony.satellite.ISatelliteDisallowedReasonsCallback;
 import android.telephony.satellite.ISatelliteProvisionStateCallback;
 import android.telephony.satellite.ISatelliteSupportedStateCallback;
+import android.telephony.satellite.SatelliteAccessConfiguration;
 import android.telephony.satellite.SatelliteManager;
 import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
 import android.text.TextUtils;
@@ -116,6 +119,7 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
@@ -160,6 +164,8 @@
     protected static final int EVENT_LOCATION_SETTINGS_ENABLED = 6;
 
     public static final int DEFAULT_REGIONAL_SATELLITE_CONFIG_ID = 0;
+    public static final int UNKNOWN_REGIONAL_SATELLITE_CONFIG_ID = -1;
+
 
     private static final String KEY_AVAILABLE_NOTIFICATION_SHOWN = "available_notification_shown";
     private static final String KEY_UNAVAILABLE_NOTIFICATION_SHOWN =
@@ -260,11 +266,11 @@
     private long mOverriddenLocationFreshDurationNanos;
     @GuardedBy("mLock")
     @NonNull
-    private final Map<SatelliteOnDeviceAccessController.LocationToken, Boolean>
+    private final Map<SatelliteOnDeviceAccessController.LocationToken, Integer>
             mCachedAccessRestrictionMap = new LinkedHashMap<>() {
         @Override
         protected boolean removeEldestEntry(
-                Entry<SatelliteOnDeviceAccessController.LocationToken, Boolean> eldest) {
+                Entry<SatelliteOnDeviceAccessController.LocationToken, Integer> eldest) {
             return size() > MAX_CACHE_SIZE;
         }
     };
@@ -277,7 +283,15 @@
     private Location mFreshLastKnownLocation = null;
     @GuardedBy("mLock")
     @Nullable
-    private Integer mRegionalConfigId = null;
+    protected Integer mRegionalConfigId = null;
+    @GuardedBy("mLock")
+    @Nullable
+    protected Integer mNewRegionalConfigId = null;
+
+    /** Key: Config ID; Value: SatelliteAccessConfiguration */
+    @NonNull
+    private HashMap<Integer, SatelliteAccessConfiguration> mSatelliteAccessConfigMap =
+            new HashMap<>();
 
     /** These are used for CTS test */
     private Path mCtsSatS2FilePath = null;
@@ -531,6 +545,13 @@
                 mCurrentSatelliteAllowedState = isAllowed;
                 notifySatelliteCommunicationAllowedStateChanged(isAllowed);
                 mControllerMetricsStats.reportAllowedStateChanged();
+                if (!isAllowed) {
+                    synchronized (mLock) {
+                        plogd("updateCurrentSatelliteAllowedState : set mNewRegionalConfigId null");
+                        mNewRegionalConfigId = null;
+                    }
+                }
+                updateRegionalConfigId();
             }
         }
     }
@@ -605,6 +626,66 @@
     }
 
     /**
+     * Request to get satellite access configuration for the current location.
+     *
+     * @param result The result receiver that returns satellite access configuration
+     *               for the current location if the request is successful or an error code
+     *               if the request failed.
+     */
+    public void requestSatelliteAccessConfigurationForCurrentLocation(
+            @NonNull ResultReceiver result) {
+        if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+            plogd("carrierRoamingNbIotNtnFlag is disabled");
+            result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
+            return;
+        }
+        plogd("requestSatelliteAccessConfigurationForCurrentLocation");
+        ResultReceiver internalResultReceiver = new ResultReceiver(this) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                plogd("requestSatelliteAccessConfigurationForCurrentLocation: resultCode="
+                        + resultCode + ", resultData=" + resultData);
+                boolean isSatelliteCommunicationAllowed = false;
+                if (resultCode == SATELLITE_RESULT_SUCCESS) {
+                    if (resultData.containsKey(KEY_SATELLITE_COMMUNICATION_ALLOWED)) {
+                        isSatelliteCommunicationAllowed =
+                                resultData.getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED);
+                    } else {
+                        loge("KEY_SATELLITE_COMMUNICATION_ALLOWED does not exist.");
+                        result.send(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, null);
+                        return;
+                    }
+                } else {
+                    loge("resultCode is not SATELLITE_RESULT_SUCCESS.");
+                    result.send(resultCode, null);
+                    return;
+                }
+
+                SatelliteAccessConfiguration satelliteAccessConfig = null;
+                synchronized (mLock) {
+                    if (isSatelliteCommunicationAllowed && isRegionalConfigIdValid(
+                            mRegionalConfigId)) {
+                        plogd("requestSatelliteAccessConfigurationForCurrentLocation : "
+                                + "mRegionalConfigId is " + mRegionalConfigId);
+                        satelliteAccessConfig =
+                                mSatelliteAccessConfigMap.get(mRegionalConfigId);
+                    }
+                }
+                plogd("requestSatelliteAccessConfigurationForCurrentLocation : "
+                        + "satelliteAccessConfig is " + satelliteAccessConfig);
+                Bundle bundle = new Bundle();
+                bundle.putParcelable(KEY_SATELLITE_ACCESS_CONFIGURATION, satelliteAccessConfig);
+                result.send(resultCode, bundle);
+            }
+        };
+        requestIsCommunicationAllowedForCurrentLocation(internalResultReceiver, false);
+    }
+
+    private boolean isRegionalConfigIdValid(@Nullable Integer configId) {
+        return (configId != null && configId >= 0);
+    }
+
+    /**
      * This API should be used by only CTS tests to override the overlay configs of satellite
      * access controller.
      */
@@ -1136,8 +1217,8 @@
                         if (isRegionDisallowed(networkCountryIsoList)) {
                             Bundle bundle = new Bundle();
                             bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED, false);
-                            mAccessControllerMetricsStats.setAccessControlType(
-                                    SatelliteConstants.ACCESS_CONTROL_TYPE_NETWORK_COUNTRY_CODE)
+                            mAccessControllerMetricsStats.setAccessControlType(SatelliteConstants
+                                            .ACCESS_CONTROL_TYPE_NETWORK_COUNTRY_CODE)
                                     .setCountryCodes(networkCountryIsoList);
                             sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle,
                                     false);
@@ -1717,8 +1798,11 @@
                                 location.getLatitude(),
                                 location.getLongitude(), mS2Level);
                 boolean satelliteAllowed;
+
                 if (mCachedAccessRestrictionMap.containsKey(locationToken)) {
-                    satelliteAllowed = mCachedAccessRestrictionMap.get(locationToken);
+                    mNewRegionalConfigId = mCachedAccessRestrictionMap.get(locationToken);
+                    satelliteAllowed = (mNewRegionalConfigId != null);
+                    plogd("mNewRegionalConfigId is " + mNewRegionalConfigId);
                 } else {
                     if (!initSatelliteOnDeviceAccessController()) {
                         ploge("Failed to init SatelliteOnDeviceAccessController");
@@ -1731,16 +1815,20 @@
 
                     if (mFeatureFlags.carrierRoamingNbIotNtn()) {
                         synchronized (mLock) {
-                            mRegionalConfigId = mSatelliteOnDeviceAccessController
+                            mNewRegionalConfigId = mSatelliteOnDeviceAccessController
                                     .getRegionalConfigIdForLocation(locationToken);
-                            plogd("mRegionalConfigId is " + mRegionalConfigId);
-                            satelliteAllowed = (mRegionalConfigId != null);
+                            plogd("mNewRegionalConfigId is " + mNewRegionalConfigId);
+                            satelliteAllowed = (mNewRegionalConfigId != null);
                         }
                     } else {
+                        plogd("checkSatelliteAccessRestrictionForLocation: "
+                                + "carrierRoamingNbIotNtn is disabled");
                         satelliteAllowed = mSatelliteOnDeviceAccessController
                                 .isSatCommunicationAllowedAtLocation(locationToken);
+                        mNewRegionalConfigId =
+                                satelliteAllowed ? UNKNOWN_REGIONAL_SATELLITE_CONFIG_ID : null;
                     }
-                    updateCachedAccessRestrictionMap(locationToken, satelliteAllowed);
+                    updateCachedAccessRestrictionMap(locationToken, mNewRegionalConfigId);
                 }
                 mAccessControllerMetricsStats.setOnDeviceLookupTime(mOnDeviceLookupStartTimeMillis);
                 Bundle bundle = new Bundle();
@@ -1769,11 +1857,23 @@
         }
     }
 
+    private void updateRegionalConfigId() {
+        synchronized (mLock) {
+            plogd("mNewRegionalConfigId: updatedValue = " + mNewRegionalConfigId
+                    + " | mRegionalConfigId: beforeValue = " + mRegionalConfigId);
+            if (!Objects.equals(mRegionalConfigId, mNewRegionalConfigId)) {
+                mRegionalConfigId = mNewRegionalConfigId;
+                notifyRegionalSatelliteConfigurationChanged(
+                        mSatelliteAccessConfigMap.get(mRegionalConfigId));
+            }
+        }
+    }
+
     private void updateCachedAccessRestrictionMap(
             @NonNull SatelliteOnDeviceAccessController.LocationToken locationToken,
-            boolean satelliteAllowed) {
+            Integer regionalConfigId) {
         synchronized (mLock) {
-            mCachedAccessRestrictionMap.put(locationToken, satelliteAllowed);
+            mCachedAccessRestrictionMap.put(locationToken, regionalConfigId);
         }
     }
 
@@ -2212,6 +2312,14 @@
                     logd("registerForCommunicationAllowedStateChanged: "
                             + "mCurrentSatelliteAllowedState " + mCurrentSatelliteAllowedState);
                 }
+                synchronized (mLock) {
+                    SatelliteAccessConfiguration satelliteAccessConfig =
+                            mSatelliteAccessConfigMap.get(mRegionalConfigId);
+                    callback.onSatelliteAccessConfigurationChanged(satelliteAccessConfig);
+                    logd("registerForCommunicationAllowedStateChanged: satelliteAccessConfig: "
+                            + satelliteAccessConfig + " of mRegionalConfigId: "
+                            + mRegionalConfigId);
+                }
             } catch (RemoteException ex) {
                 ploge("registerForCommunicationAllowedStateChanged: RemoteException ex=" + ex);
             }
@@ -2395,6 +2503,25 @@
         });
     }
 
+    protected void notifyRegionalSatelliteConfigurationChanged(
+            @Nullable SatelliteAccessConfiguration satelliteAccessConfig) {
+        plogd("notifyRegionalSatelliteConfigurationChanged : satelliteAccessConfig is "
+                + satelliteAccessConfig);
+
+        List<ISatelliteCommunicationAllowedStateCallback> deadCallersList = new ArrayList<>();
+        mSatelliteCommunicationAllowedStateChangedListeners.values().forEach(listener -> {
+            try {
+                listener.onSatelliteAccessConfigurationChanged(satelliteAccessConfig);
+            } catch (RemoteException e) {
+                plogd("handleEventNtnSignalStrengthChanged RemoteException: " + e);
+                deadCallersList.add(listener);
+            }
+        });
+        deadCallersList.forEach(listener -> {
+            mSatelliteCommunicationAllowedStateChangedListeners.remove(listener.asBinder());
+        });
+    }
+
     private void reportMetrics(int resultCode, boolean allowed) {
         if (resultCode == SATELLITE_RESULT_SUCCESS) {
             mControllerMetricsStats.reportAllowedSatelliteAccessCount(allowed);
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index bda4b28..4d98d92 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -1425,7 +1425,9 @@
     }
 
     private void updateNetworkType() {
-        if (SubscriptionManager.isValidPhoneId(mPhoneId)) {
+        SubscriptionManager mSm = getSystemService(SubscriptionManager.class);
+        if (SubscriptionManager.isValidPhoneId(mPhoneId)
+                && mSm.isActiveSubscriptionId(mSubId)) {
             mDataNetwork.setText(ServiceState.rilRadioTechnologyToString(
                     mTelephonyManager.getServiceStateForSlot(mPhoneId)
                             .getRilDataRadioTechnology()));
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index edbbabd..8956266 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -70,6 +70,7 @@
 import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.phone.PhoneGlobals;
+import com.android.phone.PhoneInterfaceManager;
 import com.android.phone.PhoneUtils;
 import com.android.phone.R;
 import com.android.telephony.Rlog;
@@ -1062,8 +1063,10 @@
 
             boolean hasVoiceAvailability = isImsVoiceAvailable();
 
-            boolean isRttSupported = PhoneGlobals.getInstance().phoneMgr
-                    .isRttEnabled(mPhone.getSubId());
+            PhoneInterfaceManager phoneMgr = PhoneGlobals.getInstance()
+                .phoneMgr;
+            boolean isRttSupported = (phoneMgr != null) ?
+                phoneMgr.isRttEnabled(mPhone.getSubId()) : false;
 
             boolean isRoaming = mTelephonyManager.isNetworkRoaming(mPhone.getSubId());
             boolean isOnWfc = mPhone.getImsRegistrationTech()
diff --git a/testapps/TestSatelliteApp/AndroidManifest.xml b/testapps/TestSatelliteApp/AndroidManifest.xml
index eaddf95..a1f22fa 100644
--- a/testapps/TestSatelliteApp/AndroidManifest.xml
+++ b/testapps/TestSatelliteApp/AndroidManifest.xml
@@ -20,6 +20,7 @@
     <uses-permission android:name="android.permission.BIND_SATELLITE_SERVICE"/>
     <uses-permission android:name="android.permission.SATELLITE_COMMUNICATION"/>
     <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+    <uses-permission android:name="android.permission.SEND_SMS"/>
     <application android:label="SatelliteTestApp">
         <activity android:name=".SatelliteTestApp"
              android:label="SatelliteTestApp"
diff --git a/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml b/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
index 9aec52b..d046f03 100644
--- a/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
+++ b/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
@@ -191,6 +191,19 @@
             android:layout_height="wrap_content"
             android:paddingRight="4dp"
             android:text="@string/deprovisionSatellite"/>
+        <Button
+            android:id="@+id/setNtnSmsSupportedTrue"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingRight="4dp"
+            android:text="@string/setNtnSmsSupportedTrue"/>
+        <Button
+            android:id="@+id/setNtnSmsSupportedFalse"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingRight="4dp"
+            android:text="@string/setNtnSmsSupportedFalse"/>
+
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
diff --git a/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml b/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
index 54f2722..4b5ea5b 100644
--- a/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
+++ b/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
@@ -97,6 +97,9 @@
     <string name="requestSatelliteSubscriberProvisionStatus">requestSatelliteSubscriberProvisionStatus</string>
     <string name="provisionSatellite">provisionSatellite</string>
     <string name="deprovisionSatellite">deprovisionSatellite</string>
+    <string name="setNtnSmsSupportedTrue">setNtnSmsSupportedTrue</string>
+    <string name="setNtnSmsSupportedFalse">setNtnSmsSupportedFalse</string>
+
 
     <string name="Back">Back</string>
     <string name="ClearLog">Clear Log</string>
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java
index 7c4ae00..cb56e87 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java
@@ -16,11 +16,13 @@
 
 package com.android.phone.testapps.satellitetestapp;
 
+import android.Manifest;
 import android.app.Activity;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.telephony.satellite.stub.SatelliteDatagram;
@@ -42,6 +44,7 @@
 
     private TestSatelliteServiceConnection mSatelliteServiceConn;
     private List<SatelliteDatagram> mSentSatelliteDatagrams = new ArrayList<>();
+    private static final int REQUEST_CODE_SEND_SMS = 1;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -105,6 +108,16 @@
         });
     }
 
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (checkSelfPermission(Manifest.permission.SEND_SMS)
+                != PackageManager.PERMISSION_GRANTED) {
+            requestPermissions(new String[]{Manifest.permission.SEND_SMS}, REQUEST_CODE_SEND_SMS);
+        }
+    }
+
+
     private final ILocalSatelliteListener mSatelliteListener =
             new ILocalSatelliteListener.Stub() {
                 @Override
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
index 97cb9c3..7d5e9af 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
@@ -127,6 +127,11 @@
                 .setOnClickListener(this::provisionSatellite);
         findViewById(R.id.deprovisionSatelliteWrapper)
                 .setOnClickListener(this::deprovisionSatellite);
+        findViewById(R.id.setNtnSmsSupportedTrue)
+                .setOnClickListener(this::setNtnSmsSupportedTrue);
+        findViewById(R.id.setNtnSmsSupportedFalse)
+                .setOnClickListener(this::setNtnSmsSupportedFalse);
+
 
         findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
             @Override
@@ -799,6 +804,31 @@
         }
     }
 
+    private void setNtnSmsSupportedTrue(View view) {
+        setNtnSmsSupported(true);
+    }
+
+    private void setNtnSmsSupportedFalse(View view) {
+        setNtnSmsSupported(false);
+    }
+
+    private void setNtnSmsSupported(boolean ntnSmsSupported) {
+        String msg = "setNtnSmsSupported:" + ntnSmsSupported;
+        addLogMessage(msg);
+        logd(msg);
+
+        try {
+            mSatelliteManagerWrapper.setNtnSmsSupported(ntnSmsSupported);
+            msg = "setNtnSmsSupported=" + ntnSmsSupported + " is successful";
+            logd(msg);
+            addLogMessage(msg);
+        } catch (SecurityException | IllegalStateException ex) {
+            msg = "setNtnSmsSupported=" + ntnSmsSupported + " failed. " + ex.getMessage();
+            logd(msg);
+            addLogMessage(msg);
+        }
+    }
+
     private int getActiveSubId() {
         int subId;
         List<SubscriptionInfo> subscriptionInfoList =
diff --git a/tests/src/com/android/TestContext.java b/tests/src/com/android/TestContext.java
index 6e14574..a684ef5 100644
--- a/tests/src/com/android/TestContext.java
+++ b/tests/src/com/android/TestContext.java
@@ -103,6 +103,11 @@
     }
 
     @Override
+    public String getOpPackageName() {
+        return getPackageName();
+    }
+
+    @Override
     public String getAttributionTag() {
         return "";
     }
diff --git a/tests/src/com/android/phone/CarrierConfigLoaderTest.java b/tests/src/com/android/phone/CarrierConfigLoaderTest.java
index b670de5..5190b21 100644
--- a/tests/src/com/android/phone/CarrierConfigLoaderTest.java
+++ b/tests/src/com/android/phone/CarrierConfigLoaderTest.java
@@ -41,7 +41,6 @@
 import android.content.res.Resources;
 import android.os.Build;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.PermissionEnforcer;
 import android.os.PersistableBundle;
 import android.os.UserHandle;
@@ -51,10 +50,10 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.TelephonyRegistryManager;
+import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
 import androidx.test.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import com.android.TelephonyTestBase;
 import com.android.internal.telephony.IccCardConstants;
@@ -80,7 +79,8 @@
 /**
  * Unit Test for CarrierConfigLoader.
  */
-@RunWith(AndroidJUnit4.class)
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
 public class CarrierConfigLoaderTest extends TelephonyTestBase {
     @Rule
     public TestRule compatChangeRule = new PlatformCompatChangeRule();
@@ -107,7 +107,6 @@
     private TelephonyManager mTelephonyManager;
     private CarrierConfigLoader mCarrierConfigLoader;
     private Handler mHandler;
-    private HandlerThread mHandlerThread;
     private TestableLooper mTestableLooper;
 
     // The AIDL stub will use PermissionEnforcer to check permission from the caller.
@@ -149,10 +148,7 @@
         when(mContext.getSystemService(TelephonyRegistryManager.class)).thenReturn(
                 mTelephonyRegistryManager);
 
-        mHandlerThread = new HandlerThread("CarrierConfigLoaderTest");
-        mHandlerThread.start();
-
-        mTestableLooper = new TestableLooper(mHandlerThread.getLooper());
+        mTestableLooper = TestableLooper.get(this);
         mCarrierConfigLoader = new CarrierConfigLoader(mContext, mTestableLooper.getLooper(),
                 mFeatureFlags);
         mHandler = mCarrierConfigLoader.getHandler();
@@ -167,8 +163,6 @@
         mFakePermissionEnforcer.revoke(android.Manifest.permission.DUMP);
         mFakePermissionEnforcer.revoke(android.Manifest.permission.MODIFY_PHONE_STATE);
         mFakePermissionEnforcer.revoke(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
-        mTestableLooper.destroy();
-        mHandlerThread.quit();
         super.tearDown();
     }
 
diff --git a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
index c2f5979..5c18cc5 100644
--- a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
+++ b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
@@ -17,6 +17,8 @@
 package com.android.phone.satellite.accesscontrol;
 
 import static android.location.LocationManager.MODE_CHANGED_ACTION;
+import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_ACCESS_CONFIGURATION;
 import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED;
 import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_PROVISIONED;
 import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_SUPPORTED;
@@ -29,15 +31,17 @@
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
 
 import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.ALLOWED_STATE_CACHE_VALID_DURATION_NANOS;
-import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_REGIONAL_SATELLITE_CONFIG_ID;
-import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.EVENT_COUNTRY_CODE_CHANGED;
 import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.CMD_IS_SATELLITE_COMMUNICATION_ALLOWED;
 import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_DELAY_MINUTES_BEFORE_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_MAX_RETRY_COUNT_FOR_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_REGIONAL_SATELLITE_CONFIG_ID;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_S2_LEVEL;
 import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_THROTTLE_INTERVAL_FOR_LOCATION_QUERY_MINUTES;
 import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.EVENT_CONFIG_DATA_UPDATED;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.EVENT_COUNTRY_CODE_CHANGED;
 import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.EVENT_WAIT_FOR_CURRENT_LOCATION_TIMEOUT;
 import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.GOOGLE_US_SAN_SAT_S2_FILE_NAME;
-import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_MAX_RETRY_COUNT_FOR_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.UNKNOWN_REGIONAL_SATELLITE_CONFIG_ID;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -51,6 +55,7 @@
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
@@ -83,13 +88,18 @@
 import android.os.DropBoxManager;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Parcel;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
 import android.telecom.TelecomManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.satellite.ISatelliteCommunicationAllowedStateCallback;
+import android.telephony.satellite.SatelliteAccessConfiguration;
+import android.telephony.satellite.SatelliteInfo;
 import android.telephony.satellite.SatelliteManager;
 import android.testing.TestableLooper;
 import android.util.Log;
@@ -124,6 +134,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
@@ -188,15 +199,16 @@
     @Mock
     private SharedPreferences.Editor mMockSharedPreferencesEditor;
     @Mock
-    private Map<SatelliteOnDeviceAccessController.LocationToken, Boolean>
+    private Map<SatelliteOnDeviceAccessController.LocationToken, Integer>
             mMockCachedAccessRestrictionMap;
     @Mock
+    HashMap<Integer, SatelliteAccessConfiguration> mMockSatelliteAccessConfigMap;
+
+    @Mock
     private Intent mMockLocationIntent;
     @Mock
     private Set<ResultReceiver> mMockSatelliteAllowResultReceivers;
     @Mock
-    private ResultReceiver mMockSatelliteSupportedResultReceiver;
-    @Mock
     private TelephonyManager mMockTelephonyManager;
     @Mock
     private PackageManager mMockPackageManager;
@@ -206,7 +218,11 @@
     private NotificationManager mMockNotificationManager;
     @Mock
     private ApplicationInfo mMockApplicationInfo;
-
+    @Mock
+    private ResultReceiver mMockResultReceiver;
+    @Mock
+    private ConcurrentHashMap<IBinder, ISatelliteCommunicationAllowedStateCallback>
+            mSatelliteCommunicationAllowedStateCallbackMap;
 
     private Looper mLooper;
     private TestableLooper mTestableLooper;
@@ -241,6 +257,8 @@
     private ArgumentCaptor<Integer> mResultCodeIntCaptor;
     @Captor
     private ArgumentCaptor<Bundle> mResultDataBundleCaptor;
+    @Captor
+    private ArgumentCaptor<ISatelliteCommunicationAllowedStateCallback> mAllowedStateCallbackCaptor;
 
     private boolean mQueriedSatelliteAllowed = false;
     private int mQueriedSatelliteAllowedResultCode = SATELLITE_RESULT_SUCCESS;
@@ -304,6 +322,7 @@
                 mMockCountryDetector);
         when(mMockSatelliteController.getSatellitePhone()).thenReturn(mMockPhone);
         when(mMockPhone.getSubId()).thenReturn(SubscriptionManager.getDefaultSubscriptionId());
+
         when(mMockContext.getResources()).thenReturn(mMockResources);
         when(mMockResources.getStringArray(
                 com.android.internal.R.array.config_oem_enabled_satellite_country_codes))
@@ -430,11 +449,11 @@
         // and allowedState is false when the location is null and the cache is expired
         mSatelliteAccessControllerUT.elapsedRealtimeNanos =
                 ALLOWED_STATE_CACHE_VALID_DURATION_NANOS + 1;
-        Iterator<ResultReceiver> mockIterator = mock(Iterator.class);
-        doReturn(mockIterator).when(mMockSatelliteAllowResultReceivers).iterator();
-        doReturn(true, false).when(mockIterator).hasNext();
+        Iterator<ResultReceiver> mockResultReceiverIterator = mock(Iterator.class);
+        doReturn(mockResultReceiverIterator).when(mMockSatelliteAllowResultReceivers).iterator();
+        doReturn(true, false).when(mockResultReceiverIterator).hasNext();
         doNothing().when(mMockSatelliteAllowResultReceivers).clear();
-        doReturn(mMockSatelliteSupportedResultReceiver).when(mockIterator).next();
+        doReturn(mMockResultReceiver).when(mockResultReceiverIterator).next();
         replaceInstance(SatelliteAccessController.class, "mSatelliteAllowResultReceivers",
                 mSatelliteAccessControllerUT, mMockSatelliteAllowResultReceivers);
         mSatelliteAccessControllerUT.setIsSatelliteCommunicationAllowedForCurrentLocationCache(
@@ -442,7 +461,7 @@
         mSatelliteAccessControllerUT.setLocationRequestCancellationSignalAsNull(false);
 
         sendCurrentLocationTimeoutEvent();
-        verify(mMockSatelliteSupportedResultReceiver)
+        verify(mMockResultReceiver)
                 .send(mResultCodeIntCaptor.capture(), any());
         assertEquals(Integer.valueOf(SATELLITE_RESULT_LOCATION_NOT_AVAILABLE),
                 mResultCodeIntCaptor.getValue());
@@ -514,6 +533,314 @@
                 .isSatelliteAccessAllowedForLocation(List.of(TEST_SATELLITE_COUNTRY_CODE_US)));
     }
 
+
+    private void setSatelliteCommunicationAllowed() throws Exception {
+        when(mMockContext.getResources()).thenReturn(mMockResources);
+        when(mMockResources.getBoolean(
+                com.android.internal.R.bool.config_oem_enabled_satellite_access_allow))
+                .thenReturn(TEST_SATELLITE_ALLOW);
+        setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+        setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+        doReturn(true).when(mMockLocationManager).isLocationEnabled();
+        when(mMockSatelliteOnDeviceAccessController.getRegionalConfigIdForLocation(
+                any(SatelliteOnDeviceAccessController.LocationToken.class)))
+                .thenReturn(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID);
+        replaceInstance(SatelliteAccessController.class, "mCachedAccessRestrictionMap",
+                mSatelliteAccessControllerUT, mMockCachedAccessRestrictionMap);
+        doReturn(true).when(mMockCachedAccessRestrictionMap).containsKey(any());
+        doReturn(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID)
+                .when(mMockCachedAccessRestrictionMap).get(any());
+    }
+
+    @Test
+    public void testRequestSatelliteAccessConfigurationForCurrentLocation() throws Exception {
+        // setup result receiver and satellite access configuration data
+        ResultReceiver mockResultReceiver = mock(ResultReceiver.class);
+        ArgumentCaptor<Integer> resultCodeCaptor = ArgumentCaptor.forClass(Integer.class);
+        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        SatelliteAccessConfiguration satelliteAccessConfig = getSatelliteAccessConfiguration();
+
+        // setup satellite communication allwed state as true
+        setSatelliteCommunicationAllowed();
+
+        // setup map data of location and configId.
+        replaceInstance(SatelliteAccessController.class, "mSatelliteAccessConfigMap",
+                mSatelliteAccessControllerUT, mMockSatelliteAccessConfigMap);
+        doReturn(satelliteAccessConfig).when(mMockSatelliteAccessConfigMap).get(anyInt());
+        doReturn(null).when(mMockSatelliteAccessConfigMap).get(eq(null));
+        doReturn(null).when(mMockSatelliteAccessConfigMap)
+                .get(eq(UNKNOWN_REGIONAL_SATELLITE_CONFIG_ID));
+
+        // setup callback
+        ISatelliteCommunicationAllowedStateCallback mockSatelliteAllowedStateCallback = mock(
+                ISatelliteCommunicationAllowedStateCallback.class);
+        ArgumentCaptor<SatelliteAccessConfiguration> satelliteAccessConfigurationCaptor =
+                ArgumentCaptor.forClass(SatelliteAccessConfiguration.class);
+
+        when(mSatelliteCommunicationAllowedStateCallbackMap.values())
+                .thenReturn(List.of(mockSatelliteAllowedStateCallback));
+        replaceInstance(SatelliteAccessController.class,
+                "mSatelliteCommunicationAllowedStateChangedListeners", mSatelliteAccessControllerUT,
+                mSatelliteCommunicationAllowedStateCallbackMap);
+
+        // Test when the featureFlags.carrierRoamingNbIotNtn() is false
+        doReturn(false).when(mMockFeatureFlags).carrierRoamingNbIotNtn();
+
+        clearInvocations(mockResultReceiver);
+        mSatelliteAccessControllerUT
+                .requestSatelliteAccessConfigurationForCurrentLocation(mockResultReceiver);
+        mTestableLooper.processAllMessages();
+        verify(mockResultReceiver, times(1)).send(resultCodeCaptor.capture(),
+                bundleCaptor.capture());
+        assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, (int) resultCodeCaptor.getValue());
+        assertNull(bundleCaptor.getValue());
+        verify(mockSatelliteAllowedStateCallback, never())
+                .onSatelliteAccessConfigurationChanged(any());
+
+        doReturn(true).when(mMockFeatureFlags).carrierRoamingNbIotNtn();
+
+        // satellite communication allowed state is enabled and
+        // regional config id is DEFAULT_REGIONAL_SATELLITE_CONFIG_ID.
+        clearInvocations(mockResultReceiver);
+        clearInvocations(mockSatelliteAllowedStateCallback);
+        mSatelliteAccessControllerUT
+                .requestSatelliteAccessConfigurationForCurrentLocation(mockResultReceiver);
+        mTestableLooper.processAllMessages();
+        verify(mockResultReceiver, times(1)).send(resultCodeCaptor.capture(),
+                bundleCaptor.capture());
+        assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS, (int) resultCodeCaptor.getValue());
+        assertTrue(bundleCaptor.getValue().containsKey(KEY_SATELLITE_ACCESS_CONFIGURATION));
+        assertSame(bundleCaptor.getValue().getParcelable(KEY_SATELLITE_ACCESS_CONFIGURATION,
+                SatelliteAccessConfiguration.class), satelliteAccessConfig);
+        verify(mockSatelliteAllowedStateCallback, times(1))
+                .onSatelliteAccessConfigurationChanged(
+                        satelliteAccessConfigurationCaptor.capture());
+        assertEquals(satelliteAccessConfigurationCaptor.getValue(), satelliteAccessConfig);
+
+        // satellite communication allowed state is disabled and
+        // regional config id is null.
+        clearInvocations(mockResultReceiver);
+        clearInvocations(mockSatelliteAllowedStateCallback);
+        when(mMockCachedAccessRestrictionMap.get(any())).thenReturn(null);
+        mSatelliteAccessControllerUT
+                .requestSatelliteAccessConfigurationForCurrentLocation(mockResultReceiver);
+        mTestableLooper.processAllMessages();
+
+        verify(mockResultReceiver, times(1)).send(resultCodeCaptor.capture(),
+                bundleCaptor.capture());
+        assertEquals(SATELLITE_RESULT_SUCCESS, (int) resultCodeCaptor.getValue());
+        assertTrue(bundleCaptor.getValue().containsKey(KEY_SATELLITE_ACCESS_CONFIGURATION));
+        assertNull(bundleCaptor.getValue().getParcelable(KEY_SATELLITE_ACCESS_CONFIGURATION,
+                SatelliteAccessConfiguration.class));
+        verify(mockSatelliteAllowedStateCallback, times(1))
+                .onSatelliteAccessConfigurationChanged(
+                        satelliteAccessConfigurationCaptor.capture());
+        assertNull(satelliteAccessConfigurationCaptor.getValue());
+    }
+
+    private SatelliteAccessConfiguration getSatelliteAccessConfiguration() {
+        Parcel satelliteAccessconfigParcel = Parcel.obtain();
+
+        List<SatelliteInfo> satelliteInfoList = new ArrayList<>();
+        satelliteInfoList.add(mock(SatelliteInfo.class));
+        satelliteAccessconfigParcel.writeTypedList(satelliteInfoList);
+
+        List<Integer> tagIds = new ArrayList<>(List.of(1, 2));
+        satelliteAccessconfigParcel.writeList(tagIds);
+
+        return new SatelliteAccessConfiguration(satelliteAccessconfigParcel);
+    }
+
+    @Test
+    public void testRegisterForCommunicationAllowedStateChanged() throws Exception {
+        ISatelliteCommunicationAllowedStateCallback mockSatelliteAllowedStateCallback = mock(
+                ISatelliteCommunicationAllowedStateCallback.class);
+        doReturn(true).when(mSatelliteCommunicationAllowedStateCallbackMap)
+                .put(any(IBinder.class), any(ISatelliteCommunicationAllowedStateCallback.class));
+        replaceInstance(SatelliteAccessController.class,
+                "mSatelliteCommunicationAllowedStateChangedListeners", mSatelliteAccessControllerUT,
+                mSatelliteCommunicationAllowedStateCallbackMap);
+
+        doReturn(false).when(mMockFeatureFlags).oemEnabledSatelliteFlag();
+        int result = mSatelliteAccessControllerUT.registerForCommunicationAllowedStateChanged(
+                DEFAULT_SUBSCRIPTION_ID, mockSatelliteAllowedStateCallback);
+        mTestableLooper.processAllMessages();
+        assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, result);
+        verify(mockSatelliteAllowedStateCallback, never())
+                .onSatelliteCommunicationAllowedStateChanged(anyBoolean());
+        verify(mockSatelliteAllowedStateCallback, never())
+                .onSatelliteAccessConfigurationChanged(any(SatelliteAccessConfiguration.class));
+
+        doReturn(true).when(mMockFeatureFlags).oemEnabledSatelliteFlag();
+        result = mSatelliteAccessControllerUT.registerForCommunicationAllowedStateChanged(
+                DEFAULT_SUBSCRIPTION_ID, mockSatelliteAllowedStateCallback);
+        mTestableLooper.processAllMessages();
+        assertEquals(SATELLITE_RESULT_SUCCESS, result);
+        verify(mockSatelliteAllowedStateCallback, times(1))
+                .onSatelliteCommunicationAllowedStateChanged(anyBoolean());
+        verify(mockSatelliteAllowedStateCallback, times(1))
+                .onSatelliteAccessConfigurationChanged(
+                        nullable(SatelliteAccessConfiguration.class));
+    }
+
+    @Test
+    public void testNotifyRegionalSatelliteConfigurationChanged() throws Exception {
+        // setup test
+        ISatelliteCommunicationAllowedStateCallback mockSatelliteAllowedStateCallback = mock(
+                ISatelliteCommunicationAllowedStateCallback.class);
+        ArgumentCaptor<SatelliteAccessConfiguration> satelliteAccessConfigurationCaptor =
+                ArgumentCaptor.forClass(SatelliteAccessConfiguration.class);
+
+        when(mSatelliteCommunicationAllowedStateCallbackMap.values())
+                .thenReturn(List.of(mockSatelliteAllowedStateCallback));
+        replaceInstance(SatelliteAccessController.class,
+                "mSatelliteCommunicationAllowedStateChangedListeners", mSatelliteAccessControllerUT,
+                mSatelliteCommunicationAllowedStateCallbackMap);
+
+        // register callback
+        mSatelliteAccessControllerUT.registerForCommunicationAllowedStateChanged(
+                DEFAULT_SUBSCRIPTION_ID, mockSatelliteAllowedStateCallback);
+
+        // verify if the callback is
+        // the same instance from onmSatelliteCommunicationAllowedStateCallbackMap
+        verify(mSatelliteCommunicationAllowedStateCallbackMap).put(any(),
+                mAllowedStateCallbackCaptor.capture());
+        assertSame(mockSatelliteAllowedStateCallback, mAllowedStateCallbackCaptor.getValue());
+
+        // create SatelliteAccessConfiguration data for this test
+        SatelliteAccessConfiguration satelliteAccessConfig = getSatelliteAccessConfiguration();
+
+        // trigger notifyRegionalSatelliteConfigurationChanged
+        mSatelliteAccessControllerUT
+                .notifyRegionalSatelliteConfigurationChanged(satelliteAccessConfig);
+
+        // verify if the satelliteAccessConfig is the same instance with the captured one.
+        verify(mockSatelliteAllowedStateCallback).onSatelliteAccessConfigurationChanged(
+                satelliteAccessConfigurationCaptor.capture());
+        assertSame(satelliteAccessConfig, satelliteAccessConfigurationCaptor.getValue());
+    }
+
+    @Test
+    public void testCheckSatelliteAccessRestrictionForLocation() throws Exception {
+        // Setup
+        logd("testCheckSatelliteAccessRestrictionForLocation : setup");
+        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        ArgumentCaptor<Integer> regionalConfigIdCaptor = ArgumentCaptor.forClass(Integer.class);
+        replaceInstance(SatelliteAccessController.class, "mS2Level",
+                mSatelliteAccessControllerUT, DEFAULT_S2_LEVEL);
+        Iterator<ResultReceiver> mockResultReceiverIterator = mock(Iterator.class);
+        mSatelliteAccessControllerUT.setRegionalConfigId(null);
+
+        doReturn(mockResultReceiverIterator).when(mMockSatelliteAllowResultReceivers).iterator();
+        doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+        doNothing().when(mMockSatelliteAllowResultReceivers).clear();
+        doReturn(mMockResultReceiver).when(mockResultReceiverIterator).next();
+        replaceInstance(SatelliteAccessController.class, "mSatelliteAllowResultReceivers",
+                mSatelliteAccessControllerUT, mMockSatelliteAllowResultReceivers);
+        replaceInstance(SatelliteAccessController.class, "mCachedAccessRestrictionMap",
+                mSatelliteAccessControllerUT, mMockCachedAccessRestrictionMap);
+
+        // when mMockCachedAccessRestrictionMap is hit and has DEFAULT_REGIONAL_SATELLITE_CONFIG_ID,
+        // verify belows
+        // - the bundle data of KEY_SATELLITE_COMMUNICATION_ALLOWED is true
+        // - the newRegionalConfigId is the same as DEFAULT_REGIONAL_SATELLITE_CONFIG_ID
+        // - the regionalConfigId is the same as DEFAULT_REGIONAL_SATELLITE_CONFIG_ID
+        logd("testCheckSatelliteAccessRestrictionForLocation : case 1");
+        clearInvocations(mMockSatelliteOnDeviceAccessController);
+        clearInvocations(mMockCachedAccessRestrictionMap);
+
+        doReturn(true).when(mMockCachedAccessRestrictionMap)
+                .containsKey(any(SatelliteOnDeviceAccessController.LocationToken.class));
+        doReturn(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID).when(mMockCachedAccessRestrictionMap)
+                .get(any(SatelliteOnDeviceAccessController.LocationToken.class));
+
+        mSatelliteAccessControllerUT.checkSatelliteAccessRestrictionForLocation(mMockLocation0);
+        verify(mMockResultReceiver, times(1))
+                .send(mResultCodeIntCaptor.capture(), bundleCaptor.capture());
+        verify(mMockSatelliteOnDeviceAccessController, never()).getRegionalConfigIdForLocation(
+                any(SatelliteOnDeviceAccessController.LocationToken.class));
+        assertEquals(Integer.valueOf(SATELLITE_RESULT_SUCCESS), mResultCodeIntCaptor.getValue());
+        assertTrue(bundleCaptor.getValue().getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED));
+        assertEquals(Integer.valueOf(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID),
+                mSatelliteAccessControllerUT.getNewRegionalConfigId());
+        assertEquals(Integer.valueOf(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID),
+                mSatelliteAccessControllerUT.getRegionalConfigId());
+
+        // when mMockCachedAccessRestrictionMap is not hit and regionalConfigId is null
+        // verify belows
+        // - the bundle data of KEY_SATELLITE_COMMUNICATION_ALLOWED is false
+        // - the regionalConfigId is null
+        logd("testCheckSatelliteAccessRestrictionForLocation : case 2");
+        clearInvocations(mMockCachedAccessRestrictionMap);
+        doReturn(false).when(mMockCachedAccessRestrictionMap)
+                .containsKey(any(SatelliteOnDeviceAccessController.LocationToken.class));
+        doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+        when(mMockSatelliteOnDeviceAccessController.getRegionalConfigIdForLocation(
+                any(SatelliteOnDeviceAccessController.LocationToken.class)))
+                .thenReturn(null);
+
+        mSatelliteAccessControllerUT.checkSatelliteAccessRestrictionForLocation(mMockLocation0);
+        verify(mMockResultReceiver, times(2))
+                .send(mResultCodeIntCaptor.capture(), bundleCaptor.capture());
+        assertEquals(Integer.valueOf(SATELLITE_RESULT_SUCCESS), mResultCodeIntCaptor.getValue());
+        assertFalse(bundleCaptor.getValue().getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED));
+        verify(mMockCachedAccessRestrictionMap, times(1))
+                .put(any(), regionalConfigIdCaptor.capture());
+        assertNull(regionalConfigIdCaptor.getValue());
+        assertNull(mSatelliteAccessControllerUT.getNewRegionalConfigId());
+        assertNull(mSatelliteAccessControllerUT.getRegionalConfigId());
+
+        // when mMockCachedAccessRestrictionMap is not hit and
+        // regionalConfigId is DEFAULT_REGIONAL_SATELLITE_CONFIG_ID
+        // verify belows
+        // - the bundle data of KEY_SATELLITE_COMMUNICATION_ALLOWED is true
+        // - the regionalConfigId is DEFAULT_REGIONAL_SATELLITE_CONFIG_ID
+        logd("testCheckSatelliteAccessRestrictionForLocation : case 3");
+        clearInvocations(mMockCachedAccessRestrictionMap);
+        when(mMockSatelliteOnDeviceAccessController.getRegionalConfigIdForLocation(
+                any(SatelliteOnDeviceAccessController.LocationToken.class)))
+                .thenReturn(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID);
+        doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+
+        mSatelliteAccessControllerUT.checkSatelliteAccessRestrictionForLocation(mMockLocation0);
+        verify(mMockResultReceiver, times(3))
+                .send(mResultCodeIntCaptor.capture(), bundleCaptor.capture());
+        assertEquals(Integer.valueOf(SATELLITE_RESULT_SUCCESS), mResultCodeIntCaptor.getValue());
+        assertTrue(bundleCaptor.getValue().getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED));
+        verify(mMockCachedAccessRestrictionMap, times(1))
+                .put(any(), regionalConfigIdCaptor.capture());
+
+        assertEquals(Integer.valueOf(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID),
+                regionalConfigIdCaptor.getValue());
+        assertEquals(Integer.valueOf(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID),
+                mSatelliteAccessControllerUT.getNewRegionalConfigId());
+        assertEquals(Integer.valueOf(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID),
+                mSatelliteAccessControllerUT.getRegionalConfigId());
+
+
+        // when mMockCachedAccessRestrictionMap is not hit and regionalConfigId is null
+        // verify belows
+        // - the bundle data of KEY_SATELLITE_COMMUNICATION_ALLOWED is false
+        // - the regionalConfigId is null
+        logd("testCheckSatelliteAccessRestrictionForLocation : case 4");
+        clearInvocations(mMockCachedAccessRestrictionMap);
+        when(mMockSatelliteOnDeviceAccessController.getRegionalConfigIdForLocation(
+                any(SatelliteOnDeviceAccessController.LocationToken.class)))
+                .thenReturn(null);
+        doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+
+        mSatelliteAccessControllerUT.checkSatelliteAccessRestrictionForLocation(mMockLocation0);
+        verify(mMockResultReceiver, times(4))
+                .send(mResultCodeIntCaptor.capture(), bundleCaptor.capture());
+        assertEquals(Integer.valueOf(SATELLITE_RESULT_SUCCESS), mResultCodeIntCaptor.getValue());
+        assertFalse(bundleCaptor.getValue().getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED));
+        verify(mMockCachedAccessRestrictionMap, times(1))
+                .put(any(), regionalConfigIdCaptor.capture());
+        assertNull(regionalConfigIdCaptor.getValue());
+        assertNull(mSatelliteAccessControllerUT.getNewRegionalConfigId());
+        assertNull(mSatelliteAccessControllerUT.getRegionalConfigId());
+    }
+
     @Test
     public void testIsRegionDisallowed() throws Exception {
         // setup to make the return value of mQueriedSatelliteAllowed 'true'
@@ -531,7 +858,8 @@
         replaceInstance(SatelliteAccessController.class, "mCachedAccessRestrictionMap",
                 mSatelliteAccessControllerUT, mMockCachedAccessRestrictionMap);
         doReturn(true).when(mMockCachedAccessRestrictionMap).containsKey(any());
-        doReturn(true).when(mMockCachedAccessRestrictionMap).get(any());
+        doReturn(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID)
+                .when(mMockCachedAccessRestrictionMap).get(any());
 
         // get allowed country codes EMPTY from resources
         when(mMockResources.getStringArray(
@@ -946,7 +1274,6 @@
         // current time is greater than the location query throttle interval
         // verify mMockLocationManager.getCurrentLocation() is invoked
         // verify time(mLastLocationQueryForPossibleChangeInAllowedRegionTimeNanos) is updated
-        logd("youngcha 1");
         clearInvocations(mMockLocationManager);
         mSatelliteAccessControllerUT.setLocationRequestCancellationSignalAsNull(true);
         mSatelliteAccessControllerUT.elapsedRealtimeNanos =
@@ -1254,10 +1581,10 @@
     @Test
     public void testHandleIsSatelliteSupportedResult() throws Exception {
         // Setup for this test case
-        Iterator<ResultReceiver> mockIterator = mock(Iterator.class);
-        doReturn(mockIterator).when(mMockSatelliteAllowResultReceivers).iterator();
-        doReturn(true, false).when(mockIterator).hasNext();
-        doReturn(mMockSatelliteSupportedResultReceiver).when(mockIterator).next();
+        Iterator<ResultReceiver> mockResultReceiverIterator = mock(Iterator.class);
+        doReturn(mockResultReceiverIterator).when(mMockSatelliteAllowResultReceivers).iterator();
+        doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+        doReturn(mMockResultReceiver).when(mockResultReceiverIterator).next();
 
         replaceInstance(SatelliteAccessController.class, "mSatelliteAllowResultReceivers",
                 mSatelliteAccessControllerUT, mMockSatelliteAllowResultReceivers);
@@ -1266,10 +1593,10 @@
         // case that resultCode is not SATELLITE_RESULT_SUCCESS
         int resultCode = SATELLITE_RESULT_ERROR;
         Bundle bundle = new Bundle();
-        doReturn(true, false).when(mockIterator).hasNext();
-        clearInvocations(mMockSatelliteSupportedResultReceiver);
+        doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+        clearInvocations(mMockResultReceiver);
         mSatelliteAccessControllerUT.handleIsSatelliteSupportedResult(resultCode, bundle);
-        verify(mMockSatelliteSupportedResultReceiver)
+        verify(mMockResultReceiver)
                 .send(mResultCodeIntCaptor.capture(), any());
         assertEquals(Integer.valueOf(SATELLITE_RESULT_ERROR), mResultCodeIntCaptor.getValue());
 
@@ -1277,20 +1604,19 @@
         // verify that the resultCode is delivered as it were
         resultCode = SATELLITE_RESULT_SUCCESS;
         bundle.putBoolean(KEY_SATELLITE_PROVISIONED, false);
-        doReturn(true, false).when(mockIterator).hasNext();
-        clearInvocations(mMockSatelliteSupportedResultReceiver);
+        doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+        clearInvocations(mMockResultReceiver);
         mSatelliteAccessControllerUT.handleIsSatelliteSupportedResult(resultCode, bundle);
-        verify(mMockSatelliteSupportedResultReceiver)
-                .send(mResultCodeIntCaptor.capture(), any());
+        verify(mMockResultReceiver).send(mResultCodeIntCaptor.capture(), any());
         assertEquals(Integer.valueOf(SATELLITE_RESULT_SUCCESS), mResultCodeIntCaptor.getValue());
 
         // case KEY_SATELLITE_SUPPORTED is false
         // verify SATELLITE_RESULT_NOT_SUPPORTED is captured
         bundle.putBoolean(KEY_SATELLITE_SUPPORTED, false);
-        doReturn(true, false).when(mockIterator).hasNext();
-        clearInvocations(mMockSatelliteSupportedResultReceiver);
+        doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+        clearInvocations(mMockResultReceiver);
         mSatelliteAccessControllerUT.handleIsSatelliteSupportedResult(resultCode, bundle);
-        verify(mMockSatelliteSupportedResultReceiver)
+        verify(mMockResultReceiver)
                 .send(mResultCodeIntCaptor.capture(), mResultDataBundleCaptor.capture());
         assertEquals(Integer.valueOf(SATELLITE_RESULT_NOT_SUPPORTED),
                 mResultCodeIntCaptor.getValue());
@@ -1302,10 +1628,10 @@
         bundle.putBoolean(KEY_SATELLITE_SUPPORTED, true);
         when(mMockCountryDetector.getCurrentNetworkCountryIso())
                 .thenReturn(List.of(TEST_SATELLITE_COUNTRY_CODE_KR));
-        doReturn(true, false).when(mockIterator).hasNext();
-        clearInvocations(mMockSatelliteSupportedResultReceiver);
+        doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+        clearInvocations(mMockResultReceiver);
         mSatelliteAccessControllerUT.handleIsSatelliteSupportedResult(resultCode, bundle);
-        verify(mMockSatelliteSupportedResultReceiver)
+        verify(mMockResultReceiver)
                 .send(mResultCodeIntCaptor.capture(), mResultDataBundleCaptor.capture());
         assertEquals(Integer.valueOf(SATELLITE_RESULT_SUCCESS),
                 mResultCodeIntCaptor.getValue());
@@ -1317,10 +1643,10 @@
         when(mMockCountryDetector.getCurrentNetworkCountryIso())
                 .thenReturn(List.of(TEST_SATELLITE_COUNTRY_CODE_US));
         doReturn(false).when(mMockLocationManager).isLocationEnabled();
-        doReturn(true, false).when(mockIterator).hasNext();
-        clearInvocations(mMockSatelliteSupportedResultReceiver);
+        doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+        clearInvocations(mMockResultReceiver);
         mSatelliteAccessControllerUT.handleIsSatelliteSupportedResult(resultCode, bundle);
-        verify(mMockSatelliteSupportedResultReceiver)
+        verify(mMockResultReceiver)
                 .send(mResultCodeIntCaptor.capture(), mResultDataBundleCaptor.capture());
         assertEquals(Integer.valueOf(SATELLITE_RESULT_LOCATION_DISABLED),
                 mResultCodeIntCaptor.getValue());
@@ -1367,7 +1693,7 @@
 
     private void sendSatelliteCommunicationAllowedEvent() {
         Pair<Integer, ResultReceiver> requestPair =
-                new Pair<>(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+                new Pair<>(DEFAULT_SUBSCRIPTION_ID,
                         mSatelliteAccessControllerUT.getResultReceiverCurrentLocation());
         Message msg = mSatelliteAccessControllerUT.obtainMessage(
                 CMD_IS_SATELLITE_COMMUNICATION_ALLOWED);
@@ -1567,5 +1893,25 @@
                 return mCurrentSatelliteAllowedState;
             }
         }
+
+        @Nullable
+        public Integer getRegionalConfigId() {
+            synchronized (mLock) {
+                return mRegionalConfigId;
+            }
+        }
+
+        @Nullable
+        public Integer getNewRegionalConfigId() {
+            synchronized (mLock) {
+                return mNewRegionalConfigId;
+            }
+        }
+
+        public void setRegionalConfigId(@Nullable Integer regionalConfigId) {
+            synchronized (mLock) {
+                mRegionalConfigId = regionalConfigId;
+            }
+        }
     }
 }
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index 5618770..6a10d75 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -61,7 +61,6 @@
 import android.os.AsyncResult;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.Looper;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.telecom.Conference;
 import android.telecom.Conferenceable;
@@ -283,7 +282,7 @@
     @Before
     public void setUp() throws Exception {
         super.setUp();
-        doReturn(Looper.getMainLooper()).when(mContext).getMainLooper();
+
         mTestConnectionService = new TestTelephonyConnectionService(mContext);
         mTestConnectionService.setFeatureFlags(mFeatureFlags);
         mTestConnectionService.setPhoneFactoryProxy(mPhoneFactoryProxy);
diff --git a/tests/src/com/android/services/telephony/TestTelephonyConnection.java b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
index d91435c..9f1a0ec 100644
--- a/tests/src/com/android/services/telephony/TestTelephonyConnection.java
+++ b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
@@ -16,27 +16,31 @@
 
 package com.android.services.telephony;
 
-import android.content.AttributionSource;
-import android.content.ContentResolver;
-import android.os.Process;
-import android.os.UserHandle;
-import android.telephony.TelephonyManager;
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.notNull;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import android.content.AttributionSource;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.res.Resources;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.PersistableBundle;
+import android.os.Process;
+import android.os.UserHandle;
+import android.provider.Settings;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.VideoProfile;
 import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+import android.test.mock.MockContentProvider;
+import android.test.mock.MockContentResolver;
 
 import com.android.ims.ImsCall;
 import com.android.internal.telephony.Call;
@@ -70,9 +74,6 @@
     Context mMockContext;
 
     @Mock
-    ContentResolver mMockContentResolver;
-
-    @Mock
     Resources mMockResources;
 
     @Mock
@@ -96,6 +97,7 @@
     @Mock
     CarrierConfigManager mCarrierConfigManager;
 
+    private MockContentResolver mMockContentResolver;
     private boolean mIsImsConnection;
     private boolean mIsImsExternalConnection;
     private boolean mIsConferenceSupported = true;
@@ -136,6 +138,14 @@
         mMockContext = mock(Context.class);
         mMockTelephonyManager = mock(TelephonyManager.class);
         mOriginalConnection = mMockRadioConnection;
+
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
+        doReturn(applicationInfo).when(mMockContext).getApplicationInfo();
+        mMockContentResolver = new MockContentResolver(mMockContext);
+        mMockContentResolver.addProvider(Settings.AUTHORITY,
+                new EmptyContentProvider(mMockContext));
+
         // Set up mMockRadioConnection and mMockPhone to contain an active call
         when(mMockRadioConnection.getState()).thenReturn(Call.State.ACTIVE);
         when(mOriginalConnection.getState()).thenReturn(Call.State.ACTIVE);
@@ -159,8 +169,7 @@
         when(mMockContext.getSystemService(Context.TELEPHONY_SERVICE))
                 .thenReturn(mMockTelephonyManager);
         when(mMockContext.getAttributionSource()).thenReturn(attributionSource);
-        when(mMockContentResolver.getUserId()).thenReturn(UserHandle.USER_CURRENT);
-        when(mMockContentResolver.getAttributionSource()).thenReturn(attributionSource);
+        when(mMockContext.getUserId()).thenReturn(UserHandle.USER_CURRENT);
         when(mMockResources.getBoolean(anyInt())).thenReturn(false);
         when(mMockPhone.getDefaultPhone()).thenReturn(mMockPhone);
         when(mMockPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_IMS);
@@ -320,4 +329,15 @@
     public void setMockImsPhoneConnection(ImsPhoneConnection connection) {
         mImsPhoneConnection = connection;
     }
+
+    static class EmptyContentProvider extends MockContentProvider {
+        EmptyContentProvider(Context context) {
+            super(context);
+        }
+
+        @Override
+        public Bundle call(String method, String request, Bundle args) {
+            return new Bundle();
+        }
+    }
 }
diff --git a/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java b/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
index 07c9fd0..649d3dd 100644
--- a/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
@@ -45,6 +45,7 @@
 import com.android.ims.FeatureConnector;
 import com.android.ims.RcsFeatureManager;
 import com.android.internal.telephony.imsphone.ImsRegistrationCallbackHelper;
+import com.android.phone.ImsStateCallbackController;
 
 import org.junit.After;
 import org.junit.Before;
@@ -84,6 +85,9 @@
     @Before
     public void setUp() throws Exception {
         super.setUp();
+
+        replaceInstance(ImsStateCallbackController.class, "sInstance", null,
+                mock(ImsStateCallbackController.class));
     }
 
     @After
diff --git a/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java b/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java
index 42a45f4..df7a37e 100644
--- a/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java
@@ -147,12 +147,16 @@
 
     @After
     public void tearDown() throws Exception {
-        super.tearDown();
-        boolean isShutdown = mExecutorService == null || mExecutorService.isShutdown();
-        if (!isShutdown) {
+        var monitor = RcsProvisioningMonitor.getInstance();
+        if (monitor != null) {
+            monitor.overrideImsFeatureValidation(TEST_SUB_ID, null);
+        }
+
+        if (mExecutorService != null && !mExecutorService.isShutdown()) {
             mExecutorService.shutdownNow();
         }
-        RcsProvisioningMonitor.getInstance().overrideImsFeatureValidation(TEST_SUB_ID, null);
+
+        super.tearDown();
     }
 
     @SmallTest
diff --git a/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java b/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
index 4cabf95..34ed5c6 100644
--- a/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
+++ b/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
@@ -20,6 +20,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -40,6 +41,7 @@
 import com.android.ims.RcsFeatureManager;
 import com.android.internal.telephony.ISub;
 import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.phone.ImsStateCallbackController;
 
 import org.junit.After;
 import org.junit.Before;
@@ -103,6 +105,9 @@
                 eq(1), anyInt());
         doReturn(true).when(mResourceProxy).getDeviceUceEnabled(any());
 
+        replaceInstance(ImsStateCallbackController.class, "sInstance", null,
+                mock(ImsStateCallbackController.class));
+
         replaceInstance(TelephonyManager.class, "sInstance", null, mTelephonyManager);
         doReturn(2).when(mTelephonyManager).getActiveModemCount();
     }