Merge "Add public method to retrun whether the satellite request is for an emergency or not" into main
diff --git a/flags/domainselection.aconfig b/flags/domainselection.aconfig
index 623c3b6..4b1ad4a 100644
--- a/flags/domainselection.aconfig
+++ b/flags/domainselection.aconfig
@@ -33,3 +33,11 @@
     description: "This flag controls domain selection metrics."
     bug:"258112541"
 }
+
+# OWNER=jdyou TARGET=24Q4
+flag {
+    name: "hangup_emergency_call_for_cross_sim_redialing"
+    namespace: "telephony"
+    description: "This flag controls the behavior of terminating an emergency call for cross SIM redialing."
+    bug:"336398541"
+}
diff --git a/flags/messaging.aconfig b/flags/messaging.aconfig
index 1030ba7..63f707f 100644
--- a/flags/messaging.aconfig
+++ b/flags/messaging.aconfig
@@ -38,4 +38,12 @@
     metadata {
         purpose: PURPOSE_BUGFIX
     }
+}
+
+# OWNER=nykkumar TARGET=25Q2
+flag {
+  name: "sms_mms_deliver_broadcasts_redirect_to_main_user"
+  namespace: "telephony"
+  description: "This flag controls the redirection of SMS_DELIVER AND WAP_PUSH_DELIVER broadcasts to the MAIN user."
+  bug: "335820374"
 }
\ No newline at end of file
diff --git a/flags/misc.aconfig b/flags/misc.aconfig
index 4fe925c..538a114 100644
--- a/flags/misc.aconfig
+++ b/flags/misc.aconfig
@@ -228,3 +228,14 @@
         purpose: PURPOSE_BUGFIX
     }
 }
+
+# OWNER=joonhunshin TARGET=24Q4
+flag {
+    name: "use_carrier_config_for_cfnry_time_via_mmi"
+    namespace: "telephony"
+    description: "This flag allows the no reply timer to be referenced in the carrier config when setting up call forward via MMI code and there is no timer value."
+    bug:"342346827"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/proto/Android.bp b/proto/Android.bp
index 15c0aea..adc9b5e 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -31,3 +31,12 @@
     // Pin java_version until jarjar is certified to support later versions. http://b/72703434
     java_version: "1.8",
 }
+
+java_library_static {
+    name: "telephony-config-update-proto-lite",
+    proto: {
+        type: "lite",
+    },
+    srcs: ["src/**/telephony_config_update.proto"],
+    host_supported: true,
+}
diff --git a/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java b/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
index 10a3a32..0c72998 100644
--- a/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
+++ b/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
@@ -152,7 +152,8 @@
         CarrierConfigManager carrierConfigManager = mContext.getSystemService(
                 CarrierConfigManager.class);
         // Callback which directly handle config change should be executed on handler thread
-        carrierConfigManager.registerCarrierConfigChangeListener(this::post,
+        if (carrierConfigManager != null) {
+            carrierConfigManager.registerCarrierConfigChangeListener(this::post,
                 (slotIndex, subId, carrierId, specificCarrierId) -> {
                     if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
                         logd("CarrierConfig changed slotIndex = " + slotIndex + " subId = " + subId
@@ -187,6 +188,7 @@
                         }
                     }
                 });
+        }
         mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
     }
 
diff --git a/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java b/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
index 67be1b6..98d0536 100644
--- a/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
+++ b/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
@@ -346,9 +346,11 @@
         mCarrierConfigManager =
                 (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
         // Callback is executed in handler thread and directly handles carrier config update
-        mCarrierConfigManager.registerCarrierConfigChangeListener(this::post,
-                (slotIndex, subId, carrierId, specificCarrierId) -> handleCarrierConfigUpdated(
-                        subId, slotIndex));
+        if (mCarrierConfigManager != null) {
+            mCarrierConfigManager.registerCarrierConfigChangeListener(this::post,
+                    (slotIndex, subId, carrierId, specificCarrierId) -> handleCarrierConfigUpdated(
+                            subId, slotIndex));
+        }
         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
         mTelephonyRegistryManager =
                 (TelephonyRegistryManager)
@@ -444,7 +446,8 @@
                 CarrierConfigManager.getCarrierConfigSubset(
                         mContext, subId, KEY_CARRIER_CERTIFICATE_STRING_ARRAY);
         // CarrierConfigManager#isConfigForIdentifiedCarrier can handle null or empty bundle
-        if (!mCarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfigs)) {
+        if (mCarrierConfigManager == null
+                || !mCarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfigs)) {
             return Collections.EMPTY_LIST;
         }
 
diff --git a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
index 6b99b56..d47c2c4 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
@@ -116,7 +116,8 @@
         mTelephonyManager = mPhone.getContext().getSystemService(
                 TelephonyManager.class).createForSubscriptionId(mPhone.getSubId());
         CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class);
