Merge "Add Satellite Availability config check in SatelliteController" into main
diff --git a/Android.bp b/Android.bp
index da32208..a6e526c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -82,14 +82,14 @@
         "android.hardware.radio-V1.4-java",
         "android.hardware.radio-V1.5-java",
         "android.hardware.radio-V1.6-java",
-        "android.hardware.radio.config-V3-java",
-        "android.hardware.radio.data-V3-java",
-        "android.hardware.radio.ims-V2-java",
-        "android.hardware.radio.messaging-V3-java",
-        "android.hardware.radio.modem-V3-java",
-        "android.hardware.radio.network-V3-java",
-        "android.hardware.radio.sim-V3-java",
-        "android.hardware.radio.voice-V3-java",
+        "android.hardware.radio.config-V4-java",
+        "android.hardware.radio.data-V4-java",
+        "android.hardware.radio.ims-V3-java",
+        "android.hardware.radio.messaging-V4-java",
+        "android.hardware.radio.modem-V4-java",
+        "android.hardware.radio.network-V4-java",
+        "android.hardware.radio.sim-V4-java",
+        "android.hardware.radio.voice-V4-java",
         "voip-common",
         "ims-common",
         "unsupportedappusage",
diff --git a/flags/carrier.aconfig b/flags/carrier.aconfig
index 265d258..14aedc6 100644
--- a/flags/carrier.aconfig
+++ b/flags/carrier.aconfig
@@ -21,3 +21,12 @@
       purpose: PURPOSE_BUGFIX
     }
 }
+
+# OWNER=melhuishj TARGET=25Q2
+flag {
+    name: "temporary_failures_in_carrier_messaging_service"
+    is_exported: true
+    namespace: "telephony"
+    description: "Enable temporary failures in CarrierMessagingService"
+    bug:"326610112"
+}
diff --git a/flags/misc.aconfig b/flags/misc.aconfig
index 303c0ff..03d1f4e 100644
--- a/flags/misc.aconfig
+++ b/flags/misc.aconfig
@@ -220,3 +220,13 @@
     }
 }
 
+# OWNER=jackyu TARGET=25Q2
+flag {
+    name: "power_down_race_fix"
+    namespace: "telephony"
+    description: "Fixed race condition while powering down"
+    bug:"378616116"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/flags/network.aconfig b/flags/network.aconfig
index 7c09ba3..be599ea 100644
--- a/flags/network.aconfig
+++ b/flags/network.aconfig
@@ -93,3 +93,20 @@
     }
 }
 
+# OWNER=yomna TARGET=25Q2
+flag {
+  name: "security_algorithms_update_indications"
+  is_exported: true
+  namespace: "telephony"
+  description: "guard system API onSecurityAlgorithmsChanged"
+  bug: "355062720"
+}
+
+# OWNER=yomna TARGET=25Q2
+flag {
+  name: "cellular_identifier_disclosure_indications"
+  is_exported: true
+  namespace: "telephony"
+  description: "guard system API onCellularIdentifierDisclosedChanged"
+  bug: "355062720"
+}
diff --git a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 732582f..dc05608 100644
--- a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -25,12 +25,14 @@
 import android.telephony.CallQuality;
 import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
+import android.telephony.CellularIdentifierDisclosure;
 import android.telephony.LinkCapacityEstimate;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PhoneCapability;
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
 import android.telephony.PreciseDataConnectionState;
+import android.telephony.SecurityAlgorithmUpdate;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyDisplayInfo;
 import android.telephony.TelephonyManager.DataEnabledReason;
@@ -356,6 +358,23 @@
                 sender.getSubId(), ntnSignalStrength);
     }
 
+    @Override
+    public void notifySecurityAlgorithmsChanged(Phone sender, SecurityAlgorithmUpdate update) {
+        if (!mFeatureFlags.securityAlgorithmsUpdateIndications()) return;
+
+        mTelephonyRegistryMgr.notifySecurityAlgorithmsChanged(sender.getPhoneId(),
+                sender.getSubId(), update);
+    }
+
+    @Override
+    public void notifyCellularIdentifierDisclosedChanged(Phone sender,
+            CellularIdentifierDisclosure disclosure) {
+        if (!mFeatureFlags.cellularIdentifierDisclosureIndications()) return;
+
+        mTelephonyRegistryMgr.notifyCellularIdentifierDisclosedChanged(sender.getPhoneId(),
+                sender.getSubId(), disclosure);
+    }
+
     /**
      * Convert the {@link Call.State} enum into the PreciseCallState.PRECISE_CALL_STATE_* constants
      * for the public API.
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index a91000e..6a6e4d0 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -1893,8 +1893,15 @@
     @Override
     public void setRadioPowerForReason(boolean power, boolean forEmergencyCall,
             boolean isSelectedPhoneForEmergencyCall, boolean forceApply, int reason) {
-        mSST.setRadioPowerForReason(power, forEmergencyCall, isSelectedPhoneForEmergencyCall,
-                forceApply, reason);
+        if (mFeatureFlags.powerDownRaceFix()) {
+            // setRadioPowerForReason can be called by the binder thread. We need to move that into
+            // the main thread to prevent race condition.
+            post(() -> mSST.setRadioPowerForReason(power, forEmergencyCall,
+                    isSelectedPhoneForEmergencyCall, forceApply, reason));
+        } else {
+            mSST.setRadioPowerForReason(power, forEmergencyCall, isSelectedPhoneForEmergencyCall,
+                    forceApply, reason);
+        }
     }
 
     @Override
diff --git a/src/java/com/android/internal/telephony/PhoneNotifier.java b/src/java/com/android/internal/telephony/PhoneNotifier.java
index faf4fd1..6c8b222 100644
--- a/src/java/com/android/internal/telephony/PhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/PhoneNotifier.java
@@ -25,11 +25,13 @@
 import android.telephony.CallQuality;
 import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
+import android.telephony.CellularIdentifierDisclosure;
 import android.telephony.LinkCapacityEstimate;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PhoneCapability;
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseDataConnectionState;
+import android.telephony.SecurityAlgorithmUpdate;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyDisplayInfo;
 import android.telephony.TelephonyManager.DataEnabledReason;
@@ -174,4 +176,11 @@
     /** Notify carrier roaming non-terrestrial network signal strength changed. */
     void notifyCarrierRoamingNtnSignalStrengthChanged(Phone sender,
             @NonNull NtnSignalStrength ntnSignalStrength);
