Merge cherrypicks of ['googleplex-android-review.googlesource.com/30799519'] into 25Q1-release.

Change-Id: I4af4de943241452e32749a18c16f53c227d6c2c4
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index 3309d21..d0b2527 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -76,6 +76,8 @@
 import android.telephony.TelephonyManager;
 import android.telephony.VoiceSpecificRegistrationInfo;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.satellite.ISatelliteModemStateCallback;
+import android.telephony.satellite.SatelliteManager;
 import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.LocalLog;
@@ -619,6 +621,83 @@
      */
     private AccessNetworksManagerCallback mAccessNetworksManagerCallback = null;
 
+    /**
+     * Listens status of nb iot satellite modem.
+     */
+    private SatelliteModemStateListener mSatelliteModemStateListener = null;
+
+    /**
+     * SatelliteModemStateListener class
+     */
+    protected class SatelliteModemStateListener extends ISatelliteModemStateCallback.Stub {
+
+        /**
+         * Satellite Modem Connection Status. True when satellite is connected
+         */
+        private boolean mSatelliteNbIotConnected = false;
+
+        /**
+         * Marks the satellite display change as true.
+         */
+        private boolean mUpdateSatelliteCarrierDisplay = false;
+
+        @Override
+        public void onSatelliteModemStateChanged(int state) {
+            boolean isConnected = isInConnectedState();
+            if (isConnected != mSatelliteNbIotConnected) {
+                log("Satellite connection state is changed to " + isConnected);
+                mSatelliteNbIotConnected = isConnected;
+                mUpdateSatelliteCarrierDisplay = true;
+                // trigger pollStats() because the service state is already OOO in demo mode.
+                pollState();
+            }
+        }
+
+        @Override
+        public void onEmergencyModeChanged(boolean isEmergency) {}
+
+        @Override
+        public void onRegistrationFailure(int causeCode) {}
+
+        @Override
+        public void onTerrestrialNetworkAvailableChanged(boolean isAvailable) {}
+
+        /**
+         * Returns true when statellite is connected.
+         *
+         * Note that this connection state is only applicable carrier roaming nb iot satellite.
+         */
+        public boolean isInConnectedState() {
+            SatelliteController sc = SatelliteController.getInstance();
+            if (sc == null) {
+                return false;
+            }
+            int subId = sc.getSelectedSatelliteSubId();
+            if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
+                    || subId != mPhone.getSubId()
+                    || subId == sc.getNtnOnlySubscriptionId()) {
+                return false;
+            }
+            return sc.isInConnectedState();
+        }
+
+        /**
+         * Returns true if the satellite connection has changed and the satellite display needs
+         * to be updated.
+         */
+        public boolean needToUpdateSatelliteCarrierDisplay() {
+            return mUpdateSatelliteCarrierDisplay;
+        }
+
+        /**
+         * The satellite carrier display update is complete and is marked to not be updated any
+         * further.
+         */
+        public void doneForUpdateSatelliteCarrierDisplay() {
+            mUpdateSatelliteCarrierDisplay = false;
+        }
+    }
+
     public ServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci,
             FeatureFlags featureFlags) {
         mNitzState = TelephonyComponentFactory.getInstance()
@@ -2912,6 +2991,17 @@
             crossSimSpnFormat = crossSimSpnFormats[crossSimSpnFormatIdx];
         }
 