-        ccm.registerCarrierConfigChangeListener(
+        if (ccm != null) {
+            ccm.registerCarrierConfigChangeListener(
                 mPhone.getContext().getMainExecutor(),
                 (slotIndex, subId, carrierId, specificCarrierId) -> {
                     if (slotIndex != mPhone.getPhoneId()) return;
@@ -143,6 +144,7 @@
                     }
                     handleConfigChanges();
                 });
+        }
 
         // Listen for subscriber changes
         SubscriptionManager.from(mPhone.getContext()).addOnSubscriptionsChangedListener(
diff --git a/src/java/com/android/internal/telephony/CarrierSignalAgent.java b/src/java/com/android/internal/telephony/CarrierSignalAgent.java
index 3250cef..2abe643 100644
--- a/src/java/com/android/internal/telephony/CarrierSignalAgent.java
+++ b/src/java/com/android/internal/telephony/CarrierSignalAgent.java
@@ -130,13 +130,15 @@
         CarrierConfigManager carrierConfigManager = mPhone.getContext().getSystemService(
                 CarrierConfigManager.class);
         loadCarrierConfig();
-        carrierConfigManager.registerCarrierConfigChangeListener(
-                mPhone.getContext().getMainExecutor(),
-                (slotIndex, subId, carrierId, specificCarrierId) -> {
-                    if (slotIndex == mPhone.getPhoneId()) {
-                        loadCarrierConfig();
-                    }
-                });
+        if (carrierConfigManager != null) {
+            carrierConfigManager.registerCarrierConfigChangeListener(
+                    mPhone.getContext().getMainExecutor(),
+                    (slotIndex, subId, carrierId, specificCarrierId) -> {
+                        if (slotIndex == mPhone.getPhoneId()) {
+                            loadCarrierConfig();
+                        }
+                    });
+        }
         mPhone.getCarrierActionAgent().registerForCarrierAction(
                 CarrierActionAgent.CARRIER_ACTION_REPORT_DEFAULT_NETWORK_STATUS, this,
                 EVENT_REGISTER_DEFAULT_NETWORK_AVAIL, null, false);
diff --git a/src/java/com/android/internal/telephony/DeviceStateMonitor.java b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
index 7bdf2ff..e3bf40c 100644
--- a/src/java/com/android/internal/telephony/DeviceStateMonitor.java
+++ b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
@@ -217,7 +217,13 @@
                 public void onDisplayAdded(int displayId) { }
 
                 @Override
-                public void onDisplayRemoved(int displayId) { }
+                public void onDisplayRemoved(int displayId) {
+                    /* adapter for virtual display removed */
+                    boolean screenOn = isScreenOn();
+                    Message msg = obtainMessage(EVENT_SCREEN_STATE_CHANGED);
+                    msg.arg1 = screenOn ? 1 : 0;
+                    sendMessage(msg);
+                }
 
                 @Override
                 public void onDisplayChanged(int displayId) {
diff --git a/src/java/com/android/internal/telephony/DisplayInfoController.java b/src/java/com/android/internal/telephony/DisplayInfoController.java
index e8a0566..d3f0264 100644
--- a/src/java/com/android/internal/telephony/DisplayInfoController.java
+++ b/src/java/com/android/internal/telephony/DisplayInfoController.java
@@ -87,23 +87,26 @@
         mLogTag = "DIC-" + mPhone.getPhoneId();
         mServiceState = mPhone.getServiceStateTracker().getServiceState();
         mConfigs = new PersistableBundle();
+        CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class);
         try {
-            mConfigs = mPhone.getContext().getSystemService(CarrierConfigManager.class)
-                    .getConfigForSubId(mPhone.getSubId(),
-                            CarrierConfigManager.KEY_SHOW_ROAMING_INDICATOR_BOOL);
+            if (ccm != null) {
+                mConfigs = ccm.getConfigForSubId(mPhone.getSubId(),
+                        CarrierConfigManager.KEY_SHOW_ROAMING_INDICATOR_BOOL);
+            }
         } catch (Exception ignored) {
             // CarrierConfigLoader might not be available yet.
             // Once it's available, configs will be updated through the listener.
         }
         mPhone.getServiceStateTracker()
                 .registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED, null);
-        mPhone.getContext().getSystemService(CarrierConfigManager.class)
-                .registerCarrierConfigChangeListener(Runnable::run,
-                        (slotIndex, subId, carrierId, specificCarrierId) -> {
-                            if (slotIndex == mPhone.getPhoneId()) {
-                                obtainMessage(EVENT_CARRIER_CONFIG_CHANGED).sendToTarget();
-                            }
-                        });
+        if (ccm != null) {
+            ccm.registerCarrierConfigChangeListener(Runnable::run,
+                    (slotIndex, subId, carrierId, specificCarrierId) -> {
+                        if (slotIndex == mPhone.getPhoneId()) {
+                            obtainMessage(EVENT_CARRIER_CONFIG_CHANGED).sendToTarget();
+                        }
+                    });
+        }
         mTelephonyDisplayInfo = new TelephonyDisplayInfo(
                 TelephonyManager.NETWORK_TYPE_UNKNOWN,
                 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
diff --git a/src/java/com/android/internal/telephony/MultiSimSettingController.java b/src/java/com/android/internal/telephony/MultiSimSettingController.java
index a14ae89..0436ae5 100644
--- a/src/java/com/android/internal/telephony/MultiSimSettingController.java
+++ b/src/java/com/android/internal/telephony/MultiSimSettingController.java
@@ -247,9 +247,11 @@
 
         CarrierConfigManager ccm = mContext.getSystemService(CarrierConfigManager.class);
         // Listener callback is executed on handler thread to directly handle config change
-        ccm.registerCarrierConfigChangeListener(this::post,
-                (slotIndex, subId, carrierId, specificCarrierId) ->
-                        onCarrierConfigChanged(slotIndex, subId));
+        if (ccm != null) {
+            ccm.registerCarrierConfigChangeListener(this::post,
+                    (slotIndex, subId, carrierId, specificCarrierId) ->
+                            onCarrierConfigChanged(slotIndex, subId));
+        }
 
         mConvertedPsimSubId = getConvertedPsimSubscriptionId();
     }
diff --git a/src/java/com/android/internal/telephony/NetworkRegistrationManager.java b/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
index 91cd4ec..cc2e94d 100644
--- a/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
+++ b/src/java/com/android/internal/telephony/NetworkRegistrationManager.java
@@ -75,17 +75,19 @@
 
         CarrierConfigManager ccm = phone.getContext().getSystemService(CarrierConfigManager.class);
         // Callback directly calls rebindService and should be executed in handler thread
-        ccm.registerCarrierConfigChangeListener(
-                this::post,
-                (slotIndex, subId, carrierId, specificCarrierId) -> {
-                    if (slotIndex == phone.getPhoneId()) {
-                        // We should wait for carrier config changed event because the target
-                        // binding package name can come from the carrier config. Note that
-                        // we still get this event even when SIM is absent.
-                        logd("Carrier config changed. Try to bind network service.");
-                        rebindService();
-                    }
-                });
+        if (ccm != null) {
+            ccm.registerCarrierConfigChangeListener(
+                    this::post,
+                    (slotIndex, subId, carrierId, specificCarrierId) -> {
+                        if (slotIndex == phone.getPhoneId()) {
+                            // We should wait for carrier config changed event because the target
+                            // binding package name can come from the carrier config. Note that
+                            // we still get this event even when SIM is absent.
+                            logd("Carrier config changed. Try to bind network service.");
+                            rebindService();
+                        }
+                    });
+        }
 
         PhoneConfigurationManager.registerForMultiSimConfigChange(
                 this, EVENT_BIND_NETWORK_SERVICE, null);
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index 67ca1e1..2078cd9 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -315,7 +315,9 @@
         filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
         mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
         CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class);
-        ccm.registerCarrierConfigChangeListener(Runnable::run, mCarrierConfigChangeListener);
+        if (ccm != null) {
+            ccm.registerCarrierConfigChangeListener(Runnable::run, mCarrierConfigChangeListener);
+        }
     }
 
     private void unRegisterForAllEvents() {
@@ -327,7 +329,7 @@
                 mDataNetworkControllerCallback);
         mPhone.getContext().unregisterReceiver(mIntentReceiver);
         CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class);
-        if (mCarrierConfigChangeListener != null) {
+        if (ccm != null && mCarrierConfigChangeListener != null) {
             ccm.unregisterCarrierConfigChangeListener(mCarrierConfigChangeListener);
         }
     }
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 2a9bf7f..72c8cd3 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -666,7 +666,9 @@
         mCarrierConfig = getCarrierConfig();
         CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class);
         // Callback which directly handle config change should be executed in handler thread