+
+    /** Notify of a cellular identifier disclosure change. */
+    void notifyCellularIdentifierDisclosedChanged(Phone sender,
+            CellularIdentifierDisclosure disclosure);
+
+    /** Notify of a security algorithm update change. */
+    void notifySecurityAlgorithmsChanged(Phone sender, SecurityAlgorithmUpdate update);
 }
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java
index 871cabc..b209d1d 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -825,6 +825,9 @@
 
         SmsResponse smsResponse = new SmsResponse(messageRef, null /* ackPdu */, NO_ERROR_CODE,
                 tracker.mMessageId);
+        if (Flags.temporaryFailuresInCarrierMessagingService()) {
+            tracker.mResultCodeFromCarrierMessagingService = result;
+        }
 
         switch (result) {
             case CarrierMessagingService.SEND_STATUS_OK:
@@ -836,10 +839,34 @@
                                                           smsResponse,
                                                           null /* exception*/)));
                 break;
-            case CarrierMessagingService.SEND_STATUS_ERROR:
-                Rlog.d(TAG, "processSendSmsResponse: Sending SMS by CarrierMessagingService"
-                        + " failed. "
-                        + SmsController.formatCrossStackMessageId(tracker.mMessageId));
+            case CarrierMessagingService.SEND_STATUS_ERROR: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_GENERIC_FAILURE: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_NULL_PDU: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_NO_SERVICE: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_LIMIT_EXCEEDED: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_FDN_CHECK_FAILURE: // fall through
+            case CarrierMessagingService
+                    .SEND_STATUS_RESULT_ERROR_SHORT_CODE_NOT_ALLOWED: // fall through
+            case CarrierMessagingService
+                    .SEND_STATUS_RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_NETWORK_REJECT: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_ARGUMENTS: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_STATE: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_SMS_FORMAT: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_NETWORK_ERROR: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_ENCODING_ERROR: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_SMSC_ADDRESS: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_OPERATION_NOT_ALLOWED: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_CANCELLED: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_REQUEST_NOT_SUPPORTED: // fall through
+            case CarrierMessagingService
+                    .SEND_STATUS_RESULT_SMS_BLOCKED_DURING_EMERGENCY: // fall through
+            case CarrierMessagingService.SEND_STATUS_RESULT_SMS_SEND_RETRY_FAILED: // fall through
+                Rlog.d(
+                        TAG,
+                        "processSendSmsResponse: Sending SMS by CarrierMessagingService"
+                                + " failed. "
+                                + SmsController.formatCrossStackMessageId(tracker.mMessageId));
                 sendMessage(obtainMessage(EVENT_SEND_SMS_COMPLETE,
                         new AsyncResult(tracker, smsResponse,
                                 new CommandException(CommandException.Error.GENERIC_FAILURE))));
@@ -858,6 +885,55 @@
         }
     }
 
+    private int toSmsManagerResultForSendSms(int carrierMessagingServiceResult) {
+        switch (carrierMessagingServiceResult) {
+            case CarrierMessagingService.SEND_STATUS_OK:
+                return Activity.RESULT_OK;
+            case CarrierMessagingService.SEND_STATUS_ERROR:
+                return SmsManager.RESULT_RIL_GENERIC_ERROR;
+            case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_GENERIC_FAILURE:
+                return SmsManager.RESULT_ERROR_GENERIC_FAILURE;
+            case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_NULL_PDU:
+                return SmsManager.RESULT_ERROR_NULL_PDU;
+            case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_NO_SERVICE:
+                return SmsManager.RESULT_ERROR_NO_SERVICE;
+            case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_LIMIT_EXCEEDED:
+                return SmsManager.RESULT_ERROR_LIMIT_EXCEEDED;
+            case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_FDN_CHECK_FAILURE:
+                return SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE;
+            case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_SHORT_CODE_NOT_ALLOWED:
+                return SmsManager.RESULT_ERROR_SHORT_CODE_NOT_ALLOWED;
+            case CarrierMessagingService.SEND_STATUS_RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED:
+                return SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED;
+            case CarrierMessagingService.SEND_STATUS_RESULT_NETWORK_REJECT:
+                return SmsManager.RESULT_NETWORK_REJECT;
+            case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_ARGUMENTS:
+                return SmsManager.RESULT_INVALID_ARGUMENTS;
+            case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_STATE:
+                return SmsManager.RESULT_INVALID_STATE;
+            case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_SMS_FORMAT:
+                return SmsManager.RESULT_INVALID_SMS_FORMAT;
+            case CarrierMessagingService.SEND_STATUS_RESULT_NETWORK_ERROR:
+                return SmsManager.RESULT_NETWORK_ERROR;
+            case CarrierMessagingService.SEND_STATUS_RESULT_ENCODING_ERROR:
+                return SmsManager.RESULT_ENCODING_ERROR;
+            case CarrierMessagingService.SEND_STATUS_RESULT_INVALID_SMSC_ADDRESS:
+                return SmsManager.RESULT_INVALID_SMSC_ADDRESS;
+            case CarrierMessagingService.SEND_STATUS_RESULT_OPERATION_NOT_ALLOWED:
+                return SmsManager.RESULT_OPERATION_NOT_ALLOWED;
+            case CarrierMessagingService.SEND_STATUS_RESULT_CANCELLED:
+                return SmsManager.RESULT_CANCELLED;
+            case CarrierMessagingService.SEND_STATUS_RESULT_REQUEST_NOT_SUPPORTED:
+                return SmsManager.RESULT_REQUEST_NOT_SUPPORTED;
+            case CarrierMessagingService.SEND_STATUS_RESULT_SMS_BLOCKED_DURING_EMERGENCY:
+                return SmsManager.RESULT_SMS_BLOCKED_DURING_EMERGENCY;
+            case CarrierMessagingService.SEND_STATUS_RESULT_SMS_SEND_RETRY_FAILED:
+                return SmsManager.RESULT_SMS_SEND_RETRY_FAILED;
+            default:
+                return SmsManager.RESULT_ERROR_GENERIC_FAILURE;
+        }
+    }
+
     /**
      * Use the carrier messaging service to send a multipart text SMS.
      */