+        String satellitePlmn = null;
+        SatelliteModemStateListener satelliteModemStateListener = getSatelliteModemStateListener();
+        if (combinedRegState == ServiceState.STATE_OUT_OF_SERVICE
+                && satelliteModemStateListener != null
+                && satelliteModemStateListener.isInConnectedState()) {
+            // If device is connected to the nb-iot satellite,
+            // 1) No service but nb-iot satellite is connected ->
+            //    expected to show "Satellite" for demo mode.
+            satellitePlmn = getSatelliteDisplayName();
+        }
+
         if (mPhone.isPhoneTypeGsm()) {
             // The values of plmn/showPlmn change in different scenarios.
             // 1) No service but emergency call allowed -> expected
@@ -2981,7 +3071,12 @@
                     && ((rule & CARRIER_NAME_DISPLAY_BITMASK_SHOW_SPN)
                     == CARRIER_NAME_DISPLAY_BITMASK_SHOW_SPN);
             if (DBG) log("updateCarrierDisplayName: rawSpn = " + spn);
-            if (!TextUtils.isEmpty(crossSimSpnFormat)) {
+            if (!TextUtils.isEmpty(satellitePlmn)) {
+                plmn = satellitePlmn;
+                showPlmn = true;
+                showSpn = false;
+                log("updateCarrierDisplayName: Update satellite network name:" + plmn);
+            } else if (!TextUtils.isEmpty(crossSimSpnFormat)) {
                 if (!TextUtils.isEmpty(spn)) {
                     // Show SPN + Cross-SIM Calling If SIM has SPN and SPN display condition
                     // is satisfied or SPN override is enabled for this carrier.
@@ -3077,6 +3172,46 @@
                 .build();
     }
 
+    private void updateSatelliteDisplayOverride() {
+        String satelliteDisplayName = getSatelliteDisplayName();
+        if (TextUtils.isEmpty(satelliteDisplayName)) {
+            // Return, if there is no value to override.
+            return;
+        }
+
+        SatelliteModemStateListener satelliteModemStateListener = getSatelliteModemStateListener();
+        if (satelliteModemStateListener != null
+                && satelliteModemStateListener.isInConnectedState()) {
+            // override satellite display name.
+            mNewSS.setOperatorName(
+                    satelliteDisplayName, satelliteDisplayName, mNewSS.getOperatorNumeric());
+            log("Override satellite display name to " + satelliteDisplayName);
+        }
+    }
+
+    @Nullable
+    private SatelliteModemStateListener getSatelliteModemStateListener() {
+        if (mSatelliteModemStateListener != null) {
+            return mSatelliteModemStateListener;
+        }
+
+        SatelliteController sc = SatelliteController.getInstance();
+        if (sc != null) {
+            SatelliteModemStateListener listener = new SatelliteModemStateListener();
+            if (sc.registerForSatelliteModemStateChanged(listener)
+                    == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
+                mSatelliteModemStateListener = listener;
+                log("created SatelliteModemStateListener");
+            }
+        }
+        return mSatelliteModemStateListener;
+    }
+
+    private String getSatelliteDisplayName() {
+        return mCarrierConfig.getString(
+                        CarrierConfigManager.KEY_SATELLITE_DISPLAY_NAME_STRING);
+    }
+
     /**
      * Returns whether out-of-service will be displayed as "no service" to the user.
      */
@@ -3431,6 +3566,19 @@
                 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
         setPhyCellInfoFromCellIdentity(mNewSS, networkRegState.getCellIdentity());
 
+        boolean hasSatelliteConnectionChanged = false;
+        SatelliteModemStateListener satelliteModemStateListener = getSatelliteModemStateListener();
+        if (satelliteModemStateListener != null) {
+            hasSatelliteConnectionChanged =
+                    satelliteModemStateListener.needToUpdateSatelliteCarrierDisplay();
+            if (hasSatelliteConnectionChanged) {
+                log("Poll ServiceState done : hasSatelliteConnectionChanged="
+                        + hasSatelliteConnectionChanged);
+                satelliteModemStateListener.doneForUpdateSatelliteCarrierDisplay();
+                updateSatelliteDisplayOverride();
+            }
+        }
+
         if (DBG) {
             log("Poll ServiceState done: oldSS=" + mSS);
             log("Poll ServiceState done: newSS=" + mNewSS);
@@ -3700,7 +3848,8 @@
         // Trigger updateCarrierDisplayName when
         // 1. Service state is changed.
         // 2. phone type is Cdma or CdmaLte and ERI text has changed.
-        if (hasChanged || (!mPhone.isPhoneTypeGsm() && hasEriChanged)) {
+        if (hasChanged || (!mPhone.isPhoneTypeGsm() && hasEriChanged)
+                || hasSatelliteConnectionChanged) {
             updateCarrierDisplayName();
         }
 
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index a44b251..5426410 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -8173,7 +8173,10 @@
         }
     }
 
-    private int getNtnOnlySubscriptionId() {
+    /**
+     * This method returns subscription id for supporting Ntn Only
+     */
+    public int getNtnOnlySubscriptionId() {
         List<SubscriptionInfo> infoList = mSubscriptionManagerService.getAllSubInfoList(
                         mContext.getOpPackageName(), mContext.getAttributionTag());
         int subId = infoList.stream()
@@ -8390,11 +8393,15 @@
         return carrierRoamingNtnSignalStrength;
     }
 
-    private boolean isInConnectedState() {
+    /**
+     * Returns satellite connected state from modem, return true if connected.
+     */
+    public boolean isInConnectedState() {
         synchronized (mSatelliteModemStateLock) {
             switch (mSatelliteModemState) {
-                case SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED:
-                case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING:
+                case SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED: //fallthrough
+                case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING: //fallthrough
+                case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING:
                     plogd("isInConnectedState: return true");
                     return true;
                 default:
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index 70bdcba..404c1b2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -89,6 +89,8 @@
 import android.telephony.cdma.CdmaCellLocation;
 import android.telephony.gsm.GsmCellLocation;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.satellite.ISatelliteModemStateCallback;
+import android.telephony.satellite.SatelliteManager;
 import android.text.TextUtils;
 import android.util.Pair;
 
@@ -185,6 +187,7 @@
     private static final String[] CARRIER_CONFIG_PNN = new String[] {
             String.format("%s,%s", HOME_PNN, "short"), "f2,s2"
     };
+    private static final String SATELLITE_DISPLAY_NAME = "SatelliteTest";
 
     private class ServiceStateTrackerTestHandler extends HandlerThread {
 
@@ -391,6 +394,11 @@
                     30  /* SIGNAL_STRENGTH_GREAT */
                 });
 
+        // satellite display name
+        mBundle.putString(
+                CarrierConfigManager.KEY_SATELLITE_DISPLAY_NAME_STRING,
+                SATELLITE_DISPLAY_NAME);
+
         sendCarrierConfigUpdate(PHONE_ID);
         waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
 
@@ -3546,4 +3554,42 @@
             }
         }
     }
+
+    @Test
+    public void testSatelliteModemStateCallback() throws Exception {
+        ArgumentCaptor<ISatelliteModemStateCallback> captor =
+                ArgumentCaptor.forClass(ISatelliteModemStateCallback.class);
+        verify(mSatelliteController, times(1)).registerForSatelliteModemStateChanged(
+                captor.capture());
+        ISatelliteModemStateCallback callback = captor.getValue();
+
+        doReturn(1).when(mSatelliteController).getSelectedSatelliteSubId();
+        doReturn(1).when(mPhone).getSubId();
+
+        mSimulatedCommands.setVoiceRegState(
+                NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING);
+        mSimulatedCommands.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN);
+        mSimulatedCommands.setDataRegState(
+                NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING);
+        mSimulatedCommands.setDataRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN);
+        doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getState();
+        doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getDataRegistrationState();
+        sst.mSS = mServiceState;
+
+        mBundle.putBoolean(
+                CarrierConfigManager.KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL, false);
+        sendCarrierConfigUpdate(PHONE_ID);
+
+        doReturn(true).when(mSatelliteController).isInConnectedState();
+        callback.onSatelliteModemStateChanged(SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
+
+        // update the spn
+        sst.updateCarrierDisplayName();
+
+        Bundle b = getExtrasFromLastSpnUpdateIntent();
+        assertThat(b.getString(TelephonyManager.EXTRA_PLMN)).isEqualTo(SATELLITE_DISPLAY_NAME);
+        assertThat(b.getBoolean(TelephonyManager.EXTRA_SHOW_PLMN)).isTrue();
+    }
+
 }