-        ccm.registerCarrierConfigChangeListener(this::post, mCarrierConfigChangeListener);
+        if (ccm != null) {
+            ccm.registerCarrierConfigChangeListener(this::post, mCarrierConfigChangeListener);
+        }
 
         mAccessNetworksManager = mPhone.getAccessNetworksManager();
         mOutOfServiceSS = new ServiceState();
diff --git a/src/java/com/android/internal/telephony/SignalStrengthController.java b/src/java/com/android/internal/telephony/SignalStrengthController.java
index 98f84b2..31e1950 100644
--- a/src/java/com/android/internal/telephony/SignalStrengthController.java
+++ b/src/java/com/android/internal/telephony/SignalStrengthController.java
@@ -164,9 +164,11 @@
         CarrierConfigManager ccm = mPhone.getContext().getSystemService(CarrierConfigManager.class);
         mCarrierConfig = getCarrierConfig();
         // Callback which directly handle config change should be executed on handler thread
-        ccm.registerCarrierConfigChangeListener(this::post,
-                (slotIndex, subId, carrierId, specificCarrierId) ->
-                        onCarrierConfigurationChanged(slotIndex));
+        if (ccm != null) {
+            ccm.registerCarrierConfigChangeListener(this::post,
+                    (slotIndex, subId, carrierId, specificCarrierId) ->
+                            onCarrierConfigurationChanged(slotIndex));
+        }
 
         mPhone.registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED, null);
     }
diff --git a/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java b/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
index 077ee0b..0893b75 100644
--- a/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
+++ b/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
@@ -296,7 +296,8 @@
         int subId = SubscriptionManager.getDefaultSmsSubscriptionId();
         CarrierConfigManager configManager =
                 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
-        PersistableBundle bundle = configManager.getConfigForSubId(subId);
+        PersistableBundle bundle = null;
+        if (configManager != null) bundle = configManager.getConfigForSubId(subId);
 
         if (bundle != null) {
             return bundle.getLong(CarrierConfigManager.KEY_UNDELIVERED_SMS_MESSAGE_EXPIRATION_TIME,
diff --git a/src/java/com/android/internal/telephony/data/AccessNetworksManager.java b/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
index bc684af..1bbc692 100644
--- a/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
+++ b/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
@@ -414,15 +414,19 @@
 
         // bindQualifiedNetworksService posts real work to handler thread. So here we can
         // let the callback execute in binder thread to avoid post twice.
-        mCarrierConfigManager.registerCarrierConfigChangeListener(Runnable::run,
-                (slotIndex, subId, carrierId, specificCarrierId) -> {
-                    if (slotIndex != mPhone.getPhoneId()) return;
-                    // We should wait for carrier config changed event because the target binding
-                    // package name can come from the carrier config. Note that we still get this
-                    // event even when SIM is absent.
-                    if (DBG) log("Carrier config changed. Try to bind qualified network service.");
-                    bindQualifiedNetworksService();
-                });
+        if (mCarrierConfigManager != null) {
+            mCarrierConfigManager.registerCarrierConfigChangeListener(Runnable::run,
+                    (slotIndex, subId, carrierId, specificCarrierId) -> {
+                        if (slotIndex != mPhone.getPhoneId()) return;
+                        // We should wait for carrier config changed event because the target
+                        // binding package name can come from the carrier config. Note that we still
+                        // get this event even when SIM is absent.
+                        if (DBG) {
+                            log("Carrier config changed. Try to bind qualified network service.");
+                        }
+                        bindQualifiedNetworksService();
+                    });
+        }
         bindQualifiedNetworksService();
 
         // Using post to delay the registering because data retry manager and data config
diff --git a/src/java/com/android/internal/telephony/data/DataConfigManager.java b/src/java/com/android/internal/telephony/data/DataConfigManager.java
index 20761e2..a5db8fb 100644
--- a/src/java/com/android/internal/telephony/data/DataConfigManager.java
+++ b/src/java/com/android/internal/telephony/data/DataConfigManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.StringDef;
 import android.content.res.Resources;
 import android.net.LinkProperties;
@@ -272,7 +273,7 @@
     private final String mLogTag;
     @NonNull
     private final FeatureFlags mFeatureFlags;
-    @NonNull
+    @Nullable
     private final CarrierConfigManager mCarrierConfigManager;
     @NonNull
     private PersistableBundle mCarrierConfig = null;
@@ -355,12 +356,14 @@
 
         mCarrierConfigManager = mPhone.getContext().getSystemService(CarrierConfigManager.class);
         // Callback send msg to handler thread, so callback itself can be executed in binder thread.
-        mCarrierConfigManager.registerCarrierConfigChangeListener(Runnable::run,
-                (slotIndex, subId, carrierId, specificCarrierId) -> {
-                    if (slotIndex == mPhone.getPhoneId()) {
-                        sendEmptyMessage(EVENT_CARRIER_CONFIG_CHANGED);
-                    }
-                });
+        if (mCarrierConfigManager != null) {
+            mCarrierConfigManager.registerCarrierConfigChangeListener(Runnable::run,
+                    (slotIndex, subId, carrierId, specificCarrierId) -> {
+                        if (slotIndex == mPhone.getPhoneId()) {
+                            sendEmptyMessage(EVENT_CARRIER_CONFIG_CHANGED);
+                        }
+                    });
+        }
 
         // Register for device config update
         DeviceConfig.addOnPropertiesChangedListener(
@@ -1503,6 +1506,14 @@
     }
 
     /**
+     * {@code True} enables mms to be attempted on iwlan if possible, even if existing cellular
+     *  networks already supports iwlan.
+     */
+    public boolean isForceIwlanMmsFeatureEnabled() {
+        return mResources.getBoolean(com.android.internal.R.bool.force_iwlan_mms_feature_enabled);
+    }
+
+    /**
      * Log debug messages.
      * @param s debug messages
      */
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java
index eaa0962..f47abfc 100644
--- a/src/java/com/android/internal/telephony/data/DataNetwork.java
+++ b/src/java/com/android/internal/telephony/data/DataNetwork.java
@@ -1266,7 +1266,7 @@
                         getHandler(), EVENT_VOICE_CALL_ENDED, null);
             }
 