@@ -1084,10 +1160,20 @@
                         + SmsController.formatCrossStackMessageId(tracker.mMessageId));
             }
 
-            int ss = mPhone.getServiceState().getState();
-            int error = rilErrorToSmsManagerResult(
-                    ((CommandException) (ar.exception)).getCommandError(), tracker);
+            int error;
+            if (Flags.temporaryFailuresInCarrierMessagingService()
+                    && tracker.mResultCodeFromCarrierMessagingService
+                            != CarrierMessagingService.SEND_STATUS_OK) {
+                error =
+                        toSmsManagerResultForSendSms(
+                                tracker.mResultCodeFromCarrierMessagingService);
+            } else {
+                error =
+                        rilErrorToSmsManagerResult(
+                                ((CommandException) (ar.exception)).getCommandError(), tracker);
+            }
 
+            int ss = mPhone.getServiceState().getState();
             if (tracker.mImsRetry > 0 && ss != ServiceState.STATE_IN_SERVICE) {
                 // This is retry after failure over IMS but voice is not available.
                 // Set retry to max allowed, so no retry is sent and cause
@@ -2489,6 +2575,9 @@
 
         public final long mMessageId;
 
+        // A CarrierMessagingService result code to be returned to the caller.
+        public int mResultCodeFromCarrierMessagingService;
+
         private Boolean mIsFromDefaultSmsApplication;
 
         private int mCarrierId;
@@ -2533,6 +2622,7 @@
             mCarrierId = carrierId;
             mSkipShortCodeDestAddrCheck = skipShortCodeDestAddrCheck;
             mUniqueMessageId = uniqueMessageId;
+            mResultCodeFromCarrierMessagingService = CarrierMessagingService.SEND_STATUS_OK;
         }
 
         @VisibleForTesting
@@ -2552,6 +2642,7 @@
             mCarrierId = 0;
             mSkipShortCodeDestAddrCheck = false;
             mUniqueMessageId = 0;
+            mResultCodeFromCarrierMessagingService = CarrierMessagingService.SEND_STATUS_OK;
         }
 
         public HashMap<String, Object> getData() {
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index f01a8e6..936975a 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -30,6 +30,7 @@
 import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE;
 import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT;
 import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL;
+import static android.telephony.CarrierConfigManager.KEY_REGIONAL_SATELLITE_EARFCN_BUNDLE;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL;
@@ -55,6 +56,7 @@
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_ERROR;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NO_VALID_SATELLITE_SUBSCRIPTION;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
@@ -140,6 +142,7 @@
 import android.telephony.satellite.SatelliteSubscriberInfo;
 import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
 import android.telephony.satellite.SatelliteSubscriptionInfo;
+import android.telephony.satellite.SystemSelectionSpecifier;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
@@ -299,6 +302,8 @@
     private static final int EVENT_TERRESTRIAL_NETWORK_AVAILABLE_CHANGED = 55;
     private static final int EVENT_SET_NETWORK_SELECTION_AUTO_DONE = 56;
     private static final int EVENT_SIGNAL_STRENGTH_CHANGED = 57;
+    private static final int CMD_UPDATE_SYSTEM_SELECTION_CHANNELS = 58;
+    private static final int EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE = 59;
 
     @NonNull private static SatelliteController sInstance;
     @NonNull private final Context mContext;
@@ -481,6 +486,13 @@
      * {@code true} for enabled and {@code false} for disabled. */
     @NonNull private final Map<Integer, Boolean> mIsSatelliteAttachEnabledForCarrierArrayPerSub =
             new HashMap<>();
+    /** Key: subId, value: (key: Regional satellite config Id string, value: Integer
+     * arrays of earfcns in the corresponding regions.)
+     */
+    @GuardedBy("mRegionalSatelliteEarfcnsLock")
+    @NonNull private final Map<Integer, Map<String, Set<Integer>>>
+            mRegionalSatelliteEarfcns = new HashMap<>();
+    @NonNull private final Object mRegionalSatelliteEarfcnsLock = new Object();
     @NonNull private final FeatureFlags mFeatureFlags;
     @NonNull private final Object mSatelliteConnectedLock = new Object();
     /** Key: Subscription ID; Value: Last satellite connected time */
@@ -1223,6 +1235,17 @@
         }
     }
 
