Merge "Consider MMS as mutable cap" into main
diff --git a/flags/calling.aconfig b/flags/calling.aconfig
index c1dc7e7..2809f79 100644
--- a/flags/calling.aconfig
+++ b/flags/calling.aconfig
@@ -21,6 +21,17 @@
 
 # OWNER=stevestatia TARGET=24Q4
 flag {
+    name: "national_country_code_formatting_for_local_calls"
+    namespace: "telephony"
+    description: "Make requests and bug fixes for formatting local calls based on country codes easier with a more scalable solution."
+    bug: "293993310"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+# OWNER=stevestatia TARGET=24Q4
+flag {
     name: "remove_country_code_from_local_singapore_calls"
     namespace: "telephony"
     description: "Fix bug where the country code is being shown when merging in local Singapore numbers to conference calls."
diff --git a/flags/satellite.aconfig b/flags/satellite.aconfig
index 27ab0b1..ea814f3 100644
--- a/flags/satellite.aconfig
+++ b/flags/satellite.aconfig
@@ -25,4 +25,20 @@
     namespace: "telephony"
     description: "This flag enables satellite internet support."
     bug:"326972202"
-}
\ No newline at end of file
+}
+
+# OWNER=xalle TARGET=24Q3
+flag {
+    name: "satellite_persistent_logging"
+    namespace: "telephony"
+    description: "This flag enables satellite persistent logging"
+    bug:"339877723"
+}
+
+# OWNER=hyosunkim TARGET=24Q3
+flag {
+    name: "carrier_roaming_nb_iot_ntn"
+    namespace: "telephony"
+    description: "This flag enables satellite carrier roaming to nb iot ntn."
+    bug:"348253735"
+}
diff --git a/src/java/com/android/internal/telephony/Connection.java b/src/java/com/android/internal/telephony/Connection.java
index 68fd6ab..82b4c2b8e 100644
--- a/src/java/com/android/internal/telephony/Connection.java
+++ b/src/java/com/android/internal/telephony/Connection.java
@@ -33,6 +33,7 @@
 
 import com.android.ims.internal.ConferenceParticipant;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.domainselection.DomainSelectionResolver;
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 import com.android.internal.telephony.util.TelephonyUtils;
 import com.android.telephony.Rlog;
@@ -634,7 +635,7 @@
      *
      * @hide
      */
-    public void setEmergencyCallInfo(CallTracker ct) {
+    public void setEmergencyCallInfo(CallTracker ct, Phone.DialArgs dialArgs) {
         if (ct != null) {
             Phone currentPhone = ct.getPhone();
             if (currentPhone != null) {
@@ -677,20 +678,52 @@
         } else {
             Rlog.e(TAG, "setEmergencyCallInfo: call tracker is null");
         }
+
+        if (DomainSelectionResolver.getInstance().isDomainSelectionSupported()) {
+            if (mEmergencyNumberInfo == null) {
+                Rlog.d(TAG, "setEmergencyCallInfo: create EmergencyNumber");
+                setNonDetectableEmergencyCallInfo((dialArgs != null) ? dialArgs.eccCategory
+                        : EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+                        new ArrayList<String>());
+            }
+            if (dialArgs != null && dialArgs.intentExtras != null
+                    && dialArgs.intentExtras.getBoolean(
+                            PhoneConstants.EXTRA_USE_EMERGENCY_ROUTING, false)
+                    && mEmergencyNumberInfo.getEmergencyCallRouting()
+                        != EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY) {
+                int eccCategory = dialArgs.intentExtras.getInt(
+                        PhoneConstants.EXTRA_EMERGENCY_SERVICE_CATEGORY,
+                        mEmergencyNumberInfo.getEmergencyServiceCategoryBitmask());
+                Rlog.d(TAG, "setEmergencyCallInfo: enforce emergency routing eccCategory="
+                        + eccCategory);
+                List<String> emergencyUrns = dialArgs.intentExtras.getStringArrayList(
+                        PhoneConstants.EXTRA_EMERGENCY_URNS);
+                if (emergencyUrns == null || emergencyUrns.isEmpty()) {
+                    emergencyUrns = mEmergencyNumberInfo.getEmergencyUrns();
+                }
+                mEmergencyNumberInfo = new EmergencyNumber(mEmergencyNumberInfo.getNumber(),
+                        mEmergencyNumberInfo.getCountryIso(),
+                        mEmergencyNumberInfo.getMnc(),
+                        eccCategory,
+                        emergencyUrns,
+                        mEmergencyNumberInfo.getEmergencyNumberSourceBitmask(),
+                        EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
+            }
+        }
     }
 
     /**
      * Set the non-detectable emergency number information.
      */
-    public void setNonDetectableEmergencyCallInfo(int eccCategory) {
-        if (!mIsEmergencyCall) {
-            mIsEmergencyCall = true;
-            mEmergencyNumberInfo = new EmergencyNumber(mAddress, ""/*countryIso*/,
-                                    ""/*mnc*/, eccCategory,
-                                    new ArrayList<String>(),
-                                    EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
-                                    EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN);
-        }
+    public void setNonDetectableEmergencyCallInfo(int eccCategory,
+            @NonNull List<String> emergencyUrns) {
+        Rlog.d(TAG, "setNonDetectableEmergencyCallInfo: eccCategory=" + eccCategory
+                + ", emergencyUrns=" + emergencyUrns);
+        mIsEmergencyCall = true;
+        mEmergencyNumberInfo = new EmergencyNumber(mAddress, ""/*countryIso*/, ""/*mnc*/,
+                                eccCategory, emergencyUrns,
+                                EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+                                EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN);
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/GsmCdmaConnection.java b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
index e06520a..cc07047 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaConnection.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
@@ -139,7 +139,7 @@
         mHandler = new MyHandler(mOwner.getLooper());
 
         mAddress = dc.number;
-        setEmergencyCallInfo(mOwner);
+        setEmergencyCallInfo(mOwner, null);
 
         String forwardedNumber = TextUtils.isEmpty(dc.forwardedNumber) ? null : dc.forwardedNumber;
         Rlog.i(LOG_TAG, "create, forwardedNumber=" + Rlog.pii(LOG_TAG, forwardedNumber));
@@ -186,13 +186,13 @@
 
         mAddress = PhoneNumberUtils.extractNetworkPortionAlt(dialString);
         if (dialArgs.isEmergency) {
-            setEmergencyCallInfo(mOwner);
+            setEmergencyCallInfo(mOwner, null);
 
             // There was no emergency number info found for this call, however it is
             // still marked as an emergency number. This may happen if it was a redialed
             // non-detectable emergency call from IMS.
             if (getEmergencyNumberInfo() == null) {
-                setNonDetectableEmergencyCallInfo(dialArgs.eccCategory);
+                setNonDetectableEmergencyCallInfo(dialArgs.eccCategory, new ArrayList<String>());
             }
         }
 
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index a9e21a3..aa62acb 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -150,10 +150,10 @@
  */
 
 public abstract class Phone extends Handler implements PhoneInternalInterface {
-    private static final String LOG_TAG = "Phone";
 
     protected final static Object lockForRadioTechnologyChange = new Object();
 
+    private final String mLogTag;
     protected final int USSD_MAX_QUEUE = 10;
 
     // Key used to read and write the saved network selection numeric value
@@ -597,6 +597,7 @@
                     boolean unitTestMode, int phoneId,
                     TelephonyComponentFactory telephonyComponentFactory,
                     FeatureFlags featureFlags) {
+        mLogTag = "Phone-" + phoneId;
         mPhoneId = phoneId;
         mName = name;
         mNotifier = notifier;
@@ -638,10 +639,10 @@
          */
         mDoesRilSendMultipleCallRing = TelephonyProperties.ril_sends_multiple_call_ring()
                 .orElse(true);
-        Rlog.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
+        Rlog.d(mLogTag, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
 
         mCallRingDelay = TelephonyProperties.call_ring_delay().orElse(3000);
-        Rlog.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay);
+        Rlog.d(mLogTag, "mCallRingDelay=" + mCallRingDelay);
 
         // Initialize SMS stats
         mSmsStats = new SmsStats(this);
@@ -785,7 +786,7 @@
 
         switch(msg.what) {
             case EVENT_CALL_RING:
-                Rlog.d(LOG_TAG, "Event EVENT_CALL_RING Received state=" + getState());
+                Rlog.d(mLogTag, "Event EVENT_CALL_RING Received state=" + getState());
                 ar = (AsyncResult)msg.obj;
                 if (ar.exception == null) {
                     PhoneConstants.State state = getState();
@@ -801,7 +802,7 @@
                 break;
 
             case EVENT_CALL_RING_CONTINUE:
-                Rlog.d(LOG_TAG, "Event EVENT_CALL_RING_CONTINUE Received state=" + getState());
+                Rlog.d(mLogTag, "Event EVENT_CALL_RING_CONTINUE Received state=" + getState());
                 if (getState() == PhoneConstants.State.RINGING) {
                     sendIncomingCallRingNotification(msg.arg1);
                 }
@@ -814,7 +815,7 @@
             case EVENT_INITIATE_SILENT_REDIAL:
                 // This is an ImsPhone -> GsmCdmaPhone redial
                 // See ImsPhone#initiateSilentRedial
-                Rlog.d(LOG_TAG, "Event EVENT_INITIATE_SILENT_REDIAL Received");
+                Rlog.d(mLogTag, "Event EVENT_INITIATE_SILENT_REDIAL Received");
                 ar = (AsyncResult) msg.obj;
                 if ((ar.exception == null) && (ar.result != null)) {
                     SilentRedialParam result = (SilentRedialParam) ar.result;
@@ -828,13 +829,13 @@
                         // one with a callback registered to TelephonyConnection. Notify the
                         // redial happened over that Phone so that it can be replaced with the
                         // new GSM/CDMA Connection.
-                        Rlog.d(LOG_TAG, "Notify redial connection changed cn: " + cn);
+                        Rlog.d(mLogTag, "Notify redial connection changed cn: " + cn);
                         if (mImsPhone != null) {
                             // Don't care it is null or not.
                             mImsPhone.notifyRedialConnectionChanged(cn);
                         }
                     } catch (CallStateException e) {
-                        Rlog.e(LOG_TAG, "silent redial failed: " + e);
+                        Rlog.e(mLogTag, "silent redial failed: " + e);
                         if (mImsPhone != null) {
                             mImsPhone.notifyRedialConnectionChanged(null);
                         }
@@ -847,7 +848,7 @@
                 if (ar.exception == null) {
                     handleSrvccStateChanged((int[]) ar.result);
                 } else {
-                    Rlog.e(LOG_TAG, "Srvcc exception: " + ar.exception);
+                    Rlog.e(mLogTag, "Srvcc exception: " + ar.exception);
                 }
                 break;
 
@@ -866,7 +867,7 @@
                     try {
                         mUsageSettingFromModem = ((int[]) ar.result)[0];
                     } catch (NullPointerException | ClassCastException e) {
-                        Rlog.e(LOG_TAG, "Invalid response for usage setting " + ar.result);
+                        Rlog.e(mLogTag, "Invalid response for usage setting " + ar.result);
                         break;
                     }
 
@@ -881,9 +882,9 @@
                         if (ce.getCommandError() == CommandException.Error.REQUEST_NOT_SUPPORTED) {
                             mIsUsageSettingSupported = false;
                         }
-                        Rlog.w(LOG_TAG, "Unexpected failure to retrieve usage setting " + ce);
+                        Rlog.w(mLogTag, "Unexpected failure to retrieve usage setting " + ce);
                     } catch (ClassCastException unused) {
-                        Rlog.e(LOG_TAG, "Invalid Exception for usage setting " + ar.exception);
+                        Rlog.e(mLogTag, "Invalid Exception for usage setting " + ar.exception);
                         break; // technically extraneous, but good hygiene
                     }
                 }
@@ -896,9 +897,9 @@
                         if (ce.getCommandError() == CommandException.Error.REQUEST_NOT_SUPPORTED) {
                             mIsUsageSettingSupported = false;
                         }
-                        Rlog.w(LOG_TAG, "Unexpected failure to set usage setting " + ce);
+                        Rlog.w(mLogTag, "Unexpected failure to set usage setting " + ce);
                     } catch (ClassCastException unused) {
-                        Rlog.e(LOG_TAG, "Invalid Exception for usage setting " + ar.exception);
+                        Rlog.e(mLogTag, "Invalid Exception for usage setting " + ar.exception);
                         break; // technically extraneous, but good hygiene
                     }
                 }
@@ -932,7 +933,7 @@
     }
 
     private void handleSrvccStateChanged(int[] ret) {
-        Rlog.d(LOG_TAG, "handleSrvccStateChanged");
+        Rlog.d(mLogTag, "handleSrvccStateChanged");
 
         ArrayList<Connection> conn = null;
         Phone imsPhone = mImsPhone;
@@ -949,7 +950,7 @@
                         conn = imsPhone.getHandoverConnection();
                         migrateFrom(imsPhone);
                     } else {
-                        Rlog.d(LOG_TAG, "HANDOVER_STARTED: mImsPhone null");
+                        Rlog.d(mLogTag, "HANDOVER_STARTED: mImsPhone null");
                     }
                     break;
                 case TelephonyManager.SRVCC_STATE_HANDOVER_COMPLETED:
@@ -1187,7 +1188,7 @@
                     to.add((Registrant) from.get(i));
                 }
             } else {
-                Rlog.d(LOG_TAG, "msg is null");
+                Rlog.d(mLogTag, "msg is null");
             }
         }
     }