-            if (mFlags.forceIwlanMms()) {
+            if (mFlags.forceIwlanMms() && mDataConfigManager.isForceIwlanMmsFeatureEnabled()) {
                 if (mDataProfile.canSatisfy(NetworkCapabilities.NET_CAPABILITY_MMS)) {
                     mAccessNetworksManagerCallback = new AccessNetworksManagerCallback(
                             getHandler()::post) {
@@ -1292,7 +1292,8 @@
         @Override
         public void exit() {
             logv("Unregistering all events.");
-            if (mFlags.forceIwlanMms() && mAccessNetworksManagerCallback != null) {
+            if (mFlags.forceIwlanMms() && mAccessNetworksManagerCallback != null
+                    && mDataConfigManager.isForceIwlanMmsFeatureEnabled()) {
                 mAccessNetworksManager.unregisterCallback(mAccessNetworksManagerCallback);
             }
 
@@ -2491,7 +2492,8 @@
         // will be attempted on IWLAN if possible, even if existing cellular networks already
         // supports IWLAN.
         if (mFlags.forceIwlanMms() && builder.build()
-                .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+                .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
+                && mDataConfigManager.isForceIwlanMmsFeatureEnabled()) {
             // If QNS sets MMS preferred on IWLAN, and it is possible to setup an MMS network on
             // IWLAN, then we need to remove the MMS capability on the cellular network. This will
             // allow the new MMS network to be brought up on IWLAN when MMS network request arrives.
diff --git a/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java b/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
index fddeb06..c3276b2 100644
--- a/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
+++ b/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
@@ -50,6 +50,7 @@
 import com.android.internal.telephony.IWwanSelectorResultCallback;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.data.AccessNetworksManager.QualifiedNetworks;
+import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.io.PrintWriter;
@@ -185,7 +186,10 @@
                     return;
                 }
                 DomainSelectionConnection.this.onSelectionTerminated(cause);
-                dispose();
+                if (!Flags.hangupEmergencyCallForCrossSimRedialing()
+                        || !mIsEmergency || !checkState(STATUS_DOMAIN_SELECTED)) {
+                    dispose();
+                }
             }
         }
     }
diff --git a/src/java/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnection.java b/src/java/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnection.java
index 66b977d..4153c93 100644
--- a/src/java/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnection.java
+++ b/src/java/com/android/internal/telephony/domainselection/EmergencyCallDomainSelectionConnection.java
@@ -47,6 +47,7 @@
 import com.android.internal.telephony.data.AccessNetworksManager;
 import com.android.internal.telephony.data.AccessNetworksManager.QualifiedNetworks;
 import com.android.internal.telephony.emergency.EmergencyStateTracker;
+import com.android.internal.telephony.flags.Flags;
 
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
@@ -198,6 +199,32 @@
         super.cancelSelection();
     }
 
+    @Override
+    public @NonNull CompletableFuture<Integer> reselectDomain(
+        @NonNull DomainSelectionService.SelectionAttributes attr) {
+        if (Flags.hangupEmergencyCallForCrossSimRedialing()) {
+            int disconnectCause = getDisconnectCause();
+            int preciseDisconnectCause = attr.getCsDisconnectCause();
+            if (disconnectCause == android.telephony.DisconnectCause.EMERGENCY_TEMP_FAILURE) {
+                preciseDisconnectCause = PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE;
+            } else if (disconnectCause
+                    == android.telephony.DisconnectCause.EMERGENCY_PERM_FAILURE) {
+                preciseDisconnectCause = PreciseDisconnectCause.EMERGENCY_PERM_FAILURE;
+            }
+            if (preciseDisconnectCause != attr.getCsDisconnectCause()) {
+                attr = EmergencyCallDomainSelectionConnection.getSelectionAttributes(
+                        attr.getSlotIndex(), attr.getSubscriptionId(),
+                        attr.isExitedFromAirplaneMode(), attr.getCallId(),
+                        (attr.getAddress() != null)
+                        ? attr.getAddress().getSchemeSpecificPart() : "",
+                        attr.isTestEmergencyNumber(), preciseDisconnectCause,
+                        attr.getPsDisconnectCause(),
+                        attr.getEmergencyRegistrationResult());
+            }
+        }
+        return super.reselectDomain(attr);
+    }
+
     /**
      * Returns the attributes required to determine the domain for a telephony service.
      *
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index 10cbe77..cb188ea 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -1016,8 +1016,8 @@
 
         // Only look at the Network portion for mmi
         String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString);
-        ImsPhoneMmiCode mmi =
-                ImsPhoneMmiCode.newFromDialString(networkPortion, this, wrappedCallback);
+        ImsPhoneMmiCode mmi =  ImsPhoneMmiCode.newFromDialString(networkPortion, this,
+                wrappedCallback, mFeatureFlags);
         if (DBG) logd("dialInternal: dialing w/ mmi '" + mmi + "'...");
 
         if (mmi == null) {
@@ -1440,12 +1440,13 @@
     }
 
     @Override
-    public void sendUssdResponse(String ussdMessge) {
+    public void sendUssdResponse(String ussdMessage) {
         logd("sendUssdResponse");
-        ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newFromUssdUserInput(ussdMessge, this);
+        ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newFromUssdUserInput(ussdMessage, this,
+                mFeatureFlags);
         mPendingMMIs.add(mmi);
         mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
-        mmi.sendUssd(ussdMessge);
+        mmi.sendUssd(ussdMessage);
     }
 
     public void sendUSSD(String ussdString, Message response) {
@@ -1575,14 +1576,12 @@
                 // also, discard if there is no message to present
                 ImsPhoneMmiCode mmi;
                 mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(ussdMessage,
-                        isUssdRequest,
-                        this);
+                        isUssdRequest, this, mFeatureFlags);
                 onNetworkInitiatedUssd(mmi);
         } else if (isUssdError) {
             ImsPhoneMmiCode mmi;
             mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(ussdMessage,
-                    true,
-                    this);
+                    true, this, mFeatureFlags);
             mmi.onUssdFinishedError();
         }
     }
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index 7fd970b..b2966b6 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -4959,7 +4959,7 @@
             }
             case EVENT_SUPP_SERVICE_INDICATION: {
                 ar = (AsyncResult) msg.obj;
-                ImsPhoneMmiCode mmiCode = new ImsPhoneMmiCode(mPhone);
+                ImsPhoneMmiCode mmiCode = new ImsPhoneMmiCode(mPhone, mFeatureFlags);
                 try {
                     mmiCode.setIsSsInfo(true);
                     mmiCode.processImsSsData(ar);
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
index 25fa8a2..d573f5d 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
@@ -63,6 +63,7 @@
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.MmiCode;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.gsm.GsmMmiCode;
 import com.android.internal.telephony.uicc.IccRecords;
 import com.android.telephony.Rlog;
@@ -165,6 +166,9 @@
     private static final int NUM_PRESENTATION_ALLOWED     = 0;
     private static final int NUM_PRESENTATION_RESTRICTED  = 1;
 
+    // Using same value with CallForwardEditPreference#DEFAULT_NO_REPLY_TIMER_FOR_CFNRY
+    private static final int DEFAULT_NO_REPLY_TIMER_FOR_CFNRY = 20;
+
     //***** Supplementary Service Query Bundle Keys
     // Used by IMS Service layer to put supp. serv. query
     // responses into the ssInfo Bundle.
@@ -245,6 +249,8 @@
     private static final int MATCH_GROUP_DIALING_NUMBER = 12;
     static private String[] sTwoDigitNumberPattern;
 
+    private final FeatureFlags mFeatureFlags;
+
     //***** Public Class methods
 
     /**
@@ -262,12 +268,13 @@
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     @VisibleForTesting
-    public static ImsPhoneMmiCode newFromDialString(String dialString, ImsPhone phone) {
-       return newFromDialString(dialString, phone, null);
+    public static ImsPhoneMmiCode newFromDialString(String dialString, ImsPhone phone,
+            FeatureFlags featureFlags) {
+        return newFromDialString(dialString, phone, null, featureFlags);
     }
 
-    static ImsPhoneMmiCode newFromDialString(String dialString,
-                                             ImsPhone phone, ResultReceiver wrappedCallback) {
+    static ImsPhoneMmiCode newFromDialString(String dialString, ImsPhone phone,
+            ResultReceiver wrappedCallback, FeatureFlags featureFlags) {
         Matcher m;
         ImsPhoneMmiCode ret = null;
 
@@ -287,7 +294,7 @@
 
         // Is this formatted like a standard supplementary service code?
         if (m.matches()) {
-            ret = new ImsPhoneMmiCode(phone);
+            ret = new ImsPhoneMmiCode(phone, featureFlags);
             ret.mPoundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING));
             ret.mAction = makeEmptyNull(m.group(MATCH_GROUP_ACTION));
             ret.mSc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE));
@@ -305,7 +312,7 @@
             if (ret.mDialingNumber != null &&
                     ret.mDialingNumber.endsWith("#") &&
                     dialString.endsWith("#")){
-                ret = new ImsPhoneMmiCode(phone);
+                ret = new ImsPhoneMmiCode(phone, featureFlags);
                 ret.mPoundString = dialString;
             }
         } else if (dialString.endsWith("#")) {
@@ -313,7 +320,7 @@
             // "Entry of any characters defined in the 3GPP TS 23.038 [8] Default Alphabet
             // (up to the maximum defined in 3GPP TS 24.080 [10]), followed by #SEND".
 
-            ret = new ImsPhoneMmiCode(phone);
+            ret = new ImsPhoneMmiCode(phone, featureFlags);
             ret.mPoundString = dialString;
         } else if (GsmMmiCode.isTwoDigitShortCode(phone.getContext(), phone.getSubId(),
                 dialString)) {
@@ -321,7 +328,7 @@
             ret = null;
         } else if (isShortCode(dialString, phone)) {
             // this may be a short code, as defined in TS 22.030, 6.5.3.2
-            ret = new ImsPhoneMmiCode(phone);
+            ret = new ImsPhoneMmiCode(phone, featureFlags);
             ret.mDialingNumber = dialString;
         }
         return ret;
@@ -348,10 +355,10 @@
     }
 
     public static ImsPhoneMmiCode newNetworkInitiatedUssd(String ussdMessage,
-            boolean isUssdRequest, ImsPhone phone) {
+            boolean isUssdRequest, ImsPhone phone, FeatureFlags featureFlags) {
         ImsPhoneMmiCode ret;
 
-        ret = new ImsPhoneMmiCode(phone);
+        ret = new ImsPhoneMmiCode(phone, featureFlags);
 
         ret.mMessage = ussdMessage;
         ret.mIsUssdRequest = isUssdRequest;
@@ -368,10 +375,11 @@
         return ret;
     }
 
-    static ImsPhoneMmiCode newFromUssdUserInput(String ussdMessge, ImsPhone phone) {
-        ImsPhoneMmiCode ret = new ImsPhoneMmiCode(phone);
+    static ImsPhoneMmiCode newFromUssdUserInput(String ussdMessage, ImsPhone phone,
+            FeatureFlags featureFlags) {
+        ImsPhoneMmiCode ret = new ImsPhoneMmiCode(phone, featureFlags);
 
-        ret.mMessage = ussdMessge;
+        ret.mMessage = ussdMessage;
         ret.mState = State.PENDING;
         ret.mIsPendingUSSD = true;
 
@@ -584,13 +592,15 @@
 
     //***** Constructor
 
-    public ImsPhoneMmiCode(ImsPhone phone) {
+    public ImsPhoneMmiCode(ImsPhone phone, FeatureFlags featureFlags) {
         // The telephony unit-test cases may create ImsPhoneMmiCode's
         // in secondary threads
         super(phone.getHandler().getLooper());
         mPhone = phone;
         mContext = phone.getContext();
         mIccRecords = mPhone.mDefaultPhone.getIccRecords();
+
+        mFeatureFlags = featureFlags;
     }
 
     //***** MmiCode implementation
@@ -907,7 +917,19 @@
                 String dialingNumber = mSia;
                 int reason = scToCallForwardReason(mSc);
                 int serviceClass = siToServiceClass(mSib);
-                int time = siToTime(mSic);
+                int time;
+
+                if (mFeatureFlags.useCarrierConfigForCfnryTimeViaMmi()) {
+                    // If the code is CFNRy and time is null(empty)
+                    // use the default time value from CarrierConfig
+                    if (mSc.equals(SC_CFNRy) && isEmptyOrNull(mSic)) {
+                        time = getCfnryTime();
+                    } else {
+                        time = siToTime(mSic);
+                    }
+                } else {
+                    time = siToTime(mSic);
+                }
 
                 if (isInterrogate()) {
                     mPhone.getCallForwardingOption(reason, serviceClass,
@@ -1147,6 +1169,27 @@
         }
     }
 
+    private int getCfnryTime() {
+        CarrierConfigManager configManager = mContext.getSystemService(CarrierConfigManager.class);
+        if (configManager == null) {
+            return DEFAULT_NO_REPLY_TIMER_FOR_CFNRY;
+        }
+
+        PersistableBundle carrierConfig = configManager.getConfigForSubId(mPhone.getSubId());
+        if (carrierConfig == null
+                || !carrierConfig.getBoolean(
+                        CarrierConfigManager.KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL, true)) {
+            return DEFAULT_NO_REPLY_TIMER_FOR_CFNRY;
+        }
+
+        int time = carrierConfig.getInt(
+                CarrierConfigManager.KEY_NO_REPLY_TIMER_FOR_CFNRY_SEC_INT,
+                DEFAULT_NO_REPLY_TIMER_FOR_CFNRY);
+
+        Rlog.d(LOG_TAG, "getCfnryTime: " + time);
+        return time;
+    }
+
     private boolean isUssdOverImsAllowed() {
         if (mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_allow_ussd_over_ims)) {
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index ea94624..ca83953 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -573,8 +573,10 @@
         mCarrierConfigChangeListener =
                 (slotIndex, subId, carrierId, specificCarrierId) ->
                         handleCarrierConfigChanged(slotIndex, subId, carrierId, specificCarrierId);
-        mCarrierConfigManager.registerCarrierConfigChangeListener(
-                        new HandlerExecutor(new Handler(looper)), mCarrierConfigChangeListener);
+        if (mCarrierConfigManager != null) {
+            mCarrierConfigManager.registerCarrierConfigChangeListener(
+                    new HandlerExecutor(new Handler(looper)), mCarrierConfigChangeListener);
+        }
 
         mConfigDataUpdatedCallback = new ConfigProviderAdaptor.Callback() {
             @Override
@@ -3004,8 +3006,9 @@
             return true;
         }
 
-        if (getWwanIsInService(serviceState)) {
-            // Device is connected to terrestrial network which has coverage
+        if (getWwanIsInService(serviceState)
+                || serviceState.getState() == ServiceState.STATE_POWER_OFF) {
+            // Device is connected to terrestrial network which has coverage or radio is turned off
             resetCarrierRoamingSatelliteModeParams(subId);
             return false;
         }
@@ -4070,15 +4073,18 @@
     }
 
     @NonNull private PersistableBundle getConfigForSubId(int subId) {
-        PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId,
-                KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
-                KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
-                KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT,
-                KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
-                KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY,
-                KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL,
-                KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT,
-                KEY_SATELLITE_ESOS_SUPPORTED_BOOL);
+        PersistableBundle config = null;
+        if (mCarrierConfigManager != null) {
+            config = mCarrierConfigManager.getConfigForSubId(subId,
+                    KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                    KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                    KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT,
+                    KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
+                    KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY,
+                    KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL,
+                    KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT,
+                    KEY_SATELLITE_ESOS_SUPPORTED_BOOL);
+        }
         if (config == null || config.isEmpty()) {
             config = CarrierConfigManager.getDefaultConfig();
         }
@@ -4537,7 +4543,8 @@
                     }
                 } else {
                     Boolean connected = mWasSatelliteConnectedViaCarrier.get(subId);
-                    if (getWwanIsInService(serviceState)) {
+                    if (getWwanIsInService(serviceState)
+                            || serviceState.getState() == ServiceState.STATE_POWER_OFF) {
                         resetCarrierRoamingSatelliteModeParams(subId);
                     } else if (connected != null && connected) {
                         // The device just got disconnected from a satellite network
@@ -5311,7 +5318,7 @@
                                 + "subscriberId.");
                         continue;
                     }
-                    list.add(new ProvisionSubscriberId(subscriberId, carrierId));
+                    list.add(new ProvisionSubscriberId(subscriberId, carrierId, ""));
                     mSubscriberIdPerSub.put(subscriberId, info.getSubscriptionId());
                 }
             }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index 7f3eb0f..a0e186b 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -44,6 +44,7 @@
 import android.provider.DeviceConfig;
 import android.telecom.Connection;
 import android.telephony.AccessNetworkConstants;
+import android.telephony.CellIdentity;
 import android.telephony.DropBoxManagerLoggerBackend;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PersistentLogger;
@@ -465,11 +466,13 @@
         return false;
     }
 
-    private boolean isSatellitePlmn(int subId, @NonNull ServiceState serviceState) {
+    /** Check whether device is connected to satellite PLMN */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public boolean isSatellitePlmn(int subId, @NonNull ServiceState serviceState) {
         List<String> satellitePlmnList =
                 mSatelliteController.getSatellitePlmnsForCarrier(subId);
         if (satellitePlmnList.isEmpty()) {
-            logv("isSatellitePlmn: satellitePlmnList is empty");
+            plogd("isSatellitePlmn: satellitePlmnList is empty");
             return false;
         }
 
@@ -477,19 +480,23 @@
                 serviceState.getNetworkRegistrationInfoListForTransportType(
                         AccessNetworkConstants.TRANSPORT_TYPE_WWAN)) {
             String registeredPlmn = nri.getRegisteredPlmn();
-            String mccmnc = nri.getCellIdentity().getMccString()
-                    + nri.getCellIdentity().getMncString();
+            if (TextUtils.isEmpty(registeredPlmn)) {
+                plogd("isSatellitePlmn: registeredPlmn is empty");
+                continue;
+            }
+
+            String mccmnc = getMccMnc(nri);
             for (String satellitePlmn : satellitePlmnList) {
                 if (TextUtils.equals(satellitePlmn, registeredPlmn)
                         || TextUtils.equals(satellitePlmn, mccmnc)) {
-                    logv("isSatellitePlmn: return true, satellitePlmn:" + satellitePlmn
+                    plogd("isSatellitePlmn: return true, satellitePlmn:" + satellitePlmn
                             + " registeredPlmn:" + registeredPlmn + " mccmnc:" + mccmnc);
                     return true;
                 }
             }
         }
 
-        logv("isSatellitePlmn: return false");
+        plogd("isSatellitePlmn: return false");
         return false;
     }
 
@@ -829,6 +836,24 @@
         }
     }
 