+    private static final class UpdateSystemSelectionChannelsArgument {
+        @NonNull SystemSelectionSpecifier mSelectionSpecifier;
+        @NonNull ResultReceiver mResult;
+
+        UpdateSystemSelectionChannelsArgument(@NonNull SystemSelectionSpecifier selectionSpecifier,
+                @NonNull ResultReceiver result) {
+            this.mSelectionSpecifier = selectionSpecifier;
+            this.mResult = result;
+        }
+    }
+
     /**
      * Arguments to send to SatelliteTransmissionUpdate registrants
      */
@@ -2040,6 +2063,29 @@
                 int phoneId = (int) ar.userObj;
                 updateLastNotifiedCarrierRoamingNtnSignalStrengthAndNotify(
                         PhoneFactory.getPhone(phoneId));
+                break;
+            }
+
+            case CMD_UPDATE_SYSTEM_SELECTION_CHANNELS: {
+                plogd("CMD_UPDATE_SYSTEM_SELECTION_CHANNELS");
+                request = (SatelliteControllerHandlerRequest) msg.obj;
+                onCompleted = obtainMessage(EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE, request);
+                mSatelliteModemInterface.updateSystemSelectionChannels(
+                        ((UpdateSystemSelectionChannelsArgument) (request.argument))
+                                .mSelectionSpecifier,
+                        onCompleted);
+                break;
+            }
+
+            case EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE: {
+                ar = (AsyncResult) msg.obj;
+                request = (SatelliteControllerHandlerRequest) ar.userObj;
+                int error =  SatelliteServiceUtils.getSatelliteError(
+                        ar, "updateSystemSelectionChannel");
+                plogd("EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE = " + error);
+                ((UpdateSystemSelectionChannelsArgument) (request.argument)).mResult.send(error,
+                        null);
+                break;
             }
 
             default:
@@ -4580,14 +4626,31 @@
         boolean provisionChanged = false;
         synchronized (mSatelliteTokenProvisionedLock) {
             for (SatelliteSubscriberInfo subscriberInfo : newList) {
+
+                int subId = subscriberInfo.getSubId();
                 Boolean currentProvisioned =
                         mProvisionedSubscriberId.get(subscriberInfo.getSubscriberId());
-                if (currentProvisioned != null && currentProvisioned == provisioned) {
+                if (currentProvisioned == null) {
+                    currentProvisioned = false;
+                }
+
+                Boolean isProvisionedInPersistentDb = false;
+                try {
+                    isProvisionedInPersistentDb = mSubscriptionManagerService
+                         .isSatelliteProvisionedForNonIpDatagram(subId);
+                    if (isProvisionedInPersistentDb == null) {
+                        isProvisionedInPersistentDb = false;
+                    }
+                } catch (IllegalArgumentException | SecurityException ex) {
+                    ploge("isSatelliteProvisionedForNonIpDatagram: subId=" + subId + ", ex="
+                            + ex);
+                }
+                if (currentProvisioned == provisioned
+                        && isProvisionedInPersistentDb == provisioned) {
                     continue;
                 }
                 provisionChanged = true;
                 mProvisionedSubscriberId.put(subscriberInfo.getSubscriberId(), provisioned);
-                int subId = subscriberInfo.getSubId();
                 try {
                     mSubscriptionManagerService.setIsSatelliteProvisionedForNonIpDatagram(subId,
                             provisioned);
@@ -5183,6 +5246,13 @@
                         KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE));
     }
 
+    @NonNull
+    private Map<String, Set<Integer>> readRegionalSatelliteEarfcnsFromCarrierConfig(int subId) {
+        PersistableBundle config = getPersistableBundle(subId);
+        return SatelliteServiceUtils.parseRegionalSatelliteEarfcns(
+                config.getPersistableBundle(KEY_REGIONAL_SATELLITE_EARFCN_BUNDLE));
+    }
+
     @NonNull private PersistableBundle getConfigForSubId(int subId) {
         PersistableBundle config = null;
         if (mCarrierConfigManager != null) {
@@ -5206,7 +5276,8 @@
                         KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
                         KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
                         KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE,
-                        KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY
+                        KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY,
+                        KEY_REGIONAL_SATELLITE_EARFCN_BUNDLE
                 );
             } catch (Exception e) {
                 logw("getConfigForSubId: " + e);
@@ -5237,6 +5308,7 @@
         evaluateCarrierRoamingNtnEligibilityChange();
         sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
                 mEvaluateEsosProfilesPrioritizationDurationMillis);
+        updateRegionalSatelliteEarfcns(subId);
     }
 
     // imsi, msisdn, default sms subId change
@@ -7059,6 +7131,34 @@
         }
     }
 