@@ -1484,7 +1485,7 @@
      */
     @UnsupportedAppUsage
     public void setNetworkSelectionModeAutomatic(Message response) {
-        Rlog.d(LOG_TAG, "setNetworkSelectionModeAutomatic, querying current mode");
+        Rlog.d(mLogTag, "setNetworkSelectionModeAutomatic, querying current mode");
         // we don't want to do this unnecessarily - it actually causes
         // the radio to repeat network selection and is costly
         // first check if we're already in automatic mode
@@ -1519,11 +1520,11 @@
         nsm.operatorAlphaShort = "";
 
         if (doAutomatic) {
-            Rlog.d(LOG_TAG, "setNetworkSelectionModeAutomatic - set network selection auto");
+            Rlog.d(mLogTag, "setNetworkSelectionModeAutomatic - set network selection auto");
             Message msg = obtainMessage(EVENT_SET_NETWORK_AUTOMATIC_COMPLETE, nsm);
             mCi.setNetworkSelectionModeAutomatic(msg);
         } else {
-            Rlog.d(LOG_TAG, "setNetworkSelectionModeAutomatic - already auto, ignoring");
+            Rlog.d(mLogTag, "setNetworkSelectionModeAutomatic - already auto, ignoring");
             // let the calling application know that the we are ignoring automatic mode switch.
             if (nsm.message != null) {
                 nsm.message.arg1 = ALREADY_IN_AUTO_SELECTION;
@@ -1617,10 +1618,10 @@
 
             // commit and log the result.
             if (!editor.commit()) {
-                Rlog.e(LOG_TAG, "failed to commit network selection preference");
+                Rlog.e(mLogTag, "failed to commit network selection preference");
             }
         } else {
-            Rlog.e(LOG_TAG, "Cannot update network selection preference due to invalid subId " +
+            Rlog.e(mLogTag, "Cannot update network selection preference due to invalid subId " +
                     subId);
         }
     }
@@ -1631,7 +1632,7 @@
      * @param nsm PLMN info of the selected network
      */
     protected void updateManualNetworkSelection(NetworkSelectMessage nsm)  {
-        Rlog.e(LOG_TAG, "updateManualNetworkSelection() should be overridden");
+        Rlog.e(mLogTag, "updateManualNetworkSelection() should be overridden");
     }
 
     /**
@@ -1641,7 +1642,7 @@
         // look for our wrapper within the asyncresult, skip the rest if it
         // is null.
         if (!(ar.userObj instanceof NetworkSelectMessage)) {
-            Rlog.e(LOG_TAG, "unexpected result from user object.");
+            Rlog.e(mLogTag, "unexpected result from user object.");
             return;
         }
 
@@ -1705,12 +1706,12 @@
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
         SharedPreferences.Editor editor = sp.edit();
         editor.putInt(CLIR_KEY + getSubId(), commandInterfaceCLIRMode);
-        Rlog.i(LOG_TAG, "saveClirSetting: " + CLIR_KEY + getSubId() + "="
+        Rlog.i(mLogTag, "saveClirSetting: " + CLIR_KEY + getSubId() + "="
                 + commandInterfaceCLIRMode);
 
         // Commit and log the result.
         if (!editor.commit()) {
-            Rlog.e(LOG_TAG, "Failed to commit CLIR preference");
+            Rlog.e(mLogTag, "Failed to commit CLIR preference");
         }
     }
 
@@ -1932,13 +1933,13 @@
         IccFileHandler fh;
 
         if (uiccApplication == null) {
-            Rlog.d(LOG_TAG, "getIccFileHandler: uiccApplication == null, return null");
+            Rlog.d(mLogTag, "getIccFileHandler: uiccApplication == null, return null");
             fh = null;
         } else {
             fh = uiccApplication.getIccFileHandler();
         }
 
-        Rlog.d(LOG_TAG, "getIccFileHandler: fh=" + fh);
+        Rlog.d(mLogTag, "getIccFileHandler: fh=" + fh);
         return fh;
     }
 
@@ -2025,7 +2026,7 @@
      * Retrieves the SignalStrengthController of the phone instance.
      */
     public SignalStrengthController getSignalStrengthController() {
-        Log.wtf(LOG_TAG, "getSignalStrengthController return null.");
+        Log.wtf(mLogTag, "getSignalStrengthController return null.");
         return null;
     }
 
@@ -2059,7 +2060,7 @@
      * Update voice mail count related fields and notify listeners
      */
     public void updateVoiceMail() {
-        Rlog.e(LOG_TAG, "updateVoiceMail() should be overridden");
+        Rlog.e(mLogTag, "updateVoiceMail() should be overridden");
     }
 
     public AppType getCurrentUiccAppType() {
@@ -2185,7 +2186,7 @@
         if (SubscriptionManager.isValidSubscriptionId(subId)) {
             SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
             status = sp.getInt(CF_STATUS + subId, IccRecords.CALL_FORWARDING_STATUS_UNKNOWN);
-            Rlog.d(LOG_TAG, "getCallForwardingIndicatorFromSharedPref: for subId " + subId + "= " +
+            Rlog.d(mLogTag, "getCallForwardingIndicatorFromSharedPref: for subId " + subId + "= " +
                     status);
             // Check for old preference if status is UNKNOWN for current subId. This part of the
             // code is needed only when upgrading from M to N.
@@ -2199,9 +2200,9 @@
                         status = sp.getInt(CF_STATUS, IccRecords.CALL_FORWARDING_STATUS_DISABLED);
                         setCallForwardingIndicatorInSharedPref(
                                 status == IccRecords.CALL_FORWARDING_STATUS_ENABLED ? true : false);
-                        Rlog.d(LOG_TAG, "getCallForwardingIndicatorFromSharedPref: " + status);
+                        Rlog.d(mLogTag, "getCallForwardingIndicatorFromSharedPref: " + status);
                     } else {
-                        Rlog.d(LOG_TAG, "getCallForwardingIndicatorFromSharedPref: returning " +
+                        Rlog.d(mLogTag, "getCallForwardingIndicatorFromSharedPref: returning " +
                                 "DISABLED as status for matching subscriberId not found");
                     }
 
@@ -2213,7 +2214,7 @@
                 }
             }
         } else {
-            Rlog.e(LOG_TAG, "getCallForwardingIndicatorFromSharedPref: invalid subId " + subId);
+            Rlog.e(mLogTag, "getCallForwardingIndicatorFromSharedPref: invalid subId " + subId);
         }
         return status;
     }
@@ -2222,7 +2223,7 @@
         int status = enable ? IccRecords.CALL_FORWARDING_STATUS_ENABLED :
                 IccRecords.CALL_FORWARDING_STATUS_DISABLED;
         int subId = getSubId();
-        Rlog.i(LOG_TAG, "setCallForwardingIndicatorInSharedPref: Storing status = " + status +
+        Rlog.i(mLogTag, "setCallForwardingIndicatorInSharedPref: Storing status = " + status +
                 " in pref " + CF_STATUS + subId);
 
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
@@ -2265,7 +2266,7 @@
      */
     public boolean getCallForwardingIndicator() {
         if (getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
-            Rlog.e(LOG_TAG, "getCallForwardingIndicator: not possible in CDMA");
+            Rlog.e(mLogTag, "getCallForwardingIndicator: not possible in CDMA");
             return false;
         }
         IccRecords r = getIccRecords();
@@ -2276,7 +2277,7 @@
         if (callForwardingIndicator == IccRecords.CALL_FORWARDING_STATUS_UNKNOWN) {
             callForwardingIndicator = getCallForwardingIndicatorFromSharedPref();
         }
-        Rlog.v(LOG_TAG, "getCallForwardingIndicator: iccForwardingFlag=" + (r != null
+        Rlog.v(mLogTag, "getCallForwardingIndicator: iccForwardingFlag=" + (r != null
                     ? r.getVoiceCallForwardingFlag() : "null") + ", sharedPrefFlag="
                     + getCallForwardingIndicatorFromSharedPref());
         return (callForwardingIndicator == IccRecords.CALL_FORWARDING_STATUS_ENABLED);
@@ -2473,7 +2474,7 @@
             for (String pair : result.trim().split(",")) {
                 String[] networkTypesValues = (pair.trim().toLowerCase(Locale.ROOT)).split("=");
                 if (networkTypesValues.length != 2) {
-                    Rlog.e(LOG_TAG, "Invalid ALLOWED_NETWORK_TYPES from DB, value = " + pair);
+                    Rlog.e(mLogTag, "Invalid ALLOWED_NETWORK_TYPES from DB, value = " + pair);
                     continue;
                 }
                 int key = convertAllowedNetworkTypeDbNameToMapIndex(networkTypesValues[0]);
@@ -2493,7 +2494,7 @@
                 }
             }
         } catch (NumberFormatException e) {
-            Rlog.e(LOG_TAG, "allowedNetworkTypes NumberFormat exception" + e);
+            Rlog.e(mLogTag, "allowedNetworkTypes NumberFormat exception" + e);
         }
 
         for (int key : oldAllowedNetworkTypes.keySet()) {
@@ -2612,7 +2613,7 @@
     protected void updateAllowedNetworkTypes(Message response) {
         int modemRaf = getRadioAccessFamily();
         if (modemRaf == RadioAccessFamily.RAF_UNKNOWN) {
-            Rlog.d(LOG_TAG, "setPreferredNetworkType: Abort, unknown RAF: "
+            Rlog.d(mLogTag, "setPreferredNetworkType: Abort, unknown RAF: "
                     + modemRaf);
             if (response != null) {
                 CommandException ex;
@@ -2721,7 +2722,7 @@
      * @param onComplete a callback message when the action is completed
      */
     public void setUiTTYMode(int uiTtyMode, Message onComplete) {
-        Rlog.d(LOG_TAG, "unexpected setUiTTYMode method call");
+        Rlog.d(mLogTag, "unexpected setUiTTYMode method call");
     }
 
     /**
@@ -2848,7 +2849,7 @@
     public boolean eraseDataInSharedPreferences() {
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
         SharedPreferences.Editor editor = sp.edit();
-        Rlog.d(LOG_TAG, "Erase all data saved in SharedPreferences");
+        Rlog.d(mLogTag, "Erase all data saved in SharedPreferences");
         editor.clear();
         return editor.commit();
     }
@@ -3094,7 +3095,7 @@
                     isVideoCallOrConference(mImsPhone.getBackgroundCall()) ||
                     isVideoCallOrConference(mImsPhone.getRingingCall());
         }
-        Rlog.d(LOG_TAG, "isImsVideoCallOrConferencePresent: " + isPresent);
+        Rlog.d(mLogTag, "isImsVideoCallOrConferencePresent: " + isPresent);
         return isPresent;
     }
 
@@ -3119,7 +3120,7 @@
         int subId = getSubId();
         if (SubscriptionManager.isValidSubscriptionId(subId)) {
 
-            Rlog.d(LOG_TAG, "setVoiceMessageCount: Storing Voice Mail Count = " + countWaiting +
+            Rlog.d(mLogTag, "setVoiceMessageCount: Storing Voice Mail Count = " + countWaiting +
                     " for mVmCountKey = " + VM_COUNT + subId + " in preferences.");
 
             SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
@@ -3127,16 +3128,16 @@
             editor.putInt(VM_COUNT + subId, countWaiting);
             editor.apply();
         } else {
-            Rlog.e(LOG_TAG, "setVoiceMessageCount in sharedPreference: invalid subId " + subId);
+            Rlog.e(mLogTag, "setVoiceMessageCount in sharedPreference: invalid subId " + subId);
         }
         // store voice mail count in SIM
         IccRecords records = UiccController.getInstance().getIccRecords(
                 mPhoneId, UiccController.APP_FAM_3GPP);
         if (records != null) {
-            Rlog.d(LOG_TAG, "setVoiceMessageCount: updating SIM Records");
+            Rlog.d(mLogTag, "setVoiceMessageCount: updating SIM Records");
             records.setVoiceMessageWaiting(1, countWaiting);
         } else {
-            Rlog.d(LOG_TAG, "setVoiceMessageCount: SIM Records not found");
+            Rlog.d(mLogTag, "setVoiceMessageCount: SIM Records not found");
         }
         // notify listeners of voice mail
         notifyMessageWaitingIndicator();
@@ -3152,7 +3153,7 @@
             int countFromSP = sp.getInt(VM_COUNT + subId, invalidCount);
             if (countFromSP != invalidCount) {
                 countVoiceMessages = countFromSP;
-                Rlog.d(LOG_TAG, "getStoredVoiceMessageCount: from preference for subId " + subId +
+                Rlog.d(mLogTag, "getStoredVoiceMessageCount: from preference for subId " + subId +
                         "= " + countVoiceMessages);
             } else {
                 // Check for old preference if count not found for current subId. This part of the
@@ -3165,10 +3166,10 @@
                         // get voice mail count from preferences
                         countVoiceMessages = sp.getInt(VM_COUNT, 0);
                         setVoiceMessageCount(countVoiceMessages);
-                        Rlog.d(LOG_TAG, "getStoredVoiceMessageCount: from preference = " +
+                        Rlog.d(mLogTag, "getStoredVoiceMessageCount: from preference = " +
                                 countVoiceMessages);
                     } else {
-                        Rlog.d(LOG_TAG, "getStoredVoiceMessageCount: returning 0 as count for " +
+                        Rlog.d(mLogTag, "getStoredVoiceMessageCount: returning 0 as count for " +
                                 "matching subscriberId not found");
 
                     }
@@ -3180,7 +3181,7 @@
                 }
             }
         } else {
-            Rlog.e(LOG_TAG, "getStoredVoiceMessageCount: invalid subId " + subId);
+            Rlog.e(mLogTag, "getStoredVoiceMessageCount: invalid subId " + subId);
         }
         return countVoiceMessages;
     }
@@ -3713,17 +3714,17 @@
                             }
                         }
                     } catch (NumberFormatException e) {
-                        Rlog.e(LOG_TAG, "Exception in getProvisioningUrlBaseFromFile: " + e);
+                        Rlog.e(mLogTag, "Exception in getProvisioningUrlBaseFromFile: " + e);
                     }
                 }
             }
             return null;
         } catch (FileNotFoundException e) {
-            Rlog.e(LOG_TAG, "Carrier Provisioning Urls file not found");
+            Rlog.e(mLogTag, "Carrier Provisioning Urls file not found");
         } catch (XmlPullParserException e) {
-            Rlog.e(LOG_TAG, "Xml parser exception reading Carrier Provisioning Urls file: " + e);
+            Rlog.e(mLogTag, "Xml parser exception reading Carrier Provisioning Urls file: " + e);
         } catch (IOException e) {
-            Rlog.e(LOG_TAG, "I/O exception reading Carrier Provisioning Urls file: " + e);
+            Rlog.e(mLogTag, "I/O exception reading Carrier Provisioning Urls file: " + e);
         }
         return null;
     }
@@ -3735,9 +3736,9 @@
         String url = getProvisioningUrlBaseFromFile();
         if (TextUtils.isEmpty(url)) {
             url = mContext.getResources().getString(R.string.mobile_provisioning_url);
-            Rlog.d(LOG_TAG, "getMobileProvisioningUrl: url from resource =" + url);
+            Rlog.d(mLogTag, "getMobileProvisioningUrl: url from resource =" + url);
         } else {
-            Rlog.d(LOG_TAG, "getMobileProvisioningUrl: url from File =" + url);
+            Rlog.d(mLogTag, "getMobileProvisioningUrl: url from File =" + url);
         }
         // Populate the iccid, imei and phone number in the provisioning url.
         if (!TextUtils.isEmpty(url)) {
@@ -3811,7 +3812,7 @@
      * version scoped to their packages
      */
     public void notifyNewRingingConnectionP(Connection cn) {
-        Rlog.i(LOG_TAG, String.format(
+        Rlog.i(mLogTag, String.format(
                 "notifyNewRingingConnection: phoneId=[%d], connection=[%s], registrants=[%s]",
                 getPhoneId(), cn, getNewRingingConnectionRegistrantsAsString()));
         if (!mIsVoiceCapable)
@@ -3867,12 +3868,12 @@
     private void sendIncomingCallRingNotification(int token) {
         if (mIsVoiceCapable && !mDoesRilSendMultipleCallRing &&
                 (token == mCallRingContinueToken)) {
-            Rlog.d(LOG_TAG, "Sending notifyIncomingRing");
+            Rlog.d(mLogTag, "Sending notifyIncomingRing");
             notifyIncomingRing();
             sendMessageDelayed(
                     obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);
         } else {
-            Rlog.d(LOG_TAG, "Ignoring ring notification request,"
+            Rlog.d(mLogTag, "Ignoring ring notification request,"
                     + " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing
                     + " token=" + token
                     + " mCallRingContinueToken=" + mCallRingContinueToken
@@ -3912,7 +3913,7 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public IsimRecords getIsimRecords() {
-        Rlog.e(LOG_TAG, "getIsimRecords() is only supported on LTE devices");
+        Rlog.e(mLogTag, "getIsimRecords() is only supported on LTE devices");
         return null;
     }
 
@@ -3945,7 +3946,7 @@
      */
     public void setVoiceMessageWaiting(int line, int countWaiting) {
         // This function should be overridden by class GsmCdmaPhone.
-        Rlog.e(LOG_TAG, "Error! This function should never be executed, inactive Phone.");
+        Rlog.e(mLogTag, "Error! This function should never be executed, inactive Phone.");
     }
 
     /**
@@ -4204,7 +4205,7 @@
                 isImsRegistered = sst.isImsRegistered();
             }
         }
-        Rlog.d(LOG_TAG, "isImsRegistered =" + isImsRegistered);
+        Rlog.d(mLogTag, "isImsRegistered =" + isImsRegistered);
         return isImsRegistered;
     }
 
@@ -4218,7 +4219,7 @@
         if (imsPhone != null) {
             isWifiCallingEnabled = imsPhone.isWifiCallingEnabled();
         }
-        Rlog.d(LOG_TAG, "isWifiCallingEnabled =" + isWifiCallingEnabled);
+        Rlog.d(mLogTag, "isWifiCallingEnabled =" + isWifiCallingEnabled);
         return isWifiCallingEnabled;
     }
 
@@ -4232,7 +4233,7 @@
         if (imsPhone != null) {
             isAvailable = imsPhone.isImsCapabilityAvailable(capability, regTech);
         }
-        Rlog.d(LOG_TAG, "isImsCapabilityAvailable, capability=" + capability + ", regTech="
+        Rlog.d(mLogTag, "isImsCapabilityAvailable, capability=" + capability + ", regTech="
                 + regTech + ", isAvailable=" + isAvailable);
         return isAvailable;
     }
@@ -4256,7 +4257,7 @@
         if (imsPhone != null) {
             isVolteEnabled = imsPhone.isVoiceOverCellularImsEnabled();
         }
-        Rlog.d(LOG_TAG, "isVoiceOverCellularImsEnabled=" + isVolteEnabled);
+        Rlog.d(mLogTag, "isVoiceOverCellularImsEnabled=" + isVolteEnabled);
         return isVolteEnabled;
     }
 
@@ -4270,7 +4271,7 @@
         if (imsPhone != null) {
             regTech = imsPhone.getImsRegistrationTech();
         }
-        Rlog.d(LOG_TAG, "getImsRegistrationTechnology =" + regTech);
+        Rlog.d(mLogTag, "getImsRegistrationTechnology =" + regTech);
         return regTech;
     }
 
@@ -4852,7 +4853,7 @@
     public boolean isDeviceIdle() {
         DeviceStateMonitor dsm = getDeviceStateMonitor();
         if (dsm == null) {
-            Rlog.e(LOG_TAG, "isDeviceIdle: DeviceStateMonitor is null");
+            Rlog.e(mLogTag, "isDeviceIdle: DeviceStateMonitor is null");
             return false;
         }
         return !dsm.shouldEnableHighPowerConsumptionIndications();
@@ -4866,7 +4867,7 @@
     public void notifyDeviceIdleStateChanged(boolean isIdle) {
         SignalStrengthController ssc = getSignalStrengthController();
         if (ssc == null) {
-            Rlog.e(LOG_TAG, "notifyDeviceIdleStateChanged: SignalStrengthController is null");
+            Rlog.e(mLogTag, "notifyDeviceIdleStateChanged: SignalStrengthController is null");
             return;
         }
         ssc.onDeviceIdleStateChanged(isIdle);
@@ -5298,7 +5299,7 @@
      * @param type for callback mode entry.
      */
     public void startCallbackMode(@TelephonyManager.EmergencyCallbackModeType int type) {
-        Rlog.d(LOG_TAG, "startCallbackMode:type=" + type);
+        Rlog.d(mLogTag, "startCallbackMode:type=" + type);
         mNotifier.notifyCallbackModeStarted(this, type);
     }
 
@@ -5309,7 +5310,7 @@
      */
     public void stopCallbackMode(@TelephonyManager.EmergencyCallbackModeType int type,
             @TelephonyManager.EmergencyCallbackModeStopReason int reason) {
-        Rlog.d(LOG_TAG, "stopCallbackMode:type=" + type + ", reason=" + reason);
+        Rlog.d(mLogTag, "stopCallbackMode:type=" + type + ", reason=" + reason);
         mNotifier.notifyCallbackModeStopped(this, type, reason);
     }
 
@@ -5347,7 +5348,7 @@
         pw.println(" isDnsCheckDisabled()=" + isDnsCheckDisabled());
         pw.println(" getUnitTestMode()=" + getUnitTestMode());
         pw.println(" getState()=" + getState());
-        pw.println(" getIccSerialNumber()=" + Rlog.pii(LOG_TAG, getIccSerialNumber()));
+        pw.println(" getIccSerialNumber()=" + Rlog.pii(mLogTag, getIccSerialNumber()));
         pw.println(" getIccRecordsLoaded()=" + getIccRecordsLoaded());
         pw.println(" getMessageWaitingIndicator()=" + getMessageWaitingIndicator());
         pw.println(" getCallForwardingIndicator()=" + getCallForwardingIndicator());
@@ -5532,18 +5533,14 @@
     }
 
     private void logd(String s) {
-        Rlog.d(LOG_TAG, "[" + mPhoneId + "] " + s);
+        Rlog.d(mLogTag, "[" + mPhoneId + "] " + s);
     }
 
     private void logi(String s) {
-        Rlog.i(LOG_TAG, "[" + mPhoneId + "] " + s);
+        Rlog.i(mLogTag, "[" + mPhoneId + "] " + s);
     }
 
     private void loge(String s) {
-        Rlog.e(LOG_TAG, "[" + mPhoneId + "] " + s);
-    }
-
-    private static String pii(String s) {
-        return Rlog.pii(LOG_TAG, s);
+        Rlog.e(mLogTag, "[" + mPhoneId + "] " + s);
     }
 }
diff --git a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
index ffa5b69..b96887c 100644
--- a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
+++ b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
@@ -391,9 +391,12 @@
                             }
                             mSlotsSupportingSimultaneousCellularCalls.add(i);
                         }
-                        // Ensure the slots supporting cellular DSDA does not exceed the phone count
-                        if (mSlotsSupportingSimultaneousCellularCalls.size() > getPhoneCount()) {
-                            loge("Invalid size of DSDA slots. Disabling cellular DSDA.");
+                        // Ensure the number of slots supporting cellular DSDA is valid:
+                        if (mSlotsSupportingSimultaneousCellularCalls.size() > getPhoneCount() ||
+                                mSlotsSupportingSimultaneousCellularCalls.size() < 2) {
+                            loge("Invalid size of DSDA slots. Disabling cellular DSDA. Size of "
+                                    + "mSlotsSupportingSimultaneousCellularCalls=" +
+                                    mSlotsSupportingSimultaneousCellularCalls.size());
                             mSlotsSupportingSimultaneousCellularCalls.clear();
                         }
                     } else {
diff --git a/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java b/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java
index ee8517d..e4ae592 100644
--- a/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java
+++ b/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java
@@ -271,7 +271,9 @@
                 mHandler,
                 mRestartBindingRunnable);
 
-        int numPhones = TelephonyManager.getDefault().getActiveModemCount();
+        TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+        int numPhones = tm.getSupportedModemCount();
+        logi("numPhones=" + numPhones);
         mConnectionCounts = new int[numPhones];
         for (int i = 0; i < numPhones; i++) {
             mConnectionCounts[i] = 0;
diff --git a/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java b/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java
index 410f89b..1b66e54 100644
--- a/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java
+++ b/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java
@@ -64,8 +64,7 @@
      *                               to be bound to the domain selection controller.
      */
     public static void make(Context context, String flattenedComponentName) {
-        Log.i(TAG, "make flag=" + Flags.apDomainSelectionEnabled()
-                + ", useOem=" + Flags.useOemDomainSelectionService());
+        Log.i(TAG, "make useOem=" + Flags.useOemDomainSelectionService());
         if (sInstance == null) {
             sInstance = new DomainSelectionResolver(context, flattenedComponentName);
         }
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
index 8478cff..167062f 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
@@ -564,6 +564,11 @@
         Rlog.i(TAG, "startEmergencyCall: phoneId=" + phone.getPhoneId()
                 + ", callId=" + c.getTelecomCallId());
 
+        if (needToSwitchPhone(phone)) {
+            Rlog.e(TAG, "startEmergencyCall failed. need to switch stacks.");
+            return CompletableFuture.completedFuture(DisconnectCause.EMERGENCY_PERM_FAILURE);
+        }
+
         if (mPhone != null) {
             // Create new future to return as to not interfere with any uncompleted futures.
             // Case1) When 2nd emergency call is initiated during an active call on the same phone.
@@ -2105,4 +2110,63 @@
             endNormalRoutingEmergencyCall(c);
         }
     }
+
+    /**
+     * Determines whether switching stacks is needed or not.
+     *
+     * @param phone the {@code Phone} on which to process the emergency call.
+     * @return true if switching stacks is needed.
+     */
+    @VisibleForTesting
+    public boolean needToSwitchPhone(Phone phone) {
+        int subId = phone.getSubId();
+        int phoneId = phone.getPhoneId();
+
+        if (isSimReady(phoneId, subId)) return false;
+
+        boolean switchPhone = false;
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+            Rlog.i(TAG, "needToSwitchPhone SIM absent");
+            if (phoneId != 0 || isThereOtherPhone(phoneId, true)) {
+                // Prefer default Phone or other Phone with a SIM regardless of lock state.
+                switchPhone = true;
+            }
+        } else {
+            Rlog.i(TAG, "needToSwitchPhone SIM not ready");
+            if ((phoneId == 0 && isThereOtherPhone(phoneId, false))
+                    || (phoneId != 0 && isThereOtherPhone(phoneId, true))) {
+                // If there is another one with a SIM ready, switch Phones.
+                // Otherwise, prefer default Phone if both SIMs are locked.
+                switchPhone = true;
+            }
+        }
+        Rlog.i(TAG, "needToSwitchPhone " + switchPhone);
+        return switchPhone;
+    }
+
+    private boolean isThereOtherPhone(int skipPhoneId, boolean ignoreLockState) {
+        for (Phone phone : mPhoneFactoryProxy.getPhones()) {
+            int phoneId = phone.getPhoneId();
+            if (phoneId == skipPhoneId) {
+                continue;
+            }
+
+            int subId = phone.getSubId();
+            if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+                Rlog.i(TAG, "isThereOtherPhone phoneId=" + phoneId + ", subId=" + subId);
+                continue;
+            }
+            int simState = mTelephonyManagerProxy.getSimState(phoneId);
+            if ((simState == TelephonyManager.SIM_STATE_READY) || (ignoreLockState
+                    && simState != TelephonyManager.SIM_STATE_ABSENT
+                    && simState != TelephonyManager.SIM_STATE_NOT_READY)) {
+                Rlog.i(TAG, "isThereOtherPhone found, ignoreLockState=" + ignoreLockState
+                        + ", phoneId=" + phoneId + ", simState=" + simState);
+                return true;
+            }
+            Rlog.i(TAG, "isThereOtherPhone phoneId=" + phoneId + ", simState=" + simState);
+        }
+
+        return false;
+    }
 }
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index dcb3b20..e73eafd 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -3553,8 +3553,10 @@
             if (DBG) log("onCallStartFailed reasonCode=" + reasonInfo.getCode());
 
             int eccCategory = EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED;
+            List<String> emergencyUrns = new ArrayList<>();
             if (imsCall != null && imsCall.getCallProfile() != null) {
                 eccCategory = imsCall.getCallProfile().getEmergencyServiceCategories();
+                emergencyUrns = imsCall.getCallProfile().getEmergencyUrns();
             }
 
             if (mHoldSwitchingState == HoldSwapState.HOLDING_TO_ANSWER_INCOMING) {
@@ -3581,13 +3583,14 @@
                 // Since onCallInitiating and onCallProgressing reset mPendingMO,
                 // we can't depend on mPendingMO.
                 if (conn != null) {
-                    logi("onCallStartFailed eccCategory=" + eccCategory);
+                    logi("onCallStartFailed eccCategory=" + eccCategory + ", emergencyUrns="
+                            + emergencyUrns);
                     int reason = reasonInfo.getCode();
                     int extraCode = reasonInfo.getExtraCode();
                     if ((reason == ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED
                             && extraCode == ImsReasonInfo.EXTRA_CODE_CALL_RETRY_EMERGENCY)
                             || (reason == ImsReasonInfo.CODE_SIP_ALTERNATE_EMERGENCY_CALL)) {
-                        conn.setNonDetectableEmergencyCallInfo(eccCategory);
+                        conn.setNonDetectableEmergencyCallInfo(eccCategory, emergencyUrns);
                     }
                     conn.setImsReasonInfo(reasonInfo);
                     sendCallStartFailedDisconnect(imsCall, reasonInfo);
@@ -3765,11 +3768,13 @@
                     && DomainSelectionResolver.getInstance().isDomainSelectionSupported()) {
                 if (conn != null) {
                     int eccCategory = EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED;
+                    List<String> emergencyUrns = new ArrayList<>();
                     if (imsCall != null && imsCall.getCallProfile() != null) {
                         eccCategory = imsCall.getCallProfile().getEmergencyServiceCategories();
+                        emergencyUrns = imsCall.getCallProfile().getEmergencyUrns();
                         logi("onCallTerminated eccCategory=" + eccCategory);
                     }
-                    conn.setNonDetectableEmergencyCallInfo(eccCategory);
+                    conn.setNonDetectableEmergencyCallInfo(eccCategory, emergencyUrns);
                 }
                 processCallStateChange(imsCall, ImsPhoneCall.State.DISCONNECTED, cause);
                 return;
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
old mode 100755
new mode 100644
index aee8867..316f62a
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
@@ -286,13 +286,13 @@
 
         mIsEmergency = isEmergency;
         if (isEmergency) {
-            setEmergencyCallInfo(mOwner);
+            setEmergencyCallInfo(mOwner, dialArgs);
 
             if (getEmergencyNumberInfo() == null) {
                 // There was no emergency number info found for this call, however it is
                 // still marked as an emergency number. This may happen if it was a redialed
                 // non-detectable emergency call from IMS.
-                setNonDetectableEmergencyCallInfo(dialArgs.eccCategory);
+                setNonDetectableEmergencyCallInfo(dialArgs.eccCategory, new ArrayList<String>());
             }
         }
 
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramController.java b/src/java/com/android/internal/telephony/satellite/DatagramController.java
index 8271187..ff2ee9f 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramController.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramController.java
@@ -28,11 +28,14 @@
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Build;
 import android.os.Looper;
 import android.os.SystemProperties;
+import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.PersistentLogger;
 import android.telephony.Rlog;
 import android.telephony.satellite.ISatelliteDatagramCallback;
 import android.telephony.satellite.SatelliteDatagram;
@@ -41,6 +44,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlags;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -55,6 +59,7 @@
 
     @NonNull private static DatagramController sInstance;
     @NonNull private final Context mContext;
+    @NonNull private final FeatureFlags mFeatureFlags;
     @NonNull private final PointingAppController mPointingAppController;
     @NonNull private final DatagramDispatcher mDatagramDispatcher;
     @NonNull private final DatagramReceiver mDatagramReceiver;
@@ -109,6 +114,8 @@
     @GuardedBy("mLock")
     @SatelliteManager.SatelliteModemState
     private int mSatelltieModemState = SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN;
+    @Nullable
+    private PersistentLogger mPersistentLogger = null;
 
     /**
      * @return The singleton instance of DatagramController.
@@ -124,14 +131,17 @@
      * Create the DatagramController singleton instance.
      * @param context The Context to use to create the DatagramController.
      * @param looper The looper for the handler.
+     * @param featureFlags The telephony feature flags.
      * @param pointingAppController PointingAppController is used to update
      *                              PointingApp about datagram transfer state changes.
      * @return The singleton instance of DatagramController.
      */
     public static DatagramController make(@NonNull Context context, @NonNull Looper looper,
+            @NonNull FeatureFlags featureFlags,
             @NonNull PointingAppController pointingAppController) {
         if (sInstance == null) {
-            sInstance = new DatagramController(context, looper, pointingAppController);
+            sInstance = new DatagramController(
+                    context, looper, featureFlags, pointingAppController);
         }
         return sInstance;
     }
@@ -141,22 +151,27 @@
      *
      * @param context The Context for the DatagramController.
      * @param looper The looper for the handler
+     * @param featureFlags The telephony feature flags.
      * @param pointingAppController PointingAppController is used to update PointingApp
      *                              about datagram transfer state changes.
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     public DatagramController(@NonNull Context context, @NonNull Looper  looper,
+            @NonNull FeatureFlags featureFlags,
             @NonNull PointingAppController pointingAppController) {
         mContext = context;
+        mFeatureFlags = featureFlags;
         mPointingAppController = pointingAppController;
 
         // Create the DatagramDispatcher singleton,
         // which is used to send satellite datagrams.
-        mDatagramDispatcher = DatagramDispatcher.make(mContext, looper, this);
+        mDatagramDispatcher = DatagramDispatcher.make(
+                mContext, looper, mFeatureFlags, this);
 
         // Create the DatagramReceiver singleton,
         // which is used to receive satellite datagrams.
-        mDatagramReceiver = DatagramReceiver.make(mContext, looper, this);
+        mDatagramReceiver = DatagramReceiver.make(
+                mContext, looper, mFeatureFlags, this);
 
         mDatagramWaitTimeForConnectedState = getDatagramWaitForConnectedStateTimeoutMillis();
         mModemImageSwitchingDuration = getSatelliteModemImageSwitchingDurationMillis();
@@ -165,6 +180,11 @@
         mDatagramWaitTimeForConnectedStateForLastMessage =
                 getDatagramWaitForConnectedStateForLastMessageTimeoutMillis();
         mDemoModeDatagramList = new ArrayList<>();
+
+        if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
+            mPersistentLogger = new PersistentLogger(
+                    DropBoxManagerLoggerBackend.getInstance(context));
+        }
     }
 
     /**
@@ -205,7 +225,7 @@
      * @param callback The callback to get {@link SatelliteManager.SatelliteResult} of the request.
      */
     public void pollPendingSatelliteDatagrams(int subId, @NonNull Consumer<Integer> callback) {
-        logd("pollPendingSatelliteDatagrams");
+        plogd("pollPendingSatelliteDatagrams");
         mDatagramReceiver.pollPendingSatelliteDatagrams(subId, callback);
     }
 
@@ -247,13 +267,13 @@
             @SatelliteManager.SatelliteDatagramTransferState int datagramTransferState,
             int sendPendingCount, int errorCode) {
         synchronized (mLock) {
-            logd("updateSendStatus"
+            plogd("updateSendStatus"
                     + " subId: " + subId
                     + " datagramType: " + datagramType
                     + " datagramTransferState: " + datagramTransferState
                     + " sendPendingCount: " + sendPendingCount + " errorCode: " + errorCode);
             if (shouldSuppressDatagramTransferStateUpdate(datagramType)) {
-                logd("Ignore the request to update send status");
+                plogd("Ignore the request to update send status");
                 return;
             }
 
@@ -295,7 +315,7 @@
             @SatelliteManager.SatelliteDatagramTransferState int datagramTransferState,
             int receivePendingCount, int errorCode) {
         synchronized (mLock) {
-            logd("updateReceiveStatus"
+            plogd("updateReceiveStatus"
                     + " subId: " + subId
                     + " datagramTransferState: " + datagramTransferState
                     + " receivePendingCount: " + receivePendingCount + " errorCode: " + errorCode);
@@ -411,7 +431,7 @@
             }
             setDeviceAlignedWithSatellite(false);
         }
-        logd("setDemoMode: mIsDemoMode=" + mIsDemoMode);
+        plogd("setDemoMode: mIsDemoMode=" + mIsDemoMode);
     }
 
     /** Get the last sent datagram for demo mode */
@@ -422,7 +442,7 @@
         }
 
         synchronized (mLock) {
-            logd("popDemoModeDatagram");
+            plogd("popDemoModeDatagram");
             return mDemoModeDatagramList.size() > 0 ? mDemoModeDatagramList.remove(0) : null;
         }
     }
@@ -440,7 +460,7 @@
         if (mIsDemoMode && SatelliteServiceUtils.isSosMessage(datagramType)) {
             synchronized (mLock) {
                 mDemoModeDatagramList.add(datagram);
-                logd("pushDemoModeDatagram size=" + mDemoModeDatagramList.size());
+                plogd("pushDemoModeDatagram size=" + mDemoModeDatagramList.size());
             }
         }
     }
@@ -473,11 +493,11 @@
     boolean setDatagramControllerTimeoutDuration(
             boolean reset, int timeoutType, long timeoutMillis) {
         if (!isMockModemAllowed()) {
-            loge("Updating timeout duration is not allowed");
+            ploge("Updating timeout duration is not allowed");
             return false;
         }
 
-        logd("setDatagramControllerTimeoutDuration: timeoutMillis=" + timeoutMillis
+        plogd("setDatagramControllerTimeoutDuration: timeoutMillis=" + timeoutMillis
                 + ", reset=" + reset + ", timeoutType=" + timeoutType);
         if (timeoutType == TIMEOUT_TYPE_ALIGN) {
             if (reset) {
@@ -499,7 +519,7 @@
         } else if (timeoutType == TIMEOUT_TYPE_DATAGRAM_DELAY_IN_DEMO_MODE) {
             mDatagramDispatcher.setTimeoutDatagramDelayInDemoMode(reset, timeoutMillis);
         } else {
-            loge("Invalid timeout type " + timeoutType);
+            ploge("Invalid timeout type " + timeoutType);
             return false;
         }
         return true;
@@ -542,7 +562,7 @@
     private void notifyDatagramTransferStateChangedToSessionController() {
         SatelliteSessionController sessionController = SatelliteSessionController.getInstance();
         if (sessionController == null) {
-            loge("notifyDatagramTransferStateChangeToSessionController: SatelliteSessionController"
+            ploge("notifyDatagramTransferStateChangeToSessionController: SatelliteSessionController"
                     + " is not initialized yet");
         } else {
             sessionController.onDatagramTransferStateChanged(
@@ -585,7 +605,7 @@
                     @Override
                     public void accept(Integer result) {
                         if (result != SATELLITE_RESULT_SUCCESS) {
-                            logd("retryPollPendingDatagramsInDemoMode result: " + result);
+                            plogd("retryPollPendingDatagramsInDemoMode result: " + result);
                         }
                     }
                 };
@@ -633,4 +653,31 @@
     private static void loge(@NonNull String log) {
         Rlog.e(TAG, log);
     }
+
+    private boolean isSatellitePersistentLoggingEnabled(
+            @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+        if (featureFlags.satellitePersistentLogging()) {
+            return true;
+        }
+        try {
+            return context.getResources().getBoolean(
+                    R.bool.config_dropboxmanager_persistent_logging_enabled);
+        } catch (RuntimeException e) {
+            return false;
+        }
+    }
+
+    private void plogd(@NonNull String log) {
+        Rlog.d(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.debug(TAG, log);
+        }
+    }
+
+    private void ploge(@NonNull String log) {
+        Rlog.e(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.error(TAG, log);
+        }
+    }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index c4667e8..2c9463f 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -32,6 +32,8 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.PersistentLogger;
 import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.telephony.satellite.SatelliteDatagram;
@@ -41,6 +43,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.metrics.SatelliteStats;
 import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
 import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
@@ -72,6 +75,7 @@
     @NonNull private final DatagramController mDatagramController;
     @NonNull private final ControllerMetricsStats mControllerMetricsStats;
     @NonNull private final SessionMetricsStats mSessionMetricsStats;
+    @NonNull private final FeatureFlags mFeatureFlags;
 
     private boolean mIsDemoMode = false;
     private boolean mIsAligned = false;
@@ -107,18 +111,21 @@
     private long mWaitTimeForDatagramSendingForLastMessageResponse;
     @SatelliteManager.DatagramType
     private int mLastSendRequestDatagramType = DATAGRAM_TYPE_UNKNOWN;
+    @Nullable private PersistentLogger mPersistentLogger = null;
 
     /**
      * Create the DatagramDispatcher singleton instance.
      * @param context The Context to use to create the DatagramDispatcher.
      * @param looper The looper for the handler.
+     * @param featureFlags The telephony feature flags.
      * @param datagramController DatagramController which is used to update datagram transfer state.
      * @return The singleton instance of DatagramDispatcher.
      */
     public static DatagramDispatcher make(@NonNull Context context, @NonNull Looper looper,
+            @NonNull FeatureFlags featureFlags,
             @NonNull DatagramController datagramController) {
         if (sInstance == null) {
-            sInstance = new DatagramDispatcher(context, looper, datagramController);
+            sInstance = new DatagramDispatcher(context, looper, featureFlags, datagramController);
         }
         return sInstance;
     }
@@ -138,16 +145,23 @@
      *
      * @param context The Context for the DatagramDispatcher.
      * @param looper The looper for the handler.
+     * @param featureFlags The telephony feature flags.
      * @param datagramController DatagramController which is used to update datagram transfer state.
      */
     @VisibleForTesting
     protected DatagramDispatcher(@NonNull Context context, @NonNull Looper looper,
+            @NonNull FeatureFlags featureFlags,
             @NonNull DatagramController datagramController) {
         super(looper);
         mContext = context;
+        mFeatureFlags = featureFlags;
         mDatagramController = datagramController;
         mControllerMetricsStats = ControllerMetricsStats.getInstance();
         mSessionMetricsStats = SessionMetricsStats.getInstance();
+        if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
+            mPersistentLogger = new PersistentLogger(
+                    DropBoxManagerLoggerBackend.getInstance(context));
+        }
 
         synchronized (mLock) {
             mSendingDatagramInProgress = false;
@@ -219,7 +233,7 @@
 
         switch(msg.what) {
             case CMD_SEND_SATELLITE_DATAGRAM: {
-                logd("CMD_SEND_SATELLITE_DATAGRAM mIsDemoMode=" + mIsDemoMode
+                plogd("CMD_SEND_SATELLITE_DATAGRAM mIsDemoMode=" + mIsDemoMode
                         + ", shouldSendDatagramToModemInDemoMode="
                         + shouldSendDatagramToModemInDemoMode());
                 request = (DatagramDispatcherHandlerRequest) msg.obj;
@@ -251,14 +265,15 @@
                 synchronized (mLock) {
                     if (mIsDemoMode && (error == SatelliteManager.SATELLITE_RESULT_SUCCESS)) {
                         if (argument.skipCheckingSatelliteAligned) {
-                            logd("Satellite was already aligned. No need to check alignment again");
+                            plogd("Satellite was already aligned. "
+                                + "No need to check alignment again");
                         } else if (mDatagramController.waitForAligningToSatellite(mIsAligned)) {
-                            logd("Satellite is not aligned in demo mode, wait for the alignment.");
+                            plogd("Satellite is not aligned in demo mode, wait for the alignment.");
                             startSatelliteAlignedTimer(request);
                             break;
                         }
                     }
-                    logd("EVENT_SEND_SATELLITE_DATAGRAM_DONE error: " + error
+                    plogd("EVENT_SEND_SATELLITE_DATAGRAM_DONE error: " + error
                             + ", mIsDemoMode=" + mIsDemoMode);
 
                     /*
@@ -269,7 +284,7 @@
                      * 3) All pending send requests have been aborted due to some error.
                      */
                     if (!shouldProcessEventSendSatelliteDatagramDone(argument)) {
-                        logw("The message " + argument.datagramId + " was already processed");
+                        plogw("The message " + argument.datagramId + " was already processed");
                         break;
                     }
 
@@ -337,7 +352,7 @@
                 break;
 
             default:
-                logw("DatagramDispatcherHandler: unexpected message code: " + msg.what);
+                plogw("DatagramDispatcherHandler: unexpected message code: " + msg.what);
                 break;
         }
     }
@@ -379,7 +394,7 @@
             }
 
             if (mDatagramController.needsWaitingForSatelliteConnected(datagramType)) {
-                logd("sendDatagram: wait for satellite connected");
+                plogd("sendDatagram: wait for satellite connected");
                 mDatagramController.updateSendStatus(subId, datagramType,
                         SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
                         getPendingDatagramCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
@@ -394,7 +409,7 @@
                         getPendingDatagramCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
                 sendRequestAsync(CMD_SEND_SATELLITE_DATAGRAM, datagramArgs, phone);
             } else {
-                logd("sendDatagram: mSendingDatagramInProgress="
+                plogd("sendDatagram: mSendingDatagramInProgress="
                         + mSendingDatagramInProgress + ", isPollingInIdleState="
                         + mDatagramController.isPollingInIdleState());
             }
@@ -414,7 +429,7 @@
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     protected void setDemoMode(boolean isDemoMode) {
         mIsDemoMode = isDemoMode;
-        logd("setDemoMode: mIsDemoMode=" + mIsDemoMode);
+        plogd("setDemoMode: mIsDemoMode=" + mIsDemoMode);
     }
 
     /**
@@ -424,14 +439,14 @@
     public void setDeviceAlignedWithSatellite(boolean isAligned) {
         synchronized (mLock) {
             mIsAligned = isAligned;
-            logd("setDeviceAlignedWithSatellite: " + mIsAligned);
+            plogd("setDeviceAlignedWithSatellite: " + mIsAligned);
             if (isAligned && mIsDemoMode) handleEventSatelliteAligned();
         }
     }
 
     private void startSatelliteAlignedTimer(@NonNull DatagramDispatcherHandlerRequest request) {
         if (isSatelliteAlignedTimerStarted()) {
-            logd("Satellite aligned timer was already started");
+            plogd("Satellite aligned timer was already started");
             return;
         }
         mSendSatelliteDatagramRequest = request;
@@ -450,7 +465,7 @@
             stopSatelliteAlignedTimer();
 
             if (mSendSatelliteDatagramRequest == null) {
-                loge("handleEventSatelliteAligned: mSendSatelliteDatagramRequest is null");
+                ploge("handleEventSatelliteAligned: mSendSatelliteDatagramRequest is null");
             } else {
                 SendSatelliteDatagramArgument argument =
                         (SendSatelliteDatagramArgument) mSendSatelliteDatagramRequest.argument;
@@ -460,14 +475,14 @@
                 mSendSatelliteDatagramRequest = null;
                 AsyncResult.forMessage(message, null, null);
                 message.sendToTarget();
-                logd("handleEventSatelliteAligned: EVENT_SEND_SATELLITE_DATAGRAM_DONE");
+                plogd("handleEventSatelliteAligned: EVENT_SEND_SATELLITE_DATAGRAM_DONE");
             }
         }
     }
 
     private void handleEventSatelliteAlignedTimeout(
             @NonNull DatagramDispatcherHandlerRequest request) {
-        logd("handleEventSatelliteAlignedTimeout");
+        plogd("handleEventSatelliteAlignedTimeout");
         mSendSatelliteDatagramRequest = null;
         SatelliteManager.SatelliteException exception =
                 new SatelliteManager.SatelliteException(
@@ -491,15 +506,15 @@
      */
     @GuardedBy("mLock")
     private void sendPendingDatagrams() {
-        logd("sendPendingDatagrams()");
+        plogd("sendPendingDatagrams()");
         if (!mDatagramController.isPollingInIdleState()) {
             // Datagram should be sent to satellite modem when modem is free.
-            logd("sendPendingDatagrams: modem is receiving datagrams");
+            plogd("sendPendingDatagrams: modem is receiving datagrams");
             return;
         }
 
         if (getPendingDatagramCount() <= 0) {
-            logd("sendPendingDatagrams: no pending datagrams to send");
+            plogd("sendPendingDatagrams: no pending datagrams to send");
             return;
         }
 
@@ -515,7 +530,7 @@
             SendSatelliteDatagramArgument datagramArg =
                     pendingDatagram.iterator().next().getValue();
             if (mDatagramController.needsWaitingForSatelliteConnected(datagramArg.datagramType)) {
-                logd("sendPendingDatagrams: wait for satellite connected");
+                plogd("sendPendingDatagrams: wait for satellite connected");
                 return;
             }
 
@@ -542,7 +557,7 @@
         if (pendingDatagramsMap.size() == 0) {
             return;
         }
-        loge("sendErrorCodeAndCleanupPendingDatagrams: cleaning up resources");
+        ploge("sendErrorCodeAndCleanupPendingDatagrams: cleaning up resources");
 
         // Send error code to all the pending datagrams
         for (Entry<Long, SendSatelliteDatagramArgument> entry :
@@ -565,7 +580,7 @@
     @GuardedBy("mLock")
     private void abortSendingPendingDatagrams(int subId,
             @SatelliteManager.SatelliteResult int errorCode) {
-        logd("abortSendingPendingDatagrams()");
+        plogd("abortSendingPendingDatagrams()");
         sendErrorCodeAndCleanupPendingDatagrams(mPendingEmergencyDatagramsMap, errorCode);
         sendErrorCodeAndCleanupPendingDatagrams(mPendingNonEmergencyDatagramsMap, errorCode);
     }
@@ -653,7 +668,7 @@
         synchronized (mLock) {
             if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF
                     || state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE) {
-                logd("onSatelliteModemStateChanged: cleaning up resources");
+                plogd("onSatelliteModemStateChanged: cleaning up resources");
                 cleanUpResources();
             } else if (state == SatelliteManager.SATELLITE_MODEM_STATE_IDLE) {
                 sendPendingDatagrams();
@@ -669,7 +684,7 @@
 
     @GuardedBy("mLock")
     private void cleanUpResources() {
-        logd("cleanUpResources");
+        plogd("cleanUpResources");
         mSendingDatagramInProgress = false;
         if (getPendingDatagramCount() > 0) {
             mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
@@ -697,7 +712,7 @@
     private void startDatagramWaitForConnectedStateTimer(
             @NonNull SendSatelliteDatagramArgument datagramArgs) {
         if (isDatagramWaitForConnectedStateTimerStarted()) {
-            logd("DatagramWaitForConnectedStateTimer is already started");
+            plogd("DatagramWaitForConnectedStateTimer is already started");
             return;
         }
         sendMessageDelayed(obtainMessage(
@@ -729,7 +744,7 @@
     private void startWaitForDatagramSendingResponseTimer(
             @NonNull SendSatelliteDatagramArgument argument) {
         if (hasMessages(EVENT_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMED_OUT)) {
-            logd("WaitForDatagramSendingResponseTimer was already started");
+            plogd("WaitForDatagramSendingResponseTimer was already started");
             return;
         }
         long waitTime = SatelliteServiceUtils.isLastSosMessage(argument.datagramType)
@@ -747,7 +762,7 @@
 
     private void handleEventDatagramWaitForConnectedStateTimedOut(
             @NonNull SendSatelliteDatagramArgument argument) {
-        logw("Timed out to wait for satellite connected before sending datagrams");
+        plogw("Timed out to wait for satellite connected before sending datagrams");
         synchronized (mLock) {
             // Update send status
             mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
@@ -776,7 +791,7 @@
             return mShouldSendDatagramToModemInDemoMode.get();
 
         } catch (Resources.NotFoundException ex) {
-            loge("shouldSendDatagramToModemInDemoMode: id= "
+            ploge("shouldSendDatagramToModemInDemoMode: id= "
                     + R.bool.config_send_satellite_datagram_to_modem_in_demo_mode + ", ex=" + ex);
             return false;
         }
@@ -806,7 +821,7 @@
     private void handleEventWaitForDatagramSendingResponseTimedOut(
             @NonNull SendSatelliteDatagramArgument argument) {
         synchronized (mLock) {
-            logw("Timed out to wait for the response of the request to send the datagram "
+            plogw("Timed out to wait for the response of the request to send the datagram "
                     + argument.datagramId);
 
             // Ask vendor service to abort all datagram-sending requests
@@ -851,7 +866,7 @@
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     protected void setShouldSendDatagramToModemInDemoMode(
             @Nullable Boolean shouldSendToModemInDemoMode) {
-        logd("setShouldSendDatagramToModemInDemoMode(" + (shouldSendToModemInDemoMode == null
+        plogd("setShouldSendDatagramToModemInDemoMode(" + (shouldSendToModemInDemoMode == null
                 ? "null" : shouldSendToModemInDemoMode) + ")");
 
         if (shouldSendToModemInDemoMode == null) {
@@ -869,12 +884,12 @@
     private void startWaitForSimulatedPollDatagramsDelayTimer(
             @NonNull DatagramDispatcherHandlerRequest request) {
         if (mIsDemoMode) {
-            logd("startWaitForSimulatedPollDatagramsDelayTimer");
+            plogd("startWaitForSimulatedPollDatagramsDelayTimer");
             sendMessageDelayed(
                     obtainMessage(EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT, request),
                     getDemoTimeoutDuration());
         } else {
-            logd("Should not start WaitForSimulatedPollDatagramsDelayTimer in non-demo mode");
+            plogd("Should not start WaitForSimulatedPollDatagramsDelayTimer in non-demo mode");
         }
     }
 
@@ -885,17 +900,17 @@
     private void handleEventWaitForSimulatedPollDatagramsDelayTimedOut(
             @NonNull SendSatelliteDatagramArgument argument) {
         if (mIsDemoMode) {
-            logd("handleEventWaitForSimulatedPollDatagramsDelayTimedOut");
+            plogd("handleEventWaitForSimulatedPollDatagramsDelayTimedOut");
             mDatagramController.pushDemoModeDatagram(argument.datagramType, argument.datagram);
             Consumer<Integer> internalCallback = new Consumer<Integer>() {
                 @Override
                 public void accept(Integer result) {
-                    logd("pollPendingSatelliteDatagrams result: " + result);
+                    plogd("pollPendingSatelliteDatagrams result: " + result);
                 }
             };
             mDatagramController.pollPendingSatelliteDatagrams(argument.subId, internalCallback);
         } else {
-            logd("Unexpected EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT in "
+            plogd("Unexpected EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT in "
                     + "non-demo mode");
         }
     }
@@ -916,7 +931,7 @@
         } else {
             mDemoTimeoutDuration = timeoutMillis;
         }
-        logd("setTimeoutDatagramDelayInDemoMode " + mDemoTimeoutDuration + " reset=" + reset);
+        plogd("setTimeoutDatagramDelayInDemoMode " + mDemoTimeoutDuration + " reset=" + reset);
     }
 
     private static void logd(@NonNull String log) {
@@ -928,4 +943,38 @@
     }
 
     private static void logw(@NonNull String log) { Rlog.w(TAG, log); }
+
+    private boolean isSatellitePersistentLoggingEnabled(
+            @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+        if (featureFlags.satellitePersistentLogging()) {
+            return true;
+        }
+        try {
+            return context.getResources().getBoolean(
+                    R.bool.config_dropboxmanager_persistent_logging_enabled);
+        } catch (RuntimeException e) {
+            return false;
+        }
+    }
+
+    private void plogd(@NonNull String log) {
+        Rlog.d(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.debug(TAG, log);
+        }
+    }
+
+    private void plogw(@NonNull String log) {
+        Rlog.w(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.warn(TAG, log);
+        }
+    }
+
+    private void ploge(@NonNull String log) {
+        Rlog.e(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.error(TAG, log);
+        }
+    }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
index 21e4318..ea75f03 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
@@ -37,6 +37,8 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.provider.Telephony;
+import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.PersistentLogger;
 import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.telephony.satellite.ISatelliteDatagramCallback;
@@ -50,6 +52,7 @@
 import com.android.internal.telephony.IIntegerConsumer;
 import com.android.internal.telephony.IVoidConsumer;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.metrics.SatelliteStats;
 import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
 import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
@@ -83,6 +86,7 @@
     @NonNull private final ControllerMetricsStats mControllerMetricsStats;
     @NonNull private final SessionMetricsStats mSessionMetricsStats;
     @NonNull private final Looper mLooper;
+    @NonNull private final FeatureFlags mFeatureFlags;
 
     private long mDatagramTransferStartTime = 0;
     private boolean mIsDemoMode = false;
@@ -93,6 +97,8 @@
     @Nullable
     private DatagramReceiverHandlerRequest mPendingPollSatelliteDatagramsRequest = null;
     private final Object mLock = new Object();
+    @Nullable
+    private PersistentLogger mPersistentLogger = null;
 
     /**
      * Map key: subId, value: SatelliteDatagramListenerHandler to notify registrants.
@@ -112,13 +118,15 @@
      * Create the DatagramReceiver singleton instance.
      * @param context The Context to use to create the DatagramReceiver.
      * @param looper The looper for the handler.
+     * @param featureFlags The telephony feature flags.
      * @param datagramController DatagramController which is used to update datagram transfer state.
      * @return The singleton instance of DatagramReceiver.
      */
     public static DatagramReceiver make(@NonNull Context context, @NonNull Looper looper,
+            @NonNull FeatureFlags featureFlags,
             @NonNull DatagramController datagramController) {
         if (sInstance == null) {
-            sInstance = new DatagramReceiver(context, looper, datagramController);
+            sInstance = new DatagramReceiver(context, looper, featureFlags, datagramController);
         }
         return sInstance;
     }
@@ -129,25 +137,31 @@
      *
      * @param context The Context for the DatagramReceiver.
      * @param looper The looper for the handler.
+     * @param featureFlags The telephony feature flags.
      * @param datagramController DatagramController which is used to update datagram transfer state.
      */
     @VisibleForTesting
     protected DatagramReceiver(@NonNull Context context, @NonNull Looper looper,
+            @NonNull FeatureFlags featureFlags,
             @NonNull DatagramController datagramController) {
         super(looper);
         mContext = context;
         mLooper = looper;
+        mFeatureFlags = featureFlags;
         mContentResolver = context.getContentResolver();
         mDatagramController = datagramController;
         mControllerMetricsStats = ControllerMetricsStats.getInstance();
         mSessionMetricsStats = SessionMetricsStats.getInstance();
-
+        if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
+            mPersistentLogger = new PersistentLogger(
+                    DropBoxManagerLoggerBackend.getInstance(context));
+        }
         try {
             mSharedPreferences =
                     mContext.getSharedPreferences(SatelliteController.SATELLITE_SHARED_PREF,
                             Context.MODE_PRIVATE);
         } catch (Exception e) {
-            loge("Cannot get default shared preferences: " + e);
+            ploge("Cannot get default shared preferences: " + e);
         }
     }
 
@@ -457,7 +471,7 @@
                     }
                 }
 
-                logd("EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE error: " + error);
+                plogd("EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE error: " + error);
                 if (error != SatelliteManager.SATELLITE_RESULT_SUCCESS) {
                     mDatagramController.updateReceiveStatus(request.subId,
                             SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
@@ -485,7 +499,7 @@
                 break;
 
             default:
-                logw("DatagramDispatcherHandler: unexpected message code: " + msg.what);
+                plogw("DatagramDispatcherHandler: unexpected message code: " + msg.what);
                 break;
         }
     }
@@ -558,7 +572,7 @@
     public void pollPendingSatelliteDatagrams(int subId, @NonNull Consumer<Integer> callback) {
         if (!mDatagramController.isPollingInIdleState()) {
             // Poll request should be sent to satellite modem only when it is free.
-            logd("pollPendingSatelliteDatagrams: satellite modem is busy receiving datagrams.");
+            plogd("pollPendingSatelliteDatagrams: satellite modem is busy receiving datagrams.");
             callback.accept(SatelliteManager.SATELLITE_RESULT_MODEM_BUSY);
             return;
         }
@@ -570,7 +584,7 @@
             if (isDatagramWaitForConnectedStateTimerStarted()) {
                 stopDatagramWaitForConnectedStateTimer();
                 if (mPendingPollSatelliteDatagramsRequest == null) {
-                    loge("handleSatelliteConnectedEvent: mPendingPollSatelliteDatagramsRequest is"
+                    ploge("handleSatelliteConnectedEvent: mPendingPollSatelliteDatagramsRequest is"
                             + " null");
                     return;
                 }
@@ -588,7 +602,7 @@
             @NonNull Consumer<Integer> callback) {
         if (!mDatagramController.isSendingInIdleState()) {
             // Poll request should be sent to satellite modem only when it is free.
-            logd("pollPendingSatelliteDatagramsInternal: satellite modem is busy sending "
+            plogd("pollPendingSatelliteDatagramsInternal: satellite modem is busy sending "
                     + "datagrams.");
             callback.accept(SatelliteManager.SATELLITE_RESULT_MODEM_BUSY);
             return;
@@ -596,7 +610,7 @@
 
         if (mDatagramController.needsWaitingForSatelliteConnected(
                 SatelliteManager.DATAGRAM_TYPE_UNKNOWN)) {
-            logd("pollPendingSatelliteDatagramsInternal: wait for satellite connected");
+            plogd("pollPendingSatelliteDatagramsInternal: wait for satellite connected");
             synchronized (mLock) {
                 mPendingPollSatelliteDatagramsRequest = new DatagramReceiverHandlerRequest(
                         callback, SatelliteServiceUtils.getPhone(), subId);
@@ -644,7 +658,7 @@
         synchronized (mLock) {
             if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF
                     || state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE) {
-                logd("onSatelliteModemStateChanged: cleaning up resources");
+                plogd("onSatelliteModemStateChanged: cleaning up resources");
                 cleanUpResources();
             } else if (state == SATELLITE_MODEM_STATE_CONNECTED) {
                 handleSatelliteConnectedEvent();
@@ -657,7 +671,7 @@
         if (isSatelliteAlignedTimerStarted()) {
             stopSatelliteAlignedTimer();
             if (mDemoPollPendingSatelliteDatagramsRequest == null) {
-                loge("Satellite aligned timer was started "
+                ploge("Satellite aligned timer was started "
                         + "but mDemoPollPendingSatelliteDatagramsRequest is null");
             } else {
                 Consumer<Integer> callback =
@@ -755,14 +769,14 @@
     public void setDeviceAlignedWithSatellite(boolean isAligned) {
         synchronized (mLock) {
             mIsAligned = isAligned;
-            logd("setDeviceAlignedWithSatellite: " + mIsAligned);
+            plogd("setDeviceAlignedWithSatellite: " + mIsAligned);
             if (isAligned && mIsDemoMode) handleEventSatelliteAligned();
         }
     }
 
     private void startSatelliteAlignedTimer(DatagramReceiverHandlerRequest request) {
         if (isSatelliteAlignedTimerStarted()) {
-            logd("Satellite aligned timer was already started");
+            plogd("Satellite aligned timer was already started");
             return;
         }
         mDemoPollPendingSatelliteDatagramsRequest = request;
@@ -781,7 +795,7 @@
             stopSatelliteAlignedTimer();
 
             if (mDemoPollPendingSatelliteDatagramsRequest == null) {
-                loge("handleSatelliteAlignedTimer: mDemoPollPendingSatelliteDatagramsRequest "
+                ploge("handleSatelliteAlignedTimer: mDemoPollPendingSatelliteDatagramsRequest "
                         + "is null");
             } else {
                 Message message = obtainMessage(
@@ -813,7 +827,7 @@
 
     private void startDatagramWaitForConnectedStateTimer() {
         if (isDatagramWaitForConnectedStateTimerStarted()) {
-            logd("DatagramWaitForConnectedStateTimer is already started");
+            plogd("DatagramWaitForConnectedStateTimer is already started");
             return;
         }
         sendMessageDelayed(obtainMessage(
@@ -833,12 +847,12 @@
     private void handleEventDatagramWaitForConnectedStateTimedOut() {
         synchronized (mLock) {
             if (mPendingPollSatelliteDatagramsRequest == null) {
-                logw("handleEventDatagramWaitForConnectedStateTimedOut: "
+                plogw("handleEventDatagramWaitForConnectedStateTimedOut: "
                         + "mPendingPollSatelliteDatagramsRequest is null");
                 return;
             }
 
-            logw("Timed out to wait for satellite connected before polling datagrams");
+            plogw("Timed out to wait for satellite connected before polling datagrams");
             mDatagramController.updateReceiveStatus(mPendingPollSatelliteDatagramsRequest.subId,
                     SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
                     mDatagramController.getReceivePendingCount(),
@@ -877,4 +891,38 @@
     private static void logw(@NonNull String log) {
         Rlog.w(TAG, log);
     }
+
+    private boolean isSatellitePersistentLoggingEnabled(
+            @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+        if (featureFlags.satellitePersistentLogging()) {
+            return true;
+        }
+        try {
+            return context.getResources().getBoolean(
+                    R.bool.config_dropboxmanager_persistent_logging_enabled);
+        } catch (RuntimeException e) {
+            return false;
+        }
+    }
+
+    private void plogd(@NonNull String log) {
+        Rlog.d(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.debug(TAG, log);
+        }
+    }
+
+    private void plogw(@NonNull String log) {
+        Rlog.w(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.warn(TAG, log);
+        }
+    }
+
+    private void ploge(@NonNull String log) {
+        Rlog.e(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.error(TAG, log);
+        }
+    }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java b/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
index 65a25ea..dfc7919 100644
--- a/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
+++ b/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
@@ -47,7 +47,8 @@
         SatelliteController satelliteController = SatelliteController.getInstance();
         List<String> satellitePlmnList = satelliteController.getSatellitePlmnsForCarrier(subId);
         for (String satellitePlmn : satellitePlmnList) {
-            if (TextUtils.equals(satellitePlmn, registeredPlmn)) {
+            if (TextUtils.equals(satellitePlmn, registeredPlmn)
+                    && networkRegistrationInfo.isInService()) {
                 logd("Registered to satellite PLMN " + satellitePlmn);
                 networkRegistrationInfo.setIsNonTerrestrialNetwork(true);
                 networkRegistrationInfo.setAvailableServices(
diff --git a/src/java/com/android/internal/telephony/satellite/PointingAppController.java b/src/java/com/android/internal/telephony/satellite/PointingAppController.java
index d6b40ca..06281c7 100644
--- a/src/java/com/android/internal/telephony/satellite/PointingAppController.java
+++ b/src/java/com/android/internal/telephony/satellite/PointingAppController.java
@@ -34,6 +34,8 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.SystemProperties;
+import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.PersistentLogger;
 import android.telephony.Rlog;
 import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
 import android.telephony.satellite.PointingInfo;
@@ -42,6 +44,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlags;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -60,6 +63,7 @@
     @NonNull
     private static PointingAppController sInstance;
     @NonNull private final Context mContext;
+    @NonNull private final FeatureFlags mFeatureFlags;
     private boolean mStartedSatelliteTransmissionUpdates;
     private boolean mLastNeedFullScreenPointingUI;
     private boolean mLastIsDemoMode;
@@ -74,6 +78,7 @@
      */
     private final ConcurrentHashMap<Integer, SatelliteTransmissionUpdateHandler>
             mSatelliteTransmissionUpdateHandlers = new ConcurrentHashMap<>();
+    @Nullable private PersistentLogger mPersistentLogger = null;
 
     /**
      * @return The singleton instance of PointingAppController.
@@ -88,11 +93,13 @@
     /**
      * Create the PointingAppController singleton instance.
      * @param context The Context to use to create the PointingAppController.
+     * @param featureFlags The telephony feature flags.
      * @return The singleton instance of PointingAppController.
      */
-    public static PointingAppController make(@NonNull Context context) {
+    public static PointingAppController make(@NonNull Context context,
+            @NonNull FeatureFlags featureFlags) {
         if (sInstance == null) {
-            sInstance = new PointingAppController(context);
+            sInstance = new PointingAppController(context, featureFlags);
         }
         return sInstance;
     }
@@ -103,14 +110,20 @@
      * @param context The Context for the PointingUIController.
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
-    public PointingAppController(@NonNull Context context) {
+    public PointingAppController(@NonNull Context context,
+            @NonNull FeatureFlags featureFlags) {
         mContext = context;
+        mFeatureFlags = featureFlags;
         mStartedSatelliteTransmissionUpdates = false;
         mLastNeedFullScreenPointingUI = false;
         mLastIsDemoMode = false;
         mLastIsEmergency = false;
         mListenerForPointingUIRegistered = false;
         mActivityManager = mContext.getSystemService(ActivityManager.class);
+        if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
+            mPersistentLogger = new PersistentLogger(
+                    DropBoxManagerLoggerBackend.getInstance(context));
+        }
     }
 
     /**
@@ -147,7 +160,7 @@
 
             if (callerPackages != null) {
                 if (Arrays.stream(callerPackages).anyMatch(pointingUiPackage::contains)) {
-                    logd("Restarting pointingUI");
+                    plogd("Restarting pointingUI");
                     startPointingUI(mLastNeedFullScreenPointingUI, mLastIsDemoMode,
                             mLastIsEmergency);
                 }
@@ -331,7 +344,7 @@
      */
     public void startSatelliteTransmissionUpdates(@NonNull Message message) {
         if (mStartedSatelliteTransmissionUpdates) {
-            logd("startSatelliteTransmissionUpdates: already started");
+            plogd("startSatelliteTransmissionUpdates: already started");
             AsyncResult.forMessage(message, null, new SatelliteManager.SatelliteException(
                     SatelliteManager.SATELLITE_RESULT_SUCCESS));
             message.sendToTarget();
@@ -359,7 +372,7 @@
             boolean isEmergency) {
         String packageName = getPointingUiPackageName();
         if (TextUtils.isEmpty(packageName)) {
-            logd("startPointingUI: config_pointing_ui_package is not set. Ignore the request");
+            plogd("startPointingUI: config_pointing_ui_package is not set. Ignore the request");
             return;
         }
 
@@ -373,10 +386,10 @@
             launchIntent = mContext.getPackageManager().getLaunchIntentForPackage(packageName);
         }
         if (launchIntent == null) {
-            loge("startPointingUI: launchIntent is null");
+            ploge("startPointingUI: launchIntent is null");
             return;
         }
-        logd("startPointingUI: needFullScreenPointingUI: " + needFullScreenPointingUI
+        plogd("startPointingUI: needFullScreenPointingUI: " + needFullScreenPointingUI
                 + ", isDemoMode: " + isDemoMode + ", isEmergency: " + isEmergency);
         launchIntent.putExtra("needFullScreen", needFullScreenPointingUI);
         launchIntent.putExtra("isDemoMode", isDemoMode);
@@ -393,7 +406,7 @@
             mLastIsEmergency = isEmergency;
             mContext.startActivity(launchIntent);
         } catch (ActivityNotFoundException ex) {
-            loge("startPointingUI: Pointing UI app activity is not found, ex=" + ex);
+            ploge("startPointingUI: Pointing UI app activity is not found, ex=" + ex);
         }
     }
 
@@ -422,7 +435,7 @@
                     request);
             msg.sendToTarget();
         } else {
-            loge("SatelliteTransmissionUpdateHandler not found for subId: " + subId);
+            ploge("SatelliteTransmissionUpdateHandler not found for subId: " + subId);
         }
     }
 
@@ -441,7 +454,7 @@
                     request);
             msg.sendToTarget();
         } else {
-            loge(" SatelliteTransmissionUpdateHandler not found for subId: " + subId);
+            ploge(" SatelliteTransmissionUpdateHandler not found for subId: " + subId);
         }
     }
 
@@ -456,12 +469,12 @@
     boolean setSatellitePointingUiClassName(
             @Nullable String packageName, @Nullable String className) {
         if (!isMockModemAllowed()) {
-            loge("setSatellitePointingUiClassName: modifying satellite pointing UI package and "
+            ploge("setSatellitePointingUiClassName: modifying satellite pointing UI package and "
                     + "class name is not allowed");
             return false;
         }
 
-        logd("setSatellitePointingUiClassName: config_pointing_ui_package is updated, new "
+        plogd("setSatellitePointingUiClassName: config_pointing_ui_package is updated, new "
                 + "packageName=" + packageName
                 + ", config_pointing_ui_class new className=" + className);
 
@@ -507,6 +520,33 @@
     private static void loge(@NonNull String log) {
         Rlog.e(TAG, log);
     }
+
+    private boolean isSatellitePersistentLoggingEnabled(
+            @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+        if (featureFlags.satellitePersistentLogging()) {
+            return true;
+        }
+        try {
+            return context.getResources().getBoolean(
+                    R.bool.config_dropboxmanager_persistent_logging_enabled);
+        } catch (RuntimeException e) {
+            return false;
+        }
+    }
+
+    private void plogd(@NonNull String log) {
+        Rlog.d(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.debug(TAG, log);
+        }
+    }
+
+    private void ploge(@NonNull String log) {
+        Rlog.e(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.error(TAG, log);
+        }
+    }
     /**
      * TODO: The following needs to be added in this class:
      * - check if pointingUI crashes - then restart it
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 3a63ac3..f826f0b 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -82,8 +82,11 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.provider.Telephony;
+import android.telephony.AccessNetworkConstants;
 import android.telephony.CarrierConfigManager;
+import android.telephony.DropBoxManagerLoggerBackend;
 import android.telephony.NetworkRegistrationInfo;
+import android.telephony.PersistentLogger;
 import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
@@ -315,6 +318,8 @@
     private final Object mIsSatelliteEnabledLock = new Object();
     @GuardedBy("mIsSatelliteEnabledLock")
     private Boolean mIsSatelliteEnabled = null;
+    private final Object mIsRadioOnLock = new Object();
+    @GuardedBy("mIsRadioOnLock")
     private boolean mIsRadioOn = false;
     private final Object mSatelliteViaOemProvisionLock = new Object();
     @GuardedBy("mSatelliteViaOemProvisionLock")
@@ -397,6 +402,8 @@
     private int mDelayInSendingEventDisplayEmergencyMessage = 0;
     @NonNull private SharedPreferences mSharedPreferences = null;
 
+    @Nullable private PersistentLogger mPersistentLogger = null;
+
     /**
      * Key : Subscription ID, Value: {@code true} if the EntitlementStatus is enabled,
      * {@code false} otherwise.
@@ -418,6 +425,11 @@
     private long mWaitTimeForSatelliteEnablingResponse;
     private long mDemoPointingAlignedDurationMillis;
     private long mDemoPointingNotAlignedDurationMillis;
+    private final Object mLock = new Object();
+    @GuardedBy("mLock")
+    private long mLastEmergencyCallTime;
+    private long mSatelliteEmergencyModeDurationMillis;
+    private static final int DEFAULT_SATELLITE_EMERGENCY_MODE_DURATION_SECONDS = 300;
 
     /** Key used to read/write satellite system notification done in shared preferences. */
     private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY =
@@ -436,6 +448,9 @@
     private long mSessionStartTimeStamp;
     private long mSessionProcessingTimeStamp;
 
+    // Variable for backup and restore device's screen rotation settings.
+    private String mDeviceRotationLockToBackupAndRestore = null;
+
     /**
      * @return The singleton instance of SatelliteController.
      */
@@ -472,6 +487,11 @@
             @NonNull Context context, @NonNull Looper looper, @NonNull FeatureFlags featureFlags) {
         super(looper);
 
+        if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
+            mPersistentLogger = new PersistentLogger(
+                    DropBoxManagerLoggerBackend.getInstance(context));
+        }
+
         mContext = context;
         mFeatureFlags = featureFlags;
         Phone phone = SatelliteServiceUtils.getPhone();
@@ -479,11 +499,12 @@
         mDSM = phone.getDeviceStateMonitor();
         // Create the SatelliteModemInterface singleton, which is used to manage connections
         // to the satellite service and HAL interface.
-        mSatelliteModemInterface = SatelliteModemInterface.make(mContext, this);
+        mSatelliteModemInterface = SatelliteModemInterface.make(
+                mContext, this, mFeatureFlags);
 
         // Create the PointingUIController singleton,
         // which is used to manage interactions with PointingUI app.
-        mPointingAppController = PointingAppController.make(mContext);
+        mPointingAppController = PointingAppController.make(mContext, mFeatureFlags);
 
         // Create the SatelliteControllerMetrics to report controller metrics
         // should be called before making DatagramController
@@ -496,10 +517,14 @@
 
         // Create the DatagramController singleton,
         // which is used to send and receive satellite datagrams.
-        mDatagramController = DatagramController.make(mContext, looper, mPointingAppController);
+        mDatagramController = DatagramController.make(
+                mContext, looper, mFeatureFlags, mPointingAppController);
 
         mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
-        mIsRadioOn = phone.isRadioOn();
+        synchronized (mIsRadioOnLock) {
+            mIsRadioOn = phone.isRadioOn();
+        }
+
         registerForSatelliteProvisionStateChanged();
         registerForPendingDatagramCount();
         registerForSatelliteModemStateChanged();
@@ -550,6 +575,8 @@
         mDemoPointingAlignedDurationMillis = getDemoPointingAlignedDurationMillisFromResources();
         mDemoPointingNotAlignedDurationMillis =
                 getDemoPointingNotAlignedDurationMillisFromResources();
+        mSatelliteEmergencyModeDurationMillis =
+                getSatelliteEmergencyModeDurationFromOverlayConfig(context);
     }
 
     /**
@@ -613,10 +640,10 @@
                 String satelliteModeRadios = Settings.Global.getString(mContentResolver,
                         Settings.Global.SATELLITE_MODE_RADIOS);
                 if (satelliteModeRadios == null) {
-                    loge("initializeSatelliteModeRadios: satelliteModeRadios is null");
+                    ploge("initializeSatelliteModeRadios: satelliteModeRadios is null");
                     return;
                 }
-                logd("Radios To be checked when satellite is on: " + satelliteModeRadios);
+                plogd("Radios To be checked when satellite is on: " + satelliteModeRadios);
 
                 if (satelliteModeRadios.contains(Settings.Global.RADIO_BLUETOOTH)) {
                     BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
@@ -653,7 +680,7 @@
                     // Unregister receiver before registering it.
                     mContext.unregisterReceiver(mBTWifiNFCSateReceiver);
                 } catch (IllegalArgumentException e) {
-                    logd("initializeSatelliteModeRadios: unregisterReceiver, e=" + e);
+                    plogd("initializeSatelliteModeRadios: unregisterReceiver, e=" + e);
                 }
                 mContext.registerReceiver(mBTWifiNFCSateReceiver, radioStateIntentFilter);
 
@@ -674,12 +701,12 @@
                     }
                 }
 
-                logd("mDisableBTOnSatelliteEnabled: " + mDisableBTOnSatelliteEnabled
+                plogd("mDisableBTOnSatelliteEnabled: " + mDisableBTOnSatelliteEnabled
                         + " mDisableNFCOnSatelliteEnabled: " + mDisableNFCOnSatelliteEnabled
                         + " mDisableWifiOnSatelliteEnabled: " + mDisableWifiOnSatelliteEnabled
                         + " mDisableUWBOnSatelliteEnabled: " + mDisableUWBOnSatelliteEnabled);
 
-                logd("mBTStateEnabled: " + mBTStateEnabled
+                plogd("mBTStateEnabled: " + mBTStateEnabled
                         + " mNfcStateEnabled: " + mNfcStateEnabled
                         + " mWifiStateEnabled: " + mWifiStateEnabled
                         + " mUwbStateEnabled: " + mUwbStateEnabled);
@@ -707,8 +734,8 @@
 
         @Override
         public void onStateChanged(int state, int reason) {
-            logd("UwbAdapterStateCallback#onStateChanged() called, state = " + toString(state));
-            logd("Adapter state changed reason " + String.valueOf(reason));
+            plogd("UwbAdapterStateCallback#onStateChanged() called, state = " + toString(state));
+            plogd("Adapter state changed reason " + String.valueOf(reason));
             synchronized (mRadioStateLock) {
                 if (state == UwbManager.AdapterStateCallback.STATE_DISABLED) {
                     mUwbStateEnabled = false;
@@ -716,7 +743,7 @@
                 } else {
                     mUwbStateEnabled = true;
                 }
-                logd("mUwbStateEnabled: " + mUwbStateEnabled);
+                plogd("mUwbStateEnabled: " + mUwbStateEnabled);
             }
         }
     }
@@ -726,7 +753,7 @@
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
             if (action == null) {
-                logd("BTWifiNFCStateReceiver NULL action for intent " + intent);
+                plogd("BTWifiNFCStateReceiver NULL action for intent " + intent);
                 return;
             }
 
@@ -743,7 +770,7 @@
                             mBTStateEnabled = true;
                         }
                         if (currentBTStateEnabled != mBTStateEnabled) {
-                            logd("mBTStateEnabled=" + mBTStateEnabled);
+                            plogd("mBTStateEnabled=" + mBTStateEnabled);
                         }
                     }
                     break;
@@ -759,7 +786,7 @@
                             evaluateToSendSatelliteEnabledSuccess();
                         }
                         if (currentNfcStateEnabled != mNfcStateEnabled) {
-                            logd("mNfcStateEnabled=" + mNfcStateEnabled);
+                            plogd("mNfcStateEnabled=" + mNfcStateEnabled);
                         }
                     }
                     break;
@@ -776,7 +803,7 @@
                             evaluateToSendSatelliteEnabledSuccess();
                         }
                         if (currentWifiStateEnabled != mWifiStateEnabled) {
-                            logd("mWifiStateEnabled=" + mWifiStateEnabled);
+                            plogd("mWifiStateEnabled=" + mWifiStateEnabled);
                         }
                     }
                     break;
@@ -965,14 +992,14 @@
                 RequestSatelliteEnabledArgument argument =
                         (RequestSatelliteEnabledArgument) request.argument;
                 int error =  SatelliteServiceUtils.getSatelliteError(ar, "setSatelliteEnabled");
-                logd("EVENT_SET_SATELLITE_ENABLED_DONE = " + error);
+                plogd("EVENT_SET_SATELLITE_ENABLED_DONE = " + error);
 
                 /*
                  * The timer to wait for EVENT_SET_SATELLITE_ENABLED_DONE might have expired and
                  * thus the request resources might have been cleaned up.
                  */
                 if (!shouldProcessEventSetSatelliteEnabledDone(argument)) {
-                    logw("The request ID=" + argument.requestId + ", enableSatellite="
+                    plogw("The request ID=" + argument.requestId + ", enableSatellite="
                             + argument.enableSatellite + " was already processed");
                     return;
                 }
@@ -984,6 +1011,7 @@
                             mWaitingForRadioDisabled = true;
                         }
                         setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_TRUE);
+                        setSettingsKeyToAllowDeviceRotation(SATELLITE_MODE_ENABLED_TRUE);
                         evaluateToSendSatelliteEnabledSuccess();
                     } else {
                         /**
@@ -1010,7 +1038,7 @@
                                         SATELLITE_RESULT_SUCCESS,
                                         argument.callback);
                             } else {
-                                logd("Wait for satellite modem off before updating satellite"
+                                plogd("Wait for satellite modem off before updating satellite"
                                         + " modem state");
                             }
                             mWaitingForDisableSatelliteModemResponse = false;
@@ -1064,6 +1092,8 @@
 
                     mControllerMetricsStats.onSatelliteDisabled();
 
+                    handlePersistentLoggingOnSessionEnd(mIsEmergency);
+
                     synchronized (mIsSatelliteEnabledLock) {
                         mWaitingForDisableSatelliteModemResponse = false;
                     }
@@ -1091,11 +1121,11 @@
                 Bundle bundle = new Bundle();
                 if (error == SATELLITE_RESULT_SUCCESS) {
                     if (ar.result == null) {
-                        loge("isSatelliteEnabled: result is null");
+                        ploge("isSatelliteEnabled: result is null");
                         error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
                     } else {
                         boolean enabled = ((int[]) ar.result)[0] == 1;
-                        if (DBG) logd("isSatelliteEnabled: " + enabled);
+                        if (DBG) plogd("isSatelliteEnabled: " + enabled);
                         bundle.putBoolean(SatelliteManager.KEY_SATELLITE_ENABLED, enabled);
                         updateSatelliteEnabledState(enabled, "EVENT_IS_SATELLITE_ENABLED_DONE");
                     }
@@ -1120,11 +1150,11 @@
                 Bundle bundle = new Bundle();
                 if (error == SATELLITE_RESULT_SUCCESS) {
                     if (ar.result == null) {
-                        loge("isSatelliteSupported: result is null");
+                        ploge("isSatelliteSupported: result is null");
                         error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
                     } else {
                         boolean supported = (boolean) ar.result;
-                        logd("isSatelliteSupported: " + supported);
+                        plogd("isSatelliteSupported: " + supported);
                         bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, supported);
                         updateSatelliteSupportedStateWhenSatelliteServiceConnected(supported);
                     }
@@ -1148,14 +1178,14 @@
                 Bundle bundle = new Bundle();
                 if (error == SATELLITE_RESULT_SUCCESS) {
                     if (ar.result == null) {
-                        loge("getSatelliteCapabilities: result is null");
+                        ploge("getSatelliteCapabilities: result is null");
                         error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
                     } else {
                         SatelliteCapabilities capabilities = (SatelliteCapabilities) ar.result;
                         synchronized (mNeedsSatellitePointingLock) {
                             mNeedsSatellitePointing = capabilities.isPointingRequired();
                         }
-                        if (DBG) logd("getSatelliteCapabilities: " + capabilities);
+                        if (DBG) plogd("getSatelliteCapabilities: " + capabilities);
                         bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES,
                                 capabilities);
                         synchronized (mSatelliteCapabilitiesLock) {
@@ -1183,13 +1213,13 @@
                 Bundle bundle = new Bundle();
                 if (error == SATELLITE_RESULT_SUCCESS) {
                     if (ar.result == null) {
-                        loge("requestTimeForNextSatelliteVisibility: result is null");
+                        ploge("requestTimeForNextSatelliteVisibility: result is null");
                         error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
                     } else {
                         int nextVisibilityDuration = ((int[]) ar.result)[0];
                         if (DBG) {
-                            logd("requestTimeForNextSatelliteVisibility: " +
-                                    nextVisibilityDuration);
+                            plogd("requestTimeForNextSatelliteVisibility: "
+                                    + nextVisibilityDuration);
                         }
                         bundle.putInt(SatelliteManager.KEY_SATELLITE_NEXT_VISIBILITY,
                                 nextVisibilityDuration);
@@ -1200,11 +1230,13 @@
             }
 
             case EVENT_RADIO_STATE_CHANGED: {
-                if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON) {
-                    mIsRadioOn = true;
-                } else if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF) {
-                    mIsRadioOn = false;
-                    resetCarrierRoamingSatelliteModeParams();
+                synchronized (mIsRadioOnLock) {
+                    logd("EVENT_RADIO_STATE_CHANGED: radioState=" + mCi.getRadioState());
+                    if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON) {
+                        mIsRadioOn = true;
+                    } else if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF) {
+                        resetCarrierRoamingSatelliteModeParams();
+                    }
                 }
 
                 if (mCi.getRadioState() != TelephonyManager.RADIO_POWER_UNAVAILABLE) {
@@ -1215,7 +1247,7 @@
                                     @Override
                                     protected void onReceiveResult(
                                             int resultCode, Bundle resultData) {
-                                        logd("onRadioStateChanged.requestIsSatelliteSupported: "
+                                        plogd("onRadioStateChanged.requestIsSatelliteSupported: "
                                                 + "resultCode=" + resultCode
                                                 + ", resultData=" + resultData);
                                     }
@@ -1243,18 +1275,18 @@
             case EVENT_SATELLITE_PROVISION_STATE_CHANGED:
                 ar = (AsyncResult) msg.obj;
                 if (ar.result == null) {
-                    loge("EVENT_SATELLITE_PROVISION_STATE_CHANGED: result is null");
+                    ploge("EVENT_SATELLITE_PROVISION_STATE_CHANGED: result is null");
                 } else {
                     handleEventSatelliteProvisionStateChanged((boolean) ar.result);
                 }
                 break;
 
             case EVENT_PENDING_DATAGRAMS:
-                logd("Received EVENT_PENDING_DATAGRAMS");
+                plogd("Received EVENT_PENDING_DATAGRAMS");
                 IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
                     @Override
                     public void accept(int result) {
-                        logd("pollPendingSatelliteDatagram result: " + result);
+                        plogd("pollPendingSatelliteDatagram result: " + result);
                     }
                 };
                 pollPendingDatagrams(
@@ -1264,7 +1296,7 @@
             case EVENT_SATELLITE_MODEM_STATE_CHANGED:
                 ar = (AsyncResult) msg.obj;
                 if (ar.result == null) {
-                    loge("EVENT_SATELLITE_MODEM_STATE_CHANGED: result is null");
+                    ploge("EVENT_SATELLITE_MODEM_STATE_CHANGED: result is null");
                 } else {
                     handleEventSatelliteModemStateChanged((int) ar.result);
                 }
@@ -1275,7 +1307,7 @@
                 break;
 
             case CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE: {
-                logd("CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE");
+                plogd("CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE");
                 request = (SatelliteControllerHandlerRequest) msg.obj;
                 handleRequestSatelliteAttachRestrictionForCarrierCmd(request);
                 break;
@@ -1306,7 +1338,7 @@
             }
 
             case CMD_REQUEST_NTN_SIGNAL_STRENGTH: {
-                logd("CMD_REQUEST_NTN_SIGNAL_STRENGTH");
+                plogd("CMD_REQUEST_NTN_SIGNAL_STRENGTH");
                 request = (SatelliteControllerHandlerRequest) msg.obj;
                 onCompleted = obtainMessage(EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE, request);
                 mSatelliteModemInterface.requestNtnSignalStrength(onCompleted);
@@ -1335,7 +1367,7 @@
                                         NTN_SIGNAL_STRENGTH_NONE);
                             }
                         }
-                        loge("EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE: ntnSignalStrength is null");
+                        ploge("EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE: ntnSignalStrength is null");
                         result.send(SatelliteManager.SATELLITE_RESULT_REQUEST_FAILED, null);
                     }
                 } else {
@@ -1352,7 +1384,7 @@
             case EVENT_NTN_SIGNAL_STRENGTH_CHANGED: {
                 ar = (AsyncResult) msg.obj;
                 if (ar.result == null) {
-                    loge("EVENT_NTN_SIGNAL_STRENGTH_CHANGED: result is null");
+                    ploge("EVENT_NTN_SIGNAL_STRENGTH_CHANGED: result is null");
                 } else {
                     handleEventNtnSignalStrengthChanged((NtnSignalStrength) ar.result);
                 }
@@ -1363,7 +1395,7 @@
                 ar = (AsyncResult) msg.obj;
                 boolean shouldReport = (boolean) ar.result;
                 if (DBG) {
-                    logd("CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING: shouldReport=" + shouldReport);
+                    plogd("CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING: shouldReport=" + shouldReport);
                 }
                 handleCmdUpdateNtnSignalStrengthReporting(shouldReport);
                 break;
@@ -1400,7 +1432,7 @@
             case EVENT_SATELLITE_CAPABILITIES_CHANGED: {
                 ar = (AsyncResult) msg.obj;
                 if (ar.result == null) {
-                    loge("EVENT_SATELLITE_CAPABILITIES_CHANGED: result is null");
+                    ploge("EVENT_SATELLITE_CAPABILITIES_CHANGED: result is null");
                 } else {
                     handleEventSatelliteCapabilitiesChanged((SatelliteCapabilities) ar.result);
                 }
@@ -1410,7 +1442,7 @@
             case EVENT_SATELLITE_SUPPORTED_STATE_CHANGED: {
                 ar = (AsyncResult) msg.obj;
                 if (ar.result == null) {
-                    loge("EVENT_SATELLITE_SUPPORTED_STATE_CHANGED: result is null");
+                    ploge("EVENT_SATELLITE_SUPPORTED_STATE_CHANGED: result is null");
                 } else {
                     handleEventSatelliteSupportedStateChanged((boolean) ar.result);
                 }
@@ -1445,7 +1477,7 @@
                 processNewCarrierConfigData(subId);
             }
         } else {
-            loge("updateSupportedSatelliteServicesForActiveSubscriptions: "
+            ploge("updateSupportedSatelliteServicesForActiveSubscriptions: "
                     + "activeSubIds is null");
         }
     }
@@ -1470,7 +1502,7 @@
      */
     public void requestSatelliteEnabled(int subId, boolean enableSatellite, boolean enableDemoMode,
             boolean isEmergency, @NonNull IIntegerConsumer callback) {
-        logd("requestSatelliteEnabled subId: " + subId + " enableSatellite: " + enableSatellite
+        plogd("requestSatelliteEnabled subId: " + subId + " enableSatellite: " + enableSatellite
                 + " enableDemoMode: " + enableDemoMode + " isEmergency: " + isEmergency);
         Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
         int error = evaluateOemSatelliteRequestAllowed(true);
@@ -1480,11 +1512,13 @@
         }
 
         if (enableSatellite) {
-            if (!mIsRadioOn) {
-                loge("Radio is not on, can not enable satellite");
-                sendErrorAndReportSessionMetrics(
-                        SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE, result);
-                return;
+            synchronized (mIsRadioOnLock) {
+                if (!mIsRadioOn) {
+                    ploge("Radio is not on, can not enable satellite");
+                    sendErrorAndReportSessionMetrics(
+                            SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE, result);
+                    return;
+                }
             }
         } else {
             /* if disable satellite, always assume demo is also disabled */
@@ -1495,13 +1529,13 @@
             if (mIsSatelliteEnabled != null) {
                 if (mIsSatelliteEnabled == enableSatellite) {
                     if (enableDemoMode != mIsDemoModeEnabled) {
-                        loge("Received invalid demo mode while satellite session is enabled"
+                        ploge("Received invalid demo mode while satellite session is enabled"
                                 + " enableDemoMode = " + enableDemoMode);
                         sendErrorAndReportSessionMetrics(
                                 SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS, result);
                         return;
                     } else {
-                        logd("Enable request matches with current state"
+                        plogd("Enable request matches with current state"
                                 + " enableSatellite = " + enableSatellite);
                         sendErrorAndReportSessionMetrics(
                                 SatelliteManager.SATELLITE_RESULT_SUCCESS, result);
@@ -1528,14 +1562,14 @@
             if (mSatelliteEnabledRequest == null) {
                 mSatelliteEnabledRequest = request;
             } else if (mSatelliteEnabledRequest.enableSatellite == request.enableSatellite) {
-                logd("requestSatelliteEnabled enableSatellite: " + enableSatellite
+                plogd("requestSatelliteEnabled enableSatellite: " + enableSatellite
                         + " is already in progress.");
                 sendErrorAndReportSessionMetrics(
                         SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS, result);
                 return;
             } else if (mSatelliteEnabledRequest.enableSatellite == false
                     && request.enableSatellite == true) {
-                logd("requestSatelliteEnabled enableSatellite: " + enableSatellite + " cannot be "
+                plogd("requestSatelliteEnabled enableSatellite: " + enableSatellite + " cannot be "
                         + "processed. Disable satellite is already in progress.");
                 sendErrorAndReportSessionMetrics(
                         SatelliteManager.SATELLITE_RESULT_ERROR, result);
@@ -1581,7 +1615,7 @@
      */
     public boolean isSatelliteEnabled() {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("isSatelliteEnabled: oemEnabledSatelliteFlag is disabled");
+            plogd("isSatelliteEnabled: oemEnabledSatelliteFlag is disabled");
             return false;
         }
         if (mIsSatelliteEnabled == null) return false;
@@ -1595,7 +1629,7 @@
      */
     public boolean isSatelliteBeingEnabled() {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("isSatelliteBeingEnabled: oemEnabledSatelliteFlag is disabled");
+            plogd("isSatelliteBeingEnabled: oemEnabledSatelliteFlag is disabled");
             return false;
         }
 
@@ -1632,7 +1666,7 @@
      */
     public boolean isDemoModeEnabled() {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("isDemoModeEnabled: oemEnabledSatelliteFlag is disabled");
+            plogd("isDemoModeEnabled: oemEnabledSatelliteFlag is disabled");
             return false;
         }
         return mIsDemoModeEnabled;
@@ -1647,7 +1681,7 @@
      */
     public void requestIsSatelliteSupported(int subId, @NonNull ResultReceiver result) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("requestIsSatelliteSupported: oemEnabledSatelliteFlag is disabled");
+            plogd("requestIsSatelliteSupported: oemEnabledSatelliteFlag is disabled");
             result.send(SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED, null);
             return;
         }
@@ -1860,7 +1894,7 @@
     public void unregisterForSatelliteProvisionStateChanged(
             int subId, @NonNull ISatelliteProvisionStateCallback callback) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("unregisterForSatelliteProvisionStateChanged: "
+            plogd("unregisterForSatelliteProvisionStateChanged: "
                     + "oemEnabledSatelliteFlag is disabled");
             return;
         }
@@ -1906,13 +1940,13 @@
     @SatelliteManager.SatelliteResult public int registerForSatelliteModemStateChanged(int subId,
             @NonNull ISatelliteModemStateCallback callback) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("registerForSatelliteModemStateChanged: oemEnabledSatelliteFlag is disabled");
+            plogd("registerForSatelliteModemStateChanged: oemEnabledSatelliteFlag is disabled");
             return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
         }
         if (mSatelliteSessionController != null) {
             mSatelliteSessionController.registerForSatelliteModemStateChanged(callback);
         } else {
-            loge("registerForSatelliteModemStateChanged: mSatelliteSessionController"
+            ploge("registerForSatelliteModemStateChanged: mSatelliteSessionController"
                     + " is not initialized yet");
             return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
         }
@@ -1930,13 +1964,13 @@
     public void unregisterForModemStateChanged(int subId,
             @NonNull ISatelliteModemStateCallback callback) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("unregisterForModemStateChanged: oemEnabledSatelliteFlag is disabled");
+            plogd("unregisterForModemStateChanged: oemEnabledSatelliteFlag is disabled");
             return;
         }
         if (mSatelliteSessionController != null) {
             mSatelliteSessionController.unregisterForSatelliteModemStateChanged(callback);
         } else {
-            loge("unregisterForModemStateChanged: mSatelliteSessionController"
+            ploge("unregisterForModemStateChanged: mSatelliteSessionController"
                     + " is not initialized yet");
         }
     }
@@ -1952,13 +1986,13 @@
     @SatelliteManager.SatelliteResult public int registerForIncomingDatagram(int subId,
             @NonNull ISatelliteDatagramCallback callback) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("registerForIncomingDatagram: oemEnabledSatelliteFlag is disabled");
+            plogd("registerForIncomingDatagram: oemEnabledSatelliteFlag is disabled");
             return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
         }
         if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
             return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
         }
-        logd("registerForIncomingDatagram: callback=" + callback);
+        plogd("registerForIncomingDatagram: callback=" + callback);
         return mDatagramController.registerForSatelliteDatagram(subId, callback);
     }
 
@@ -1973,13 +2007,13 @@
     public void unregisterForIncomingDatagram(int subId,
             @NonNull ISatelliteDatagramCallback callback) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("unregisterForIncomingDatagram: oemEnabledSatelliteFlag is disabled");
+            plogd("unregisterForIncomingDatagram: oemEnabledSatelliteFlag is disabled");
             return;
         }
         if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
             return;
         }
-        logd("unregisterForIncomingDatagram: callback=" + callback);
+        plogd("unregisterForIncomingDatagram: callback=" + callback);
         mDatagramController.unregisterForSatelliteDatagram(subId, callback);
     }
 
@@ -2025,7 +2059,7 @@
     public void sendDatagram(int subId, @SatelliteManager.DatagramType int datagramType,
             SatelliteDatagram datagram, boolean needFullScreenPointingUI,
             @NonNull IIntegerConsumer callback) {
-        logd("sendSatelliteDatagram: subId: " + subId + " datagramType: " + datagramType
+        plogd("sendSatelliteDatagram: subId: " + subId + " datagramType: " + datagramType
                 + " needFullScreenPointingUI: " + needFullScreenPointingUI);
 
         Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
@@ -2074,7 +2108,7 @@
      */
     public void setDeviceAlignedWithSatellite(@NonNull int subId, @NonNull boolean isAligned) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("setDeviceAlignedWithSatellite: oemEnabledSatelliteFlag is disabled");
+            plogd("setDeviceAlignedWithSatellite: oemEnabledSatelliteFlag is disabled");
             return;
         }
 
@@ -2191,7 +2225,7 @@
      * strength of the satellite connection.
      */
     public void requestNtnSignalStrength(int subId, @NonNull ResultReceiver result) {
-        if (DBG) logd("requestNtnSignalStrength()");
+        if (DBG) plogd("requestNtnSignalStrength()");
 
         int error = evaluateOemSatelliteRequestAllowed(true);
         if (error != SATELLITE_RESULT_SUCCESS) {
@@ -2230,7 +2264,7 @@
      */
     public void registerForNtnSignalStrengthChanged(int subId,
             @NonNull INtnSignalStrengthCallback callback) throws RemoteException {
-        if (DBG) logd("registerForNtnSignalStrengthChanged()");
+        if (DBG) plogd("registerForNtnSignalStrengthChanged()");
 
         int error = evaluateOemSatelliteRequestAllowed(true);
         if (error == SATELLITE_RESULT_SUCCESS) {
@@ -2251,7 +2285,7 @@
      */
     public void unregisterForNtnSignalStrengthChanged(
             int subId, @NonNull INtnSignalStrengthCallback callback) {
-        if (DBG) logd("unregisterForNtnSignalStrengthChanged()");
+        if (DBG) plogd("unregisterForNtnSignalStrengthChanged()");
 
         int error = evaluateOemSatelliteRequestAllowed(true);
         if (error == SATELLITE_RESULT_SUCCESS) {
@@ -2269,7 +2303,7 @@
      */
     @SatelliteManager.SatelliteResult public int registerForCapabilitiesChanged(
             int subId, @NonNull ISatelliteCapabilitiesCallback callback) {
-        if (DBG) logd("registerForCapabilitiesChanged()");
+        if (DBG) plogd("registerForCapabilitiesChanged()");
 
         int error = evaluateOemSatelliteRequestAllowed(true);
         if (error != SATELLITE_RESULT_SUCCESS) return error;
@@ -2289,7 +2323,7 @@
      */
     public void unregisterForCapabilitiesChanged(
             int subId, @NonNull ISatelliteCapabilitiesCallback callback) {
-        if (DBG) logd("unregisterForCapabilitiesChanged()");
+        if (DBG) plogd("unregisterForCapabilitiesChanged()");
 
         int error = evaluateOemSatelliteRequestAllowed(true);
         if (error == SATELLITE_RESULT_SUCCESS) {
@@ -2308,7 +2342,7 @@
     @SatelliteManager.SatelliteResult public int registerForSatelliteSupportedStateChanged(
             int subId, @NonNull ISatelliteSupportedStateCallback callback) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("registerForSatelliteSupportedStateChanged: oemEnabledSatelliteFlag is disabled");
+            plogd("registerForSatelliteSupportedStateChanged: oemEnabledSatelliteFlag is disabled");
             return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
         }
 
@@ -2327,7 +2361,7 @@
     public void unregisterForSatelliteSupportedStateChanged(
             int subId, @NonNull ISatelliteSupportedStateCallback callback) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("unregisterForSatelliteSupportedStateChanged: "
+            plogd("unregisterForSatelliteSupportedStateChanged: "
                     + "oemEnabledSatelliteFlag is disabled");
             return;
         }
@@ -2343,16 +2377,16 @@
      */
     public boolean setSatelliteServicePackageName(@Nullable String servicePackageName) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("setSatelliteServicePackageName: oemEnabledSatelliteFlag is disabled");
+            plogd("setSatelliteServicePackageName: oemEnabledSatelliteFlag is disabled");
             return false;
         }
         if (!isMockModemAllowed()) {
-            logd("setSatelliteServicePackageName: mock modem not allowed");
+            plogd("setSatelliteServicePackageName: mock modem not allowed");
             return false;
         }
 
         // Cached states need to be cleared whenever switching satellite vendor services.
-        logd("setSatelliteServicePackageName: Resetting cached states");
+        plogd("setSatelliteServicePackageName: Resetting cached states");
         synchronized (mIsSatelliteSupportedLock) {
             mIsSatelliteSupported = null;
         }
@@ -2379,11 +2413,11 @@
      */
     public boolean setSatelliteListeningTimeoutDuration(long timeoutMillis) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("setSatelliteListeningTimeoutDuration: oemEnabledSatelliteFlag is disabled");
+            plogd("setSatelliteListeningTimeoutDuration: oemEnabledSatelliteFlag is disabled");
             return false;
         }
         if (mSatelliteSessionController == null) {
-            loge("mSatelliteSessionController is not initialized yet");
+            ploge("mSatelliteSessionController is not initialized yet");
             return false;
         }
         return mSatelliteSessionController.setSatelliteListeningTimeoutDuration(timeoutMillis);
@@ -2399,10 +2433,10 @@
     public boolean setDatagramControllerTimeoutDuration(
             boolean reset, int timeoutType, long timeoutMillis) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("setDatagramControllerTimeoutDuration: oemEnabledSatelliteFlag is disabled");
+            plogd("setDatagramControllerTimeoutDuration: oemEnabledSatelliteFlag is disabled");
             return false;
         }
-        logd("setDatagramControllerTimeoutDuration: reset=" + reset + ", timeoutType="
+        plogd("setDatagramControllerTimeoutDuration: reset=" + reset + ", timeoutType="
                 + timeoutType + ", timeoutMillis=" + timeoutMillis);
         return mDatagramController.setDatagramControllerTimeoutDuration(
                 reset, timeoutType, timeoutMillis);
@@ -2437,14 +2471,14 @@
     public boolean setSatelliteControllerTimeoutDuration(
             boolean reset, int timeoutType, long timeoutMillis) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("setSatelliteControllerTimeoutDuration: oemEnabledSatelliteFlag is disabled");
+            plogd("setSatelliteControllerTimeoutDuration: oemEnabledSatelliteFlag is disabled");
             return false;
         }
         if (!isMockModemAllowed()) {
-            logd("setSatelliteControllerTimeoutDuration: mock modem is not allowed");
+            plogd("setSatelliteControllerTimeoutDuration: mock modem is not allowed");
             return false;
         }
-        logd("setSatelliteControllerTimeoutDuration: reset=" + reset + ", timeoutType="
+        plogd("setSatelliteControllerTimeoutDuration: reset=" + reset + ", timeoutType="
                 + timeoutType + ", timeoutMillis=" + timeoutMillis);
         if (timeoutType == TIMEOUT_TYPE_WAIT_FOR_SATELLITE_ENABLING_RESPONSE) {
             if (reset) {
@@ -2453,7 +2487,7 @@
             } else {
                 mWaitTimeForSatelliteEnablingResponse = timeoutMillis;
             }
-            logd("mWaitTimeForSatelliteEnablingResponse=" + mWaitTimeForSatelliteEnablingResponse);
+            plogd("mWaitTimeForSatelliteEnablingResponse=" + mWaitTimeForSatelliteEnablingResponse);
         } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS) {
             if (reset) {
                 mDemoPointingAlignedDurationMillis =
@@ -2469,7 +2503,7 @@
                 mDemoPointingNotAlignedDurationMillis = timeoutMillis;
             }
         } else {
-            logw("Invalid timeoutType=" + timeoutType);
+            plogw("Invalid timeoutType=" + timeoutType);
             return false;
         }
         return true;
@@ -2484,11 +2518,11 @@
      */
     public boolean setSatelliteGatewayServicePackageName(@Nullable String servicePackageName) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("setSatelliteGatewayServicePackageName: oemEnabledSatelliteFlag is disabled");
+            plogd("setSatelliteGatewayServicePackageName: oemEnabledSatelliteFlag is disabled");
             return false;
         }
         if (mSatelliteSessionController == null) {
-            loge("mSatelliteSessionController is not initialized yet");
+            ploge("mSatelliteSessionController is not initialized yet");
             return false;
         }
         return mSatelliteSessionController.setSatelliteGatewayServicePackageName(
@@ -2506,7 +2540,7 @@
     public boolean setSatellitePointingUiClassName(
             @Nullable String packageName, @Nullable String className) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("setSatellitePointingUiClassName: oemEnabledSatelliteFlag is disabled");
+            plogd("setSatellitePointingUiClassName: oemEnabledSatelliteFlag is disabled");
             return false;
         }
         return mPointingAppController.setSatellitePointingUiClassName(packageName, className);
@@ -2527,7 +2561,7 @@
      */
     public boolean setEmergencyCallToSatelliteHandoverType(int handoverType, int delaySeconds) {
         if (!isMockModemAllowed()) {
-            loge("setEmergencyCallToSatelliteHandoverType: mock modem not allowed");
+            ploge("setEmergencyCallToSatelliteHandoverType: mock modem not allowed");
             return false;
         }
         if (isHandoverTypeValid(handoverType)) {
@@ -2551,7 +2585,7 @@
      */
     public boolean setOemEnabledSatelliteProvisionStatus(boolean reset, boolean isProvisioned) {
         if (!isMockModemAllowed()) {
-            loge("setOemEnabledSatelliteProvisionStatus: mock modem not allowed");
+            ploge("setOemEnabledSatelliteProvisionStatus: mock modem not allowed");
             return false;
         }
         synchronized (mSatelliteViaOemProvisionLock) {
@@ -2596,7 +2630,7 @@
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     public void onSatelliteServiceConnected() {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("onSatelliteServiceConnected: oemEnabledSatelliteFlag is disabled");
+            plogd("onSatelliteServiceConnected: oemEnabledSatelliteFlag is disabled");
             return;
         }
         if (mSatelliteModemInterface.isSatelliteServiceSupported()) {
@@ -2606,7 +2640,7 @@
                         @Override
                         protected void onReceiveResult(
                                 int resultCode, Bundle resultData) {
-                            logd("onSatelliteServiceConnected.requestIsSatelliteSupported:"
+                            plogd("onSatelliteServiceConnected.requestIsSatelliteSupported:"
                                     + " resultCode=" + resultCode);
                         }
                     };
@@ -2615,7 +2649,7 @@
                 }
             }
         } else {
-            logd("onSatelliteServiceConnected: Satellite vendor service is not supported."
+            plogd("onSatelliteServiceConnected: Satellite vendor service is not supported."
                     + " Ignored the event");
         }
     }
@@ -2626,18 +2660,21 @@
      * modem. {@link SatelliteController} will then power off the satellite modem.
      */
     public void onCellularRadioPowerOffRequested() {
+        logd("onCellularRadioPowerOffRequested()");
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("onCellularRadioPowerOffRequested: oemEnabledSatelliteFlag is disabled");
+            plogd("onCellularRadioPowerOffRequested: oemEnabledSatelliteFlag is disabled");
             return;
         }
 
-        mIsRadioOn = false;
+        synchronized (mIsRadioOnLock) {
+            mIsRadioOn = false;
+        }
         requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
                 false /* enableSatellite */, false /* enableDemoMode */, false /* isEmergency */,
                 new IIntegerConsumer.Stub() {
                     @Override
                     public void accept(int result) {
-                        logd("onRadioPowerOffRequested: requestSatelliteEnabled result=" + result);
+                        plogd("onRadioPowerOffRequested: requestSatelliteEnabled result=" + result);
                     }
                 });
     }
@@ -2648,7 +2685,7 @@
      */
     public boolean isSatelliteSupportedViaOem() {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("isSatelliteSupported: oemEnabledSatelliteFlag is disabled");
+            plogd("isSatelliteSupported: oemEnabledSatelliteFlag is disabled");
             return false;
         }
         Boolean supported = isSatelliteSupportedViaOemInternal();
@@ -2729,13 +2766,13 @@
      */
     public boolean isSatelliteAttachRequired() {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("isSatelliteAttachRequired: oemEnabledSatelliteFlag is disabled");
+            plogd("isSatelliteAttachRequired: oemEnabledSatelliteFlag is disabled");
             return false;
         }
 
         synchronized (mSatelliteCapabilitiesLock) {
             if (mSatelliteCapabilities == null) {
-                loge("isSatelliteAttachRequired: mSatelliteCapabilities is null");
+                ploge("isSatelliteAttachRequired: mSatelliteCapabilities is null");
                 return false;
             }
             if (mSatelliteCapabilities.getSupportedRadioTechnologies().contains(
@@ -2864,7 +2901,7 @@
             return true;
         }
 
-        if (serviceState.getState() == ServiceState.STATE_IN_SERVICE) {
+        if (getWwanIsInService(serviceState)) {
             // Device is connected to terrestrial network which has coverage
             resetCarrierRoamingSatelliteModeParams(subId);
             return false;
@@ -2963,6 +3000,29 @@
     }
 
     /**
+     * Register the handler for SIM Refresh notifications.
+     * @param handler Handler for notification message.
+     * @param what User-defined message code.
+     */
+    public void registerIccRefresh(Handler handler, int what) {
+        for (Phone phone : PhoneFactory.getPhones()) {
+            CommandsInterface ci = phone.mCi;
+            ci.registerForIccRefresh(handler, what, null);
+        }
+    }
+
+    /**
+     * Unregister the handler for SIM Refresh notifications.
+     * @param handler Handler for notification message.
+     */
+    public void unRegisterIccRefresh(Handler handler) {
+        for (Phone phone : PhoneFactory.getPhones()) {
+            CommandsInterface ci = phone.mCi;
+            ci.unregisterForIccRefresh(handler);
+        }
+    }
+
+    /**
      * To use the satellite service, update the EntitlementStatus and the PlmnAllowedList after
      * receiving the satellite configuration from the entitlement server. If satellite
      * entitlement is enabled, enable satellite for the carrier. Otherwise, disable satellite.
@@ -3041,7 +3101,7 @@
     private boolean isValidPlmnList(@NonNull List<String> plmnList) {
         for (String plmn : plmnList) {
             if (!TelephonyUtils.isValidPlmn(plmn)) {
-                loge("Invalid PLMN = " + plmn);
+                ploge("Invalid PLMN = " + plmn);
                 return false;
             }
         }
@@ -3067,7 +3127,7 @@
                 new ResultReceiver(this) {
                     @Override
                     protected void onReceiveResult(int resultCode, Bundle resultData) {
-                        logd("isSatelliteSupportedViaOemInternal.requestIsSatelliteSupported:"
+                        plogd("isSatelliteSupportedViaOemInternal.requestIsSatelliteSupported:"
                                 + " resultCode=" + resultCode);
                     }
                 });
@@ -3077,12 +3137,12 @@
     private void handleEventProvisionSatelliteServiceDone(
             @NonNull ProvisionSatelliteServiceArgument arg,
             @SatelliteManager.SatelliteResult int result) {
-        logd("handleEventProvisionSatelliteServiceDone: result="
+        plogd("handleEventProvisionSatelliteServiceDone: result="
                 + result + ", subId=" + arg.subId);
 
         Consumer<Integer> callback = mSatelliteProvisionCallbacks.remove(arg.subId);
         if (callback == null) {
-            loge("handleEventProvisionSatelliteServiceDone: callback is null for subId="
+            ploge("handleEventProvisionSatelliteServiceDone: callback is null for subId="
                     + arg.subId);
             mProvisionMetricsStats
                     .setResultCode(SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE)
@@ -3113,10 +3173,10 @@
             @NonNull ProvisionSatelliteServiceArgument arg,
             @SatelliteManager.SatelliteResult int result) {
         if (arg == null) {
-            loge("handleEventDeprovisionSatelliteServiceDone: arg is null");
+            ploge("handleEventDeprovisionSatelliteServiceDone: arg is null");
             return;
         }
-        logd("handleEventDeprovisionSatelliteServiceDone: result="
+        plogd("handleEventDeprovisionSatelliteServiceDone: result="
                 + result + ", subId=" + arg.subId);
 
         if (result == SATELLITE_RESULT_SUCCESS
@@ -3224,7 +3284,7 @@
                 new ResultReceiver(this) {
                     @Override
                     protected void onReceiveResult(int resultCode, Bundle resultData) {
-                        logd("isSatelliteViaOemProvisioned: resultCode=" + resultCode);
+                        plogd("isSatelliteViaOemProvisioned: resultCode=" + resultCode);
                     }
                 });
         return null;
@@ -3233,10 +3293,11 @@
     private void handleSatelliteEnabled(SatelliteControllerHandlerRequest request) {
         RequestSatelliteEnabledArgument argument =
                 (RequestSatelliteEnabledArgument) request.argument;
+        handlePersistentLoggingOnSessionStart(argument);
         if (mSatelliteSessionController != null) {
             mSatelliteSessionController.onSatelliteEnablementStarted(argument.enableSatellite);
         } else {
-            loge("handleSatelliteEnabled: mSatelliteSessionController is not initialized yet");
+            ploge("handleSatelliteEnabled: mSatelliteSessionController is not initialized yet");
         }
 
         if (!argument.enableSatellite && mSatelliteModemInterface.isSatelliteServiceSupported()) {
@@ -3277,8 +3338,8 @@
             mIsSatelliteSupported = supported;
         }
         mSatelliteSessionController = SatelliteSessionController.make(
-                mContext, getLooper(), supported);
-        logd("create a new SatelliteSessionController due to isSatelliteSupported state has "
+                mContext, getLooper(), mFeatureFlags, supported);
+        plogd("create a new SatelliteSessionController due to isSatelliteSupported state has "
                 + "changed to " + supported);
 
         if (supported) {
@@ -3292,14 +3353,14 @@
                     new ResultReceiver(this) {
                         @Override
                         protected void onReceiveResult(int resultCode, Bundle resultData) {
-                            logd("requestIsSatelliteProvisioned: resultCode=" + resultCode
+                            plogd("requestIsSatelliteProvisioned: resultCode=" + resultCode
                                     + ", resultData=" + resultData);
                             requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
                                     false, false, false,
                                     new IIntegerConsumer.Stub() {
                                         @Override
                                         public void accept(int result) {
-                                            logd("requestSatelliteEnabled: result=" + result);
+                                            plogd("requestSatelliteEnabled: result=" + result);
                                         }
                                     });
                         }
@@ -3308,7 +3369,7 @@
                     new ResultReceiver(this) {
                         @Override
                         protected void onReceiveResult(int resultCode, Bundle resultData) {
-                            logd("requestSatelliteCapabilities: resultCode=" + resultCode
+                            plogd("requestSatelliteCapabilities: resultCode=" + resultCode
                                     + ", resultData=" + resultData);
                         }
                     });
@@ -3324,7 +3385,7 @@
             mSatelliteSessionController.onSatelliteEnabledStateChanged(enabled);
             mSatelliteSessionController.setDemoMode(mIsDemoModeEnabled);
         } else {
-            loge(caller + ": mSatelliteSessionController is not initialized yet");
+            ploge(caller + ": mSatelliteSessionController is not initialized yet");
         }
         if (!enabled) {
             mIsModemEnabledReportingNtnSignalStrength.set(false);
@@ -3363,7 +3424,7 @@
 
     private void registerForNtnSignalStrengthChanged() {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("registerForNtnSignalStrengthChanged: oemEnabledSatelliteFlag is disabled");
+            plogd("registerForNtnSignalStrengthChanged: oemEnabledSatelliteFlag is disabled");
             return;
         }
 
@@ -3378,7 +3439,7 @@
 
     private void registerForCapabilitiesChanged() {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("registerForCapabilitiesChanged: oemEnabledSatelliteFlag is disabled");
+            plogd("registerForCapabilitiesChanged: oemEnabledSatelliteFlag is disabled");
             return;
         }
 
@@ -3402,7 +3463,7 @@
     }
 
     private void handleEventSatelliteProvisionStateChanged(boolean provisioned) {
-        logd("handleSatelliteProvisionStateChangedEvent: provisioned=" + provisioned);
+        plogd("handleSatelliteProvisionStateChangedEvent: provisioned=" + provisioned);
 
         synchronized (mSatelliteViaOemProvisionLock) {
             persistOemEnabledSatelliteProvisionStatus(provisioned);
@@ -3414,7 +3475,7 @@
             try {
                 listener.onSatelliteProvisionStateChanged(provisioned);
             } catch (RemoteException e) {
-                logd("handleSatelliteProvisionStateChangedEvent RemoteException: " + e);
+                plogd("handleSatelliteProvisionStateChangedEvent RemoteException: " + e);
                 deadCallersList.add(listener);
             }
         });
@@ -3425,7 +3486,7 @@
 
     private void handleEventSatelliteModemStateChanged(
             @SatelliteManager.SatelliteModemState int state) {
-        logd("handleEventSatelliteModemStateChanged: state=" + state);
+        plogd("handleEventSatelliteModemStateChanged: state=" + state);
         if (state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE
                 || state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
             synchronized (mIsSatelliteEnabledLock) {
@@ -3443,8 +3504,8 @@
                     }
                     moveSatelliteToOffStateAndCleanUpResources(error, callback);
                 } else {
-                    logd("Either waiting for the response of disabling satellite modem or the event"
-                            + " should be ignored because isSatelliteEnabled="
+                    plogd("Either waiting for the response of disabling satellite modem or the"
+                            + " event should be ignored because isSatelliteEnabled="
                             + isSatelliteEnabled()
                             + ", mIsSatelliteEnabled=" + mIsSatelliteEnabled);
                 }
@@ -3454,7 +3515,7 @@
             if (mSatelliteSessionController != null) {
                 mSatelliteSessionController.onSatelliteModemStateChanged(state);
             } else {
-                loge("handleEventSatelliteModemStateChanged: mSatelliteSessionController is null");
+                ploge("handleEventSatelliteModemStateChanged: mSatelliteSessionController is null");
             }
         }
     }
@@ -3476,7 +3537,7 @@
             try {
                 listener.onNtnSignalStrengthChanged(ntnSignalStrength);
             } catch (RemoteException e) {
-                logd("handleEventNtnSignalStrengthChanged RemoteException: " + e);
+                plogd("handleEventNtnSignalStrengthChanged RemoteException: " + e);
                 deadCallersList.add(listener);
             }
         });
@@ -3486,9 +3547,9 @@
     }
 
     private void handleEventSatelliteCapabilitiesChanged(SatelliteCapabilities capabilities) {
-        logd("handleEventSatelliteCapabilitiesChanged()");
+        plogd("handleEventSatelliteCapabilitiesChanged()");
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("handleEventSatelliteCapabilitiesChanged: oemEnabledSatelliteFlag is disabled");
+            plogd("handleEventSatelliteCapabilitiesChanged: oemEnabledSatelliteFlag is disabled");
             return;
         }
 
@@ -3501,7 +3562,7 @@
             try {
                 listener.onSatelliteCapabilitiesChanged(capabilities);
             } catch (RemoteException e) {
-                logd("handleEventSatelliteCapabilitiesChanged RemoteException: " + e);
+                plogd("handleEventSatelliteCapabilitiesChanged RemoteException: " + e);
                 deadCallersList.add(listener);
             }
         });
@@ -3511,12 +3572,12 @@
     }
 
     private void handleEventSatelliteSupportedStateChanged(boolean supported) {
-        logd("handleSatelliteSupportedStateChangedEvent: supported=" + supported);
+        plogd("handleSatelliteSupportedStateChangedEvent: supported=" + supported);
 
         synchronized (mIsSatelliteSupportedLock) {
             if (mIsSatelliteSupported != null && mIsSatelliteSupported == supported) {
                 if (DBG) {
-                    logd("current satellite support state and new supported state are matched,"
+                    plogd("current satellite support state and new supported state are matched,"
                             + " ignore update.");
                 }
                 return;
@@ -3528,7 +3589,7 @@
                enabled, request disable satellite. */
             synchronized (mIsSatelliteEnabledLock) {
                 if (!supported && mIsSatelliteEnabled != null && mIsSatelliteEnabled) {
-                    logd("Invoke requestSatelliteEnabled(), supported=false, "
+                    plogd("Invoke requestSatelliteEnabled(), supported=false, "
                             + "mIsSatelliteEnabled=true");
                     requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
                             false /* enableSatellite */, false /* enableDemoMode */,
@@ -3536,7 +3597,7 @@
                             new IIntegerConsumer.Stub() {
                                 @Override
                                 public void accept(int result) {
-                                    logd("handleSatelliteSupportedStateChangedEvent: request "
+                                    plogd("handleSatelliteSupportedStateChangedEvent: request "
                                             + "satellite disable, result="
                                             + result);
                                 }
@@ -3552,7 +3613,7 @@
             try {
                 listener.onSatelliteSupportedStateChanged(supported);
             } catch (RemoteException e) {
-                logd("handleSatelliteSupportedStateChangedEvent RemoteException: " + e);
+                plogd("handleSatelliteSupportedStateChangedEvent RemoteException: " + e);
                 deadCallersList.add(listener);
             }
         });
@@ -3563,11 +3624,114 @@
 
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected void setSettingsKeyForSatelliteMode(int val) {
-        logd("setSettingsKeyForSatelliteMode val: " + val);
+        plogd("setSettingsKeyForSatelliteMode val: " + val);
         Settings.Global.putInt(mContext.getContentResolver(),
                     Settings.Global.SATELLITE_MODE_ENABLED, val);
     }
 
+    /**
+     * Allow screen rotation temporary in rotation locked foldable device.
+     * <p>
+     * Temporarily allow screen rotation user to catch satellite signals properly by UI guide in
+     * emergency situations. Unlock the setting value so that the screen rotation is not locked, and
+     * return it to the original value when the satellite service is finished.
+     * <p>
+     * Note that, only the unfolded screen will be temporarily allowed screen rotation.
+     *
+     * @param val {@link SATELLITE_MODE_ENABLED_TRUE} if satellite mode is enabled,
+     *     {@link SATELLITE_MODE_ENABLED_FALSE} satellite mode is not enabled.
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    protected void setSettingsKeyToAllowDeviceRotation(int val) {
+        // Only allows on a foldable device type.
+        if (!isFoldable(mContext)) {
+            return;
+        }
+
+        switch (val) {
+            case SATELLITE_MODE_ENABLED_TRUE:
+                mDeviceRotationLockToBackupAndRestore =
+                        Settings.Secure.getString(mContentResolver,
+                                Settings.Secure.DEVICE_STATE_ROTATION_LOCK);
+                String unlockedRotationSettings = replaceDeviceRotationValue(
+                        mDeviceRotationLockToBackupAndRestore == null
+                                ? "" : mDeviceRotationLockToBackupAndRestore,
+                        Settings.Secure.DEVICE_STATE_ROTATION_KEY_UNFOLDED,
+                        Settings.Secure.DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
+                Settings.Secure.putString(mContentResolver,
+                        Settings.Secure.DEVICE_STATE_ROTATION_LOCK, unlockedRotationSettings);
+                logd("setSettingsKeyToAllowDeviceRotation(TRUE), RotationSettings is changed"
+                        + " from " + mDeviceRotationLockToBackupAndRestore
+                        + " to " + unlockedRotationSettings);
+                break;
+            case SATELLITE_MODE_ENABLED_FALSE:
+                if (mDeviceRotationLockToBackupAndRestore == null) {
+                    break;
+                }
+                Settings.Secure.putString(mContentResolver,
+                        Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
+                        mDeviceRotationLockToBackupAndRestore);
+                logd("setSettingsKeyToAllowDeviceRotation(FALSE), RotationSettings is restored to"
+                        + mDeviceRotationLockToBackupAndRestore);
+                mDeviceRotationLockToBackupAndRestore = "";
+                break;
+            default:
+                loge("setSettingsKeyToAllowDeviceRotation(" + val + "), never reach here.");
+                break;
+        }
+    }
+
+    /**
+     * If the device type is foldable.
+     *
+     * @param context context
+     * @return {@code true} if device type is foldable. {@code false} for otherwise.
+     */
+    private boolean isFoldable(Context context) {
+        return context.getResources().getIntArray(R.array.config_foldedDeviceStates).length > 0;
+    }
+
+    /**
+     * Replaces a value of given a target key with a new value in a string of key-value pairs.
+     * <p>
+     * Replaces the value corresponding to the target key with a new value. If the key value is not
+     * found in the device rotation information, it is not replaced.
+     *
+     * @param deviceRotationValue Device rotation key values separated by colon(':').
+     * @param targetKey The key of the new item caller wants to add.
+     * @param newValue  The value of the new item caller want to add.
+     * @return A new string where all the key-value pairs.
+     */
+    private static String replaceDeviceRotationValue(
+            @NonNull String deviceRotationValue, int targetKey, int newValue) {
+        // Use list of Key-Value pair
+        List<Pair<Integer, Integer>> keyValuePairs = new ArrayList<>();
+
+        String[] pairs = deviceRotationValue.split(":");
+        if (pairs.length % 2 != 0) {
+            // Return without modifying. The key-value may be incorrect if length is an odd number.
+            loge("The length of key-value pair do not match. Return without modification.");
+            return deviceRotationValue;
+        }
+
+        // collect into keyValuePairs
+        for (int i = 0; i < pairs.length; i += 2) {
+            try {
+                int key = Integer.parseInt(pairs[i]);
+                int value = Integer.parseInt(pairs[i + 1]);
+                keyValuePairs.add(new Pair<>(key, key == targetKey ? newValue : value));
+            } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
+                // Return without modifying if got exception.
+                loge("got error while parsing key-value. Return without modification. e:" + e);
+                return deviceRotationValue;
+            }
+        }
+
+        return keyValuePairs.stream()
+                .map(pair -> pair.first + ":" + pair.second) // Convert to "key:value" format
+                .collect(Collectors.joining(":")); // Join pairs with colons
+    }
+
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected boolean areAllRadiosDisabled() {
         synchronized (mRadioStateLock) {
@@ -3575,20 +3739,20 @@
                     || (mDisableNFCOnSatelliteEnabled && mNfcStateEnabled)
                     || (mDisableWifiOnSatelliteEnabled && mWifiStateEnabled)
                     || (mDisableUWBOnSatelliteEnabled && mUwbStateEnabled)) {
-                logd("All radios are not disabled yet.");
+                plogd("All radios are not disabled yet.");
                 return false;
             }
-            logd("All radios are disabled.");
+            plogd("All radios are disabled.");
             return true;
         }
     }
 
     private void evaluateToSendSatelliteEnabledSuccess() {
-        logd("evaluateToSendSatelliteEnabledSuccess");
+        plogd("evaluateToSendSatelliteEnabledSuccess");
         synchronized (mSatelliteEnabledRequestLock) {
             if (areAllRadiosDisabled() && (mSatelliteEnabledRequest != null)
                     && mWaitingForRadioDisabled) {
-                logd("Sending success to callback that sent enable satellite request");
+                plogd("Sending success to callback that sent enable satellite request");
                 setDemoModeEnabled(mSatelliteEnabledRequest.enableDemoMode);
                 mIsEmergency = mSatelliteEnabledRequest.isEmergency;
                 synchronized (mIsSatelliteEnabledLock) {
@@ -3605,7 +3769,7 @@
     }
 
     private void resetSatelliteEnabledRequest() {
-        logd("resetSatelliteEnabledRequest");
+        plogd("resetSatelliteEnabledRequest");
         synchronized (mSatelliteEnabledRequestLock) {
             mSatelliteEnabledRequest = null;
             mWaitingForRadioDisabled = false;
@@ -3614,13 +3778,15 @@
 
     private void moveSatelliteToOffStateAndCleanUpResources(
             @SatelliteManager.SatelliteResult int error, @Nullable Consumer<Integer> callback) {
-        logd("moveSatelliteToOffStateAndCleanUpResources");
+        plogd("moveSatelliteToOffStateAndCleanUpResources");
         synchronized (mIsSatelliteEnabledLock) {
             resetSatelliteEnabledRequest();
             setDemoModeEnabled(false);
+            handlePersistentLoggingOnSessionEnd(mIsEmergency);
             mIsEmergency = false;
             mIsSatelliteEnabled = false;
             setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_FALSE);
+            setSettingsKeyToAllowDeviceRotation(SATELLITE_MODE_ENABLED_FALSE);
             if (callback != null) callback.accept(error);
             updateSatelliteEnabledState(
                     false, "moveSatelliteToOffStateAndCleanUpResources");
@@ -3630,7 +3796,7 @@
     private void setDemoModeEnabled(boolean enabled) {
         mIsDemoModeEnabled = enabled;
         mDatagramController.setDemoMode(mIsDemoModeEnabled);
-        logd("setDemoModeEnabled: mIsDemoModeEnabled=" + mIsDemoModeEnabled);
+        plogd("setDemoModeEnabled: mIsDemoModeEnabled=" + mIsDemoModeEnabled);
     }
 
     private boolean isMockModemAllowed() {
@@ -3688,19 +3854,19 @@
      * Otherwise, If the carrierPlmnList exist then used it.
      */
     private void updatePlmnListPerCarrier(int subId) {
-        logd("updatePlmnListPerCarrier: subId=" + subId);
+        plogd("updatePlmnListPerCarrier: subId=" + subId);
         synchronized (mSupportedSatelliteServicesLock) {
             List<String> carrierPlmnList, entitlementPlmnList;
             if (getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
                     false)) {
                 entitlementPlmnList = mEntitlementPlmnListPerCarrier.get(subId,
                         new ArrayList<>()).stream().toList();
-                logd("updatePlmnListPerCarrier: entitlementPlmnList="
+                plogd("updatePlmnListPerCarrier: entitlementPlmnList="
                         + String.join(",", entitlementPlmnList)
                         + " size=" + entitlementPlmnList.size());
                 if (!entitlementPlmnList.isEmpty()) {
                     mMergedPlmnListPerCarrier.put(subId, entitlementPlmnList);
-                    logd("mMergedPlmnListPerCarrier is updated by Entitlement");
+                    plogd("mMergedPlmnListPerCarrier is updated by Entitlement");
                     mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(
                             SatelliteConstants.CONFIG_DATA_SOURCE_ENTITLEMENT);
                     return;
@@ -3713,7 +3879,7 @@
                 int carrierId = tm.createForSubscriptionId(subId).getSimCarrierId();
                 List<String> plmnList = satelliteConfig.getAllSatellitePlmnsForCarrier(carrierId);
                 if (!plmnList.isEmpty()) {
-                    logd("mMergedPlmnListPerCarrier is updated by ConfigUpdater : "
+                    plogd("mMergedPlmnListPerCarrier is updated by ConfigUpdater : "
                             + String.join(",", plmnList));
                     mMergedPlmnListPerCarrier.put(subId, plmnList);
                     mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(
@@ -3726,20 +3892,20 @@
                     && mSatelliteServicesSupportedByCarriers.get(subId) != null) {
                 carrierPlmnList =
                         mSatelliteServicesSupportedByCarriers.get(subId).keySet().stream().toList();
-                logd("mMergedPlmnListPerCarrier is updated by carrier config: "
+                plogd("mMergedPlmnListPerCarrier is updated by carrier config: "
                         + String.join(",", carrierPlmnList));
                 mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(
                         SatelliteConstants.CONFIG_DATA_SOURCE_CARRIER_CONFIG);
             } else {
                 carrierPlmnList = new ArrayList<>();
-                logd("Empty mMergedPlmnListPerCarrier");
+                plogd("Empty mMergedPlmnListPerCarrier");
             }
             mMergedPlmnListPerCarrier.put(subId, carrierPlmnList);
         }
     }
 
     private void updateSupportedSatelliteServices(int subId) {
-        logd("updateSupportedSatelliteServices with subId " + subId);
+        plogd("updateSupportedSatelliteServices with subId " + subId);
         synchronized (mSupportedSatelliteServicesLock) {
             SatelliteConfig satelliteConfig = getSatelliteConfig();
 
@@ -3751,19 +3917,19 @@
                         satelliteConfig.getSupportedSatelliteServices(carrierId);
                 if (!supportedServicesPerPlmn.isEmpty()) {
                     mSatelliteServicesSupportedByCarriers.put(subId, supportedServicesPerPlmn);
-                    logd("updateSupportedSatelliteServices using ConfigUpdater, "
+                    plogd("updateSupportedSatelliteServices using ConfigUpdater, "
                             + "supportedServicesPerPlmn = " + supportedServicesPerPlmn.size());
                     updatePlmnListPerCarrier(subId);
                     return;
                 } else {
-                    logd("supportedServicesPerPlmn is empty");
+                    plogd("supportedServicesPerPlmn is empty");
                 }
             }
 
             mSatelliteServicesSupportedByCarriers.put(
                     subId, readSupportedSatelliteServicesFromCarrierConfig(subId));
             updatePlmnListPerCarrier(subId);
-            logd("updateSupportedSatelliteServices using carrier config");
+            plogd("updateSupportedSatelliteServices using carrier config");
         }
     }
 
@@ -3804,7 +3970,7 @@
 
     private void handleCarrierConfigChanged(int slotIndex, int subId, int carrierId,
             int specificCarrierId) {
-        logd("handleCarrierConfigChanged(): slotIndex(" + slotIndex + "), subId("
+        plogd("handleCarrierConfigChanged(): slotIndex(" + slotIndex + "), subId("
                 + subId + "), carrierId(" + carrierId + "), specificCarrierId("
                 + specificCarrierId + ")");
         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
@@ -3837,21 +4003,21 @@
      */
     private void updateEntitlementPlmnListPerCarrier(int subId) {
         if (!getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false)) {
-            logd("don't support entitlement");
+            plogd("don't support entitlement");
             return;
         }
 
         synchronized (mSupportedSatelliteServicesLock) {
             if (mEntitlementPlmnListPerCarrier.indexOfKey(subId) < 0) {
-                logd("updateEntitlementPlmnListPerCarrier: no correspondent cache, load from "
+                plogd("updateEntitlementPlmnListPerCarrier: no correspondent cache, load from "
                         + "persist storage");
                 List<String> entitlementPlmnList =
                         mSubscriptionManagerService.getSatelliteEntitlementPlmnList(subId);
                 if (entitlementPlmnList.isEmpty()) {
-                    logd("updateEntitlementPlmnListPerCarrier: read empty list");
+                    plogd("updateEntitlementPlmnListPerCarrier: read empty list");
                     return;
                 }
-                logd("updateEntitlementPlmnListPerCarrier: entitlementPlmnList="
+                plogd("updateEntitlementPlmnListPerCarrier: entitlementPlmnList="
                         + String.join(",", entitlementPlmnList));
                 mEntitlementPlmnListPerCarrier.put(subId, entitlementPlmnList);
             }
@@ -3881,7 +4047,7 @@
         try {
             strArray = mContext.getResources().getStringArray(id);
         } catch (Resources.NotFoundException ex) {
-            loge("readStringArrayFromOverlayConfig: id= " + id + ", ex=" + ex);
+            ploge("readStringArrayFromOverlayConfig: id= " + id + ", ex=" + ex);
         }
         if (strArray == null) {
             strArray = new String[0];
@@ -3911,7 +4077,7 @@
                 return !cachedRestrictionSet.contains(
                         SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER);
             } else {
-                logd("isSatelliteAttachEnabledForCarrierByUser() no correspondent cache, "
+                plogd("isSatelliteAttachEnabledForCarrierByUser() no correspondent cache, "
                         + "load from persist storage");
                 try {
                     String enabled =
@@ -3920,13 +4086,13 @@
                                     mContext.getOpPackageName(), mContext.getAttributionTag());
 
                     if (enabled == null) {
-                        loge("isSatelliteAttachEnabledForCarrierByUser: invalid subId, subId="
+                        ploge("isSatelliteAttachEnabledForCarrierByUser: invalid subId, subId="
                                 + subId);
                         return false;
                     }
 
                     if (enabled.isEmpty()) {
-                        loge("isSatelliteAttachEnabledForCarrierByUser: no data for subId(" + subId
+                        ploge("isSatelliteAttachEnabledForCarrierByUser: no data for subId(" + subId
                                 + ")");
                         return false;
                     }
@@ -3941,7 +4107,7 @@
                         return result;
                     }
                 } catch (IllegalArgumentException | SecurityException ex) {
-                    loge("isSatelliteAttachEnabledForCarrierByUser: ex=" + ex);
+                    ploge("isSatelliteAttachEnabledForCarrierByUser: ex=" + ex);
                     return false;
                 }
             }
@@ -3964,19 +4130,19 @@
 
     private void updateRestrictReasonForEntitlementPerCarrier(int subId) {
         if (!getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false)) {
-            logd("don't support entitlement");
+            plogd("don't support entitlement");
             return;
         }
 
         IIntegerConsumer callback = new IIntegerConsumer.Stub() {
             @Override
             public void accept(int result) {
-                logd("updateRestrictReasonForEntitlementPerCarrier:" + result);
+                plogd("updateRestrictReasonForEntitlementPerCarrier:" + result);
             }
         };
         synchronized (mSupportedSatelliteServicesLock) {
             if (mSatelliteEntitlementStatusPerCarrier.indexOfKey(subId) < 0) {
-                logd("updateRestrictReasonForEntitlementPerCarrier: no correspondent cache, "
+                plogd("updateRestrictReasonForEntitlementPerCarrier: no correspondent cache, "
                         + "load from persist storage");
                 String entitlementStatus = null;
                 try {
@@ -3985,17 +4151,17 @@
                                     SATELLITE_ENTITLEMENT_STATUS, mContext.getOpPackageName(),
                                     mContext.getAttributionTag());
                 } catch (IllegalArgumentException | SecurityException e) {
-                    loge("updateRestrictReasonForEntitlementPerCarrier, e=" + e);
+                    ploge("updateRestrictReasonForEntitlementPerCarrier, e=" + e);
                 }
 
                 if (entitlementStatus == null) {
-                    loge("updateRestrictReasonForEntitlementPerCarrier: invalid subId, subId="
+                    ploge("updateRestrictReasonForEntitlementPerCarrier: invalid subId, subId="
                             + subId + " set to default value");
                     entitlementStatus = "0";
                 }
 
                 if (entitlementStatus.isEmpty()) {
-                    loge("updateRestrictReasonForEntitlementPerCarrier: no data for subId(" + subId
+                    ploge("updateRestrictReasonForEntitlementPerCarrier: no data for subId(" + subId
                             + "). set to default value");
                     entitlementStatus = "0";
                 }
@@ -4020,9 +4186,9 @@
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected boolean persistSatelliteAttachEnabledForCarrierSetting(int subId) {
-        logd("persistSatelliteAttachEnabledForCarrierSetting");
+        plogd("persistSatelliteAttachEnabledForCarrierSetting");
         if (!isValidSubscriptionId(subId)) {
-            loge("persistSatelliteAttachEnabledForCarrierSetting: subId is not valid,"
+            ploge("persistSatelliteAttachEnabledForCarrierSetting: subId is not valid,"
                     + " subId=" + subId);
             return false;
         }
@@ -4035,7 +4201,7 @@
                                 .contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER)
                                 ? "0" : "1");
             } catch (IllegalArgumentException | SecurityException ex) {
-                loge("persistSatelliteAttachEnabledForCarrierSetting, ex=" + ex);
+                ploge("persistSatelliteAttachEnabledForCarrierSetting, ex=" + ex);
                 return false;
             }
         }
@@ -4084,12 +4250,12 @@
     private void evaluateEnablingSatelliteForCarrier(int subId, int reason,
             @Nullable Consumer<Integer> callback) {
         if (callback == null) {
-            callback = errorCode -> logd("evaluateEnablingSatelliteForCarrier: "
+            callback = errorCode -> plogd("evaluateEnablingSatelliteForCarrier: "
                     + "SetSatelliteAttachEnableForCarrier error code =" + errorCode);
         }
 
         if (!isSatelliteSupportedViaCarrier(subId)) {
-            logd("Satellite for carrier is not supported. Only user setting is stored");
+            plogd("Satellite for carrier is not supported. Only user setting is stored");
             callback.accept(SATELLITE_RESULT_SUCCESS);
             return;
         }
@@ -4121,17 +4287,17 @@
     @SatelliteManager.SatelliteResult private int evaluateOemSatelliteRequestAllowed(
             boolean isProvisionRequired) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("oemEnabledSatelliteFlag is disabled");
+            plogd("oemEnabledSatelliteFlag is disabled");
             return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
         }
         if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
-            logd("evaluateOemSatelliteRequestAllowed: satellite service is not supported");
+            plogd("evaluateOemSatelliteRequestAllowed: satellite service is not supported");
             return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
         }
 
         Boolean satelliteSupported = isSatelliteSupportedViaOemInternal();
         if (satelliteSupported == null) {
-            logd("evaluateOemSatelliteRequestAllowed: satelliteSupported is null");
+            plogd("evaluateOemSatelliteRequestAllowed: satelliteSupported is null");
             return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
         }
         if (!satelliteSupported) {
@@ -4141,7 +4307,7 @@
         if (isProvisionRequired) {
             Boolean satelliteProvisioned = isSatelliteViaOemProvisioned();
             if (satelliteProvisioned == null) {
-                logd("evaluateOemSatelliteRequestAllowed: satelliteProvisioned is null");
+                plogd("evaluateOemSatelliteRequestAllowed: satelliteProvisioned is null");
                 return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
             }
             if (!satelliteProvisioned) {
@@ -4209,7 +4375,7 @@
                         sessionStats.onSignalStrength(phone);
                         if (!mWasSatelliteConnectedViaCarrier.get(subId)) {
                             // Log satellite connection start
-                            sessionStats.onConnectionStart();
+                            sessionStats.onConnectionStart(phone);
                         }
                     }
 
@@ -4225,14 +4391,14 @@
                     }
                 } else {
                     Boolean connected = mWasSatelliteConnectedViaCarrier.get(subId);
-                    if (serviceState.getState() == ServiceState.STATE_IN_SERVICE) {
+                    if (getWwanIsInService(serviceState)) {
                         resetCarrierRoamingSatelliteModeParams(subId);
                     } else if (connected != null && connected) {
                         // The device just got disconnected from a satellite network
                         // and is not connected to any terrestrial network that  has coverage
                         mLastSatelliteDisconnectedTimesMillis.put(subId, getElapsedRealtime());
 
-                        logd("sendMessageDelayed subId:" + subId
+                        plogd("sendMessageDelayed subId:" + subId
                                 + " phoneId:" + phone.getPhoneId()
                                 + " time:" + getSatelliteConnectionHysteresisTimeMillis(subId));
                         sendMessageDelayed(obtainMessage(EVENT_NOTIFY_NTN_HYSTERESIS_TIMED_OUT,
@@ -4280,7 +4446,7 @@
                 // Log satellite session start
                 CarrierRoamingSatelliteSessionStats sessionStats =
                         CarrierRoamingSatelliteSessionStats.getInstance(subId);
-                sessionStats.onSessionStart(phone.getCarrierId());
+                sessionStats.onSessionStart(phone.getCarrierId(), phone);
                 mCarrierRoamingSatelliteSessionStatsMap.put(subId, sessionStats);
             } else if (lastNotifiedNtnMode && !currNtnMode) {
                 // Log satellite session end
@@ -4300,12 +4466,12 @@
 
     private void persistOemEnabledSatelliteProvisionStatus(boolean isProvisioned) {
         synchronized (mSatelliteViaOemProvisionLock) {
-            logd("persistOemEnabledSatelliteProvisionStatus: isProvisioned=" + isProvisioned);
+            plogd("persistOemEnabledSatelliteProvisionStatus: isProvisioned=" + isProvisioned);
 
             if (!loadSatelliteSharedPreferences()) return;
 
             if (mSharedPreferences == null) {
-                loge("persistOemEnabledSatelliteProvisionStatus: mSharedPreferences is null");
+                ploge("persistOemEnabledSatelliteProvisionStatus: mSharedPreferences is null");
             } else {
                 mSharedPreferences.edit().putBoolean(
                         OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY, isProvisioned).apply();
@@ -4318,7 +4484,7 @@
             if (!loadSatelliteSharedPreferences()) return false;
 
             if (mSharedPreferences == null) {
-                loge("getPersistedOemEnabledSatelliteProvisionStatus: mSharedPreferences is null");
+                ploge("getPersistedOemEnabledSatelliteProvisionStatus: mSharedPreferences is null");
                 return false;
             } else {
                 return mSharedPreferences.getBoolean(
@@ -4334,7 +4500,7 @@
                         mContext.getSharedPreferences(SATELLITE_SHARED_PREF,
                                 Context.MODE_PRIVATE);
             } catch (Exception e) {
-                loge("loadSatelliteSharedPreferences: Cannot get default "
+                ploge("loadSatelliteSharedPreferences: Cannot get default "
                         + "shared preferences, e=" + e);
                 return false;
             }
@@ -4349,18 +4515,18 @@
         boolean isSatelliteProvisionedInModem = false;
         if (error == SATELLITE_RESULT_SUCCESS) {
             if (ar.result == null) {
-                loge("handleIsSatelliteProvisionedDoneEvent: result is null");
+                ploge("handleIsSatelliteProvisionedDoneEvent: result is null");
                 error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
             } else {
                 isSatelliteProvisionedInModem = ((int[]) ar.result)[0] == 1;
             }
         } else if (error == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
-            logd("handleIsSatelliteProvisionedDoneEvent: Modem does not support this request");
+            plogd("handleIsSatelliteProvisionedDoneEvent: Modem does not support this request");
             isSatelliteProvisionedInModem = true;
         }
         boolean isSatelliteViaOemProvisioned =
                 isSatelliteProvisionedInModem && getPersistedOemEnabledSatelliteProvisionStatus();
-        logd("isSatelliteProvisionedInModem=" + isSatelliteProvisionedInModem
+        plogd("isSatelliteProvisionedInModem=" + isSatelliteProvisionedInModem
                 + ", isSatelliteViaOemProvisioned=" + isSatelliteViaOemProvisioned);
         Bundle bundle = new Bundle();
         bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED, isSatelliteViaOemProvisioned);
@@ -4379,11 +4545,11 @@
             @NonNull RequestSatelliteEnabledArgument argument) {
         synchronized (mSatelliteEnabledRequestLock) {
             if (hasMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT, argument)) {
-                logd("WaitForSatelliteEnablingResponseTimer of request ID "
+                plogd("WaitForSatelliteEnablingResponseTimer of request ID "
                         + argument.requestId + " was already started");
                 return;
             }
-            logd("Start timer to wait for response of the satellite enabling request ID="
+            plogd("Start timer to wait for response of the satellite enabling request ID="
                     + argument.requestId + ", enableSatellite=" + argument.enableSatellite
                     + ", mWaitTimeForSatelliteEnablingResponse="
                     + mWaitTimeForSatelliteEnablingResponse);
@@ -4395,7 +4561,7 @@
     private void stopWaitForSatelliteEnablingResponseTimer(
             @NonNull RequestSatelliteEnabledArgument argument) {
         synchronized (mSatelliteEnabledRequestLock) {
-            logd("Stop timer to wait for response of the satellite enabling request ID="
+            plogd("Stop timer to wait for response of the satellite enabling request ID="
                     + argument.requestId + ", enableSatellite=" + argument.enableSatellite);
             removeMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT, argument);
         }
@@ -4413,7 +4579,7 @@
 
     private void handleEventWaitForSatelliteEnablingResponseTimedOut(
             @NonNull RequestSatelliteEnabledArgument argument) {
-        logw("Timed out to wait for response of the satellite enabling request ID="
+        plogw("Timed out to wait for response of the satellite enabling request ID="
                 + argument.requestId + ", enableSatellite=" + argument.enableSatellite);
 
         synchronized (mSatelliteEnabledRequestLock) {
@@ -4438,7 +4604,7 @@
                     IIntegerConsumer callback = new IIntegerConsumer.Stub() {
                         @Override
                         public void accept(int result) {
-                            logd("handleEventWaitForSatelliteEnablingResponseTimedOut: "
+                            plogd("handleEventWaitForSatelliteEnablingResponseTimedOut: "
                                     + "disable satellite result=" + result);
                         }
                     };
@@ -4488,20 +4654,20 @@
 
     private void handleCmdUpdateNtnSignalStrengthReporting(boolean shouldReport) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("handleCmdUpdateNtnSignalStrengthReporting: oemEnabledSatelliteFlag is "
+            plogd("handleCmdUpdateNtnSignalStrengthReporting: oemEnabledSatelliteFlag is "
                     + "disabled");
             return;
         }
 
         if (!isSatelliteEnabled()) {
-            logd("handleCmdUpdateNtnSignalStrengthReporting: ignore request, satellite is "
+            plogd("handleCmdUpdateNtnSignalStrengthReporting: ignore request, satellite is "
                     + "disabled");
             return;
         }
 
         mLatestRequestedStateForNtnSignalStrengthReport.set(shouldReport);
         if (mIsModemEnabledReportingNtnSignalStrength.get() == shouldReport) {
-            logd("handleCmdUpdateNtnSignalStrengthReporting: ignore request. "
+            plogd("handleCmdUpdateNtnSignalStrengthReporting: ignore request. "
                     + "mIsModemEnabledReportingNtnSignalStrength="
                     + mIsModemEnabledReportingNtnSignalStrength.get());
             return;
@@ -4512,7 +4678,7 @@
 
     private void updateNtnSignalStrengthReporting(boolean shouldReport) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("updateNtnSignalStrengthReporting: oemEnabledSatelliteFlag is "
+            plogd("updateNtnSignalStrengthReporting: oemEnabledSatelliteFlag is "
                     + "disabled");
             return;
         }
@@ -4522,10 +4688,10 @@
         Message onCompleted = obtainMessage(EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE,
                 request);
         if (shouldReport) {
-            logd("updateNtnSignalStrengthReporting: startSendingNtnSignalStrength");
+            plogd("updateNtnSignalStrengthReporting: startSendingNtnSignalStrength");
             mSatelliteModemInterface.startSendingNtnSignalStrength(onCompleted);
         } else {
-            logd("updateNtnSignalStrengthReporting: stopSendingNtnSignalStrength");
+            plogd("updateNtnSignalStrengthReporting: stopSendingNtnSignalStrength");
             mSatelliteModemInterface.stopSendingNtnSignalStrength(onCompleted);
         }
     }
@@ -4542,12 +4708,12 @@
      */
     public boolean setShouldSendDatagramToModemInDemoMode(boolean shouldSendToModemInDemoMode) {
         if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("setShouldSendDatagramToModemInDemoMode: oemEnabledSatelliteFlag is disabled");
+            plogd("setShouldSendDatagramToModemInDemoMode: oemEnabledSatelliteFlag is disabled");
             return false;
         }
 
         if (!isMockModemAllowed()) {
-            logd("setShouldSendDatagramToModemInDemoMode: mock modem not allowed.");
+            plogd("setShouldSendDatagramToModemInDemoMode: mock modem not allowed.");
             return false;
         }
 
@@ -4584,7 +4750,7 @@
     }
 
     private void showSatelliteSystemNotification(int subId) {
-        logd("showSatelliteSystemNotification");
+        plogd("showSatelliteSystemNotification");
         final NotificationChannel notificationChannel = new NotificationChannel(
                 NOTIFICATION_CHANNEL_ID,
                 NOTIFICATION_CHANNEL,
@@ -4622,7 +4788,7 @@
             intent.addCategory(Intent.CATEGORY_HOME);
             return intent;
         }).orElseGet(() -> {
-            loge("showSatelliteSystemNotification: no default sms package name, Invoke "
+            ploge("showSatelliteSystemNotification: no default sms package name, Invoke "
                     + "default sms compose window instead");
             Intent newIntent = new Intent(Intent.ACTION_VIEW);
             newIntent.setData(Uri.parse("sms:"));
@@ -4695,7 +4861,7 @@
         if (mSatelliteSessionController != null) {
             mSatelliteSessionController.onSatelliteEnablementFailed();
         } else {
-            loge("notifyEnablementFailedToSatelliteSessionController: mSatelliteSessionController"
+            ploge("notifyEnablementFailedToSatelliteSessionController: mSatelliteSessionController"
                     + " is not initialized yet");
         }
     }
@@ -4734,6 +4900,25 @@
         return mDemoPointingNotAlignedDurationMillis;
     }
 
+    private boolean getWwanIsInService(ServiceState serviceState) {
+        List<NetworkRegistrationInfo> nriList = serviceState
+                .getNetworkRegistrationInfoListForTransportType(
+                        AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+        for (NetworkRegistrationInfo nri : nriList) {
+            if (nri.isInService()) {
+                logv("getWwanIsInService: return true");
+                return true;
+            }
+        }
+
+        logv("getWwanIsInService: return false");
+        return false;
+    }
+
+    private static void logv(@NonNull String log) {
+        Rlog.v(TAG, log);
+    }
+
     private static void logd(@NonNull String log) {
         Rlog.d(TAG, log);
     }
@@ -4745,4 +4930,98 @@
     private static void loge(@NonNull String log) {
         Rlog.e(TAG, log);
     }
+
+    private boolean isSatellitePersistentLoggingEnabled(
+            @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+        if (featureFlags.satellitePersistentLogging()) {
+            return true;
+        }
+        try {
+            return context.getResources().getBoolean(
+                    R.bool.config_dropboxmanager_persistent_logging_enabled);
+        } catch (RuntimeException e) {
+            return false;
+        }
+    }
+
+    private void plogd(@NonNull String log) {
+        Rlog.d(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.debug(TAG, log);
+        }
+    }
+
+    private void plogw(@NonNull String log) {
+        Rlog.w(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.warn(TAG, log);
+        }
+    }
+
+    private void ploge(@NonNull String log) {
+        Rlog.e(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.error(TAG, log);
+        }
+    }
+
+    private void handlePersistentLoggingOnSessionStart(RequestSatelliteEnabledArgument argument) {
+        if (mPersistentLogger == null) {
+            return;
+        }
+        if (argument.isEmergency) {
+            DropBoxManagerLoggerBackend.getInstance(mContext).setLoggingEnabled(true);
+        }
+    }
+
+    private void handlePersistentLoggingOnSessionEnd(boolean isEmergency) {
+        if (mPersistentLogger == null) {
+            return;
+        }
+        DropBoxManagerLoggerBackend loggerBackend =
+                DropBoxManagerLoggerBackend.getInstance(mContext);
+        // Flush persistent satellite logs on eSOS session end
+        if (isEmergency) {
+            loggerBackend.flushAsync();
+        }
+        // Also turn off persisted logging until new session is started
+        loggerBackend.setLoggingEnabled(false);
+    }
+
+    /**
+     * Set last emergency call time to the current time.
+     */
+    public void setLastEmergencyCallTime() {
+        synchronized (mLock) {
+            mLastEmergencyCallTime = getElapsedRealtime();
+            plogd("mLastEmergencyCallTime=" + mLastEmergencyCallTime);
+        }
+    }
+
+    /**
+     * Check if satellite is in emergency mode.
+     */
+    public boolean isInEmergencyMode() {
+        synchronized (mLock) {
+            if (mLastEmergencyCallTime == 0) return false;
+
+            long currentTime = getElapsedRealtime();
+            if ((currentTime - mLastEmergencyCallTime) <= mSatelliteEmergencyModeDurationMillis) {
+                plogd("Satellite is in emergency mode");
+                return true;
+            }
+            return false;
+        }
+    }
+
+    private long getSatelliteEmergencyModeDurationFromOverlayConfig(@NonNull Context context) {
+        Integer duration = DEFAULT_SATELLITE_EMERGENCY_MODE_DURATION_SECONDS;
+        try {
+            duration = context.getResources().getInteger(com.android.internal.R.integer
+                    .config_satellite_emergency_mode_duration);
+        } catch (Resources.NotFoundException ex) {
+            ploge("getSatelliteEmergencyModeDurationFromOverlayConfig: got ex=" + ex);
+        }
+        return TimeUnit.SECONDS.toMillis(duration);
+    }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
index 9f025db..da4c69b 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
@@ -30,8 +30,10 @@
 import android.os.Message;
 import android.os.RegistrantList;
 import android.os.RemoteException;
+import android.telephony.DropBoxManagerLoggerBackend;
 import android.telephony.IBooleanConsumer;
 import android.telephony.IIntegerConsumer;
+import android.telephony.PersistentLogger;
 import android.telephony.Rlog;
 import android.telephony.satellite.NtnSignalStrength;
 import android.telephony.satellite.SatelliteCapabilities;
@@ -50,6 +52,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.ExponentialBackoff;
+import com.android.internal.telephony.flags.FeatureFlags;
 
 import java.util.Arrays;
 import java.util.List;
@@ -81,6 +84,7 @@
     @NonNull private String mVendorSatellitePackageName = "";
     private boolean mIsBound;
     private boolean mIsBinding;
+    @Nullable private PersistentLogger mPersistentLogger = null;
 
     @NonNull private final RegistrantList mSatelliteProvisionStateChangedRegistrants =
             new RegistrantList();
@@ -117,7 +121,7 @@
         public void onSatelliteDatagramReceived(
                 android.telephony.satellite.stub.SatelliteDatagram datagram, int pendingCount) {
             if (notifyResultIfExpectedListener()) {
-                logd("onSatelliteDatagramReceived: pendingCount=" + pendingCount);
+                plogd("onSatelliteDatagramReceived: pendingCount=" + pendingCount);
                 mSatelliteDatagramsReceivedRegistrants.notifyResult(new Pair<>(
                         SatelliteServiceUtils.fromSatelliteDatagram(datagram), pendingCount));
             }
@@ -126,7 +130,7 @@
         @Override
         public void onPendingDatagrams() {
             if (notifyResultIfExpectedListener()) {
-                logd("onPendingDatagrams");
+                plogd("onPendingDatagrams");
                 mPendingDatagramsRegistrants.notifyResult(null);
             }
         }
@@ -222,13 +226,15 @@
      * Create the SatelliteModemInterface singleton instance.
      * @param context The Context to use to create the SatelliteModemInterface.
      * @param satelliteController The singleton instance of SatelliteController.
+     * @param featureFlags The telephony feature flags.
      * @return The singleton instance of SatelliteModemInterface.
      */
     public static SatelliteModemInterface make(@NonNull Context context,
-            SatelliteController satelliteController) {
+            SatelliteController satelliteController,
+            @NonNull FeatureFlags featureFlags) {
         if (sInstance == null) {
             sInstance = new SatelliteModemInterface(
-                    context, satelliteController, Looper.getMainLooper());
+                    context, satelliteController, Looper.getMainLooper(), featureFlags);
         }
         return sInstance;
     }
@@ -237,11 +243,18 @@
      * Create a SatelliteModemInterface to manage connections to the SatelliteService.
      *
      * @param context The Context for the SatelliteModemInterface.
+     * @param featureFlags The telephony feature flags.
      * @param looper The Looper to run binding retry on.
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected SatelliteModemInterface(@NonNull Context context,
-            SatelliteController satelliteController, @NonNull Looper looper) {
+            SatelliteController satelliteController,
+            @NonNull Looper looper,
+            @NonNull FeatureFlags featureFlags) {
+        if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
+            mPersistentLogger = new PersistentLogger(
+                    DropBoxManagerLoggerBackend.getInstance(context));
+        }
         mContext = context;
         mDemoSimulator = DemoSimulator.make(context, satelliteController);
         mVendorListener = new SatelliteListener(false);
@@ -265,7 +278,7 @@
             bindService();
         });
         mExponentialBackoff.start();
-        logd("Created SatelliteModemInterface. Attempting to bind to SatelliteService.");
+        plogd("Created SatelliteModemInterface. Attempting to bind to SatelliteService.");
         bindService();
     }
 
@@ -298,7 +311,7 @@
         }
         String packageName = getSatellitePackageName();
         if (TextUtils.isEmpty(packageName)) {
-            loge("Unable to bind to the satellite service because the package is undefined.");
+            ploge("Unable to bind to the satellite service because the package is undefined.");
             // Since the package name comes from static device configs, stop retry because
             // rebind will continue to fail without a valid package name.
             synchronized (mLock) {
@@ -311,18 +324,18 @@
         intent.setPackage(packageName);
 
         mSatelliteServiceConnection = new SatelliteServiceConnection();
-        logd("Binding to " + packageName);
+        plogd("Binding to " + packageName);
         try {
             boolean success = mContext.bindService(
                     intent, mSatelliteServiceConnection, Context.BIND_AUTO_CREATE);
             if (success) {
-                logd("Successfully bound to the satellite service.");
+                plogd("Successfully bound to the satellite service.");
             } else {
                 synchronized (mLock) {
                     mIsBinding = false;
                 }
                 mExponentialBackoff.notifyFailed();
-                loge("Error binding to the satellite service. Retrying in "
+                ploge("Error binding to the satellite service. Retrying in "
                         + mExponentialBackoff.getCurrentDelay() + " ms.");
             }
         } catch (Exception e) {
@@ -330,7 +343,7 @@
                 mIsBinding = false;
             }
             mExponentialBackoff.notifyFailed();
-            loge("Exception binding to the satellite service. Retrying in "
+            ploge("Exception binding to the satellite service. Retrying in "
                     + mExponentialBackoff.getCurrentDelay() + " ms. Exception: " + e);
         }
     }
@@ -350,7 +363,7 @@
     private class SatelliteServiceConnection implements ServiceConnection {
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
-            logd("onServiceConnected: ComponentName=" + name);
+            plogd("onServiceConnected: ComponentName=" + name);
             synchronized (mLock) {
                 mIsBound = true;
                 mIsBinding = false;
@@ -362,14 +375,14 @@
                 mDemoSimulator.setSatelliteListener(mDemoListener);
             } catch (RemoteException e) {
                 // TODO: Retry setSatelliteListener
-                logd("setSatelliteListener: RemoteException " + e);
+                plogd("setSatelliteListener: RemoteException " + e);
             }
             mSatelliteController.onSatelliteServiceConnected();
         }
 
         @Override
         public void onServiceDisconnected(ComponentName name) {
-            loge("onServiceDisconnected: Waiting for reconnect.");
+            ploge("onServiceDisconnected: Waiting for reconnect.");
             synchronized (mLock) {
                 mIsBinding = false;
             }
@@ -379,7 +392,7 @@
 
         @Override
         public void onBindingDied(ComponentName name) {
-            loge("onBindingDied: Unbinding and rebinding service.");
+            ploge("onBindingDied: Unbinding and rebinding service.");
             synchronized (mLock) {
                 mIsBound = false;
                 mIsBinding = false;
@@ -595,7 +608,7 @@
                             @Override
                             public void accept(int result) {
                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
-                                logd("requestSatelliteListeningEnabled: " + error);
+                                plogd("requestSatelliteListeningEnabled: " + error);
                                 Binder.withCleanCallingIdentity(() -> {
                                     if (message != null) {
                                         sendMessageWithResult(message, null, error);
@@ -604,14 +617,14 @@
                             }
                         });
             } catch (RemoteException e) {
-                loge("requestSatelliteListeningEnabled: RemoteException " + e);
+                ploge("requestSatelliteListeningEnabled: RemoteException " + e);
                 if (message != null) {
                     sendMessageWithResult(
                             message, null, SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
                 }
             }
         } else {
-            loge("requestSatelliteListeningEnabled: Satellite service is unavailable.");
+            ploge("requestSatelliteListeningEnabled: Satellite service is unavailable.");
             if (message != null) {
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
@@ -633,7 +646,7 @@
                     @Override
                     public void accept(int result) {
                         int error = SatelliteServiceUtils.fromSatelliteError(result);
-                        logd("enableCellularModemWhileSatelliteModeIsOn: " + error);
+                        plogd("enableCellularModemWhileSatelliteModeIsOn: " + error);
                         Binder.withCleanCallingIdentity(() -> {
                             if (message != null) {
                                 sendMessageWithResult(message, null, error);
@@ -650,14 +663,14 @@
                             enabled, errorCallback);
                 }
             } catch (RemoteException e) {
-                loge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e);
+                ploge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e);
                 if (message != null) {
                     sendMessageWithResult(
                             message, null, SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
                 }
             }
         } else {
-            loge("enableCellularModemWhileSatelliteModeIsOn: Satellite service is unavailable.");
+            ploge("enableCellularModemWhileSatelliteModeIsOn: Satellite service is unavailable.");
             if (message != null) {
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
@@ -683,18 +696,18 @@
                             @Override
                             public void accept(int result) {
                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
-                                logd("setSatelliteEnabled: " + error);
+                                plogd("setSatelliteEnabled: " + error);
                                 Binder.withCleanCallingIdentity(() ->
                                 sendMessageWithResult(message, null, error));
                     }
                 });
             } catch (RemoteException e) {
-                loge("setSatelliteEnabled: RemoteException " + e);
+                ploge("setSatelliteEnabled: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("setSatelliteEnabled: Satellite service is unavailable.");
+            ploge("setSatelliteEnabled: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -712,7 +725,7 @@
                     @Override
                     public void accept(int result) {
                         int error = SatelliteServiceUtils.fromSatelliteError(result);
-                        logd("requestIsSatelliteEnabled: " + error);
+                        plogd("requestIsSatelliteEnabled: " + error);
                         Binder.withCleanCallingIdentity(() ->
                                 sendMessageWithResult(message, null, error));
                     }
@@ -722,18 +735,18 @@
                         // Convert for compatibility with SatelliteResponse
                         // TODO: This should just report result instead.
                         int[] enabled = new int[] {result ? 1 : 0};
-                        logd("requestIsSatelliteEnabled: " + Arrays.toString(enabled));
+                        plogd("requestIsSatelliteEnabled: " + Arrays.toString(enabled));
                         Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
                                 message, enabled, SatelliteManager.SATELLITE_RESULT_SUCCESS));
                     }
                 });
             } catch (RemoteException e) {
-                loge("requestIsSatelliteEnabled: RemoteException " + e);
+                ploge("requestIsSatelliteEnabled: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("requestIsSatelliteEnabled: Satellite service is unavailable.");
+            ploge("requestIsSatelliteEnabled: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -751,25 +764,25 @@
                     @Override
                     public void accept(int result) {
                         int error = SatelliteServiceUtils.fromSatelliteError(result);
-                        logd("requestIsSatelliteSupported: " + error);
+                        plogd("requestIsSatelliteSupported: " + error);
                         Binder.withCleanCallingIdentity(() ->
                                 sendMessageWithResult(message, null, error));
                     }
                 }, new IBooleanConsumer.Stub() {
                     @Override
                     public void accept(boolean result) {
-                        logd("requestIsSatelliteSupported: " + result);
+                        plogd("requestIsSatelliteSupported: " + result);
                         Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
                                 message, result, SatelliteManager.SATELLITE_RESULT_SUCCESS));
                     }
                 });
             } catch (RemoteException e) {
-                loge("requestIsSatelliteSupported: RemoteException " + e);
+                ploge("requestIsSatelliteSupported: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("requestIsSatelliteSupported: Satellite service is unavailable.");
+            ploge("requestIsSatelliteSupported: Satellite service is unavailable.");
             sendMessageWithResult(
                     message, null, SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -787,7 +800,7 @@
                     @Override
                     public void accept(int result) {
                         int error = SatelliteServiceUtils.fromSatelliteError(result);
-                        logd("requestSatelliteCapabilities: " + error);
+                        plogd("requestSatelliteCapabilities: " + error);
                         Binder.withCleanCallingIdentity(() ->
                                 sendMessageWithResult(message, null, error));
                     }
@@ -797,18 +810,18 @@
                             result) {
                         SatelliteCapabilities capabilities =
                                 SatelliteServiceUtils.fromSatelliteCapabilities(result);
-                        logd("requestSatelliteCapabilities: " + capabilities);
+                        plogd("requestSatelliteCapabilities: " + capabilities);
                         Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
                                 message, capabilities, SatelliteManager.SATELLITE_RESULT_SUCCESS));
                     }
                 });
             } catch (RemoteException e) {
-                loge("requestSatelliteCapabilities: RemoteException " + e);
+                ploge("requestSatelliteCapabilities: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("requestSatelliteCapabilities: Satellite service is unavailable.");
+            ploge("requestSatelliteCapabilities: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -828,18 +841,18 @@
                     @Override
                     public void accept(int result) {
                         int error = SatelliteServiceUtils.fromSatelliteError(result);
-                        logd("startSendingSatellitePointingInfo: " + error);
+                        plogd("startSendingSatellitePointingInfo: " + error);
                         Binder.withCleanCallingIdentity(() ->
                                 sendMessageWithResult(message, null, error));
                     }
                 });
             } catch (RemoteException e) {
-                loge("startSendingSatellitePointingInfo: RemoteException " + e);
+                ploge("startSendingSatellitePointingInfo: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("startSendingSatellitePointingInfo: Satellite service is unavailable.");
+            ploge("startSendingSatellitePointingInfo: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -858,18 +871,18 @@
                     @Override
                     public void accept(int result) {
                         int error = SatelliteServiceUtils.fromSatelliteError(result);
-                        logd("stopSendingSatellitePointingInfo: " + error);
+                        plogd("stopSendingSatellitePointingInfo: " + error);
                         Binder.withCleanCallingIdentity(() ->
                                 sendMessageWithResult(message, null, error));
                     }
                 });
             } catch (RemoteException e) {
-                loge("stopSendingSatellitePointingInfo: RemoteException " + e);
+                ploge("stopSendingSatellitePointingInfo: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("stopSendingSatellitePointingInfo: Satellite service is unavailable.");
+            ploge("stopSendingSatellitePointingInfo: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -894,18 +907,18 @@
                             @Override
                             public void accept(int result) {
                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
-                                logd("provisionSatelliteService: " + error);
+                                plogd("provisionSatelliteService: " + error);
                                 Binder.withCleanCallingIdentity(() ->
                                         sendMessageWithResult(message, null, error));
                             }
                         });
             } catch (RemoteException e) {
-                loge("provisionSatelliteService: RemoteException " + e);
+                ploge("provisionSatelliteService: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("provisionSatelliteService: Satellite service is unavailable.");
+            ploge("provisionSatelliteService: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -926,18 +939,18 @@
                     @Override
                     public void accept(int result) {
                         int error = SatelliteServiceUtils.fromSatelliteError(result);
-                        logd("deprovisionSatelliteService: " + error);
+                        plogd("deprovisionSatelliteService: " + error);
                         Binder.withCleanCallingIdentity(() ->
                                 sendMessageWithResult(message, null, error));
                     }
                 });
             } catch (RemoteException e) {
-                loge("deprovisionSatelliteService: RemoteException " + e);
+                ploge("deprovisionSatelliteService: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("deprovisionSatelliteService: Satellite service is unavailable.");
+            ploge("deprovisionSatelliteService: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -955,7 +968,7 @@
                     @Override
                     public void accept(int result) {
                         int error = SatelliteServiceUtils.fromSatelliteError(result);
-                        logd("requestIsSatelliteProvisioned: " + error);
+                        plogd("requestIsSatelliteProvisioned: " + error);
                         Binder.withCleanCallingIdentity(() ->
                                 sendMessageWithResult(message, null, error));
                     }
@@ -965,18 +978,18 @@
                         // Convert for compatibility with SatelliteResponse
                         // TODO: This should just report result instead.
                         int[] provisioned = new int[] {result ? 1 : 0};
-                        logd("requestIsSatelliteProvisioned: " + Arrays.toString(provisioned));
+                        plogd("requestIsSatelliteProvisioned: " + Arrays.toString(provisioned));
                         Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
                                 message, provisioned, SatelliteManager.SATELLITE_RESULT_SUCCESS));
                     }
                 });
             } catch (RemoteException e) {
-                loge("requestIsSatelliteProvisioned: RemoteException " + e);
+                ploge("requestIsSatelliteProvisioned: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("requestIsSatelliteProvisioned: Satellite service is unavailable.");
+            ploge("requestIsSatelliteProvisioned: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -996,18 +1009,18 @@
                     @Override
                     public void accept(int result) {
                         int error = SatelliteServiceUtils.fromSatelliteError(result);
-                        logd("pollPendingDatagrams: " + error);
+                        plogd("pollPendingDatagrams: " + error);
                         Binder.withCleanCallingIdentity(() ->
                                 sendMessageWithResult(message, null, error));
                     }
                 });
             } catch (RemoteException e) {
-                loge("pollPendingDatagrams: RemoteException " + e);
+                ploge("pollPendingDatagrams: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("pollPendingDatagrams: Satellite service is unavailable.");
+            ploge("pollPendingDatagrams: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -1032,18 +1045,18 @@
                             @Override
                             public void accept(int result) {
                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
-                                logd("sendDatagram: " + error);
+                                plogd("sendDatagram: " + error);
                                 Binder.withCleanCallingIdentity(() ->
                                         sendMessageWithResult(message, null, error));
                             }
                         });
             } catch (RemoteException e) {
-                loge("sendDatagram: RemoteException " + e);
+                ploge("sendDatagram: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("sendDatagram: Satellite service is unavailable.");
+            ploge("sendDatagram: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -1063,7 +1076,7 @@
                     @Override
                     public void accept(int result) {
                         int error = SatelliteServiceUtils.fromSatelliteError(result);
-                        logd("requestSatelliteModemState: " + error);
+                        plogd("requestSatelliteModemState: " + error);
                         Binder.withCleanCallingIdentity(() ->
                                 sendMessageWithResult(message, null, error));
                     }
@@ -1072,18 +1085,18 @@
                     public void accept(int result) {
                         // Convert SatelliteModemState from service to frameworks definition.
                         int modemState = SatelliteServiceUtils.fromSatelliteModemState(result);
-                        logd("requestSatelliteModemState: " + modemState);
+                        plogd("requestSatelliteModemState: " + modemState);
                         Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
                                 message, modemState, SatelliteManager.SATELLITE_RESULT_SUCCESS));
                     }
                 });
             } catch (RemoteException e) {
-                loge("requestSatelliteModemState: RemoteException " + e);
+                ploge("requestSatelliteModemState: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("requestSatelliteModemState: Satellite service is unavailable.");
+            ploge("requestSatelliteModemState: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -1104,7 +1117,7 @@
                             @Override
                             public void accept(int result) {
                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
-                                logd("requestTimeForNextSatelliteVisibility: " + error);
+                                plogd("requestTimeForNextSatelliteVisibility: " + error);
                                 Binder.withCleanCallingIdentity(() ->
                                         sendMessageWithResult(message, null, error));
                             }
@@ -1114,19 +1127,19 @@
                                 // Convert for compatibility with SatelliteResponse
                                 // TODO: This should just report result instead.
                                 int[] time = new int[] {result};
-                                logd("requestTimeForNextSatelliteVisibility: "
+                                plogd("requestTimeForNextSatelliteVisibility: "
                                         + Arrays.toString(time));
                                 Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
                                         message, time, SatelliteManager.SATELLITE_RESULT_SUCCESS));
                             }
                         });
             } catch (RemoteException e) {
-                loge("requestTimeForNextSatelliteVisibility: RemoteException " + e);
+                ploge("requestTimeForNextSatelliteVisibility: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("requestTimeForNextSatelliteVisibility: Satellite service is unavailable.");
+            ploge("requestTimeForNextSatelliteVisibility: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -1159,18 +1172,18 @@
                             @Override
                             public void accept(int result) {
                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
-                                logd("setSatellitePlmn: " + error);
+                                plogd("setSatellitePlmn: " + error);
                                 Binder.withCleanCallingIdentity(() ->
                                         sendMessageWithResult(message, null, error));
                             }
                         });
             } catch (RemoteException e) {
-                loge("setSatellitePlmn: RemoteException " + e);
+                ploge("setSatellitePlmn: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("setSatellitePlmn: Satellite service is unavailable.");
+            ploge("setSatellitePlmn: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -1194,18 +1207,18 @@
                             @Override
                             public void accept(int result) {
                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
-                                logd("requestSetSatelliteEnabledForCarrier: " + error);
+                                plogd("requestSetSatelliteEnabledForCarrier: " + error);
                                 Binder.withCleanCallingIdentity(() ->
                                         sendMessageWithResult(message, null, error));
                             }
                         });
             } catch (RemoteException e) {
-                loge("requestSetSatelliteEnabledForCarrier: RemoteException " + e);
+                ploge("requestSetSatelliteEnabledForCarrier: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("requestSetSatelliteEnabledForCarrier: Satellite service is unavailable.");
+            ploge("requestSetSatelliteEnabledForCarrier: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
         }
@@ -1227,7 +1240,7 @@
                             @Override
                             public void accept(int result) {
                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
-                                logd("requestIsSatelliteEnabledForCarrier: " + error);
+                                plogd("requestIsSatelliteEnabledForCarrier: " + error);
                                 Binder.withCleanCallingIdentity(() ->
                                         sendMessageWithResult(message, null, error));
                             }
@@ -1237,7 +1250,7 @@
                                 // Convert for compatibility with SatelliteResponse
                                 // TODO: This should just report result instead.
                                 int[] enabled = new int[] {result ? 1 : 0};
-                                logd("requestIsSatelliteEnabledForCarrier: "
+                                plogd("requestIsSatelliteEnabledForCarrier: "
                                         + Arrays.toString(enabled));
                                 Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
                                         message, enabled,
@@ -1245,12 +1258,12 @@
                             }
                         });
             } catch (RemoteException e) {
-                loge("requestIsSatelliteEnabledForCarrier: RemoteException " + e);
+                ploge("requestIsSatelliteEnabledForCarrier: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("requestIsSatelliteEnabledForCarrier: Satellite service is unavailable.");
+            ploge("requestIsSatelliteEnabledForCarrier: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -1269,7 +1282,7 @@
                             @Override
                             public void accept(int result) {
                                 int error = SatelliteServiceUtils.fromSatelliteError(result);
-                                logd("requestNtnSignalStrength: " + error);
+                                plogd("requestNtnSignalStrength: " + error);
                                 Binder.withCleanCallingIdentity(() ->
                                         sendMessageWithResult(message, null, error));
                             }
@@ -1279,19 +1292,19 @@
                                     android.telephony.satellite.stub.NtnSignalStrength result) {
                                 NtnSignalStrength ntnSignalStrength =
                                         SatelliteServiceUtils.fromNtnSignalStrength(result);
-                                logd("requestNtnSignalStrength: " + ntnSignalStrength);
+                                plogd("requestNtnSignalStrength: " + ntnSignalStrength);
                                 Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
                                         message, ntnSignalStrength,
                                         SatelliteManager.SATELLITE_RESULT_SUCCESS));
                             }
                         });
             } catch (RemoteException e) {
-                loge("requestNtnSignalStrength: RemoteException " + e);
+                ploge("requestNtnSignalStrength: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("requestNtnSignalStrength: Satellite service is unavailable.");
+            ploge("requestNtnSignalStrength: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -1310,18 +1323,18 @@
                     @Override
                     public void accept(int result) {
                         int error = SatelliteServiceUtils.fromSatelliteError(result);
-                        logd("startSendingNtnSignalStrength: " + error);
+                        plogd("startSendingNtnSignalStrength: " + error);
                         Binder.withCleanCallingIdentity(() ->
                                 sendMessageWithResult(message, null, error));
                     }
                 });
             } catch (RemoteException e) {
-                loge("startSendingNtnSignalStrength: RemoteException " + e);
+                ploge("startSendingNtnSignalStrength: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("startSendingNtnSignalStrength: Satellite service is unavailable.");
+            ploge("startSendingNtnSignalStrength: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -1339,18 +1352,18 @@
                     @Override
                     public void accept(int result) {
                         int error = SatelliteServiceUtils.fromSatelliteError(result);
-                        logd("stopSendingNtnSignalStrength: " + error);
+                        plogd("stopSendingNtnSignalStrength: " + error);
                         Binder.withCleanCallingIdentity(() ->
                                 sendMessageWithResult(message, null, error));
                     }
                 });
             } catch (RemoteException e) {
-                loge("stopSendingNtnSignalStrength: RemoteException " + e);
+                ploge("stopSendingNtnSignalStrength: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("stopSendingNtnSignalStrength: Satellite service is unavailable.");
+            ploge("stopSendingNtnSignalStrength: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -1368,18 +1381,18 @@
                     @Override
                     public void accept(int result) {
                         int error = SatelliteServiceUtils.fromSatelliteError(result);
-                        logd("abortSendingSatelliteDatagrams: " + error);
+                        plogd("abortSendingSatelliteDatagrams: " + error);
                         Binder.withCleanCallingIdentity(() ->
                                 sendMessageWithResult(message, null, error));
                     }
                 });
             } catch (RemoteException e) {
-                loge("abortSendingSatelliteDatagrams: RemoteException " + e);
+                ploge("abortSendingSatelliteDatagrams: RemoteException " + e);
                 sendMessageWithResult(message, null,
                         SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
             }
         } else {
-            loge("abortSendingSatelliteDatagrams: Satellite service is unavailable.");
+            ploge("abortSendingSatelliteDatagrams: Satellite service is unavailable.");
             sendMessageWithResult(message, null,
                     SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
         }
@@ -1405,7 +1418,7 @@
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     public void setSatelliteServicePackageName(@Nullable String servicePackageName) {
-        logd("setSatelliteServicePackageName: config_satellite_service_package is "
+        plogd("setSatelliteServicePackageName: config_satellite_service_package is "
                 + "updated, new packageName=" + servicePackageName);
         mExponentialBackoff.stop();
         if (mSatelliteServiceConnection != null) {
@@ -1442,4 +1455,31 @@
     private static void loge(@NonNull String log) {
         Rlog.e(TAG, log);
     }
+
+    private boolean isSatellitePersistentLoggingEnabled(
+            @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+        if (featureFlags.satellitePersistentLogging()) {
+            return true;
+        }
+        try {
+            return context.getResources().getBoolean(
+                    R.bool.config_dropboxmanager_persistent_logging_enabled);
+        } catch (RuntimeException e) {
+            return false;
+        }
+    }
+
+    private void plogd(@NonNull String log) {
+        Rlog.d(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.debug(TAG, log);
+        }
+    }
+
+    private void ploge(@NonNull String log) {
+        Rlog.e(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.error(TAG, log);
+        }
+    }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index c497ca1..7f3eb0f 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -24,6 +24,7 @@
 import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
 import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
 
+import static com.android.internal.telephony.flags.Flags.satellitePersistentLogging;
 import static com.android.internal.telephony.satellite.SatelliteController.INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE;
 
 import android.annotation.NonNull;
@@ -42,6 +43,10 @@
 import android.os.SystemProperties;
 import android.provider.DeviceConfig;
 import android.telecom.Connection;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.PersistentLogger;
 import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
@@ -65,6 +70,7 @@
 import com.android.internal.telephony.SmsApplication;
 import com.android.internal.telephony.metrics.SatelliteStats;
 
+import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 
@@ -109,13 +115,16 @@
     protected int mCountOfTimerStarted = 0;
     private final Object mLock = new Object();
 
+    @Nullable private PersistentLogger mPersistentLogger = null;
+
     /**
      * Create an instance of SatelliteSOSMessageRecommender.
      *
      * @param context The Context for the SatelliteSOSMessageRecommender.
      * @param looper The looper used with the handler of this class.
      */
-    public SatelliteSOSMessageRecommender(@NonNull Context context, @NonNull Looper looper) {
+    public SatelliteSOSMessageRecommender(@NonNull Context context,
+            @NonNull Looper looper) {
         this(context, looper, SatelliteController.getInstance(), null);
     }
 
@@ -131,8 +140,13 @@
      */
     @VisibleForTesting
     protected SatelliteSOSMessageRecommender(@NonNull Context context, @NonNull Looper looper,
-            @NonNull SatelliteController satelliteController, ImsManager imsManager) {
+            @NonNull SatelliteController satelliteController,
+            ImsManager imsManager) {
         super(looper);
+        if (isSatellitePersistentLoggingEnabled(context)) {
+            mPersistentLogger = new PersistentLogger(
+                    DropBoxManagerLoggerBackend.getInstance(context));
+        }
         mContext = context;
         mSatelliteController = satelliteController;
         mImsManager = imsManager;
@@ -141,7 +155,7 @@
         mISatelliteProvisionStateCallback = new ISatelliteProvisionStateCallback.Stub() {
             @Override
             public void onSatelliteProvisionStateChanged(boolean provisioned) {
-                logd("onSatelliteProvisionStateChanged: provisioned=" + provisioned);
+                plogd("onSatelliteProvisionStateChanged: provisioned=" + provisioned);
                 sendMessage(obtainMessage(EVENT_SATELLITE_PROVISIONED_STATE_CHANGED, provisioned));
             }
         };
@@ -172,7 +186,7 @@
                 handleSatelliteAccessRestrictionCheckingResult((boolean) msg.obj);
                 break;
             default:
-                logd("handleMessage: unexpected message code: " + msg.what);
+                plogd("handleMessage: unexpected message code: " + msg.what);
                 break;
         }
     }
@@ -184,9 +198,8 @@
      *                   call.
      */
     public void onEmergencyCallStarted(@NonNull Connection connection) {
-        if (!mSatelliteController.isSatelliteSupportedViaOem()
-                && !mSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier()) {
-            logd("onEmergencyCallStarted: satellite is not supported");
+        if (!isSatelliteSupported()) {
+            plogd("onEmergencyCallStarted: satellite is not supported");
             return;
         }
 
@@ -215,10 +228,9 @@
      */
     public void onEmergencyCallConnectionStateChanged(
             String callId, @Connection.ConnectionState int state) {
-        logd("callId=" + callId + ", state=" + state);
-        if (!mSatelliteController.isSatelliteSupportedViaOem()
-                && !mSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier()) {
-            logd("onEmergencyCallConnectionStateChanged: satellite is not supported");
+        plogd("callId=" + callId + ", state=" + state);
+        if (!isSatelliteSupported()) {
+            plogd("onEmergencyCallConnectionStateChanged: satellite is not supported");
             return;
         }
         Pair<String, Integer> argument = new Pair<>(callId, state);
@@ -231,16 +243,19 @@
     }
 
     private void handleEmergencyCallStartedEvent(@NonNull Connection connection) {
+        mSatelliteController.setLastEmergencyCallTime();
+
         if (sendEventDisplayEmergencyMessageForcefully(connection)) {
             return;
         }
 
         selectEmergencyCallWaitForConnectionTimeoutDuration();
         if (mEmergencyConnection == null) {
-            handleStateChangedEventForHysteresisTimer();
             registerForInterestedStateChangedEvents();
         }
         mEmergencyConnection = connection;
+        handleStateChangedEventForHysteresisTimer();
+
         synchronized (mLock) {
             mCheckingAccessRestrictionInProgress = false;
             mIsSatelliteAllowedForCurrentLocation = false;
@@ -263,12 +278,12 @@
     private void evaluateSendingConnectionEventDisplayEmergencyMessage() {
         synchronized (mLock) {
             if (mEmergencyConnection == null) {
-                loge("No emergency call is ongoing...");
+                ploge("No emergency call is ongoing...");
                 return;
             }
 
             if (!mIsTimerTimedOut || mCheckingAccessRestrictionInProgress) {
-                logd("mIsTimerTimedOut=" + mIsTimerTimedOut
+                plogd("mIsTimerTimedOut=" + mIsTimerTimedOut
                         + ", mCheckingAccessRestrictionInProgress="
                         + mCheckingAccessRestrictionInProgress);
                 return;
@@ -286,14 +301,14 @@
                     && isSatelliteAllowed()
                     && (isSatelliteViaOemAvailable() || isSatelliteViaCarrierAvailable())
                     && shouldTrackCall(mEmergencyConnection.getState())) {
-                logd("handleTimeoutEvent: Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer");
+                plogd("handleTimeoutEvent: Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer");
                 Bundle extras = createExtraBundleForEventDisplayEmergencyMessage();
                 mEmergencyConnection.sendConnectionEvent(
                         TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE, extras);
                 isDialerNotified = true;
 
             }
-            logd("handleTimeoutEvent: isImsRegistered=" + isImsRegistered()
+            plogd("handleTimeoutEvent: isImsRegistered=" + isImsRegistered()
                     + ", isCellularAvailable=" + isCellularAvailable()
                     + ", isSatelliteAllowed=" + isSatelliteAllowed()
                     + ", shouldTrackCall=" + shouldTrackCall(mEmergencyConnection.getState()));
@@ -332,6 +347,7 @@
 
     private void handleEmergencyCallConnectionStateChangedEvent(
             @NonNull Pair<String, Integer> arg) {
+        mSatelliteController.setLastEmergencyCallTime();
         if (mEmergencyConnection == null) {
             // Either the call was not created or the timer already timed out.
             return;
@@ -340,7 +356,7 @@
         String callId = arg.first;
         int state = arg.second;
         if (!mEmergencyConnection.getTelecomCallId().equals(callId)) {
-            loge("handleEmergencyCallConnectionStateChangedEvent: unexpected state changed event "
+            ploge("handleEmergencyCallConnectionStateChangedEvent: unexpected state changed event "
                     + ", mEmergencyConnection=" + mEmergencyConnection + ", callId=" + callId
                     + ", state=" + state);
             /*
@@ -398,7 +414,6 @@
         for (Phone phone : PhoneFactory.getPhones()) {
             phone.registerForServiceStateChanged(
                     this, EVENT_SERVICE_STATE_CHANGED, null);
-            registerForImsRegistrationStateChanged(phone);
         }
     }
 
@@ -409,7 +424,7 @@
             imsManager.addRegistrationCallback(
                     getOrCreateImsRegistrationCallback(phone.getPhoneId()), this::post);
         } catch (ImsException ex) {
-            loge("registerForImsRegistrationStateChanged: ex=" + ex);
+            ploge("registerForImsRegistrationStateChanged: ex=" + ex);
         }
     }
 
@@ -418,7 +433,6 @@
                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, mISatelliteProvisionStateCallback);
         for (Phone phone : PhoneFactory.getPhones()) {
             phone.unregisterForServiceStateChanged(this);
-            unregisterForImsRegistrationStateChanged(phone);
         }
     }
 
@@ -430,7 +444,7 @@
             imsManager.removeRegistrationListener(
                     mImsRegistrationCallbacks.get(phone.getPhoneId()));
         } else {
-            loge("Phone ID=" + phone.getPhoneId() + " was not registered with ImsManager");
+            ploge("Phone ID=" + phone.getPhoneId() + " was not registered with ImsManager");
         }
     }
 
@@ -441,7 +455,7 @@
                 int state = serviceState.getState();
                 if ((state == STATE_IN_SERVICE || state == STATE_EMERGENCY_ONLY
                         || serviceState.isEmergencyOnly())
-                        && !serviceState.isUsingNonTerrestrialNetwork()) {
+                        && !isSatellitePlmn(phone.getSubId(), serviceState)) {
                     logv("isCellularAvailable true");
                     return true;
                 }
@@ -451,6 +465,34 @@
         return false;
     }
 
+    private boolean isSatellitePlmn(int subId, @NonNull ServiceState serviceState) {
+        List<String> satellitePlmnList =
+                mSatelliteController.getSatellitePlmnsForCarrier(subId);
+        if (satellitePlmnList.isEmpty()) {
+            logv("isSatellitePlmn: satellitePlmnList is empty");
+            return false;
+        }
+
+        for (NetworkRegistrationInfo nri :
+                serviceState.getNetworkRegistrationInfoListForTransportType(
+                        AccessNetworkConstants.TRANSPORT_TYPE_WWAN)) {
+            String registeredPlmn = nri.getRegisteredPlmn();
+            String mccmnc = nri.getCellIdentity().getMccString()
+                    + nri.getCellIdentity().getMncString();
+            for (String satellitePlmn : satellitePlmnList) {
+                if (TextUtils.equals(satellitePlmn, registeredPlmn)
+                        || TextUtils.equals(satellitePlmn, mccmnc)) {
+                    logv("isSatellitePlmn: return true, satellitePlmn:" + satellitePlmn
+                            + " registeredPlmn:" + registeredPlmn + " mccmnc:" + mccmnc);
+                    return true;
+                }
+            }
+        }
+
+        logv("isSatellitePlmn: return false");
+        return false;
+    }
+
     /**
      * @return {@link ServiceState#STATE_IN_SERVICE} if any subscription is in this state; else
      * {@link ServiceState#STATE_EMERGENCY_ONLY} if any subscription is in this state; else
@@ -482,7 +524,7 @@
     }
 
     private synchronized void handleStateChangedEventForHysteresisTimer() {
-        if (!isCellularAvailable()) {
+        if (!isCellularAvailable() && mEmergencyConnection != null) {
             startTimer();
         } else {
             logv("handleStateChangedEventForHysteresisTimer stopTimer");
@@ -523,7 +565,7 @@
         } else {
             mTimeoutMillis = mOemEnabledTimeoutMillis;
         }
-        logd("mTimeoutMillis = " + mTimeoutMillis);
+        plogd("mTimeoutMillis = " + mTimeoutMillis);
     }
 
     private static long getOemEnabledEmergencyCallWaitForConnectionTimeoutMillis(
@@ -631,7 +673,7 @@
             packageName = defaultSmsAppComponent.getPackageName();
             className = defaultSmsAppComponent.getClassName();
         }
-        logd("EVENT_DISPLAY_EMERGENCY_MESSAGE: handoverType=" + handoverType + ", packageName="
+        plogd("EVENT_DISPLAY_EMERGENCY_MESSAGE: handoverType=" + handoverType + ", packageName="
                 + packageName + ", className=" + className + ", action=" + action);
 
         Bundle result = new Bundle();
@@ -652,7 +694,7 @@
             if (mEmergencyConnection != null) {
                 emergencyNumber = mEmergencyConnection.getAddress().getSchemeSpecificPart();
             }
-            logd("emergencyNumber=" + emergencyNumber);
+            plogd("emergencyNumber=" + emergencyNumber);
 
             Uri uri = Uri.parse("smsto:" + emergencyNumber);
             intent = new Intent(Intent.ACTION_SENDTO, uri);
@@ -684,7 +726,7 @@
 
     private void handleCmdSendEventDisplayEmergencyMessageForcefully(
             @NonNull Connection connection) {
-        logd("Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer forcefully.");
+        plogd("Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer forcefully.");
         mEmergencyConnection = connection;
         Bundle extras = createExtraBundleForEventDisplayEmergencyMessage();
         connection.sendConnectionEvent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE, extras);
@@ -694,7 +736,7 @@
     private boolean isMultiSim() {
         TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
         if (telephonyManager == null) {
-            loge("isMultiSim: telephonyManager is null");
+            ploge("isMultiSim: telephonyManager is null");
             return false;
         }
         return telephonyManager.isMultiSimEnabled();
@@ -711,7 +753,7 @@
     private void requestIsSatelliteAllowedForCurrentLocation() {
         synchronized (mLock) {
             if (mCheckingAccessRestrictionInProgress) {
-                logd("requestIsSatelliteCommunicationAllowedForCurrentLocation was already sent");
+                plogd("requestIsSatelliteCommunicationAllowedForCurrentLocation was already sent");
                 return;
             }
             mCheckingAccessRestrictionInProgress = true;
@@ -721,14 +763,14 @@
                 new OutcomeReceiver<>() {
                     @Override
                     public void onResult(Boolean result) {
-                        logd("requestIsSatelliteAllowedForCurrentLocation: result=" + result);
+                        plogd("requestIsSatelliteAllowedForCurrentLocation: result=" + result);
                         sendMessage(obtainMessage(
                                 EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT, result));
                     }
 
                     @Override
                     public void onError(SatelliteManager.SatelliteException ex) {
-                        logd("requestIsSatelliteAllowedForCurrentLocation: onError, ex=" + ex);
+                        plogd("requestIsSatelliteAllowedForCurrentLocation: onError, ex=" + ex);
                         sendMessage(obtainMessage(
                                 EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT, false));
                     }
@@ -749,6 +791,19 @@
                 || SystemProperties.getBoolean(BOOT_ALLOW_MOCK_MODEM_PROPERTY, false));
     }
 
+    private boolean isSatelliteSupported() {
+        if (mSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier()) return true;
+        if (mSatelliteController.isSatelliteSupportedViaOem() && isSatelliteViaOemProvisioned()) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isSatelliteViaOemProvisioned() {
+        Boolean provisioned = mSatelliteController.isSatelliteViaOemProvisioned();
+        return (provisioned != null) && provisioned;
+    }
+
     private static void logv(@NonNull String log) {
         Rlog.v(TAG, log);
     }
@@ -760,4 +815,31 @@
     private static void loge(@NonNull String log) {
         Rlog.e(TAG, log);
     }
+
+    private boolean isSatellitePersistentLoggingEnabled(
+            @NonNull Context context) {
+        if (satellitePersistentLogging()) {
+            return true;
+        }
+        try {
+            return context.getResources().getBoolean(
+                    R.bool.config_dropboxmanager_persistent_logging_enabled);
+        } catch (RuntimeException e) {
+            return false;
+        }
+    }
+
+    private void plogd(@NonNull String log) {
+        Rlog.d(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.debug(TAG, log);
+        }
+    }
+
+    private void ploge(@NonNull String log) {
+        Rlog.e(TAG, log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.error(TAG, log);
+        }
+    }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
index dcf9bb0..dde10a0 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
@@ -39,6 +39,9 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.SystemProperties;
+import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.PersistentLogger;
+import android.telephony.Rlog;
 import android.telephony.satellite.ISatelliteModemStateCallback;
 import android.telephony.satellite.SatelliteManager;
 import android.telephony.satellite.stub.ISatelliteGateway;
@@ -50,6 +53,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.ExponentialBackoff;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
 
@@ -141,6 +145,8 @@
     @NonNull private boolean mIsDisableCellularModemInProgress = false;
     @NonNull private final SatelliteController mSatelliteController;
     @NonNull private final DatagramController mDatagramController;
+    @Nullable private PersistentLogger mPersistentLogger = null;
+
 
     /**
      * @return The singleton instance of SatelliteSessionController.
@@ -157,13 +163,21 @@
      *
      * @param context The Context for the SatelliteSessionController.
      * @param looper The looper associated with the handler of this class.
+     * @param featureFlags The telephony feature flags.
      * @param isSatelliteSupported Whether satellite is supported on the device.
      * @return The singleton instance of SatelliteSessionController.
      */
     public static SatelliteSessionController make(
-            @NonNull Context context, @NonNull Looper looper, boolean isSatelliteSupported) {
+            @NonNull Context context,
+            @NonNull Looper looper,
+            @NonNull FeatureFlags featureFlags,
+            boolean isSatelliteSupported) {
         if (sInstance == null || isSatelliteSupported != sInstance.mIsSatelliteSupported) {
-            sInstance = new SatelliteSessionController(context, looper, isSatelliteSupported,
+            sInstance = new SatelliteSessionController(
+                    context,
+                    looper,
+                    featureFlags,
+                    isSatelliteSupported,
                     SatelliteModemInterface.getInstance());
         }
         return sInstance;
@@ -174,15 +188,22 @@
      *
      * @param context The Context for the SatelliteSessionController.
      * @param looper The looper associated with the handler of this class.
+     * @param featureFlags The telephony feature flags.
      * @param isSatelliteSupported Whether satellite is supported on the device.
      * @param satelliteModemInterface The singleton of SatelliteModemInterface.
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected SatelliteSessionController(@NonNull Context context, @NonNull Looper looper,
+            @NonNull FeatureFlags featureFlags,
             boolean isSatelliteSupported,
             @NonNull SatelliteModemInterface satelliteModemInterface) {
         super(TAG, looper);
 
+        if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
+            mPersistentLogger = new PersistentLogger(
+                    DropBoxManagerLoggerBackend.getInstance(context));
+        }
+
         mContext = context;
         mSatelliteModemInterface = satelliteModemInterface;
         mSatelliteController = SatelliteController.getInstance();
@@ -297,7 +318,7 @@
             callback.onSatelliteModemStateChanged(mCurrentState);
             mListeners.put(callback.asBinder(), callback);
         } catch (RemoteException ex) {
-            loge("registerForSatelliteModemStateChanged: Got RemoteException ex=" + ex);
+            ploge("registerForSatelliteModemStateChanged: Got RemoteException ex=" + ex);
         }
     }
 
@@ -323,11 +344,11 @@
      */
     boolean setSatelliteListeningTimeoutDuration(long timeoutMillis) {
         if (!isMockModemAllowed()) {
-            loge("Updating listening timeout duration is not allowed");
+            ploge("Updating listening timeout duration is not allowed");
             return false;
         }
 
-        logd("setSatelliteListeningTimeoutDuration: timeoutMillis=" + timeoutMillis);
+        plogd("setSatelliteListeningTimeoutDuration: timeoutMillis=" + timeoutMillis);
         if (timeoutMillis == 0) {
             mSatelliteStayAtListeningFromSendingMillis =
                     getSatelliteStayAtListeningFromSendingMillis();
@@ -353,12 +374,12 @@
      */
     boolean setSatelliteGatewayServicePackageName(@Nullable String servicePackageName) {
         if (!isMockModemAllowed()) {
-            loge("setSatelliteGatewayServicePackageName: modifying satellite gateway service "
+            ploge("setSatelliteGatewayServicePackageName: modifying satellite gateway service "
                     + "package name is not allowed");
             return false;
         }
 
-        logd("setSatelliteGatewayServicePackageName: config_satellite_gateway_service_package is "
+        plogd("setSatelliteGatewayServicePackageName: config_satellite_gateway_service_package is "
                 + "updated, new packageName=" + servicePackageName);
 
         if (servicePackageName == null || servicePackageName.equals("null")) {
@@ -397,7 +418,7 @@
      * @return {@code true} if state machine is in enabling state and {@code false} otherwise.
      */
     public boolean isInEnablingState() {
-        if (DBG) logd("isInEnablingState: getCurrentState=" + getCurrentState());
+        if (DBG) plogd("isInEnablingState: getCurrentState=" + getCurrentState());
         return getCurrentState() == mEnablingState;
     }
 
@@ -419,14 +440,14 @@
     private class UnavailableState extends State {
         @Override
         public void enter() {
-            if (DBG) logd("Entering UnavailableState");
+            if (DBG) plogd("Entering UnavailableState");
             mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE;
             notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE);
         }
 
         @Override
         public boolean processMessage(Message msg) {
-            loge("UnavailableState: receive msg " + getWhatToString(msg.what) + " unexpectedly");
+            ploge("UnavailableState: receive msg " + getWhatToString(msg.what) + " unexpectedly");
             return HANDLED;
         }
     }
@@ -434,7 +455,7 @@
     private class PowerOffState extends State {
         @Override
         public void enter() {
-            if (DBG) logd("Entering PowerOffState");
+            if (DBG) plogd("Entering PowerOffState");
 
             mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_OFF;
             mIsSendingTriggeredDuringTransferringState.set(false);
@@ -449,14 +470,14 @@
 
         @Override
         public void exit() {
-            if (DBG) logd("Exiting PowerOffState");
-            logd("Attempting to bind to SatelliteGatewayService.");
+            if (DBG) plogd("Exiting PowerOffState");
+            plogd("Attempting to bind to SatelliteGatewayService.");
             bindService();
         }
 
         @Override
         public boolean processMessage(Message msg) {
-            if (DBG) log("PowerOffState: processing " + getWhatToString(msg.what));
+            if (DBG) plogd("PowerOffState: processing " + getWhatToString(msg.what));
             switch (msg.what) {
                 case EVENT_SATELLITE_ENABLEMENT_STARTED:
                     handleSatelliteEnablementStarted((boolean) msg.obj);
@@ -470,7 +491,7 @@
             if (enabled) {
                 transitionTo(mEnablingState);
             } else {
-                logw("Unexpected satellite disablement started in PowerOff state");
+                plogw("Unexpected satellite disablement started in PowerOff state");
             }
         }
     }
@@ -478,7 +499,7 @@
     private class EnablingState extends State {
         @Override
         public void enter() {
-            if (DBG) logd("Entering EnablingState");
+            if (DBG) plogd("Entering EnablingState");
 
             mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_ENABLING_SATELLITE;
             notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_ENABLING_SATELLITE);
@@ -486,12 +507,12 @@
 
         @Override
         public void exit() {
-            if (DBG) logd("Exiting EnablingState");
+            if (DBG) plogd("Exiting EnablingState");
         }
 
         @Override
         public boolean processMessage(Message msg) {
-            if (DBG) log("EnablingState: processing " + getWhatToString(msg.what));
+            if (DBG) plogd("EnablingState: processing " + getWhatToString(msg.what));
             switch (msg.what) {
                 case EVENT_SATELLITE_ENABLED_STATE_CHANGED:
                     handleSatelliteEnabledStateChanged((boolean) msg.obj);
@@ -531,7 +552,7 @@
     private class DisablingState extends State {
         @Override
         public void enter() {
-            if (DBG) logd("Entering DisablingState");
+            if (DBG) plogd("Entering DisablingState");
 
             mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_DISABLING_SATELLITE;
             notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_DISABLING_SATELLITE);
@@ -539,12 +560,12 @@
 
         @Override
         public void exit() {
-            if (DBG) logd("Exiting DisablingState");
+            if (DBG) plogd("Exiting DisablingState");
         }
 
         @Override
         public boolean processMessage(Message msg) {
-            if (DBG) log("DisablingState: processing " + getWhatToString(msg.what));
+            if (DBG) plogd("DisablingState: processing " + getWhatToString(msg.what));
             switch (msg.what) {
                 case EVENT_SATELLITE_ENABLED_STATE_CHANGED:
                     handleSatelliteEnabledStateChanged((boolean) msg.obj);
@@ -556,7 +577,7 @@
 
         private void handleSatelliteEnabledStateChanged(boolean on) {
             if (on) {
-                logw("Unexpected power on event while disabling satellite");
+                plogw("Unexpected power on event while disabling satellite");
             } else {
                 transitionTo(mPowerOffState);
             }
@@ -566,7 +587,7 @@
     private class IdleState extends State {
         @Override
         public void enter() {
-            if (DBG) logd("Entering IdleState");
+            if (DBG) plogd("Entering IdleState");
             mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_IDLE;
             mIsSendingTriggeredDuringTransferringState.set(false);
             stopNbIotInactivityTimer();
@@ -577,7 +598,7 @@
 
         @Override
         public boolean processMessage(Message msg) {
-            if (DBG) log("IdleState: processing " + getWhatToString(msg.what));
+            if (DBG) plogd("IdleState: processing " + getWhatToString(msg.what));
             switch (msg.what) {
                 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED:
                     handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj);
@@ -603,7 +624,7 @@
                     || (datagramTransferState.receiveState
                     == SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING)) {
                 if (mSatelliteController.isSatelliteAttachRequired()) {
-                    loge("Unexpected transferring state received for NB-IOT NTN");
+                    ploge("Unexpected transferring state received for NB-IOT NTN");
                 } else {
                     transitionTo(mTransferringState);
                 }
@@ -614,7 +635,7 @@
                 if (mSatelliteController.isSatelliteAttachRequired()) {
                     disableCellularModemWhileSatelliteModeIsOn();
                 } else {
-                    loge("Unexpected transferring state received for non-NB-IOT NTN");
+                    ploge("Unexpected transferring state received for non-NB-IOT NTN");
                 }
             }
         }
@@ -630,7 +651,7 @@
                     }
                     mIsDisableCellularModemInProgress = false;
                 } else {
-                    loge("DisableCellularModemWhileSatelliteModeIsOn is not in progress");
+                    ploge("DisableCellularModemWhileSatelliteModeIsOn is not in progress");
                 }
             }
         }
@@ -638,7 +659,7 @@
         private void disableCellularModemWhileSatelliteModeIsOn() {
             synchronized (mLock) {
                 if (mIsDisableCellularModemInProgress) {
-                    logd("Cellular scanning is already being disabled");
+                    plogd("Cellular scanning is already being disabled");
                     return;
                 }
 
@@ -652,7 +673,7 @@
 
         @Override
         public void exit() {
-            if (DBG) logd("Exiting IdleState");
+            if (DBG) plogd("Exiting IdleState");
             if (!mSatelliteController.isSatelliteAttachRequired()) {
                 // Disable cellular modem scanning
                 mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(false, null);
@@ -663,7 +684,7 @@
     private class TransferringState extends State {
         @Override
         public void enter() {
-            if (DBG) logd("Entering TransferringState");
+            if (DBG) plogd("Entering TransferringState");
             stopNbIotInactivityTimer();
             mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING;
             notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
@@ -671,7 +692,7 @@
 
         @Override
         public boolean processMessage(Message msg) {
-            if (DBG) log("TransferringState: processing " + getWhatToString(msg.what));
+            if (DBG) plogd("TransferringState: processing " + getWhatToString(msg.what));
             switch (msg.what) {
                 case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED:
                     handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj);
@@ -722,7 +743,7 @@
     private class ListeningState extends State {
         @Override
         public void enter() {
-            if (DBG) logd("Entering ListeningState");
+            if (DBG) plogd("Entering ListeningState");
 
             mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_LISTENING;
             long timeoutMillis = updateListeningMode(true);
@@ -733,7 +754,7 @@
 
         @Override
         public void exit() {
-            if (DBG) logd("Exiting ListeningState");
+            if (DBG) plogd("Exiting ListeningState");
 
             removeMessages(EVENT_LISTENING_TIMER_TIMEOUT);
             updateListeningMode(false);
@@ -741,7 +762,7 @@
 
         @Override
         public boolean processMessage(Message msg) {
-            if (DBG) log("ListeningState: processing " + getWhatToString(msg.what));
+            if (DBG) plogd("ListeningState: processing " + getWhatToString(msg.what));
             switch (msg.what) {
                 case EVENT_LISTENING_TIMER_TIMEOUT:
                     transitionTo(mIdleState);
@@ -785,7 +806,7 @@
     private class NotConnectedState extends State {
         @Override
         public void enter() {
-            if (DBG) logd("Entering NotConnectedState");
+            if (DBG) plogd("Entering NotConnectedState");
 
             mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED;
             notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
@@ -794,12 +815,12 @@
 
         @Override
         public void exit() {
-            if (DBG) logd("Exiting NotConnectedState");
+            if (DBG) plogd("Exiting NotConnectedState");
         }
 
         @Override
         public boolean processMessage(Message msg) {
-            if (DBG) log("NotConnectedState: processing " + getWhatToString(msg.what));
+            if (DBG) plogd("NotConnectedState: processing " + getWhatToString(msg.what));
             switch (msg.what) {
                 case EVENT_SATELLITE_ENABLED_STATE_CHANGED:
                     handleSatelliteEnabledStateChanged(
@@ -850,7 +871,7 @@
     private class ConnectedState extends State {
         @Override
         public void enter() {
-            if (DBG) logd("Entering ConnectedState");
+            if (DBG) plogd("Entering ConnectedState");
 
             mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
             notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
@@ -859,12 +880,12 @@
 
         @Override
         public void exit() {
-            if (DBG) logd("Exiting ConnectedState");
+            if (DBG) plogd("Exiting ConnectedState");
         }
 
         @Override
         public boolean processMessage(Message msg) {
-            if (DBG) log("ConnectedState: processing " + getWhatToString(msg.what));
+            if (DBG) plogd("ConnectedState: processing " + getWhatToString(msg.what));
             switch (msg.what) {
                 case EVENT_SATELLITE_ENABLED_STATE_CHANGED:
                     handleSatelliteEnabledStateChanged(
@@ -956,7 +977,7 @@
             try {
                 listener.onSatelliteModemStateChanged(state);
             } catch (RemoteException e) {
-                logd("notifyStateChangedEvent RemoteException: " + e);
+                plogd("notifyStateChangedEvent RemoteException: " + e);
                 toBeRemoved.add(listener);
             }
         });
@@ -970,7 +991,7 @@
         if (off) {
             transitionTo(mPowerOffState);
         } else {
-            loge(caller + ": Unexpected satellite radio powered-on state changed event");
+            ploge(caller + ": Unexpected satellite radio powered-on state changed event");
         }
     }
 
@@ -1003,7 +1024,7 @@
 
         String packageName = getSatelliteGatewayPackageName();
         if (TextUtils.isEmpty(packageName)) {
-            loge("Unable to bind to the satellite gateway service because the package is"
+            ploge("Unable to bind to the satellite gateway service because the package is"
                     + " undefined.");
             // Since the package name comes from static device configs, stop retry because
             // rebind will continue to fail without a valid package name.
@@ -1021,13 +1042,13 @@
             boolean success = mContext.bindService(
                     intent, mSatelliteGatewayServiceConnection, Context.BIND_AUTO_CREATE);
             if (success) {
-                logd("Successfully bound to the satellite gateway service.");
+                plogd("Successfully bound to the satellite gateway service.");
             } else {
                 synchronized (mLock) {
                     mIsBinding = false;
                 }
                 mExponentialBackoff.notifyFailed();
-                loge("Error binding to the satellite gateway service. Retrying in "
+                ploge("Error binding to the satellite gateway service. Retrying in "
                         + mExponentialBackoff.getCurrentDelay() + " ms.");
             }
         } catch (Exception e) {
@@ -1035,13 +1056,13 @@
                 mIsBinding = false;
             }
             mExponentialBackoff.notifyFailed();
-            loge("Exception binding to the satellite gateway service. Retrying in "
+            ploge("Exception binding to the satellite gateway service. Retrying in "
                     + mExponentialBackoff.getCurrentDelay() + " ms. Exception: " + e);
         }
     }
 
     private void unbindService() {
-        logd("unbindService");
+        plogd("unbindService");
         mExponentialBackoff.stop();
         mSatelliteGatewayService = null;
         synchronized (mLock) {
@@ -1056,7 +1077,7 @@
     private class SatelliteGatewayServiceConnection implements ServiceConnection {
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
-            logd("onServiceConnected: ComponentName=" + name);
+            plogd("onServiceConnected: ComponentName=" + name);
             synchronized (mLock) {
                 mIsBound = true;
                 mIsBinding = false;
@@ -1067,7 +1088,7 @@
 
         @Override
         public void onServiceDisconnected(ComponentName name) {
-            loge("onServiceDisconnected: Waiting for reconnect.");
+            ploge("onServiceDisconnected: Waiting for reconnect.");
             synchronized (mLock) {
                 mIsBinding = false;
                 mIsBound = false;
@@ -1077,7 +1098,7 @@
 
         @Override
         public void onBindingDied(ComponentName name) {
-            loge("onBindingDied: Unbinding and rebinding service.");
+            ploge("onBindingDied: Unbinding and rebinding service.");
             synchronized (mLock) {
                 mIsBound = false;
                 mIsBinding = false;
@@ -1132,7 +1153,7 @@
 
     private void startNbIotInactivityTimer() {
         if (isNbIotInactivityTimerStarted()) {
-            logd("NB IOT inactivity timer is already started");
+            plogd("NB IOT inactivity timer is already started");
             return;
         }
 
@@ -1152,4 +1173,38 @@
     private boolean isNbIotInactivityTimerStarted() {
         return hasMessages(EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT);
     }
+
+    private boolean isSatellitePersistentLoggingEnabled(
+            @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+        if (featureFlags.satellitePersistentLogging()) {
+            return true;
+        }
+        try {
+            return context.getResources().getBoolean(
+                    R.bool.config_dropboxmanager_persistent_logging_enabled);
+        } catch (RuntimeException e) {
+            return false;
+        }
+    }
+
+    private void plogd(@NonNull String log) {
+        logd(log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.debug(TAG, log);
+        }
+    }
+
+    private void plogw(@NonNull String log) {
+        logw(log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.warn(TAG, log);
+        }
+    }
+
+    private void ploge(@NonNull String log) {
+        loge(log);
+        if (mPersistentLogger != null) {
+            mPersistentLogger.error(TAG, log);
+        }
+    }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
index 0f88bd5..771432e 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
@@ -20,13 +20,18 @@
 import android.telephony.CellInfo;
 import android.telephony.CellSignalStrength;
 import android.telephony.CellSignalStrengthLte;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 import android.util.SparseArray;
 
+import com.android.internal.telephony.MccTable;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.metrics.SatelliteStats;
+import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -36,6 +41,7 @@
     private static final String TAG = CarrierRoamingSatelliteSessionStats.class.getSimpleName();
     private static final SparseArray<CarrierRoamingSatelliteSessionStats>
             sCarrierRoamingSatelliteSessionStats = new SparseArray<>();
+    @NonNull private final SubscriptionManagerService mSubscriptionManagerService;
     private int mCarrierId;
     private boolean mIsNtnRoamingInHomeCountry;
     private int mCountOfIncomingSms;
@@ -53,6 +59,7 @@
     public CarrierRoamingSatelliteSessionStats(int subId) {
         logd("Create new CarrierRoamingSatelliteSessionStats. subId=" + subId);
         initializeParams();
+        mSubscriptionManagerService = SubscriptionManagerService.getInstance();
     }
 
     /** Gets a CarrierRoamingSatelliteSessionStats instance. */
@@ -67,21 +74,24 @@
     }
 
     /** Log carrier roaming satellite session start */
-    public void onSessionStart(int carrierId) {
+    public void onSessionStart(int carrierId, Phone phone) {
         mCarrierId = carrierId;
         mSessionStartTimeSec = getCurrentTimeInSec();
-        onConnectionStart();
+        mIsNtnRoamingInHomeCountry = false;
+        onConnectionStart(phone);
     }
 
     /** Log carrier roaming satellite connection start */
-    public void onConnectionStart() {
+    public void onConnectionStart(Phone phone) {
         mConnectionStartTimeList.add(getCurrentTime());
+        updateNtnRoamingInHomeCountry(phone);
     }
 
     /** Log carrier roaming satellite session end */
     public void onSessionEnd() {
         onConnectionEnd();
         reportMetrics();
+        mIsNtnRoamingInHomeCountry = false;
     }
 
     /** Log carrier roaming satellite connection end */
@@ -292,6 +302,41 @@
         return mSessionStartTimeSec != 0;
     }
 
+    private void updateNtnRoamingInHomeCountry(Phone phone) {
+        int subId = phone.getSubId();
+        ServiceState serviceState = phone.getServiceState();
+        if (serviceState == null) {
+            logd("ServiceState is null");
+            return;
+        }
+
+        String satelliteRegisteredPlmn = "";
+        for (NetworkRegistrationInfo nri
+                : serviceState.getNetworkRegistrationInfoList()) {
+            if (nri.isNonTerrestrialNetwork()) {
+                satelliteRegisteredPlmn = nri.getRegisteredPlmn();
+            }
+        }
+
+        SubscriptionInfoInternal subscriptionInfoInternal =
+                mSubscriptionManagerService.getSubscriptionInfoInternal(subId);
+        if (subscriptionInfoInternal == null) {
+            logd("SubscriptionInfoInternal is null");
+            return;
+        }
+        String simCountry = MccTable.countryCodeForMcc(subscriptionInfoInternal.getMcc());
+        String satelliteRegisteredCountry = MccTable.countryCodeForMcc(
+                satelliteRegisteredPlmn.substring(0, 3));
+        if (simCountry.equalsIgnoreCase(satelliteRegisteredCountry)) {
+            mIsNtnRoamingInHomeCountry = false;
+        } else {
+            // If device is connected to roaming non-terrestrial network, update to true.
+            mIsNtnRoamingInHomeCountry = true;
+        }
+        logd("updateNtnRoamingInHomeCountry: mIsNtnRoamingInHomeCountry="
+                + mIsNtnRoamingInHomeCountry);
+    }
+
     private void logd(@NonNull String log) {
         Log.d(TAG, log);
     }
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
index c6dee7c..c301768 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
@@ -1430,7 +1430,7 @@
                 && mServiceCapabilities == that.mServiceCapabilities
                 && mTransferStatus == that.mTransferStatus
                 && mIsSatelliteEntitlementStatus == that.mIsSatelliteEntitlementStatus
-                && mSatelliteEntitlementPlmns == that.mSatelliteEntitlementPlmns;
+                && mSatelliteEntitlementPlmns.equals(that.mSatelliteEntitlementPlmns);
     }
 
     @Override
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/ConnectionTest.java
index 0bce5cb..329b0b8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ConnectionTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
@@ -25,9 +26,14 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import java.util.ArrayList;
+
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.telephony.emergency.EmergencyNumber;
 
+import com.android.internal.telephony.PhoneInternalInterface.DialArgs;
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
 
 import org.junit.After;
@@ -150,7 +156,7 @@
         assertNull(connection1.getEmergencyNumberInfo());
         assertFalse(connection1.hasKnownUserIntentEmergency());
 
-        connection2.setEmergencyCallInfo(mPhone.getCallTracker());
+        connection2.setEmergencyCallInfo(mPhone.getCallTracker(), null);
         connection2.setHasKnownUserIntentEmergency(true);
         connection1.migrateFrom(connection2);
 
@@ -164,7 +170,7 @@
     @Test
     public void testEmergencyCallParameters() {
         Connection connection = new TestConnection(TEST_PHONE_TYPE);
-        connection.setEmergencyCallInfo(mPhone.getCallTracker());
+        connection.setEmergencyCallInfo(mPhone.getCallTracker(), null);
         assertTrue(connection.isEmergencyCall());
         assertEquals(getTestEmergencyNumber(), connection.getEmergencyNumberInfo());
         connection.setHasKnownUserIntentEmergency(true);
@@ -186,9 +192,44 @@
                 .thenReturn(getTestEmergencyNumber());
 
         //Ensure the connection is considered as an emergency call:
-        mTestConnection.setEmergencyCallInfo(mCT);
+        mTestConnection.setEmergencyCallInfo(mCT, null);
         assertTrue(mTestConnection.isEmergencyCall());
     }
 
+    @Test
+    public void testUpdateEmergencyRouting() {
+        DialArgs dialArgs = new DialArgs.Builder().build();
+        Connection connection = new TestConnection(TEST_PHONE_TYPE);
+        connection.setEmergencyCallInfo(mPhone.getCallTracker(), dialArgs);
+
+        // Not updated when DomainSelectionService is disabled.
+        assertEquals(getTestEmergencyNumber(), connection.getEmergencyNumberInfo());
+
+        // Enable DomainSelectionService
+        doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+        connection = new TestConnection(TEST_PHONE_TYPE);
+        connection.setEmergencyCallInfo(mPhone.getCallTracker(), dialArgs);
+
+        // Not updated when IS_EMERGENCY_ROUTING is not specified.
+        assertEquals(getTestEmergencyNumber(), connection.getEmergencyNumberInfo());
+
+        Bundle extras = new Bundle();
+        extras.putBoolean(PhoneConstants.EXTRA_USE_EMERGENCY_ROUTING, true);
+        extras.putInt(PhoneConstants.EXTRA_EMERGENCY_SERVICE_CATEGORY,
+                EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE);
+        dialArgs = new DialArgs.Builder().setIntentExtras(extras).build();
+
+        connection = new TestConnection(TEST_PHONE_TYPE);
+        connection.setEmergencyCallInfo(mPhone.getCallTracker(), dialArgs);
+        EmergencyNumber expectedNumber = new EmergencyNumber("911", "us", "30",
+                EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE,
+                new ArrayList<String>(), EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+                EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
+
+        // Updated when DomainSelectionService is enabled.
+        assertNotEquals(getTestEmergencyNumber(), connection.getEmergencyNumberInfo());
+        assertEquals(expectedNumber, connection.getEmergencyNumberInfo());
+    }
+
     // TODO Verify more methods in Connection
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
index 552b5a7..4612ad9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
@@ -65,6 +65,7 @@
 import android.net.wifi.WifiManager;
 import android.os.BatteryManager;
 import android.os.Bundle;
+import android.os.DropBoxManager;
 import android.os.Handler;
 import android.os.IInterface;
 import android.os.PersistableBundle;
@@ -313,6 +314,8 @@
                     return mImsManager;
                 case Context.DEVICE_POLICY_SERVICE:
                     return mDevicePolicyManager;
+                case Context.DROPBOX_SERVICE:
+                    return mDropBoxManager;
                 default:
                     return null;
             }
@@ -364,6 +367,8 @@
                 return Context.DEVICE_POLICY_SERVICE;
             } else if (serviceClass == NotificationManager.class) {
                 return Context.NOTIFICATION_SERVICE;
+            } else if (serviceClass == DropBoxManager.class) {
+                return Context.DROPBOX_SERVICE;
             }
             return super.getSystemServiceName(serviceClass);
         }
@@ -739,6 +744,7 @@
     private final NetworkPolicyManager mNetworkPolicyManager = mock(NetworkPolicyManager.class);
     private final ImsManager mImsManager = mock(ImsManager.class);
     private final DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class);
+    private final DropBoxManager mDropBoxManager = mock(DropBoxManager.class);
     private final Configuration mConfiguration = new Configuration();
     private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
     private final SharedPreferences mSharedPreferences = PreferenceManager
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
index 0e04aff..b09d90d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
@@ -203,26 +203,40 @@
         for (int i : enabledLogicalSlots) { expectedSlots.add(i); }
         assertEquals(expectedSlots, mPcm.getSlotsSupportingSimultaneousCellularCalls());
     }
+    @Test
+    @SmallTest
+    public void testUpdateSimultaneousCallingSupportBothInvalidSlotIds() throws Exception {
+        // Test case where both slot IDs are invalid (-1 and 5).
+        testUpdateSimultaneousCallingSupportWithInvalidSlots(Arrays.asList(-1, 5));
+    }
 
     @Test
     @SmallTest
-    public void testUpdateSimultaneousCallingSupport_invalidResponse_shouldFail() throws Exception {
-        doReturn(false).when(mFeatureFlags).simultaneousCallingIndications();
-        init(2);
-        mPcm.updateSimultaneousCallingSupport();
+    public void testUpdateSimultaneousCallingSupportOneInvalidSlotId() throws Exception {
+        // Test case where one slot ID is valid (1) and the other is invalid (2).
+        testUpdateSimultaneousCallingSupportWithInvalidSlots(Arrays.asList(1, 2));
+    }
 
-        // Have the modem send invalid phone slots -1 and 5:
-        List<Integer> invalidEnabledLogicalSlots = Arrays.asList(-1, 5);
-        ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
-        verify(mMockRadioConfig).updateSimultaneousCallingSupport(captor.capture());
-        Message msg = captor.getValue();
-        AsyncResult.forMessage(msg, invalidEnabledLogicalSlots, null);
-        msg.sendToTarget();
-        processAllMessages();
+    @Test
+    @SmallTest
+    public void testUpdateSimultaneousCallingSupportInvalidExtraSlotId() throws Exception {
+        // Test case where the number of slot IDs exceeds the phone count (2) and one slot ID is
+        // invalid (2).
+        testUpdateSimultaneousCallingSupportWithInvalidSlots(Arrays.asList(0, 1, 2));
+    }
 
-        // We would expect to DSDA to be disabled and mSlotsSupportingSimultaneousCellularCalls to
-        // have been cleared:
-        assertTrue(mPcm.getSlotsSupportingSimultaneousCellularCalls().isEmpty());
+    @Test
+    @SmallTest
+    public void testUpdateSimultaneousCallingSupportInvalidSingularSlotId() throws Exception {
+        // Test case where only a single, invalid slot ID (0) is provided.
+        testUpdateSimultaneousCallingSupportWithInvalidSlots(List.of(0));
+    }
+
+    @Test
+    @SmallTest
+    public void testUpdateSimultaneousCallingSupportInvalidEmptySlotIds() throws Exception {
+        // Test case where an empty list of slot IDs is provided.
+        testUpdateSimultaneousCallingSupportWithInvalidSlots(List.of());
     }
 
     /**
@@ -576,4 +590,28 @@
 
         assertEquals(capability, mPcm.getStaticPhoneCapability());
     }
+
+    private void testUpdateSimultaneousCallingSupportWithInvalidSlots(List<Integer> invalidSlots)
+            throws Exception {
+        doReturn(false).when(mFeatureFlags).simultaneousCallingIndications();
+        init(2);
+        mPcm.updateSimultaneousCallingSupport();
+
+        sendInvalidSlotsToModem(invalidSlots);
+        processAllMessages();
+
+        assertDsdaDisabledAndSlotsCleared();
+    }
+
+    private void sendInvalidSlotsToModem(List<Integer> invalidSlots) {
+        ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
+        verify(mMockRadioConfig).updateSimultaneousCallingSupport(captor.capture());
+        Message msg = captor.getValue();
+        AsyncResult.forMessage(msg, invalidSlots, null);
+        msg.sendToTarget();
+    }
+
+    private void assertDsdaDisabledAndSlotsCleared() {
+        assertTrue(mPcm.getSlotsSupportingSimultaneousCellularCalls().isEmpty());
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
index bf9ced3..72d8197 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -675,6 +675,43 @@
 
     @SmallTest
     @Test
+    public void testFormatTaiwanNational() {
+        // Disable feature flag.
+        mSetFlagsRule.disableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
+        assertEquals("+886 2 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "TW"));
+        assertEquals("+886 2 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "tw"));
+        assertEquals("+886 988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "TW"));
+        assertEquals("+886 988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "tw"));
+
+        // Enable feature flag.
+        mSetFlagsRule.enableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
+        assertEquals("02 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "TW"));
+        assertEquals("02 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "tw"));
+        assertEquals("0988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "TW"));
+        assertEquals("0988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "tw"));
+        mSetFlagsRule.disableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
+    }
+
+    @SmallTest
+    @Test
+    public void testFormatTaiwanInternational() {
+        // Disable feature flag.
+        mSetFlagsRule.disableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
+        assertEquals("+886 2 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "US"));
+        assertEquals("+886 2 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "us"));
+        assertEquals("+886 988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "US"));
+        assertEquals("+886 988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "us"));
+
+        mSetFlagsRule.enableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
+        assertEquals("+886 2 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "US"));
+        assertEquals("+886 2 8729 6000", PhoneNumberUtils.formatNumber("+886287296000", "us"));
+        assertEquals("+886 988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "US"));
+        assertEquals("+886 988 102 544", PhoneNumberUtils.formatNumber("+886988102544", "us"));
+        mSetFlagsRule.disableFlags(Flags.FLAG_NATIONAL_COUNTRY_CODE_FORMATTING_FOR_LOCAL_CALLS);
+    }
+
+    @SmallTest
+    @Test
     public void testFormatNumber_LeadingStarAndHash() {
         // Numbers with a leading '*' or '#' should be left unchanged.
         assertEquals("*650 2910000", PhoneNumberUtils.formatNumber("*650 2910000", "US"));
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index fd99ad0..e3da458 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -3471,9 +3471,12 @@
                         AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
         assertEquals(2, nriList.size());
         for (NetworkRegistrationInfo nri : nriList) {
-            assertTrue(Arrays.equals(satelliteSupportedServices, nri.getAvailableServices().stream()
-                    .mapToInt(Integer::intValue)
-                    .toArray()));
+            if (nri.isInService()) {
+                assertTrue(Arrays.equals(satelliteSupportedServices,
+                        nri.getAvailableServices().stream()
+                        .mapToInt(Integer::intValue)
+                        .toArray()));
+            }
         }
     }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java
index 879b184..054df07 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java
@@ -254,7 +254,7 @@
 
     /**
      * Test that simultaneous calling is not supported when IMS is not registered and cellular
-     * simultaneous calling is only supported for one SIM subscription.
+     * simultaneous calling is not supported for any SIM subscriptions.
      */
     @Test
     @SmallTest
@@ -264,8 +264,8 @@
         init(2);
         setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY);
 
-        // Have the modem inform telephony that only phone slot 0 supports DSDA:
-        List<Integer> enabledLogicalSlots = List.of(0);
+        // Have the modem inform telephony that no phone slots currently support DSDA:
+        List<Integer> enabledLogicalSlots = List.of();
         setAndVerifySlotsSupportingSimultaneousCellularCalling(enabledLogicalSlots);
 
         // Trigger onSubscriptionsChanged by updating the subscription ID of a phone slot:
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkRequestTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkRequestTest.java
index 1517006..9f11a3a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkRequestTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkRequestTest.java
@@ -168,18 +168,12 @@
                         .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
                         .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
                         .build(), mPhone, mFeatureFlags);
-        assertThat(internetRequest.getCapabilities()).isEqualTo(
-                new int[]{NetworkCapabilities.NET_CAPABILITY_INTERNET,
-                        NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED,
-                        NetworkCapabilities.NET_CAPABILITY_TRUSTED,
-                        NetworkCapabilities.NET_CAPABILITY_NOT_VPN,
-                        NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED});
+        assertThat(internetRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED))
+                .isTrue();
         assertThat(internetRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN))
                 .isTrue();
         assertThat(internetRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET))
                 .isTrue();
-        assertThat(internetRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN))
-                .isTrue();
         assertThat(internetRequest.hasCapability(
                 NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)).isTrue();
         assertThat(internetRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS))
diff --git a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionControllerTest.java
index f5ccdd6..a55ad69 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionControllerTest.java
@@ -16,8 +16,11 @@
 
 package com.android.internal.telephony.domainselection;
 
+import static android.telephony.DomainSelectionService.SELECTOR_TYPE_CALLING;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -36,6 +39,8 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.telephony.DomainSelectionService;
+import android.telephony.TelephonyManager;
+import android.test.mock.MockContext;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -71,6 +76,8 @@
                 }
             };
 
+    Context mTestContext;
+
     // Mocked classes
     IDomainSelectionServiceController mMockServiceControllerBinder;
     Context mMockContext;
@@ -84,9 +91,40 @@
     public void setUp() throws Exception {
         super.setUp(this.getClass().getSimpleName());
 
+        when(mTelephonyManager.getSupportedModemCount()).thenReturn(2);
         mMockContext = mock(Context.class);
+        mTestContext = new MockContext() {
+            @Override
+            public String getSystemServiceName(Class<?> serviceClass) {
+                if (serviceClass == TelephonyManager.class) {
+                    return Context.TELEPHONY_SERVICE;
+                }
+                return super.getSystemServiceName(serviceClass);
+            }
+
+            @Override
+            public Object getSystemService(String name) {
+                switch (name) {
+                    case (Context.TELEPHONY_SERVICE) : {
+                        return mTelephonyManager;
+                    }
+                }
+                return super.getSystemService(name);
+            }
+
+            @Override
+            public boolean bindService(Intent service, ServiceConnection conn, int flags) {
+                return mMockContext.bindService(service, conn, flags);
+            }
+
+            @Override
+            public void unbindService(ServiceConnection conn) {
+                mMockContext.unbindService(conn);
+            }
+        };
+
         mMockServiceControllerBinder = mock(IDomainSelectionServiceController.class);
-        mTestController = new DomainSelectionController(mMockContext,
+        mTestController = new DomainSelectionController(mTestContext,
                 Looper.getMainLooper(), BIND_RETRY);
         mHandler = mTestController.getHandlerForTest();
 
@@ -264,6 +302,17 @@
         verify(mMockContext, times(1)).bindService(any(), any(), anyInt());
     }
 
+    @SmallTest
+    @Test
+    public void testGetDomainSelectionConnection() throws Exception {
+        when(mPhone.getPhoneId()).thenReturn(1);
+        DomainSelectionConnection dsc = mTestController.getDomainSelectionConnection(
+                mPhone, SELECTOR_TYPE_CALLING, false);
+
+        assertNotNull(dsc);
+        assertTrue(dsc instanceof NormalCallDomainSelectionConnection);
+    }
+
     private void bindAndNullServiceError() {
         ServiceConnection connection = bindService(mTestComponentName);
         connection.onNullBinding(mTestComponentName);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
index f05099d..0eb5c13 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
@@ -3171,6 +3171,207 @@
                 anyBoolean(), eq(0));
     }
 
+    /**
+     * Test Phone selection.
+     * SIM absent and SIM ready on the other Phone.
+     */
+    @Test
+    @SmallTest
+    public void testSwitchPhoneAbsentAndReady() {
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+        Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+                /* isRadioOn= */ true);
+        Phone phone1 = getPhone(1);
+
+        // Phone0
+        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+                .when(phone0).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_ABSENT)
+                .when(mTelephonyManagerProxy).getSimState(eq(0));
+
+        // Phone1
+        doReturn(2).when(phone1).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_READY)
+                .when(mTelephonyManagerProxy).getSimState(eq(1));
+
+        CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(
+                phone0, mTestConnection1, true);
+        processAllMessages();
+
+        assertTrue(future.isDone());
+        // Expect: DisconnectCause#EMERGENCY_PERM_FAILURE
+        assertEquals(future.getNow(DisconnectCause.NOT_DISCONNECTED),
+                Integer.valueOf(DisconnectCause.EMERGENCY_PERM_FAILURE));
+        verify(phone0, never()).setEmergencyMode(anyInt(), any(Message.class));
+    }
+
+    /**
+     * Test Phone selection.
+     * PIN locked and SIM ready on the other Phone.
+     */
+    @Test
+    @SmallTest
+    public void testSwitchPhonePinLockedAndReady() {
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+        Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+                /* isRadioOn= */ true);
+        Phone phone1 = getPhone(1);
+
+        // Phone0
+        doReturn(1).when(phone0).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
+                .when(mTelephonyManagerProxy).getSimState(eq(0));
+
+        // Phone1
+        doReturn(2).when(phone1).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_READY)
+                .when(mTelephonyManagerProxy).getSimState(eq(1));
+
+        CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(
+                phone0, mTestConnection1, true);
+        processAllMessages();
+
+        assertTrue(future.isDone());
+        // Expect: DisconnectCause#EMERGENCY_PERM_FAILURE
+        assertEquals(future.getNow(DisconnectCause.NOT_DISCONNECTED),
+                Integer.valueOf(DisconnectCause.EMERGENCY_PERM_FAILURE));
+        verify(phone0, never()).setEmergencyMode(anyInt(), any(Message.class));
+    }
+
+    /**
+     * Test Phone selection.
+     * SIM ready and SIM ready on the other Phone.
+     */
+    @Test
+    @SmallTest
+    public void testSwitchPhoneReadyAndReady() {
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+        Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+                /* isRadioOn= */ true);
+        Phone phone1 = getPhone(1);
+
+        // Phone0
+        doReturn(1).when(phone0).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_READY)
+                .when(mTelephonyManagerProxy).getSimState(eq(0));
+
+        // Phone1
+        doReturn(2).when(phone1).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_READY)
+                .when(mTelephonyManagerProxy).getSimState(eq(1));
+
+        CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(
+                phone0, mTestConnection1, true);
+        processAllMessages();
+
+        assertFalse(future.isDone());
+        verify(phone0).setEmergencyMode(anyInt(), any(Message.class));
+    }
+
+    /**
+     * Test Phone selection.
+     * PIN locked and PIN locked on the other Phone.
+     */
+    @Test
+    @SmallTest
+    public void testSwitchPhonePinLockedAndPinLocked() {
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+        Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+                /* isRadioOn= */ true);
+        Phone phone1 = getPhone(1);
+
+        // Phone0
+        doReturn(1).when(phone0).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
+                .when(mTelephonyManagerProxy).getSimState(eq(0));
+
+        // Phone1
+        doReturn(2).when(phone1).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
+                .when(mTelephonyManagerProxy).getSimState(eq(1));
+
+        CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(
+                phone0, mTestConnection1, true);
+        processAllMessages();
+
+        assertFalse(future.isDone());
+        verify(phone0).setEmergencyMode(anyInt(), any(Message.class));
+    }
+
+    /**
+     * Test Phone selection.
+     * SIM absent and SIM absent on default Phone.
+     */
+    @Test
+    @SmallTest
+    public void testSwitchPhoneAbsentAndAbsentOnDefaultPhone() {
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+        Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+                /* isRadioOn= */ true);
+        Phone phone1 = getPhone(1);
+
+        // Phone0
+        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+                .when(phone0).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_ABSENT)
+                .when(mTelephonyManagerProxy).getSimState(eq(0));
+
+        // Phone1
+        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+                .when(phone1).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_ABSENT)
+                .when(mTelephonyManagerProxy).getSimState(eq(1));
+
+        CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(
+                phone1, mTestConnection1, true);
+        processAllMessages();
+
+        assertTrue(future.isDone());
+        // Expect: DisconnectCause#EMERGENCY_PERM_FAILURE
+        assertEquals(future.getNow(DisconnectCause.NOT_DISCONNECTED),
+                Integer.valueOf(DisconnectCause.EMERGENCY_PERM_FAILURE));
+        verify(phone1, never()).setEmergencyMode(anyInt(), any(Message.class));
+    }
+
+    /**
+     * Test Phone selection.
+     * PIN locked and PIN locked on default Phone.
+     */
+    @Test
+    @SmallTest
+    public void testSwitchPhonePinLockedandPinLockedOnDefaultPhone() {
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+        Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+                /* isRadioOn= */ true);
+        Phone phone1 = getPhone(1);
+
+        // Phone0
+        doReturn(1).when(phone0).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
+                .when(mTelephonyManagerProxy).getSimState(eq(0));
+
+        // Phone1
+        doReturn(2).when(phone1).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
+                .when(mTelephonyManagerProxy).getSimState(eq(1));
+
+        CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(
+                phone1, mTestConnection1, true);
+        processAllMessages();
+
+        assertTrue(future.isDone());
+        // Expect: DisconnectCause#EMERGENCY_PERM_FAILURE
+        assertEquals(future.getNow(DisconnectCause.NOT_DISCONNECTED),
+                Integer.valueOf(DisconnectCause.EMERGENCY_PERM_FAILURE));
+        verify(phone1, never()).setEmergencyMode(anyInt(), any(Message.class));
+    }
+
     private EmergencyStateTracker setupEmergencyStateTracker(
             boolean isSuplDdsSwitchRequiredForEmergencyCall) {
         doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
index f1508ee..2961b4d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
@@ -87,7 +87,7 @@
         when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
         mDatagramControllerUT = new DatagramController(
-                mContext, Looper.myLooper(), mMockPointingAppController);
+                mContext, Looper.myLooper(), mFeatureFlags, mMockPointingAppController);
 
         // Move both send and receive to IDLE state
         mDatagramControllerUT.updateSendStatus(SUB_ID, DATAGRAM_TYPE_UNKNOWN,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
index 1bb45b8..7094399 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -60,6 +60,7 @@
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
 import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
 
@@ -155,7 +156,9 @@
                 mMockSessionMetricsStats);
 
         when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+        when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
         mDatagramDispatcherUT = new TestDatagramDispatcher(mContext, Looper.myLooper(),
+                mFeatureFlags,
                 mMockDatagramController);
 
         mResultListener = new LinkedBlockingQueue<>(1);
@@ -782,8 +785,9 @@
         private long mLong = SATELLITE_ALIGN_TIMEOUT;
 
         TestDatagramDispatcher(@NonNull Context context, @NonNull Looper looper,
+                @NonNull FeatureFlags featureFlags,
                 @NonNull DatagramController datagramController) {
-            super(context, looper, datagramController);
+            super(context, looper, featureFlags, datagramController);
         }
 
         @Override
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
index 4d3acb4..947661b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
@@ -58,6 +58,7 @@
 
 import com.android.internal.telephony.IVoidConsumer;
 import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
 import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
 
@@ -126,9 +127,11 @@
         replaceInstance(SessionMetricsStats.class, "sInstance", null,
                 mMockSessionMetricsStats);
 
-        mDatagramReceiverUT = DatagramReceiver.make(mContext, Looper.myLooper(),
+        when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
+        mDatagramReceiverUT = DatagramReceiver.make(mContext, Looper.myLooper(), mFeatureFlags,
                 mMockDatagramController);
         mTestDemoModeDatagramReceiver = new TestDatagramReceiver(mContext, Looper.myLooper(),
+                mFeatureFlags,
                 mMockDatagramController);
         mSatelliteDatagramListenerHandler = new DatagramReceiver.SatelliteDatagramListenerHandler(
                 Looper.myLooper(), SUB_ID);
@@ -490,8 +493,9 @@
         private long mLong =  SATELLITE_ALIGN_TIMEOUT;
 
         TestDatagramReceiver(@NonNull Context context, @NonNull Looper looper,
+                @NonNull FeatureFlags featureFlags,
                 @NonNull DatagramController datagramController) {
-            super(context, looper, datagramController);
+            super(context, looper, featureFlags, datagramController);
         }
 
         @Override
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/PointingAppControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/PointingAppControllerTest.java
index c1f3a88..36d32fe 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/PointingAppControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/PointingAppControllerTest.java
@@ -100,12 +100,13 @@
         super.setUp(getClass().getSimpleName());
         MockitoAnnotations.initMocks(this);
         logd(TAG + " Setup!");
+        when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
         mInOrderForPointingUi = inOrder(mContext);
         replaceInstance(SatelliteModemInterface.class, "sInstance", null,
                 mMockSatelliteModemInterface);
         replaceInstance(SatelliteController.class, "sInstance", null,
                 mMockSatelliteController);
-        mPointingAppController = new PointingAppController(mContext);
+        mPointingAppController = new PointingAppController(mContext, mFeatureFlags);
         mContextFixture.putResource(R.string.config_pointing_ui_package,
                 KEY_POINTING_UI_PACKAGE_NAME);
         mContextFixture.putResource(R.string.config_pointing_ui_class,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
index c37d7e9..da40c32 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -786,6 +786,7 @@
         // Successfully enable satellite
         mIIntegerConsumerResults.clear();
         mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+        mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
         setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
         mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
                 mIIntegerConsumer);
@@ -795,6 +796,7 @@
         assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
         verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
         assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
+        assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
         assertEquals(
                 SATELLITE_MODE_ENABLED_TRUE, mSatelliteControllerUT.satelliteModeSettingValue);
         verify(mMockSatelliteSessionController, times(1)).onSatelliteEnabledStateChanged(eq(true));
@@ -805,6 +807,7 @@
 
         // Successfully disable satellite when radio is turned off.
         mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+        mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
         setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
         setRadioPower(false);
         mSatelliteControllerUT.onCellularRadioPowerOffRequested();
@@ -813,6 +816,7 @@
         processAllMessages();
         verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
         assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
+        assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
         assertEquals(
                 SATELLITE_MODE_ENABLED_FALSE, mSatelliteControllerUT.satelliteModeSettingValue);
         verify(mMockSatelliteSessionController, times(2)).onSatelliteEnabledStateChanged(eq(false));
@@ -838,6 +842,7 @@
         mIIntegerConsumerResults.clear();
         clearInvocations(mMockPointingAppController);
         mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+        mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
         setUpResponseForRequestSatelliteEnabled(true, false, false,
                 SATELLITE_RESULT_INVALID_MODEM_STATE);
         mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
@@ -849,11 +854,13 @@
         verify(mMockPointingAppController, never()).startPointingUI(anyBoolean(), anyBoolean(),
                 anyBoolean());
         assertFalse(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
+        assertFalse(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
         verify(mMockControllerMetricsStats, times(1)).reportServiceEnablementFailCount();
 
         // Successfully enable satellite when radio is on.
         mIIntegerConsumerResults.clear();
         mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+        mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
         setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
         mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
                 mIIntegerConsumer);
@@ -862,6 +869,7 @@
         assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
         verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
         assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
+        assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
         assertEquals(SATELLITE_MODE_ENABLED_TRUE, mSatelliteControllerUT.satelliteModeSettingValue);
         verify(mMockSatelliteSessionController, times(2)).onSatelliteEnabledStateChanged(eq(true));
         verify(mMockSatelliteSessionController, times(4)).setDemoMode(eq(false));
@@ -3458,6 +3466,7 @@
 
         // startSendingNtnSignalStrength should be invoked when satellite is enabled
         mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+        mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
         setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
         mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
                 mIIntegerConsumer);
@@ -3466,6 +3475,7 @@
         assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
         verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
         assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
+        assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
         assertEquals(
                 SATELLITE_MODE_ENABLED_TRUE, mSatelliteControllerUT.satelliteModeSettingValue);
         verify(mMockSatelliteModemInterface, times(1)).startSendingNtnSignalStrength(
@@ -3517,6 +3527,7 @@
         reset(mMockSatelliteModemInterface);
         doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
         mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+        mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
         setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
         mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
                 mIIntegerConsumer);
@@ -3525,6 +3536,7 @@
         assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
         verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
         assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
+        assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
         assertEquals(
                 SATELLITE_MODE_ENABLED_TRUE, mSatelliteControllerUT.satelliteModeSettingValue);
         verify(mMockSatelliteModemInterface, times(1)).startSendingNtnSignalStrength(
@@ -4479,6 +4491,7 @@
         public boolean allRadiosDisabled = true;
         public long elapsedRealtime = 0;
         public int satelliteModeSettingValue = SATELLITE_MODE_ENABLED_FALSE;
+        public boolean setSettingsKeyToAllowDeviceRotationCalled = false;
 
         TestSatelliteController(
                 Context context, Looper looper, @NonNull FeatureFlags featureFlags) {
@@ -4499,6 +4512,12 @@
         }
 
         @Override
+        protected void setSettingsKeyToAllowDeviceRotation(int val) {
+            logd("setSettingsKeyToAllowDeviceRotation: val=" + val);
+            setSettingsKeyToAllowDeviceRotationCalled = true;
+        }
+
+        @Override
         protected boolean areAllRadiosDisabled() {
             return allRadiosDisabled;
         }
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 876fc51..f4fa48e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.telephony.satellite;
 
-import static android.telephony.ServiceState.STATE_IN_SERVICE;
 import static android.telephony.ServiceState.STATE_OUT_OF_SERVICE;
 import static android.telephony.TelephonyManager.EXTRA_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE;
 import static android.telephony.TelephonyManager.EXTRA_EMERGENCY_CALL_TO_SATELLITE_LAUNCH_INTENT;
@@ -193,14 +192,25 @@
                 DEFAULT_HANDOVER_INTENT_ACTION);
     }
 
+    @Test
+    public void testStartTimer_emergencyCallNull() {
+        when(mServiceState.getState()).thenReturn(STATE_OUT_OF_SERVICE);
+        when(mServiceState2.getState()).thenReturn(STATE_OUT_OF_SERVICE);
+        mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
+        mTestSOSMessageRecommender.onEmergencyCallStarted(null);
+        processAllMessages();
+        assertFalse(mTestSOSMessageRecommender.isTimerStarted());
+        assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
+    }
+
     private void testTimeoutBeforeEmergencyCallEnd(int expectedHandoverType,
             String expectedPackageName, String expectedClassName, String expectedAction) {
         mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
         processAllMessages();
         assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone, 1,  1);
+        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
         assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
 
         // Move Location service to emergency mode
@@ -220,8 +230,8 @@
             assertTrue(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE,
                     expectedHandoverType, expectedPackageName, expectedClassName, expectedAction));
         }
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
     }
 
     @Test
@@ -232,8 +242,8 @@
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
         processAllMessages();
         assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
         assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
 
         // Move Location service to emergency mode
@@ -247,8 +257,8 @@
         moveTimeForward(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
         processAllMessages();
         assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE));
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
     }
 
     @Test
@@ -259,8 +269,8 @@
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
         processAllMessages();
         assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
         assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
 
         // Move Location service to emergency mode
@@ -277,8 +287,8 @@
                 EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
                 DEFAULT_SATELLITE_MESSAGING_PACKAGE, DEFAULT_SATELLITE_MESSAGING_CLASS,
                 DEFAULT_T911_HANDOVER_INTENT_ACTION));
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
         mTestSatelliteController.isOemEnabledSatelliteSupported = true;
     }
 
@@ -299,45 +309,8 @@
         processAllMessages();
         assertTrue(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
-        assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
-
-        when(mPhone.isImsRegistered()).thenReturn(true);
-        when(mServiceState.getState()).thenReturn(STATE_IN_SERVICE);
-        mTestImsManager.sendImsRegistrationStateChangedEvent(0, true);
-        processAllMessages();
-
-        assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE));
-        assertFalse(mTestSOSMessageRecommender.isTimerStarted());
-        assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 0, 0, 0);
-
-        when(mPhone.isImsRegistered()).thenReturn(false);
-        when(mServiceState.getState()).thenReturn(STATE_OUT_OF_SERVICE);
-        mTestImsManager.sendImsRegistrationStateChangedEvent(0, true);
-        processAllMessages();
-
-        assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE));
-        assertTrue(mTestSOSMessageRecommender.isTimerStarted());
-        assertEquals(2, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 0, 0, 0);
-
-        when(mPhone.isImsRegistered()).thenReturn(false);
-        when(mPhone2.isImsRegistered()).thenReturn(true);
-        when(mServiceState.getState()).thenReturn(STATE_IN_SERVICE);
-        mTestImsManager.sendImsRegistrationStateChangedEvent(1, true);
-        processAllMessages();
-        assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE));
-        assertFalse(mTestSOSMessageRecommender.isTimerStarted());
-        assertEquals(2, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 0, 0, 0);
-
-        when(mPhone2.isImsRegistered()).thenReturn(false);
-        when(mServiceState.getState()).thenReturn(STATE_OUT_OF_SERVICE);
-        mTestImsManager.sendImsRegistrationStateChangedEvent(1, false);
-        processAllMessages();
-        assertEquals(3, mTestSOSMessageRecommender.getCountOfTimerStarted());
+        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
         assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
 
         // Move Location service to emergency mode
@@ -354,8 +327,8 @@
         assertTrue(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE,
                 EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911, DEFAULT_SATELLITE_MESSAGING_PACKAGE,
                 DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_T911_HANDOVER_INTENT_ACTION));
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
         assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
     }
 
@@ -366,8 +339,8 @@
 
         assertTrue(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
 
         mTestSatelliteController.sendProvisionStateChangedEvent(
                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, false);
@@ -375,15 +348,15 @@
 
         assertFalse(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
 
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
         processAllMessages();
         assertTrue(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertRegisterForStateChangedEventsTriggered(mPhone, 2, 4, 2);
-        assertRegisterForStateChangedEventsTriggered(mPhone2, 2, 4, 2);
+        assertRegisterForStateChangedEventsTriggered(mPhone, 2, 2);
+        assertRegisterForStateChangedEventsTriggered(mPhone2, 2, 2);
 
         // Move Location service to emergency mode
         mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
@@ -405,8 +378,8 @@
                 DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_T911_HANDOVER_INTENT_ACTION));
         assertFalse(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 2, 4, 2);
-        assertUnregisterForStateChangedEventsTriggered(mPhone2, 2, 4, 2);
+        assertUnregisterForStateChangedEventsTriggered(mPhone, 2, 2);
+        assertUnregisterForStateChangedEventsTriggered(mPhone2, 2, 2);
     }
 
     @Test
@@ -416,8 +389,8 @@
         processAllMessages();
         assertTrue(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
         assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
 
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
@@ -425,8 +398,8 @@
         assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
         assertTrue(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
 
         // Move Location service to emergency mode
         mTestSOSMessageRecommender.onEmergencyCallConnectionStateChanged(
@@ -442,8 +415,8 @@
         assertTrue(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE,
                 EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911, DEFAULT_SATELLITE_MESSAGING_PACKAGE,
                 DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_T911_HANDOVER_INTENT_ACTION));
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
         assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
         assertFalse(mTestSOSMessageRecommender.isTimerStarted());
     }
@@ -479,8 +452,8 @@
 
         assertTrue(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
 
         mTestSOSMessageRecommender.onEmergencyCallConnectionStateChanged(
                 WRONG_CALL_ID, Connection.STATE_ACTIVE);
@@ -489,8 +462,8 @@
         assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE));
         assertFalse(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
     }
 
     @Test
@@ -514,10 +487,10 @@
 
         assertFalse(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
     }
 
     @Test
@@ -586,8 +559,8 @@
 
         assertTrue(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
 
         mTestSOSMessageRecommender.onEmergencyCallConnectionStateChanged(CALL_ID, connectionState);
         processAllMessages();
@@ -595,8 +568,8 @@
         assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE));
         assertFalse(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
     }
 
     private void testCellularServiceStateChangedBeforeTimeout(
@@ -608,8 +581,8 @@
         assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
         assertTrue(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
 
         when(mServiceState.getState()).thenReturn(availableServiceState);
         mTestSOSMessageRecommender.sendServiceStateChangedEvent();
@@ -617,8 +590,8 @@
         assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE));
         assertFalse(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 0, 0, 0);
-        assertUnregisterForStateChangedEventsTriggered(mPhone2, 0, 0, 0);
+        assertUnregisterForStateChangedEventsTriggered(mPhone, 0, 0);
+        assertUnregisterForStateChangedEventsTriggered(mPhone2, 0, 0);
 
         when(mServiceState.getState()).thenReturn(unavailableServiceState);
         when(mServiceState2.getState()).thenReturn(availableServiceState);
@@ -647,28 +620,24 @@
         assertTrue(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE,
                 EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911, DEFAULT_SATELLITE_MESSAGING_PACKAGE,
                 DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_T911_HANDOVER_INTENT_ACTION));
-        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
-        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
         assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
         assertFalse(mTestSOSMessageRecommender.isTimerStarted());
     }
 
-    private void assertRegisterForStateChangedEventsTriggered(
-            Phone phone, int registerForProvisionCount, int registerForImsCount,
-            int registerForCellularCount) {
+    private void assertRegisterForStateChangedEventsTriggered(Phone phone,
+            int registerForProvisionCount, int registerForCellularCount) {
         assertEquals(registerForProvisionCount,
                 mTestSatelliteController.getRegisterForSatelliteProvisionStateChangedCalls());
-        assertEquals(registerForImsCount, mTestImsManager.getAddRegistrationCallbackCalls());
         verify(phone, times(registerForCellularCount))
                 .registerForServiceStateChanged(any(), anyInt(), any());
     }
 
     private void assertUnregisterForStateChangedEventsTriggered(
-            Phone phone, int unregisterForProvisionCount, int unregisterForImsCount,
-            int unregisterForCellularCount) {
+            Phone phone, int unregisterForProvisionCount, int unregisterForCellularCount) {
         assertEquals(unregisterForProvisionCount,
                 mTestSatelliteController.getUnregisterForSatelliteProvisionStateChangedCalls());
-        assertEquals(unregisterForImsCount, mTestImsManager.getRemoveRegistrationListenerCalls());
         verify(phone, times(unregisterForCellularCount)).unregisterForServiceStateChanged(any());
     }
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
index f6131ea..78763d1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
@@ -45,6 +45,7 @@
 import android.testing.TestableLooper;
 
 import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.flags.FeatureFlags;
 
 import org.junit.After;
 import org.junit.Before;
@@ -105,11 +106,12 @@
         Resources resources = mContext.getResources();
         when(resources.getInteger(anyInt())).thenReturn(TEST_SATELLITE_TIMEOUT_MILLIS);
 
+        when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
         when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(false);
         mSatelliteModemInterface = new TestSatelliteModemInterface(
-                mContext, mMockSatelliteController, Looper.myLooper());
+                mContext, mMockSatelliteController, Looper.myLooper(), mFeatureFlags);
         mTestSatelliteSessionController = new TestSatelliteSessionController(mContext,
-                Looper.myLooper(), true, mSatelliteModemInterface);
+                Looper.myLooper(), mFeatureFlags, true, mSatelliteModemInterface);
         processAllMessages();
 
         mTestSatelliteModemStateCallback = new TestSatelliteModemStateCallback();
@@ -131,7 +133,7 @@
          * state.
          */
         TestSatelliteSessionController sessionController1 = new TestSatelliteSessionController(
-                mContext, Looper.myLooper(), false, mSatelliteModemInterface);
+                mContext, Looper.myLooper(), mFeatureFlags, false, mSatelliteModemInterface);
         assertNotNull(sessionController1);
         processAllMessages();
         assertEquals(STATE_UNAVAILABLE, sessionController1.getCurrentStateName());
@@ -140,7 +142,7 @@
          * Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
          */
         TestSatelliteSessionController sessionController2 = new TestSatelliteSessionController(
-                mContext, Looper.myLooper(), true, mSatelliteModemInterface);
+                mContext, Looper.myLooper(), mFeatureFlags, true, mSatelliteModemInterface);
         assertNotNull(sessionController2);
         processAllMessages();
         assertEquals(STATE_POWER_OFF, sessionController2.getCurrentStateName());
@@ -153,7 +155,7 @@
          * state.
          */
         TestSatelliteSessionController sessionController = new TestSatelliteSessionController(
-                mContext, Looper.myLooper(), false, mSatelliteModemInterface);
+                mContext, Looper.myLooper(), mFeatureFlags, false, mSatelliteModemInterface);
         assertNotNull(sessionController);
         processAllMessages();
         assertEquals(STATE_UNAVAILABLE, sessionController.getCurrentStateName());
@@ -1117,8 +1119,9 @@
         private int mErrorCode = SatelliteManager.SATELLITE_RESULT_SUCCESS;
 
         TestSatelliteModemInterface(@NonNull Context context,
-                SatelliteController satelliteController, @NonNull Looper looper) {
-            super(context, satelliteController, looper);
+                SatelliteController satelliteController, @NonNull Looper looper,
+                @NonNull FeatureFlags featureFlags) {
+            super(context, satelliteController, looper, featureFlags);
             mExponentialBackoff.stop();
         }
 
@@ -1161,9 +1164,10 @@
     }
 
     private static class TestSatelliteSessionController extends SatelliteSessionController {
-        TestSatelliteSessionController(Context context, Looper looper, boolean isSatelliteSupported,
+        TestSatelliteSessionController(Context context, Looper looper, FeatureFlags featureFlags,
+                boolean isSatelliteSupported,
                 SatelliteModemInterface satelliteModemInterface) {
-            super(context, looper, isSatelliteSupported, satelliteModemInterface);
+            super(context, looper, featureFlags, isSatelliteSupported, satelliteModemInterface);
         }
 
         String getCurrentStateName() {