+    @Nullable
+    private String getMccMnc(@NonNull NetworkRegistrationInfo nri) {
+        CellIdentity cellIdentity = nri.getCellIdentity();
+        if (cellIdentity == null) {
+            plogd("getMccMnc: cellIdentity is null");
+            return null;
+        }
+
+        String mcc = cellIdentity.getMccString();
+        String mnc = cellIdentity.getMncString();
+        if (mcc == null || mnc == null) {
+            plogd("getMccMnc: mcc or mnc is null. mcc=" + mcc + " mnc=" + mnc);
+            return null;
+        }
+
+        return mcc + mnc;
+    }
+
     private void plogd(@NonNull String log) {
         Rlog.d(TAG, log);
         if (mPersistentLogger != null) {
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
index e6928b9..30cf3ad 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -1937,7 +1937,10 @@
                     + "carrier privilege");
         }
 
-        enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfo");
+        if (!mContext.getResources().getBoolean(
+                    com.android.internal.R.bool.config_force_phone_globals_creation)) {
+            enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfo");
+        }
 
         SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
                 .getSubscriptionInfoInternal(subId);
@@ -2066,7 +2069,10 @@
             return Collections.emptyList();
         }
 
-        enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfoList");
+        if (!mContext.getResources().getBoolean(
+                    com.android.internal.R.bool.config_force_phone_globals_creation)) {
+            enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfoList");
+        }
 
         if (isForAllProfiles) {
             enforcePermissionAccessAllUserProfiles();
@@ -2158,7 +2164,11 @@
         enforcePermissions("getAvailableSubscriptionInfoList",
                 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
 
-        enforceTelephonyFeatureWithException(callingPackage, "getAvailableSubscriptionInfoList");
+        if (!mContext.getResources().getBoolean(
+                    com.android.internal.R.bool.config_force_phone_globals_creation)) {
+            enforceTelephonyFeatureWithException(callingPackage,
+                    "getAvailableSubscriptionInfoList");
+        }
 
         return getAvailableSubscriptionsInternalStream()
                 .sorted(Comparator.comparing(SubscriptionInfoInternal::getSimSlotIndex)
@@ -2742,7 +2752,10 @@
             return Collections.emptyList();
         }
 
-        enforceTelephonyFeatureWithException(callingPackage, "getOpportunisticSubscriptions");
+        if (!mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_force_phone_globals_creation)) {
+            enforceTelephonyFeatureWithException(callingPackage, "getOpportunisticSubscriptions");
+        }
 
         return mSubscriptionDatabaseManager.getAllSubscriptions().stream()
                 // callers have READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE can get a full
@@ -3315,7 +3328,10 @@
     public int[] getActiveSubIdList(boolean visibleOnly) {
         enforcePermissions("getActiveSubIdList", Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
 
-        enforceTelephonyFeatureWithException(getCurrentPackageName(), "getActiveSubIdList");
+        if (!mContext.getResources().getBoolean(
+                    com.android.internal.R.bool.config_force_phone_globals_creation)) {
+            enforceTelephonyFeatureWithException(getCurrentPackageName(), "getActiveSubIdList");
+        }
 
         // UserHandle.ALL because this API is exposed as system API.
         return getActiveSubIdListAsUser(visibleOnly, UserHandle.ALL);
@@ -4498,9 +4514,16 @@
      */
     @NonNull
     private String getCallingPackage() {
-        if (Binder.getCallingUid() == Process.PHONE_UID) {
-            // Too many packages running with phone uid. Just return one here.
-            return "com.android.phone";
+        if (Flags.supportPhoneUidCheckForMultiuser()) {
+            if (UserHandle.isSameApp(Binder.getCallingUid(), Process.PHONE_UID)) {
+                // Too many packages running with phone uid. Just return one here.
+                return "com.android.phone";
+            }
+        } else {
+            if (Binder.getCallingUid() == Process.PHONE_UID) {
+                // Too many packages running with phone uid. Just return one here.
+                return "com.android.phone";
+            }
         }
         return Arrays.toString(mContext.getPackageManager().getPackagesForUid(
                 Binder.getCallingUid()));
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index 3e447a9..b8dc786 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
@@ -329,6 +329,10 @@
         mContextFixture.putStringArrayResource(
                 com.android.internal.R.array.config_serviceStateLocationAllowedPackages,
                 new String[0]);
+
+        UserInfo userInfo = new UserInfo(UserHandle.myUserId(), "" /* name */, 0 /* flags */);
+        doReturn(userInfo.id).when(mIActivityManager).getCurrentUserId();
+
         processAllMessages();
         assertEquals(mTelephonyRegistry.asBinder(),
                 ServiceManager.getService("telephony.registry"));
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
index 8be0f8b..1a5c1af 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
@@ -2419,6 +2419,7 @@
     @Test
     public void testMmsCapabilityRemovedWhenMmsPreferredOnIwlan() throws Exception {
         doReturn(true).when(mFeatureFlags).forceIwlanMms();
+        doReturn(true).when(mDataConfigManager).isForceIwlanMmsFeatureEnabled();
         setupDataNetwork();
 
         TelephonyNetworkAgent mockNetworkAgent = Mockito.mock(TelephonyNetworkAgent.class);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
index 3c1b045..6f42350 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
@@ -19,10 +19,13 @@
 import static junit.framework.Assert.fail;
 
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import android.os.AsyncResult;
@@ -35,6 +38,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.TelephonyTest;
 import com.android.internal.telephony.flags.FeatureFlags;
 
@@ -54,6 +58,9 @@
     private static final String TEST_DIAL_STRING_SERVICE_CODE = "*67911";
     private static final String TEST_DIAL_STRING_NO_SERVICE_CODE = "*767911";
     private static final String TEST_DIAL_STRING_NON_EMERGENCY_NUMBER = "11976";
+    private static final String TEST_DIAL_NUMBER = "123456789";
+    private static final String TEST_DIAL_STRING_CFNRY_ACTIVE_CODE = "**61*" + TEST_DIAL_NUMBER;
+    private static final String TEST_DIAL_STRING_CFNRY_DEACTIVE_CODE = "##61#";
     private ImsPhoneMmiCode mImsPhoneMmiCode;
     private ImsPhone mImsPhoneUT;
 
@@ -90,7 +97,7 @@
         // Test *67911 is treated as temporary mode CLIR
         doReturn(true).when(mTelephonyManager).isEmergencyNumber(TEST_DIAL_STRING_SERVICE_CODE);
         mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(TEST_DIAL_STRING_SERVICE_CODE,
-                mImsPhoneUT);
+                mImsPhoneUT, mFeatureFlags);
         assertTrue(mImsPhoneMmiCode.isTemporaryModeCLIR());
     }
 
@@ -99,7 +106,7 @@
         // Test if prefix isn't *67 or *82
         doReturn(true).when(mTelephonyManager).isEmergencyNumber(TEST_DIAL_STRING_NO_SERVICE_CODE);
         mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(TEST_DIAL_STRING_NO_SERVICE_CODE,
-                mImsPhoneUT);
+                mImsPhoneUT, mFeatureFlags);
         assertTrue(mImsPhoneMmiCode == null);
     }
 
@@ -107,13 +114,14 @@
     public void testIsTemporaryModeCLIRForNonEmergencyNumber() {
         // Test if dialing string isn't an emergency number
         mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(TEST_DIAL_STRING_NON_EMERGENCY_NUMBER,
-                mImsPhoneUT);
+                mImsPhoneUT, mFeatureFlags);
         assertTrue(mImsPhoneMmiCode == null);
     }
 
     @Test
     public void testNoCrashOnEmptyMessage() {
-        ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(null, true, mImsPhoneUT);
+        ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(null, true, mImsPhoneUT,
+                mFeatureFlags);
         try {
             mmi.onUssdFinishedError();
         } catch (Exception e) {
@@ -134,7 +142,8 @@
     @Test
     @SmallTest
     public void testOperationNotSupported() {
-        mImsPhoneMmiCode = ImsPhoneMmiCode.newNetworkInitiatedUssd(null, true, mImsPhoneUT);
+        mImsPhoneMmiCode = ImsPhoneMmiCode.newNetworkInitiatedUssd(null, true, mImsPhoneUT,
+                mFeatureFlags);
 
         // Emulate request not supported from the network.
         AsyncResult ar = new AsyncResult(null, null,
@@ -143,4 +152,80 @@
         verify(mContext.getResources()).getText(
                 eq(com.android.internal.R.string.mmiErrorNotSupported));
     }
+
+    @Test
+    @SmallTest
+    public void testActivationCfnrWithCfnry() throws Exception {
+        doNothing().when(mImsPhone).setCallForwardingOption(
+                anyInt(), anyInt(), any(), anyInt(), anyInt(), any());
+
+        doReturn(true).when(mFeatureFlags).useCarrierConfigForCfnryTimeViaMmi();
+
+        int carrierConfigTime = 40;
+        PersistableBundle bundle = new PersistableBundle();
+        bundle.putInt(CarrierConfigManager
+                .KEY_NO_REPLY_TIMER_FOR_CFNRY_SEC_INT, carrierConfigTime);
+        doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
+
+        int mmiTime = 30;
+        String withoutTimeCode = TEST_DIAL_STRING_CFNRY_ACTIVE_CODE + "#";
+        String withTimeCode = TEST_DIAL_STRING_CFNRY_ACTIVE_CODE + "**" + mmiTime + "#";
+
+        mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(withoutTimeCode, mImsPhoneUT,
+                mFeatureFlags);
+        // For verification, replace the internal object of target with mock
+        replaceInstance(ImsPhoneMmiCode.class, "mPhone", mImsPhoneMmiCode, mImsPhone);
+
+        mImsPhoneMmiCode.processCode();
+        verify(mImsPhone, times(1)).setCallForwardingOption(
+                eq(CommandsInterface.CF_ACTION_REGISTRATION),
+                anyInt(),
+                eq(TEST_DIAL_NUMBER),
+                anyInt(),
+                eq(carrierConfigTime),
+                any());
+
+        mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(withTimeCode, mImsPhoneUT,
+                mFeatureFlags);
+        // For verification, replace the internal object of target with mock
+        replaceInstance(ImsPhoneMmiCode.class, "mPhone", mImsPhoneMmiCode, mImsPhone);
+
+        mImsPhoneMmiCode.processCode();
+        verify(mImsPhone, times(1)).setCallForwardingOption(
+                eq(CommandsInterface.CF_ACTION_REGISTRATION),
+                anyInt(),
+                eq(TEST_DIAL_NUMBER),
+                anyInt(),
+                eq(mmiTime),
+                any());
+    }
+
+    @Test
+    @SmallTest
+    public void testDeactivationCfnrWithCfnry() throws Exception {
+        doNothing().when(mImsPhone).setCallForwardingOption(
+                anyInt(), anyInt(), any(), anyInt(), anyInt(), any());
+
+        doReturn(true).when(mFeatureFlags).useCarrierConfigForCfnryTimeViaMmi();
+
+        int carrierConfigTime = 40;
+        PersistableBundle bundle = new PersistableBundle();
+        bundle.putInt(CarrierConfigManager
+                .KEY_NO_REPLY_TIMER_FOR_CFNRY_SEC_INT, carrierConfigTime);
+        doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
+
+        mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(TEST_DIAL_STRING_CFNRY_DEACTIVE_CODE,
+                mImsPhoneUT, mFeatureFlags);
+        // For verification, replace the internal object of target with mock
+        replaceInstance(ImsPhoneMmiCode.class, "mPhone", mImsPhoneMmiCode, mImsPhone);
+
+        mImsPhoneMmiCode.processCode();
+        verify(mImsPhone, times(1)).setCallForwardingOption(
+                eq(CommandsInterface.CF_ACTION_ERASURE),
+                anyInt(),
+                eq(null),
+                anyInt(),
+                eq(carrierConfigTime),
+                any());
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
index f4fa48e..cffb1a9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
@@ -29,6 +29,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -46,7 +47,9 @@
 import android.os.RemoteException;
 import android.telecom.Connection;
 import android.telecom.TelecomManager;
+import android.telephony.AccessNetworkConstants;
 import android.telephony.BinderCacheManager;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -552,6 +555,75 @@
         assertEquals(carrierTimeoutMillis, mTestSOSMessageRecommender.getTimeOutMillis());
     }
 
+    @Test
+    public void testIsSatellitePlmn() {
+        int subId = 1;
+
+        // Satellite PLMN list is empty
+        SatelliteSOSMessageRecommender sosMessageRecommender = new TestSOSMessageRecommender(
+                mContext, Looper.myLooper(), mSatelliteController, mTestImsManager);
+        when(mSatelliteController.getSatellitePlmnsForCarrier(eq(subId)))
+                .thenReturn(new ArrayList<>());
+        assertFalse(sosMessageRecommender.isSatellitePlmn(subId, mServiceState));
+
+        // registered PLMN is null
+        NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+                .setRegisteredPlmn(null)
+                .build();
+        when(mServiceState.getNetworkRegistrationInfoListForTransportType(
+                eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+                .thenReturn(List.of(nri));
+        assertFalse(sosMessageRecommender.isSatellitePlmn(subId, mServiceState));
+
+        // cell identity is null
+        when(mSatelliteController.getSatellitePlmnsForCarrier(eq(subId))).thenReturn(
+                List.of("120260"));
+        nri = new NetworkRegistrationInfo.Builder()
+                .setRegisteredPlmn("123456")
+                .setCellIdentity(null)
+                .build();
+        when(mServiceState.getNetworkRegistrationInfoListForTransportType(
+                eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+                .thenReturn(List.of(nri));
+        assertFalse(sosMessageRecommender.isSatellitePlmn(subId, mServiceState));
+
+        // mcc and mnc are null
+        when(mCellIdentity.getMccString()).thenReturn(null);
+        when(mCellIdentity.getMncString()).thenReturn(null);
+        nri = new NetworkRegistrationInfo.Builder()
+                .setRegisteredPlmn("123456")
+                .setCellIdentity(mCellIdentity)
+                .build();
+        when(mServiceState.getNetworkRegistrationInfoListForTransportType(
+                eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+                .thenReturn(List.of(nri));
+        assertFalse(sosMessageRecommender.isSatellitePlmn(subId, mServiceState));
+
+        // mccmnc equal to satellite PLMN
+        when(mCellIdentity.getMccString()).thenReturn("120");
+        when(mCellIdentity.getMncString()).thenReturn("260");
+        nri = new NetworkRegistrationInfo.Builder()
+                .setRegisteredPlmn("123456")
+                .setCellIdentity(mCellIdentity)
+                .build();
+        when(mServiceState.getNetworkRegistrationInfoListForTransportType(
+                eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+                .thenReturn(List.of(nri));
+        assertTrue(sosMessageRecommender.isSatellitePlmn(subId, mServiceState));
+
+        // registered PLMN equal to satellite PLMN
+        when(mCellIdentity.getMccString()).thenReturn("123");
+        when(mCellIdentity.getMncString()).thenReturn("456");
+        nri = new NetworkRegistrationInfo.Builder()
+                .setRegisteredPlmn("120260")
+                .setCellIdentity(mCellIdentity)
+                .build();
+        when(mServiceState.getNetworkRegistrationInfoListForTransportType(
+                eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+                .thenReturn(List.of(nri));
+        assertTrue(sosMessageRecommender.isSatellitePlmn(subId, mServiceState));
+    }
+
     private void testStopTrackingCallBeforeTimeout(
             @Connection.ConnectionState int connectionState) {
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);