+    /**
+     * Request to get the currently selected satellite subscription id.
+     *
+     * @param result The result receiver that returns the currently selected satellite subscription
+     *               id if the request is successful or an error code if the request failed.
+     */
+    public void requestSelectedNbIotSatelliteSubscriptionId(@NonNull ResultReceiver result) {
+        if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+            result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
+            logd("requestSelectedNbIotSatelliteSubscriptionId: carrierRoamingNbIotNtn is disabled");
+            return;
+        }
+
+        int selectedSatelliteSubId = getSelectedSatelliteSubId();
+        plogd("requestSelectedNbIotSatelliteSubscriptionId: " + selectedSatelliteSubId);
+        if (selectedSatelliteSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            result.send(SATELLITE_RESULT_NO_VALID_SATELLITE_SUBSCRIPTION, null);
+            logd("requestSelectedNbIotSatelliteSubscriptionId: "
+                    + "selectedSatelliteSubId is invalid");
+            return;
+        }
+
+        Bundle bundle = new Bundle();
+        bundle.putInt(SatelliteManager.KEY_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_ID,
+                selectedSatelliteSubId);
+        result.send(SATELLITE_RESULT_SUCCESS, bundle);
+    }
+
     private void selectBindingSatelliteSubscription(boolean shouldIgnoreEnabledState) {
         if ((isSatelliteEnabled() || isSatelliteBeingEnabled()) && !shouldIgnoreEnabledState) {
             plogd("selectBindingSatelliteSubscription: satellite subscription will be selected "
@@ -7154,6 +7254,63 @@
     }
 
     /**
+     * Request to update system selection channels.
+     *
+     * @param result The result receiver that returns if the request is successful or
+     *               an error code if the request failed.
+     */
+    public void updateSystemSelectionChannels(@NonNull SystemSelectionSpecifier selectionSpecifier,
+            @NonNull ResultReceiver result) {
+        if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+            plogd("updateSystemSelectionChannels: "
+                    + "carrierRoamingNbIotNtn flag is disabled");
+            result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
+            return;
+        }
+
+        sendRequestAsync(CMD_UPDATE_SYSTEM_SELECTION_CHANNELS,
+                new UpdateSystemSelectionChannelsArgument(selectionSpecifier, result), null);
+    }
+
+    /**
+     * @param subId Subscription ID.
+     * @return The The map of earfcns with key: regional satellite config Id,
+     * value: set of earfcns in the corresponding regions associated with the {@code subId}.
+     */
+    @NonNull
+    public Map<String, Set<Integer>> getRegionalSatelliteEarfcns(int subId) {
+        if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+            logd("getRegionalSatelliteEarfcns: carrierRoamingNbIotNtnFlag is disabled");
+            return new HashMap<>();
+        }
+        synchronized (mRegionalSatelliteEarfcnsLock) {
+            if (mRegionalSatelliteEarfcns.containsKey(subId)) {
+                return mRegionalSatelliteEarfcns.get(subId);
+            } else {
+                logd("getRegionalSatelliteEarfcns: Earfcns for subId: " + subId + " not found");
+                return new HashMap<>();
+            }
+        }
+    }
+
+    /**
+     * Update regional satellite earfcn information from carrier config.
+     */
+    public void updateRegionalSatelliteEarfcns(int subId) {
+        plogd("updateRegionalSatelliteEarfcns with subId " + subId);
+        if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+            plogd("updateRegionalSatelliteEarfcns: "
+                    + "carrierRoamingNbIotNtn flag is disabled");
+            return;
+        }
+
+        synchronized (mRegionalSatelliteEarfcnsLock) {
+            mRegionalSatelliteEarfcns.put(subId,
+                    readRegionalSatelliteEarfcnsFromCarrierConfig(subId));
+        }
+    }
+
+    /**
      * Deliver the list of deprovisioned satellite subscriber ids.
      *
      * @param list List of deprovisioned satellite subscriber ids.
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
index 5fa85db..6f88f59 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
@@ -41,6 +41,7 @@
 import android.telephony.satellite.SatelliteManager;
 import android.telephony.satellite.SatelliteManager.SatelliteException;
 import android.telephony.satellite.SatelliteModemEnableRequestAttributes;
+import android.telephony.satellite.SystemSelectionSpecifier;
 import android.telephony.satellite.stub.INtnSignalStrengthConsumer;
 import android.telephony.satellite.stub.ISatellite;
 import android.telephony.satellite.stub.ISatelliteCapabilitiesConsumer;
@@ -1383,6 +1384,42 @@
         mExponentialBackoff.start();
     }
 
+    /**
+     * Request to update system selection channels
+     *
+     * @param systemSelectionSpecifier system selection specifiers
+     * @param message The Message to send to result of the operation to.
+     */
+    public void updateSystemSelectionChannels(
+            @NonNull SystemSelectionSpecifier systemSelectionSpecifier,
+            @Nullable Message message) {
+        plogd("updateSystemSelectionChannels: SystemSelectionSpecifier: "
+                + systemSelectionSpecifier.toString());
+        if (mSatelliteService != null) {
+            try {
+                mSatelliteService.updateSystemSelectionChannels(SatelliteServiceUtils
+                                .toSystemSelectionSpecifier(systemSelectionSpecifier),
+                        new IIntegerConsumer.Stub() {
+                            @Override
+                            public void accept(int result) {
+                                int error = SatelliteServiceUtils.fromSatelliteError(result);
+                                plogd("updateSystemSelectionChannels: " + error);
+                                Binder.withCleanCallingIdentity(() ->
+                                        sendMessageWithResult(message, null, error));
+                            }
+                        });
+            } catch (RemoteException e) {
+                ploge("updateSystemSelectionChannels: RemoteException " + e);
+                sendMessageWithResult(message, null,
+                        SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
+            }
+        } else {
+            ploge("updateSystemSelectionChannels: Satellite service is unavailable.");
+            sendMessageWithResult(message, null,
+                    SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
+        }
+    }
+
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected static void sendMessageWithResult(@NonNull Message message, @Nullable Object result,
             @SatelliteManager.SatelliteResult int error) {
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
index 3936a7e..9217ba1 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
@@ -43,6 +43,7 @@
 import android.telephony.satellite.SatelliteManager;
 import android.telephony.satellite.SatelliteModemEnableRequestAttributes;
 import android.telephony.satellite.SatelliteSubscriptionInfo;
+import android.telephony.satellite.SystemSelectionSpecifier;
 import android.telephony.satellite.stub.NTRadioTechnology;
 import android.telephony.satellite.stub.SatelliteModemState;
 import android.telephony.satellite.stub.SatelliteResult;
@@ -53,6 +54,7 @@
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.internal.telephony.util.TelephonyUtils;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -542,6 +544,56 @@
         return mcc + mnc;
     }
 
+    /**
+     * Convert SystemSelectionSpecifier from framework definition to service definition
+     * @param systemSelectionSpecifier The SystemSelectionSpecifier from the framework.
+     * @return The converted SystemSelectionSpecifier for the satellite service.
+     */
+    @NonNull public static List<android.telephony.satellite.stub
+            .SystemSelectionSpecifier> toSystemSelectionSpecifier(
+            @NonNull SystemSelectionSpecifier systemSelectionSpecifier) {
+        List<android.telephony.satellite.stub.SystemSelectionSpecifier> converted =
+                new ArrayList<>();
+        android.telephony.satellite.stub.SystemSelectionSpecifier convertedSpecifier =
+                new android.telephony.satellite.stub.SystemSelectionSpecifier();
+
+        convertedSpecifier.mMccMnc = systemSelectionSpecifier.getMccMnc();
+        convertedSpecifier.mBands = systemSelectionSpecifier.getBands().toArray();
+        convertedSpecifier.mEarfcs = systemSelectionSpecifier.getEarfcs().toArray();
+        converted.add(convertedSpecifier);
+        return converted;
+    }
+
+    /**
+     * Expected format of the input dictionary bundle is:
+     * <ul>
+     *     <li>Key: Regional satellite config Id string.</li>
+     *     <li>Value: Integer arrays of earfcns in the corresponding regions."</li>
+     * </ul>
+     * @return The map of earfcns with key: regional satellite config Id,
+     * value: set of earfcns in the corresponding regions.
+     */
+    @NonNull
+    public static Map<String, Set<Integer>> parseRegionalSatelliteEarfcns(
+            @Nullable PersistableBundle earfcnsBundle) {
+        Map<String, Set<Integer>> earfcnsMap = new HashMap<>();
+        if (earfcnsBundle == null || earfcnsBundle.isEmpty()) {
+            logd("parseRegionalSatelliteEarfcns: earfcnsBundle is null or empty");
+            return earfcnsMap;
+        }
+
+        for (String configId : earfcnsBundle.keySet()) {
+            Set<Integer> earfcnsSet = new HashSet<>();
+            for (int earfcn : earfcnsBundle.getIntArray(configId)) {
+                earfcnsSet.add(earfcn);
+            }
+            logd("parseRegionalSatelliteEarfcns: configId = " + configId + ", earfcns ="
+                    + earfcnsSet.stream().map(String::valueOf).collect(joining(",")));
+            earfcnsMap.put(configId, earfcnsSet);
+        }
+        return earfcnsMap;
+    }
+
     private static void logd(@NonNull String log) {
         Rlog.d(TAG, log);
     }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
index 8720171..522cdac 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
@@ -15,6 +15,12 @@
  */
 package com.android.internal.telephony;
 
+import static android.telephony.CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI;
+import static android.telephony.CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST;
+import static android.telephony.SecurityAlgorithmUpdate.CONNECTION_EVENT_VOLTE_SIP;
+import static android.telephony.SecurityAlgorithmUpdate.SECURITY_ALGORITHM_EEA2;
+import static android.telephony.SecurityAlgorithmUpdate.SECURITY_ALGORITHM_HMAC_SHA1_96;
+
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Matchers.eq;
@@ -26,9 +32,11 @@
 
 import android.telephony.CellIdentityGsm;
 import android.telephony.CellInfo;
+import android.telephony.CellularIdentifierDisclosure;
 import android.telephony.DisconnectCause;
 import android.telephony.PreciseCallState;
 import android.telephony.PreciseDisconnectCause;
+import android.telephony.SecurityAlgorithmUpdate;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
 import android.telephony.ims.ImsCallProfile;
@@ -449,4 +457,35 @@
         verify(mTelephonyRegistryManager).notifyCarrierRoamingNtnAvailableServicesChanged(
                 eq(subId), eq(testServices));
     }
+
+    @Test
+    @SmallTest
+    public void testSecurityAlgorithmsChanged() {
+        doReturn(true).when(mFeatureFlags).securityAlgorithmsUpdateIndications();
+        int phoneId = mPhone.getPhoneId();
+        int subId = mPhone.getSubId();
+        SecurityAlgorithmUpdate update =
+                new SecurityAlgorithmUpdate(
+                        CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+                        SECURITY_ALGORITHM_HMAC_SHA1_96, false);
+        mDefaultPhoneNotifierUT.notifySecurityAlgorithmsChanged(mPhone, update);
+        verify(mTelephonyRegistryManager).notifySecurityAlgorithmsChanged(
+                eq(phoneId), eq(subId), eq(update));
+    }
+
+    @Test
+    @SmallTest
+    public void testCellularIdentifierDisclosedChanged() {
+        doReturn(true).when(mFeatureFlags).cellularIdentifierDisclosureIndications();
+        int phoneId = mPhone.getPhoneId();
+        int subId = mPhone.getSubId();
+        CellularIdentifierDisclosure disclosure =
+                new CellularIdentifierDisclosure(NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST,
+                        CELLULAR_IDENTIFIER_IMSI,
+                        "001001",
+                        false);
+        mDefaultPhoneNotifierUT.notifyCellularIdentifierDisclosedChanged(mPhone, disclosure);
+        verify(mTelephonyRegistryManager).notifyCellularIdentifierDisclosedChanged(
+                eq(phoneId), eq(subId), eq(disclosure));
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index 2ff38b2..5dc4719 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
@@ -15,7 +15,12 @@
  */
 package com.android.internal.telephony;
 
+import static android.telephony.CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI;
+import static android.telephony.CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST;
 import static android.telephony.PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN;
+import static android.telephony.SecurityAlgorithmUpdate.CONNECTION_EVENT_VOLTE_SIP;
+import static android.telephony.SecurityAlgorithmUpdate.SECURITY_ALGORITHM_EEA2;
+import static android.telephony.SecurityAlgorithmUpdate.SECURITY_ALGORITHM_HMAC_SHA1_96;
 import static android.telephony.ServiceState.FREQUENCY_RANGE_LOW;
 import static android.telephony.SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED;
 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -57,11 +62,13 @@
 import android.telephony.CellInfo;
 import android.telephony.CellInfoLte;
 import android.telephony.CellLocation;
+import android.telephony.CellularIdentifierDisclosure;
 import android.telephony.LinkCapacityEstimate;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PhoneCapability;
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseDataConnectionState;
+import android.telephony.SecurityAlgorithmUpdate;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -181,6 +188,10 @@
                 TelephonyCallback.EVENT_EMERGENCY_CALLBACK_MODE_CHANGED);
         READ_PRIVILEGED_PHONE_STATE_EVENTS.add(
                 TelephonyCallback.EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED);
+        READ_PRIVILEGED_PHONE_STATE_EVENTS.add(
+                TelephonyCallback.EVENT_CELLULAR_IDENTIFIER_DISCLOSED_CHANGED);
+        READ_PRIVILEGED_PHONE_STATE_EVENTS.add(
+                TelephonyCallback.EVENT_SECURITY_ALGORITHMS_CHANGED);
     }
 
     // All events contribute to TelephonyRegistry#isActiveEmergencySessionPermissionRequired
@@ -211,7 +222,9 @@
             TelephonyCallback.DataActivityListener,
             TelephonyCallback.SimultaneousCellularCallingSupportListener,
             TelephonyCallback.EmergencyCallbackModeListener,
-            TelephonyCallback.CarrierRoamingNtnModeListener {
+            TelephonyCallback.CarrierRoamingNtnModeListener,
+            TelephonyCallback.SecurityAlgorithmsListener,
+            TelephonyCallback.CellularIdentifierDisclosedListener {
         // This class isn't mockable to get invocation counts because the IBinder is null and
         // crashes the TelephonyRegistry. Make a cheesy verify(times()) alternative.
         public AtomicInteger invocationCount = new AtomicInteger(0);
@@ -351,6 +364,16 @@
             invocationCount.incrementAndGet();
             mCarrierRoamingNtnSignalStrength = ntnSignalStrength;
         }
+
+        @Override
+        public void onSecurityAlgorithmsChanged(SecurityAlgorithmUpdate update) {
+            invocationCount.incrementAndGet();
+        }
+
+        @Override
+        public void onCellularIdentifierDisclosedChanged(CellularIdentifierDisclosure disclosure) {
+            invocationCount.incrementAndGet();
+        }
     }
 
     public class MySatelliteStateChangeListener implements ISatelliteStateChangeListener {
@@ -1838,4 +1861,49 @@
         // We should not receive the new state change after monitoring end
         assertFalse(mIsSatelliteEnabled);
     }
+
+
+    @Test
+    @EnableFlags(Flags.FLAG_SECURITY_ALGORITHMS_UPDATE_INDICATIONS)
+    public void testNotifySecurityAlgorithmsChanged() {
+        int subId = 1;
+        int[] events = {TelephonyCallback.EVENT_SECURITY_ALGORITHMS_CHANGED};
+
+        mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+                mContext.getAttributionTag(), mTelephonyCallback.callback, events, false);
+
+        SecurityAlgorithmUpdate update =
+                new SecurityAlgorithmUpdate(
+                        CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+                        SECURITY_ALGORITHM_HMAC_SHA1_96, false);
+
+        mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+                mContext.getAttributionTag(), mTelephonyCallback.callback, events, false);
+        int invocationCount = mTelephonyCallback.invocationCount.get();
+        mTelephonyRegistry.notifySecurityAlgorithmsChanged(0, 1, update);
+        processAllMessages();
+        assertEquals(invocationCount + 1, mTelephonyCallback.invocationCount.get());
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_CELLULAR_IDENTIFIER_DISCLOSURE_INDICATIONS)
+    public void testNotifyCellularIdentifierDisclosedChanged() {
+        int subId = 1;
+        int[] events = {TelephonyCallback.EVENT_CELLULAR_IDENTIFIER_DISCLOSED_CHANGED};
+
+        CellularIdentifierDisclosure disclosure =
+                new CellularIdentifierDisclosure(NAS_PROTOCOL_MESSAGE_ATTACH_REQUEST,
+                        CELLULAR_IDENTIFIER_IMSI,
+                        "001001",
+                        false);
+
+        mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+                mContext.getAttributionTag(), mTelephonyCallback.callback, events, false);
+        int invocationCount = mTelephonyCallback.invocationCount.get();
+        mTelephonyRegistry.notifyCellularIdentifierDisclosedChanged(0, 1,
+                disclosure);
+        processAllMessages();
+        assertEquals(invocationCount + 1, mTelephonyCallback.invocationCount.get());
+    }
+
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
index 639a2a3..a29de0f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
@@ -70,6 +70,7 @@
 import com.android.internal.telephony.TelephonyTest;
 import com.android.internal.telephony.TelephonyTestUtils;
 import com.android.internal.telephony.TestApplication;
+import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.uicc.IccUtils;
 import com.android.internal.telephony.uicc.IsimUiccRecords;
 
@@ -377,23 +378,35 @@
                 any(ICarrierMessagingCallback.class));
     }
 
-    @Test
-    @SmallTest
-    @Ignore("b/256282780")
-    public void testSendSmsByCarrierApp() throws Exception {
+    private int sendSmsWithCarrierAppResponse(int carrierAppResultCode) throws Exception {
         mockCarrierApp();
-        mockCarrierAppStubResults(CarrierMessagingService.SEND_STATUS_OK,
-                mICarrierAppMessagingService, true);
+        mockCarrierAppStubResults(carrierAppResultCode, mICarrierAppMessagingService, true);
         registerTestIntentReceiver();
 
-        PendingIntent pendingIntent = PendingIntent.getBroadcast(TestApplication.getAppContext(), 0,
-                new Intent(TEST_INTENT)
-                        .setPackage(TestApplication.getAppContext().getPackageName()),
-                PendingIntent.FLAG_MUTABLE);
+        PendingIntent pendingIntent =
+                PendingIntent.getBroadcast(
+                        TestApplication.getAppContext(),
+                        0,
+                        new Intent(TEST_INTENT)
+                                .setPackage(TestApplication.getAppContext().getPackageName()),
+                        PendingIntent.FLAG_MUTABLE);
         mReceivedTestIntent = false;
 
-        mGsmSmsDispatcher.sendText("6501002000", "121" /*scAddr*/, "test sms",
-                pendingIntent, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
+        mGsmSmsDispatcher.sendText(
+                "6501002000",
+                "121" /*scAddr*/,
+                "test sms",
+                pendingIntent,
+                null,
+                null,
+                null,
+                mCallingUserId,
+                false,
+                -1,
+                false,
+                -1,
+                false,
+                0L);
         processAllMessages();
         synchronized (mLock) {
             if (!mReceivedTestIntent) {
@@ -402,15 +415,48 @@
             }
             assertEquals(true, mReceivedTestIntent);
             int resultCode = mTestReceiver.getResultCode();
-            assertTrue("Unexpected result code: " + resultCode,
-                    resultCode == SmsManager.RESULT_ERROR_NONE || resultCode == Activity.RESULT_OK);
-            verify(mSimulatedCommandsVerifier, times(0)).sendSMS(anyString(), anyString(),
-                    any(Message.class));
+            verify(mSimulatedCommandsVerifier, times(0))
+                    .sendSMS(anyString(), anyString(), any(Message.class));
+            return resultCode;
         }
     }
 
     @Test
     @SmallTest
+    @Ignore("b/256282780")
+    public void testSendSmsByCarrierApp() throws Exception {
+        int resultCode = sendSmsWithCarrierAppResponse(CarrierMessagingService.SEND_STATUS_OK);
+        assertTrue(
+                "Unexpected result code: " + resultCode,
+                resultCode == SmsManager.RESULT_ERROR_NONE || resultCode == Activity.RESULT_OK);
+    }
+
+    @Test
+    @SmallTest
+    public void testSendSmsByCarrierApp_PermanentFailure() throws Exception {
+        int resultCode = sendSmsWithCarrierAppResponse(CarrierMessagingService.SEND_STATUS_ERROR);
+        assertTrue(
+                "Unexpected result code: " + resultCode,
+                resultCode == SmsManager.RESULT_RIL_GENERIC_ERROR);
+    }
+
+    @Test
+    @SmallTest
+    public void testSendSmsByCarrierApp_FailureWithReason() throws Exception {
+        if (!Flags.temporaryFailuresInCarrierMessagingService()) {
+            return;
+        }
+        doReturn(true).when(mFeatureFlags).temporaryFailuresInCarrierMessagingService();
+        int resultCode =
+                sendSmsWithCarrierAppResponse(
+                        CarrierMessagingService.SEND_STATUS_RESULT_ERROR_NO_SERVICE);
+        assertTrue(
+                "Unexpected result code: " + resultCode,
+                resultCode == SmsManager.RESULT_ERROR_NO_SERVICE);
+    }
+
+    @Test
+    @SmallTest
     public void testSendSmsByCarrierAppNoResponse() throws Exception {
         mockCarrierApp();
         // do not mock result, instead reduce the timeout for test
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 0e0defc..cf6f6a9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -4574,6 +4574,18 @@
                 }
             }
         };
+
+        TestSubscriptionManager testSubscriptionManager = new TestSubscriptionManager();
+        doAnswer(invocation -> {
+            testSubscriptionManager.setIsSatelliteProvisionedForNonIpDatagram(
+                    invocation.getArgument(0), invocation.getArgument(1));
+            return null;
+        }).when(mMockSubscriptionManagerService).setIsSatelliteProvisionedForNonIpDatagram(anyInt(),
+                anyBoolean());
+        doAnswer(invocation -> testSubscriptionManager.isSatelliteProvisionedForNonIpDatagram(
+                invocation.getArgument(0))).when(
+                mMockSubscriptionManagerService).isSatelliteProvisionedForNonIpDatagram(anyInt());
+
         setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
         verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
         int errorCode = mSatelliteControllerUT.registerForSatelliteProvisionStateChanged(callback);
@@ -6027,4 +6039,21 @@
         assertTrue(mSharedPreferences.getBoolean(
                 SatelliteController.NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY, false));
     }
+
+    private static class TestSubscriptionManager {
+        public Map<Integer, Boolean> mSatelliteProvisionedForNonIpDatagram = new HashMap<>();
+
+        public void resetProvisionMapForNonIpDatagram() {
+            mSatelliteProvisionedForNonIpDatagram.clear();
+        }
+
+        public void setIsSatelliteProvisionedForNonIpDatagram(int subId, boolean provisioned) {
+            mSatelliteProvisionedForNonIpDatagram.put(subId, provisioned);
+        }
+
+        public boolean isSatelliteProvisionedForNonIpDatagram(int subId) {
+            Boolean isProvisioned = mSatelliteProvisionedForNonIpDatagram.get(subId);
+            return isProvisioned != null ? isProvisioned : false;
+        }
+    }
 }