Merge tag 'android-16.0.0_r1' of https://android.googlesource.com/platform/frameworks/opt/telephony into HEAD

Android 16.0.0 release 1

Change-Id: I93b22ce540126327816c4cdeb3ed67070c3bd1c8
diff --git a/Android.bp b/Android.bp
index a6e526c..e667cb3 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-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",
+        "android.hardware.radio.config-V5-java",
+        "android.hardware.radio.data-V5-java",
+        "android.hardware.radio.ims-V4-java",
+        "android.hardware.radio.messaging-V5-java",
+        "android.hardware.radio.modem-V5-java",
+        "android.hardware.radio.network-V5-java",
+        "android.hardware.radio.sim-V5-java",
+        "android.hardware.radio.voice-V5-java",
         "voip-common",
         "ims-common",
         "unsupportedappusage",
diff --git a/OWNERS b/OWNERS
index ff1a04e..aa0dee2 100644
--- a/OWNERS
+++ b/OWNERS
@@ -18,4 +18,4 @@
 xiaotonj@google.com
 
 # Domain Selection code is co-owned, adding additional owners for this code
-per-file EmergencyStateTracker*=hwangoo@google.com,forestchoi@google.com,avinashmp@google.com,mkoon@google.com,seheele@google.com,jdyou@google.com
+per-file EmergencyStateTracker*=hwangoo@google.com,avinashmp@google.com,mkoon@google.com,seheele@google.com,jdyou@google.com
diff --git a/flags/Android.bp b/flags/Android.bp
index edcfc3f..862b519 100644
--- a/flags/Android.bp
+++ b/flags/Android.bp
@@ -22,6 +22,7 @@
     name: "telephony_flags",
     package: "com.android.internal.telephony.flags",
     container: "system",
+    exportable: true,
     srcs: [
         "calling.aconfig",
         "data.aconfig",
diff --git a/flags/calling.aconfig b/flags/calling.aconfig
index 27d3518..3646f73 100644
--- a/flags/calling.aconfig
+++ b/flags/calling.aconfig
@@ -29,6 +29,18 @@
     }
 }
 
+# OWNER=tgunn TARGET=25Q2
+flag {
+    name: "robust_number_verification"
+    namespace: "telephony"
+    description: "Makes range matching more robust for TelephonyManager#requestNumberVerification"
+    bug:"400984263"
+    is_exported: true
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
 # OWNER=stevestatia TARGET=24Q4
 flag {
     name: "remove_country_code_from_local_singapore_calls"
@@ -78,7 +90,8 @@
     namespace: "telephony"
     description: "To prevent passing the TelephonyRegistry's original instance to listeners in the same process"
     bug:"379126049"
+    is_exported: true
     metadata {
         purpose: PURPOSE_BUGFIX
     }
-}
\ No newline at end of file
+}
diff --git a/flags/carrier.aconfig b/flags/carrier.aconfig
index 14aedc6..19d2145 100644
--- a/flags/carrier.aconfig
+++ b/flags/carrier.aconfig
@@ -30,3 +30,14 @@
     description: "Enable temporary failures in CarrierMessagingService"
     bug:"326610112"
 }
+
+# OWNER=melhuishj TARGET=25Q3
+flag {
+    name: "disable_carrier_network_change_on_carrier_app_lost"
+    namespace: "telephony"
+    description: "Set carrier network change status to false whenever the carrier app is lost"
+    bug:"333571417"
+    metadata {
+      purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/flags/data.aconfig b/flags/data.aconfig
index 4a90c10..cdd73ac 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -1,40 +1,17 @@
 package: "com.android.internal.telephony.flags"
 container: "system"
 
-# OWNER=linggm TARGET=24Q4
+# OWNER=linggm TARGET=25Q2
 flag {
-  name: "keep_empty_requests_network"
+  name: "auto_data_switch_enhanced"
   namespace: "telephony"
-  description: "Don't tear down network even if no requests attached to it."
-  bug: "331301784"
-  metadata {
-    purpose: PURPOSE_BUGFIX
-  }
-}
-
-# OWNER=linggm TARGET=24Q3
-flag {
-  name: "auto_data_switch_allow_roaming"
-  namespace: "telephony"
-  description: "Allow using roaming network as target if user allows it from settings."
+  description: "Ramp up RAT signal strength based auto data switch"
   bug: "287132491"
   metadata {
     purpose: PURPOSE_BUGFIX
   }
 }
 
-# OWNER=linggm TARGET=24Q3
-flag {
-  name: "auto_data_switch_uses_data_enabled"
-  namespace: "telephony"
-  description: "Separately consider the backup phone's data allowed and data enabled."
-  bug: "338552223"
-  metadata {
-    purpose: PURPOSE_BUGFIX
-  }
-}
-
-
 # OWNER=sarahchin TARGET=24Q3
 flag {
   name: "slicing_additional_error_codes"
@@ -44,15 +21,6 @@
   bug: "307378699"
 }
 
-# OWNER=nagendranb TARGET=24Q3
-flag {
-  name: "apn_setting_field_support_flag"
-  is_exported: true
-  namespace: "telephony"
-  description: "Expose apn setting supporting field"
-  bug: "307038091"
-}
-
 # OWNER=sangyun TARGET=24Q3
 flag {
   name: "network_validation"
@@ -62,46 +30,6 @@
   bug:"286171724"
 }
 
-# OWNER=qingqi TARGET=24Q3
-flag {
-  name: "vonr_enabled_metric"
-  namespace: "telephony"
-  description: "Collect vonr status in voice call metric"
-  bug:"288449751"
-}
-
-# OWNER=apsankar TARGET=24Q3
-flag {
-  name: "data_call_session_stats_captures_cross_sim_calling"
-  namespace: "telephony"
-  description: "The DataCallSessionStats metrics will capture whether the IWLAN PDN is set up on cross-SIM calling."
-  bug: "313956117"
-}
-
-# OWNER=sewook TARGET=24Q3
-flag {
-  name: "reconnect_qualified_network"
-  namespace: "telephony"
-  description: "This flag is for internal implementation to handle reconnect request from QNS in telephony FWK."
-  bug: "319520561"
-}
-
-# OWNER=jackyu TARGET=24Q3
-flag {
-  name: "dsrs_diagnostics_enabled"
-  namespace: "telephony"
-  description: "Enable DSRS diagnostics."
-  bug: "319601607"
-}
-
-# OWNER=jackyu TARGET=24Q3
-flag {
-  name: "data_rat_metric_enabled"
-  namespace: "telephony"
-  description: "Write DataRatStateChanged atom"
-  bug:"318519337"
-}
-
 # OWNER=jackyu TARGET=24Q4
 flag {
   name: "dds_callback"
@@ -110,17 +38,6 @@
   bug:"353723350"
 }
 
-# OWNER=jackyu TARGET=25Q1
-flag {
-  name: "support_network_provider"
-  namespace: "telephony"
-  description: "Deprecate network factory and adapt the new network provider model from connectivity service"
-  bug: "343370895"
-  metadata {
-    purpose: PURPOSE_BUGFIX
-  }
-}
-
 # OWNER=jackyu TARGET=25Q2
 flag {
   name: "oem_paid_private"
@@ -129,3 +46,25 @@
   bug: "366194627"
   is_exported: true
 }
+
+# OWNER=gwenlin TARGET=25Q2
+flag {
+  name: "incall_handover_policy"
+  namespace: "telephony"
+  description: "Support IWLAN handover policy based on incall."
+  bug:"376765521"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+# OWNER=nagendranb TARGET=25Q2
+flag {
+  name: "data_service_check"
+  namespace: "telephony"
+  description: "Support data service check based on nri available services."
+  bug:"381338283"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
diff --git a/flags/domainselection.aconfig b/flags/domainselection.aconfig
index 4b1ad4a..88a6e9e 100644
--- a/flags/domainselection.aconfig
+++ b/flags/domainselection.aconfig
@@ -41,3 +41,44 @@
     description: "This flag controls the behavior of terminating an emergency call for cross SIM redialing."
     bug:"336398541"
 }
+
+# OWNER=avinashmp TARGET=25Q1
+flag {
+    name: "add_ims_redial_codes_for_emergency_calls"
+    namespace: "telephony"
+    description: "This flag controls the addition of EMERGENCY_REDIAL_ON_IMS and EMERGENCY_REDIAL_ON_VOWIFI redial codes for normal routed emergency calls."
+    bug:"357980439"
+}
+
+# OWNER=jaesikkong TARGET=25Q2
+flag {
+    name: "disable_ecbm_based_on_rat"
+    namespace: "telephony"
+    description: "Fix bug entering the emergency callback mode in GSM or UMTS network."
+    bug:"389010789"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+# OWNER=hwangoo TARGET=25Q2
+flag {
+    name: "hangup_active_call_based_on_emergency_call_domain"
+    namespace: "telephony"
+    description: "This flag disconnects an active call if the domain selected for the emergency call is different from the domain of the currently active call."
+    bug:"391287237"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+# OWNER=hwangoo TARGET=25Q2
+flag {
+    name: "perform_cross_stack_redial_check_for_emergency_call"
+    namespace: "telephony"
+    description: "This flag performs a quick cross stack redial if the subscription is being invalid and an exception occurs, while an emergency call is in progress."
+    bug:"389190613"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/flags/ims.aconfig b/flags/ims.aconfig
index 703440f..5f49c46 100644
--- a/flags/ims.aconfig
+++ b/flags/ims.aconfig
@@ -166,3 +166,14 @@
     bug:"359721349"
     is_exported: true
 }
+
+# OWNER=joonhunshin TARGET=25Q2
+flag {
+    name: "skip_mmi_code_check_for_emergency_call"
+    namespace: "telephony"
+    description: "This flag allows to skip the MMI code check for the emergency number."
+    bug:"378065922"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/flags/misc.aconfig b/flags/misc.aconfig
index ec7b8fa..3641c60 100644
--- a/flags/misc.aconfig
+++ b/flags/misc.aconfig
@@ -1,17 +1,6 @@
 package: "com.android.internal.telephony.flags"
 container: "system"
 
-# OWNER=linggm TARGET=24Q3
-flag {
-    name: "combine_ril_death_handle"
-    namespace: "telephony"
-    description: "Upon radio service death, combine its handling to prevent race condition"
-    bug:"319612362"
-    metadata {
-        purpose: PURPOSE_BUGFIX
-    }
-}
-
 # OWNER=tjstuart TARGET=24Q3
 flag {
   name: "do_not_override_precise_label"
@@ -54,30 +43,6 @@
   bug: "309655251"
 }
 
-# OWNER=sangyun TARGET=24Q2
-flag {
-  name: "reorganize_roaming_notification"
-  namespace: "telephony"
-  description: "Reorganize conditions to show and dismiss roaming notifications."
-  bug: "310594087"
-}
-
-# OWNER=sangyun TARGET=24Q2
-flag {
-  name: "dismiss_network_selection_notification_on_sim_disable"
-  namespace: "telephony"
-  description: "Fix to dismiss network selection notification when disable sim."
-  bug: "310594186"
-}
-
-# OWNER=nagendranb TARGET=24Q3
-flag {
-  name: "enable_telephony_analytics"
-  namespace: "telephony"
-  description: "Enable Telephony Analytics information of Service State , Sms and Call scenarios"
-  bug: "309896524"
-}
-
 # OWNER=rambowang TARGET=24Q3
 flag {
     name: "reset_mobile_network_settings"
@@ -87,33 +52,6 @@
     bug:"271921464"
 }
 
-# OWNER=sangyun TARGET=24Q3
-flag {
-    name: "roaming_notification_for_single_data_network"
-    namespace: "telephony"
-    description: "Fix bug where roaming notification was not shown on a single data network."
-    bug:"249908996"
-    metadata {
-        purpose: PURPOSE_BUGFIX
-    }
-}
-
-# OWNER=joonhunshin TARGET=24Q3
-flag {
-    name: "enforce_telephony_feature_mapping"
-    namespace: "telephony"
-    description: "This flag controls telephony feature flags mapping."
-    bug:"297989574"
-}
-
-# OWNER=joonhunshin TARGET=24Q3
-flag {
-    name: "enforce_telephony_feature_mapping_for_public_apis"
-    namespace: "telephony"
-    description: "This flag controls telephony feature flags mapping for public APIs and CTS."
-    bug:"297989574"
-}
-
 # OWNER=stevestatia TARGET=24Q3
 flag {
     name: "prevent_system_server_and_phone_deadlock"
@@ -130,22 +68,6 @@
     bug: "290833783"
 }
 
-# OWNER=jackyu TARGET=24Q3
-flag {
-    name: "minimal_telephony_cdm_check"
-    namespace: "telephony"
-    description: "This flag disables Calling/Data/Messaging features if their respective feature is missing"
-    bug: "310710841"
-}
-
-# OWNER=jackyu TARGET=24Q3
-flag {
-    name: "minimal_telephony_managers_conditional_on_features"
-    namespace: "telephony"
-    description: "This flag enables checking for telephony features before initializing corresponding managers"
-    bug: "310710841"
-}
-
 # OWNER=joonhunshin TARGET=24Q3
 flag {
     name: "set_no_reply_timer_for_cfnry"
@@ -246,3 +168,55 @@
     description: "Disable CDMA and NV backing code"
     bug: "379356026"
 }
+
+# OWNER=jackyu TARGET=25Q2
+flag {
+    name: "phone_type_cleanup"
+    namespace: "telephony"
+    description: "As CDMA deprecated, there is no need to switch phone type between CDMA and GSM"
+    bug: "379356026"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+# OWNER=tjstuart TARGET=25Q2
+flag {
+    name: "dynamic_do_not_ask_again_text"
+    namespace: "telephony"
+    description: "Make No Emergency Wifi Calling Do Not Ask Again text translatable"
+    bug:"382006472"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+# OWNER=jackyu,boullanger TARGET=25Q3
+flag {
+    name: "use_i18n_for_mcc_mapping"
+    namespace: "telephony"
+    description: "Use the newly introduced MCC to country table, from the time zone mainline module"
+    bug:"381070025"
+}
+
+# OWNER=nharold TARGET=25Q4
+flag {
+    name: "thread_shred"
+    namespace: "telephony"
+    description: "Consolidate a bunch of unneeded worker threads to save resources"
+    bug:"390244513"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+# OWNER=jackyu TARGET=25Q2
+flag {
+    name: "carrier_config_changed_callback_fix"
+    namespace: "telephony"
+    description: "Carrier config callback race condition fix"
+    bug:"375526692"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/flags/network.aconfig b/flags/network.aconfig
index be599ea..bf2dcad 100644
--- a/flags/network.aconfig
+++ b/flags/network.aconfig
@@ -1,61 +1,6 @@
 package: "com.android.internal.telephony.flags"
 container: "system"
 
-# OWNER=nharold TARGET=24Q1
-flag {
-    name: "enable_carrier_config_n1_control_attempt2"
-    namespace: "telephony"
-    description: "enabling this flag allows KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY to control N1 mode enablement"
-    bug:"328848947"
-
-    metadata {
-        purpose: PURPOSE_BUGFIX
-    }
-}
-
-# OWNER=sarahchin TARGET=24Q1
-flag {
-  name: "hide_roaming_icon"
-  is_exported: true
-  namespace: "telephony"
-  description: "Allow carriers to hide the roaming (R) icon when roaming."
-  bug: "301467052"
-}
-
-# OWNER=cukie TARGET=24Q3
-flag {
-  name: "enable_identifier_disclosure_transparency"
-  is_exported: true
-  namespace: "telephony"
-  description: "Guards APIs for enabling and disabling identifier disclosure transparency"
-  bug: "276752426"
-}
-
-# OWNER=cukie TARGET=24Q3
-flag {
-  name: "enable_identifier_disclosure_transparency_unsol_events"
-  namespace: "telephony"
-  description: "Allows the framework to register for CellularIdentifierDisclosure events and emit notifications to the user about them"
-  bug: "276752426"
-}
-
-# OWNER=cukie TARGET=24Q3
-flag {
-  name: "enable_modem_cipher_transparency"
-  is_exported: true
-  namespace: "telephony"
-  description: "Guards APIs for enabling and disabling modem cipher transparency."
-  bug: "283336425"
-}
-
-# OWNER=cukie TARGET=24Q3
-flag {
-  name: "enable_modem_cipher_transparency_unsol_events"
-  namespace: "telephony"
-  description: "Allows the framework to register for SecurityAlgorithmChanged events and emit notifications to the user when a device is using null ciphers."
-  bug: "283336425"
-}
-
 # OWNER=songferngwang TARGET=24Q3
 flag {
   name: "hide_prefer_3g_item"
@@ -65,14 +10,6 @@
   bug: "310639009"
 }
 
-# OWNER=sarahchin TARGET=24Q2
-flag {
-  name: "support_nr_sa_rrc_idle"
-  namespace: "telephony"
-  description: "Support RRC idle for NR SA."
-  bug: "298233308"
-}
-
 # OWNER=nharold TARGET=24Q3
 flag {
   name: "network_registration_info_reject_cause"
@@ -82,17 +19,6 @@
   bug: "239730435"
 }
 
-# OWNER=sangyun TARGET=24Q3
-flag {
-    name: "backup_and_restore_for_enable_2g"
-    namespace: "telephony"
-    description: "Support backup & restore for allow 2g (setting) option."
-    bug:"314734614"
-    metadata {
-        purpose: PURPOSE_BUGFIX
-    }
-}
-
 # OWNER=yomna TARGET=25Q2
 flag {
   name: "security_algorithms_update_indications"
@@ -110,3 +36,22 @@
   description: "guard system API onCellularIdentifierDisclosedChanged"
   bug: "355062720"
 }
+
+# OWNER=jackyu TARGET=25Q3
+flag {
+    name: "ignore_mcc_mnc_from_operator_for_locale"
+    namespace: "telephony"
+    description: "Ignoring mcc/mnc from RIL indication OPERATOR but only relying MCC/MNC from registered or nearby cells."
+    bug:"374589521"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+flag {
+    name: "vendor_specific_cellular_identifier_disclosure_indications"
+    is_exported: true
+    namespace: "telephony"
+    description: "Guard system API for vendor-specific classifications of cellular ID disclosures"
+    bug: "355062720"
+}
diff --git a/flags/satellite.aconfig b/flags/satellite.aconfig
index ee4570e..b433030 100644
--- a/flags/satellite.aconfig
+++ b/flags/satellite.aconfig
@@ -19,14 +19,6 @@
     bug:"296437388"
 }
 
-# OWNER=nagendranb TARGET=24Q3
-flag {
-    name: "satellite_internet"
-    namespace: "telephony"
-    description: "This flag enables satellite internet support."
-    bug:"326972202"
-}
-
 # OWNER=xalle TARGET=24Q3
 flag {
     name: "satellite_persistent_logging"
@@ -81,3 +73,33 @@
   bug: "357638490"
   is_exported: true
 }
+
+# OWNER=karthickmj TARGET=25Q4
+flag {
+  name: "satellite_25q4_apis"
+  namespace: "telephony"
+  description: "This flag controls the changes for the new satellite APIs"
+  bug: "383254935"
+  is_exported: true
+}
+
+# OWNER=arunvoddu TARGET=25Q2
+flag {
+  name: "starlink_data_bugfix"
+  namespace: "telephony"
+  description: "This flag controls the satellite related bug fixes"
+  bug: "393966687"
+  is_exported: true
+}
+
+# OWNER=amallampati TARGET=25Q3
+flag {
+    name: "satellite_exit_p2p_session_outside_geofence"
+    is_exported: true
+    namespace: "telephony"
+    description: "Exit P2P satellite session outside geofence"
+    bug:"391926447"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/flags/subscription.aconfig b/flags/subscription.aconfig
index 0522a3c..ea12ce8 100644
--- a/flags/subscription.aconfig
+++ b/flags/subscription.aconfig
@@ -46,42 +46,6 @@
   bug: "325045841"
 }
 
-# OWNER=nharold TARGET=24Q3
-flag {
-  name: "safer_get_phone_number"
-  namespace: "telephony"
-  description: "Safety and performance improvements for getPhoneNumber()"
-  bug: "317673478"
-
-  metadata {
-    purpose: PURPOSE_BUGFIX
-  }
-}
-
-# OWNER=songferngwang TARGET=24Q3
-flag {
-  name: "reset_primary_sim_default_values"
-  namespace: "telephony"
-  description: "Reset the default values to the remaining sim"
-  bug: "339394518"
-
-  metadata {
-    purpose: PURPOSE_BUGFIX
-  }
-}
-
-# OWNER=jackyu TARGET=24Q4
-flag {
-  name: "uicc_phone_number_fix"
-  namespace: "telephony"
-  description: "Fixed that empty phone number when getLine1Number returns empty"
-  bug: "302437869"
-
-  metadata {
-    purpose: PURPOSE_BUGFIX
-  }
-}
-
 # OWNER=jmattis TARGET=25Q2
 flag {
   name: "subscription_plan_allow_status_and_end_date"
diff --git a/jarjar-rules-shared.txt b/jarjar-rules-shared.txt
index 2353507..01bdb75 100644
--- a/jarjar-rules-shared.txt
+++ b/jarjar-rules-shared.txt
@@ -18,6 +18,7 @@
 rule com.android.internal.util.State* com.android.internal.telephony.State@1
 rule com.android.internal.util.StateMachine* com.android.internal.telephony.StateMachine@1
 rule com.android.internal.util.UserIcons* com.android.internal.telephony.UserIcons@1
+rule com.android.server.updates.ConfigUpdateInstallReceiver* com.android.internal.telephony.server.updates.ConfigUpdateInstallReceiver@1
 rule com.google.i18n.phonenumbers.** com.android.internal.telephony.phonenumbers.@1
 
 # Module library in frameworks/libs/net
diff --git a/proguard.flags b/proguard.flags
index ebc8922..1c79a2d 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -6,24 +6,27 @@
 
 # Keep deprecated GSM SMS API
 -keepclasseswithmembers class android.telephony.gsm.SmsManager,android.telephony.gsm.SmsManager$* {
-public *;
+    public *;
 }
 -keepclasseswithmembers class android.telephony.gsm.SmsMessage,android.telephony.gsm.SmsMessage$* {
-public protected *;
+    public protected *;
 }
 
 # Keep telephony sysprop
 -keepclasseswithmembers class android.internal.telephony.sysprop.TelephonyProperties {
-public *;
+    public *;
 }
 
 # Keep public classes and public/protected members
 -keepclasseswithmembers class com.android.internal.telephony.** {
-public protected *;
+    public protected *;
 }
 
 # Keep classes and members that have the @UnsupportedAppUsage annotation
--keep @**.UnsupportedAppUsage class *
+# TODO(b/373579455): Evaluate if <init> needs to be kept.
+-keep @**.UnsupportedAppUsage class * {
+    void <init>();
+}
 -keepclassmembers class * {
-@**.UnsupportedAppUsage *;
+    @**.UnsupportedAppUsage *;
 }
diff --git a/proto/src/persist_atoms.proto b/proto/src/persist_atoms.proto
index 8d87a27..d6dff87 100644
--- a/proto/src/persist_atoms.proto
+++ b/proto/src/persist_atoms.proto
@@ -352,6 +352,7 @@
     optional bool is_managed_profile = 16;
     optional bool is_ntn = 17;
     optional bool is_emergency = 18;
+    optional bool is_nb_iot_ntn = 19;
 
     // Internal use only
     optional int32 hashCode = 10001;
@@ -378,6 +379,8 @@
     optional bool is_managed_profile = 18;
     optional bool is_emergency = 19;
     optional bool is_ntn = 20;
+    optional bool is_mt_sms_polling = 21;
+    optional bool is_nb_iot_ntn = 22;
 
     // Internal use only
     optional int32 hashCode = 10001;
@@ -417,6 +420,7 @@
     optional bool is_ntn = 24;
     optional bool is_satellite_transport = 25;
     optional bool is_provisioning_profile = 26;
+    optional bool is_nb_iot_ntn = 27;
 }
 
 message CellularServiceState {
@@ -436,6 +440,8 @@
     optional bool isDataEnabled = 14;
     optional bool is_iwlan_cross_sim = 15;
     optional bool is_ntn = 16;
+    optional bool is_nb_iot_ntn = 17;
+    optional bool is_opportunistic = 18;
 
     // Internal use only
     optional int64 last_used_millis = 10001;
@@ -448,6 +454,7 @@
     optional bool is_multi_sim = 4;
     optional int32 carrier_id = 5;
     optional int32 switch_count = 6;
+    optional bool is_opportunistic = 7;
 
     // Internal use only
     optional int64 last_used_millis = 10001;
@@ -726,6 +733,13 @@
     optional int32 count_of_p2p_sms_available_notification_shown = 34;
     optional int32 count_of_p2p_sms_available_notification_removed = 35;
     optional bool is_ntn_only_carrier = 36;
+    optional int32 version_of_satellite_access_config = 37;
+    optional int32 count_of_incoming_datagram_type_sos_sms_success = 38;
+    optional int32 count_of_incoming_datagram_type_sos_sms_fail = 39;
+    optional int32 count_of_outgoing_datagram_type_sms_success = 40;
+    optional int32 count_of_outgoing_datagram_type_sms_fail = 41;
+    optional int32 count_of_incoming_datagram_type_sms_success = 42;
+    optional int32 count_of_incoming_datagram_type_sms_fail = 43;
 }
 
 message SatelliteSession {
@@ -820,6 +834,11 @@
     optional int32 count_of_outgoing_sms = 14;
     optional int32 count_of_incoming_mms = 15;
     optional int32 count_of_outgoing_mms = 16;
+    repeated int32 supported_satellite_services = 17;
+    optional int32 service_data_policy = 18;
+    optional int64 satellite_data_consumed_bytes = 19;
+    optional bool is_multi_sim = 20;
+    optional bool is_nb_iot_ntn = 21;
 }
 
 message CarrierRoamingSatelliteControllerStats {
@@ -832,6 +851,9 @@
     optional int32 satellite_session_gap_max_sec = 7;
     optional int32 carrier_id = 8;
     optional bool is_device_entitled = 9;
+    optional bool is_multi_sim = 10;
+    optional int32 count_of_satellite_sessions = 11;
+    optional bool is_nb_iot_ntn = 12;
 }
 
 message SatelliteEntitlement {
@@ -840,6 +862,9 @@
     optional int32 entitlement_status = 3;
     optional bool is_retry = 4;
     optional int32 count = 5;
+    optional bool is_allowed_service_entitlement = 6;
+    repeated int32 entitlement_service_type = 7;
+    optional int32 entitlement_data_policy = 8;
 }
 
 message SatelliteConfigUpdater {
diff --git a/proto/src/telephony_config_update.proto b/proto/src/telephony_config_update.proto
index c193f35..83156ce 100644
--- a/proto/src/telephony_config_update.proto
+++ b/proto/src/telephony_config_update.proto
@@ -43,4 +43,5 @@
   optional bytes s2_cell_file = 1;
   repeated string country_codes = 2;
   optional bool is_allowed = 3;
-}
\ No newline at end of file
+  optional bytes satellite_access_config_file = 4;
+}
diff --git a/src/java/com/android/internal/telephony/CallManager.java b/src/java/com/android/internal/telephony/CallManager.java
index 9d19c17..26e107e 100644
--- a/src/java/com/android/internal/telephony/CallManager.java
+++ b/src/java/com/android/internal/telephony/CallManager.java
@@ -30,6 +30,8 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.imsphone.ImsPhoneConnection;
+import com.android.server.telecom.flags.FeatureFlags;
+import com.android.server.telecom.flags.FeatureFlagsImpl;
 import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
@@ -120,6 +122,7 @@
 
     private Object mRegistrantidentifier = new Object();
 
+    private FeatureFlags mTelecomFeatureFlags;
     // state registrants
     protected final RegistrantList mPreciseCallStateRegistrants
     = new RegistrantList();
@@ -196,6 +199,7 @@
         mBackgroundCalls = new ArrayList<Call>();
         mForegroundCalls = new ArrayList<Call>();
         mDefaultPhone = null;
+        mTelecomFeatureFlags = new FeatureFlagsImpl();
     }
 
     /**
@@ -2070,7 +2074,8 @@
                         incomingRejected = true;
                     }
                     if ((getActiveFgCallState(subId).isDialing() || hasMoreThanOneRingingCall())
-                            && (!incomingRejected)) {
+                            && (!incomingRejected)
+                            && !mTelecomFeatureFlags.enableCallSequencing()) {
                         try {
                             Rlog.d(LOG_TAG, "silently drop incoming call: " + c.getCall());
                             c.getCall().hangup();
diff --git a/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java b/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
index 6326d6c..2b426b8 100644
--- a/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
+++ b/src/java/com/android/internal/telephony/CarrierPrivilegesTracker.java
@@ -71,6 +71,7 @@
 import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.uicc.UiccPort;
 import com.android.internal.telephony.uicc.UiccProfile;
+import com.android.internal.telephony.util.WorkerThread;
 import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
@@ -369,48 +370,72 @@
 
         if (mFeatureFlags.asyncInitCarrierPrivilegesTracker()) {
             final Object localLock = new Object();
-            HandlerThread initializerThread =
-                    new HandlerThread("CarrierPrivilegesTracker Initializer") {
-                        @Override
-                        protected void onLooperPrepared() {
-                            synchronized (localLock) {
-                                localLock.notifyAll();
-                            }
+            if (mFeatureFlags.threadShred()) {
+                mCurrentHandler = new Handler(WorkerThread.get().getLooper()) {
+                    @Override
+                    public void handleMessage(Message msg) {
+                        switch(msg.what) {
+                            case ACTION_INITIALIZE_TRACKER:
+                                handleInitializeTracker();
+                                if (!hasMessagesOrCallbacks()) {
+                                    mCurrentHandler = CarrierPrivilegesTracker.this;
+                                }
+                                break;
+                            default:
+                                Message m = CarrierPrivilegesTracker.this.obtainMessage();
+                                m.copyFrom(msg);
+                                m.sendToTarget();
+                                if (!hasMessagesOrCallbacks()) {
+                                    mCurrentHandler = CarrierPrivilegesTracker.this;
+                                }
+                                break;
                         }
-                    };
-            synchronized (localLock) {
-                initializerThread.start();
-                while (true) {
-                    try {
-                        localLock.wait();
-                        break;
-                    } catch (InterruptedException ie) {
+                    }
+                };
+            } else {
+                HandlerThread initializerThread =
+                        new HandlerThread("CarrierPrivilegesTracker Initializer") {
+                            @Override
+                            protected void onLooperPrepared() {
+                                synchronized (localLock) {
+                                    localLock.notifyAll();
+                                }
+                            }
+                        };
+                synchronized (localLock) {
+                    initializerThread.start();
+                    while (true) {
+                        try {
+                            localLock.wait();
+                            break;
+                        } catch (InterruptedException ie) {
+                        }
                     }
                 }
+                mCurrentHandler = new Handler(initializerThread.getLooper()) {
+                    @Override
+                    public void handleMessage(Message msg) {
+                        switch(msg.what) {
+                            case ACTION_INITIALIZE_TRACKER:
+                                handleInitializeTracker();
+                                if (!hasMessagesOrCallbacks()) {
+                                    mCurrentHandler = CarrierPrivilegesTracker.this;
+                                    initializerThread.quitSafely();
+                                }
+                                break;
+                            default:
+                                Message m = CarrierPrivilegesTracker.this.obtainMessage();
+                                m.copyFrom(msg);
+                                m.sendToTarget();
+                                if (!hasMessagesOrCallbacks()) {
+                                    mCurrentHandler = CarrierPrivilegesTracker.this;
+                                    initializerThread.quitSafely();
+                                }
+                                break;
+                        }
+                    }
+                };
             }
-            mCurrentHandler = new Handler(initializerThread.getLooper()) {
-                @Override
-                public void handleMessage(Message msg) {
-                    switch(msg.what) {
-                        case ACTION_INITIALIZE_TRACKER:
-                            handleInitializeTracker();
-                            if (!hasMessagesOrCallbacks()) {
-                                mCurrentHandler = CarrierPrivilegesTracker.this;
-                                initializerThread.quitSafely();
-                            }
-                            break;
-                        default:
-                            Message m = CarrierPrivilegesTracker.this.obtainMessage();
-                            m.copyFrom(msg);
-                            m.sendToTarget();
-                            if (!hasMessagesOrCallbacks()) {
-                                mCurrentHandler = CarrierPrivilegesTracker.this;
-                                initializerThread.quitSafely();
-                            }
-                            break;
-                    }
-                }
-            };
         } else {
             mCurrentHandler = this;
         }
@@ -534,6 +559,9 @@
     private void handleSimStateChanged(int slotId, int simState) {
         if (slotId != mPhone.getPhoneId()) return;
 
+        // TODO(b/398737967): remove or silence down when diagnosed
+        Rlog.d(TAG, "handleSimStateChanged: slotId=" + slotId + " simState=" + simState);
+
         List<UiccAccessRule> updatedUiccRules = Collections.EMPTY_LIST;
 
         mPrivilegedPackageInfoLock.writeLock().lock();
@@ -545,7 +573,7 @@
 
         // Only include the UICC rules if the SIM is fully loaded
         if (simState == SIM_STATE_LOADED) {
-            mLocalLog.log("SIM fully loaded, handleUiccAccessRulesLoaded.");
+            Rlog.d(TAG, "handleSimStateChanged: SIM fully loaded.");
             handleUiccAccessRulesLoaded();
         } else {
             if (!mUiccRules.isEmpty()
@@ -554,12 +582,13 @@
                         SystemClock.uptimeMillis() + CLEAR_UICC_RULES_DELAY_MILLIS;
                 mCurrentHandler.sendMessageAtTime(obtainMessage(ACTION_CLEAR_UICC_RULES),
                         mClearUiccRulesUptimeMillis);
-                mLocalLog.log("SIM is gone, simState=" + TelephonyManager.simStateToString(simState)
+                Rlog.d(TAG, "handleSimStateChanged: SIM is gone, simState="
+                        + TelephonyManager.simStateToString(simState)
                         + ". Delay " + TimeUnit.MILLISECONDS.toSeconds(
                         CLEAR_UICC_RULES_DELAY_MILLIS) + " seconds to clear UICC rules.");
             } else {
-                mLocalLog.log(
-                        "Ignore SIM gone event while UiccRules is empty or waiting to be emptied.");
+                Rlog.d(TAG, "handleSimStateChanged: Ignore SIM gone event while"
+                        + " UiccRules is empty or waiting to be emptied.");
             }
         }
     }
diff --git a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
index 4f9d84d..300ebdf 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceBindHelper.java
@@ -40,6 +40,7 @@
 import android.service.carrier.CarrierService;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
 import android.text.TextUtils;
 import android.util.LocalLog;
 import android.util.Log;
@@ -335,7 +336,7 @@
             bindCount++;
             lastBindStartMillis = System.currentTimeMillis();
 
-            connection = new CarrierServiceConnection();
+            connection = new CarrierServiceConnection(getPhoneId());
 
             String error;
             try {
@@ -431,6 +432,11 @@
 
     private class CarrierServiceConnection implements ServiceConnection {
         private boolean connected;
+        private final int mPhoneId;
+
+        CarrierServiceConnection(int phoneId) {
+            mPhoneId = phoneId;
+        }
 
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
@@ -438,16 +444,38 @@
             connected = true;
         }
 
+        private void maybeDisableCarrierNetworkChangeNotification() {
+            int subscriptionId = SubscriptionManager.getSubscriptionId(mPhoneId);
+            // TODO(b/117525047): switch to phoneId-based solution when available in
+            // TelephonyRegistryManager to address SIM remove/disable case.
+            if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+                logdWithLocalLog(
+                        "No valid subscription found when trying to disable carrierNetworkChange"
+                                + " for phoneId: "
+                                + mPhoneId);
+                return;
+            }
+            TelephonyRegistryManager telephonyRegistryManager =
+                    mContext.getSystemService(TelephonyRegistryManager.class);
+            telephonyRegistryManager.notifyCarrierNetworkChange(subscriptionId, false);
+        }
+
         @Override
         public void onServiceDisconnected(ComponentName name) {
             logdWithLocalLog("Disconnected from carrier app: " + name.flattenToString());
             connected = false;
+            if (Flags.disableCarrierNetworkChangeOnCarrierAppLost()) {
+                maybeDisableCarrierNetworkChangeNotification();
+            }
         }
 
         @Override
         public void onBindingDied(ComponentName name) {
             logdWithLocalLog("Binding from carrier app died: " + name.flattenToString());
             connected = false;
+            if (Flags.disableCarrierNetworkChangeOnCarrierAppLost()) {
+                maybeDisableCarrierNetworkChangeNotification();
+            }
         }
 
         @Override
diff --git a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
index b470e2e..1e73fbb 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
@@ -714,14 +714,17 @@
          * add a button to the notification that has a broadcast intent embedded to silence the
          * notification
          */
-        private Notification.Action createDoNotShowAgainAction(Context context) {
+        private Notification.Action createDoNotShowAgainAction(Context c) {
             final PendingIntent pendingIntent = PendingIntent.getBroadcast(
-                    context,
+                    c,
                     0,
                     new Intent(ACTION_NEVER_ASK_AGAIN),
                     PendingIntent.FLAG_IMMUTABLE);
-            return new Notification.Action.Builder(null, "Do Not Show Again",
-                    pendingIntent).build();
+            CharSequence text = "Do Not Ask Again";
+            if (c != null && mFeatureFlags.dynamicDoNotAskAgainText()) {
+                text = c.getText(com.android.internal.R.string.emergency_calling_do_not_show_again);
+            }
+            return new Notification.Action.Builder(null, text, pendingIntent).build();
         }
     }
 
diff --git a/src/java/com/android/internal/telephony/CellBroadcastConfigTracker.java b/src/java/com/android/internal/telephony/CellBroadcastConfigTracker.java
index adb9904..6cc2d77 100644
--- a/src/java/com/android/internal/telephony/CellBroadcastConfigTracker.java
+++ b/src/java/com/android/internal/telephony/CellBroadcastConfigTracker.java
@@ -31,6 +31,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
+import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
@@ -192,7 +193,8 @@
                         // set gsm config if the config is changed
                         setGsmConfig(request.get3gppRanges(), request);
                         transitionTo(mGsmConfiguringState);
-                    } else if (!mCbRanges3gpp2.equals(request.get3gpp2Ranges())) {
+                    } else if (!Flags.cleanupCdma()
+                            && !mCbRanges3gpp2.equals(request.get3gpp2Ranges())) {
                         // set cdma config directly if no gsm config change but cdma config is
                         // changed
                         setCdmaConfig(request.get3gpp2Ranges(), request);
@@ -283,7 +285,8 @@
                     }
                     if (ar.exception == null) {
                         mCbRanges3gpp = request.get3gppRanges();
-                        if (!mCbRanges3gpp2.equals(request.get3gpp2Ranges())) {
+                        if (!Flags.cleanupCdma()
+                                && !mCbRanges3gpp2.equals(request.get3gpp2Ranges())) {
                             // set cdma config and transit to cdma configuring state if the config
                             // is changed.
                             setCdmaConfig(request.get3gpp2Ranges(), request);
diff --git a/src/java/com/android/internal/telephony/DeviceStateMonitor.java b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
index f572bf8..58d2f65 100644
--- a/src/java/com/android/internal/telephony/DeviceStateMonitor.java
+++ b/src/java/com/android/internal/telephony/DeviceStateMonitor.java
@@ -619,12 +619,10 @@
         }
 
         // Determine whether to notify registrants about the non-terrestrial signal strength change.
-        if (mFeatureFlags.oemEnabledSatelliteFlag()) {
-            if (shouldEnableSignalStrengthReports()) {
-                mSignalStrengthReportDecisionCallbackRegistrants.notifyResult(true);
-            } else {
-                mSignalStrengthReportDecisionCallbackRegistrants.notifyResult(false);
-            }
+        if (shouldEnableSignalStrengthReports()) {
+            mSignalStrengthReportDecisionCallbackRegistrants.notifyResult(true);
+        } else {
+            mSignalStrengthReportDecisionCallbackRegistrants.notifyResult(false);
         }
 
         if (mFeatureFlags.carrierRoamingNbIotNtn()) {
@@ -815,10 +813,6 @@
      * @param obj AsyncResult.userObj when the message is delivered
      */
     public void registerForSignalStrengthReportDecision(Handler h, int what, Object obj) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            Rlog.d(TAG, "oemEnabledSatelliteFlag is disabled");
-            return;
-        }
         Registrant r = new Registrant(h, what, obj);
         mSignalStrengthReportDecisionCallbackRegistrants.add(r);
     }
@@ -859,10 +853,6 @@
      * @param h Handler to notify
      */
     public void unregisterForSignalStrengthReportDecision(Handler h) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            Rlog.d(TAG, "oemEnabledSatelliteFlag is disabled");
-            return;
-        }
         mSignalStrengthReportDecisionCallbackRegistrants.remove(h);
     }
 
diff --git a/src/java/com/android/internal/telephony/DisplayInfoController.java b/src/java/com/android/internal/telephony/DisplayInfoController.java
index 57ea022..8521849 100644
--- a/src/java/com/android/internal/telephony/DisplayInfoController.java
+++ b/src/java/com/android/internal/telephony/DisplayInfoController.java
@@ -118,10 +118,8 @@
 
         // To Support Satellite bandwidth constrained data capability status at telephony
         // display info
-        if (mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            log("register for satellite network callback");
-            mNetworkTypeController.registerForSatelliteNetwork();
-        }
+        log("register for satellite network callback");
+        mNetworkTypeController.registerForSatelliteNetwork();
     }
 
     /**
@@ -166,8 +164,7 @@
      */
     private boolean isRoaming() {
         boolean roaming = mServiceState.getRoaming();
-        if (roaming && mFeatureFlags.hideRoamingIcon()
-                && !mConfigs.getBoolean(CarrierConfigManager.KEY_SHOW_ROAMING_INDICATOR_BOOL)) {
+        if (roaming && !mConfigs.getBoolean(CarrierConfigManager.KEY_SHOW_ROAMING_INDICATOR_BOOL)) {
             logl("Override roaming for display due to carrier configs.");
             roaming = false;
         }
diff --git a/src/java/com/android/internal/telephony/GbaManager.java b/src/java/com/android/internal/telephony/GbaManager.java
index 047d5d5..ec194db 100644
--- a/src/java/com/android/internal/telephony/GbaManager.java
+++ b/src/java/com/android/internal/telephony/GbaManager.java
@@ -39,7 +39,9 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.metrics.RcsStats;
+import com.android.internal.telephony.util.WorkerThread;
 import com.android.telephony.Rlog;
 
 import java.util.NoSuchElementException;
@@ -66,6 +68,8 @@
     public static final int REQUEST_TIMEOUT_MS = 5000;
     private final RcsStats mRcsStats;
 
+    private final FeatureFlags mFeatureFlags;
+
     private final String mLogTag;
     private final Context mContext;
     private final int mSubId;
@@ -202,7 +206,7 @@
 
     @VisibleForTesting
     public GbaManager(Context context, int subId, String servicePackageName, int releaseTime,
-            RcsStats rcsStats) {
+            RcsStats rcsStats, Looper looper, FeatureFlags featureFlags) {
         mContext = context;
         mSubId = subId;
         mLogTag = "GbaManager[" + subId + "]";
@@ -210,9 +214,15 @@
         mServicePackageName = servicePackageName;
         mReleaseTime = releaseTime;
 
-        HandlerThread headlerThread = new HandlerThread(mLogTag);
-        headlerThread.start();
-        mHandler = new GbaManagerHandler(headlerThread.getLooper());
+        mFeatureFlags = featureFlags;
+
+        if (mFeatureFlags.threadShred()) {
+            mHandler = new GbaManagerHandler(looper);
+        } else {
+            HandlerThread headlerThread = new HandlerThread(mLogTag);
+            headlerThread.start();
+            mHandler = new GbaManagerHandler(headlerThread.getLooper());
+        }
 
         if (mReleaseTime < 0) {
             mHandler.sendEmptyMessage(EVENT_BIND_SERVICE);
@@ -224,9 +234,15 @@
      * create a GbaManager instance for a sub
      */
     public static GbaManager make(Context context, int subId,
-            String servicePackageName, int releaseTime) {
-        GbaManager gm = new GbaManager(context, subId, servicePackageName, releaseTime,
-                RcsStats.getInstance());
+            String servicePackageName, int releaseTime, FeatureFlags featureFlags) {
+        GbaManager gm;
+        if (featureFlags.threadShred()) {
+            gm = new GbaManager(context, subId, servicePackageName, releaseTime,
+                    RcsStats.getInstance(), WorkerThread.get().getLooper(), featureFlags);
+        } else {
+            gm = new GbaManager(context, subId, servicePackageName, releaseTime,
+                    RcsStats.getInstance(), null, featureFlags);
+        }
         synchronized (sGbaManagers) {
             sGbaManagers.put(subId, gm);
         }
@@ -521,11 +537,15 @@
     @VisibleForTesting
     public void destroy() {
         mHandler.removeCallbacksAndMessages(null);
-        mHandler.getLooper().quit();
+        if (!mFeatureFlags.threadShred()) {
+            mHandler.getLooper().quit();
+        }
         mRequestQueue.clear();
         mCallbacks.clear();
         unbindService();
-        sGbaManagers.remove(mSubId);
+        synchronized (sGbaManagers) {
+            sGbaManagers.remove(mSubId);
+        }
     }
 
     private void logv(String msg) {
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index f190a43..f08e237 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -349,7 +349,6 @@
         super(precisePhoneType == PhoneConstants.PHONE_TYPE_GSM ? "GSM" : "CDMA",
                 notifier, context, ci, unitTestMode, phoneId, telephonyComponentFactory,
                 featureFlags);
-
         // phone type needs to be set before other initialization as other objects rely on it
         mPrecisePhoneType = precisePhoneType;
         mVoiceCallSessionStats = new VoiceCallSessionStats(mPhoneId, this, featureFlags);
@@ -370,7 +369,7 @@
                 SignalStrengthController.class.getName()).makeSignalStrengthController(this);
         mSST = mTelephonyComponentFactory.inject(ServiceStateTracker.class.getName())
                 .makeServiceStateTracker(this, this.mCi, featureFlags);
-        if (hasCalling()) {
+        if (hasCalling() || hasMessaging()) {
             mEmergencyNumberTracker = mTelephonyComponentFactory
                     .inject(EmergencyNumberTracker.class.getName()).makeEmergencyNumberTracker(
                             this, this.mCi, mFeatureFlags);
@@ -538,37 +537,30 @@
 
         mCi.registerForImeiMappingChanged(this, EVENT_IMEI_MAPPING_CHANGED, null);
 
-        if (mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()
-                || mFeatureFlags.enableModemCipherTransparencyUnsolEvents()) {
-            mSafetySource =
-                    mTelephonyComponentFactory.makeCellularNetworkSecuritySafetySource(mContext);
-        }
+        mSafetySource = mTelephonyComponentFactory
+                .makeCellularNetworkSecuritySafetySource(mContext);
 
-        if (mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()) {
-            logi(
-                    "enable_identifier_disclosure_transparency_unsol_events is on. Registering for "
-                            + "cellular identifier disclosures from phone "
-                            + getPhoneId());
-            mIdentifierDisclosureNotifier =
-                    mTelephonyComponentFactory
-                            .inject(CellularIdentifierDisclosureNotifier.class.getName())
-                            .makeIdentifierDisclosureNotifier(mSafetySource);
-            mCi.registerForCellularIdentifierDisclosures(
-                    this, EVENT_CELL_IDENTIFIER_DISCLOSURE, null);
-        }
+        logi(
+                "enable_identifier_disclosure_transparency_unsol_events is on. Registering for "
+                        + "cellular identifier disclosures from phone "
+                        + getPhoneId());
+        mIdentifierDisclosureNotifier =
+                mTelephonyComponentFactory
+                        .inject(CellularIdentifierDisclosureNotifier.class.getName())
+                        .makeIdentifierDisclosureNotifier(mSafetySource);
+        mCi.registerForCellularIdentifierDisclosures(
+                this, EVENT_CELL_IDENTIFIER_DISCLOSURE, null);
 
-        if (mFeatureFlags.enableModemCipherTransparencyUnsolEvents()) {
-            logi(
-                    "enable_modem_cipher_transparency_unsol_events is on. Registering for security "
-                            + "algorithm updates from phone "
-                            + getPhoneId());
-            mNullCipherNotifier =
-                    mTelephonyComponentFactory
-                            .inject(NullCipherNotifier.class.getName())
-                            .makeNullCipherNotifier(mSafetySource);
-            mCi.registerForSecurityAlgorithmUpdates(
-                    this, EVENT_SECURITY_ALGORITHM_UPDATE, null);
-        }
+        logi(
+                "enable_modem_cipher_transparency_unsol_events is on. Registering for security "
+                        + "algorithm updates from phone "
+                        + getPhoneId());
+        mNullCipherNotifier =
+                mTelephonyComponentFactory
+                        .inject(NullCipherNotifier.class.getName())
+                        .makeNullCipherNotifier(mSafetySource);
+        mCi.registerForSecurityAlgorithmUpdates(
+                this, EVENT_SECURITY_ALGORITHM_UPDATE, null);
 
         initializeCarrierApps();
     }
@@ -1711,9 +1703,16 @@
         String newDialString = PhoneNumberUtils.stripSeparators(dialString);
 
         if (isPhoneTypeGsm()) {
-            // handle in-call MMI first if applicable
-            if (handleInCallMmiCommands(newDialString)) {
-                return null;
+            if (mFeatureFlags.skipMmiCodeCheckForEmergencyCall()) {
+                // If not emergency number, handle in-call MMI first if applicable
+                if (!dialArgs.isEmergency && handleInCallMmiCommands(newDialString)) {
+                    return null;
+                }
+            } else {
+                // handle in-call MMI first if applicable
+                if (handleInCallMmiCommands(newDialString)) {
+                    return null;
+                }
             }
 
             // Only look at the Network portion for mmi
@@ -2463,24 +2462,20 @@
      */
     @Override
     public void setN1ModeEnabled(boolean enable, @Nullable Message result) {
-        if (mFeatureFlags.enableCarrierConfigN1ControlAttempt2()) {
-            // This might be called by IMS on another thread, so to avoid the requirement to
-            // lock, post it through the handler.
-            post(() -> {
-                if (enable) {
-                    mN1ModeDisallowedReasons.remove(N1_MODE_DISALLOWED_REASON_IMS);
-                } else {
-                    mN1ModeDisallowedReasons.add(N1_MODE_DISALLOWED_REASON_IMS);
-                }
-                if (mModemN1Mode == null) {
-                    mCi.isN1ModeEnabled(obtainMessage(EVENT_GET_N1_MODE_ENABLED_DONE, result));
-                } else {
-                    maybeUpdateModemN1Mode(result);
-                }
-            });
-        } else {
-            super.setN1ModeEnabled(enable, result);
-        }
+        // This might be called by IMS on another thread, so to avoid the requirement to
+        // lock, post it through the handler.
+        post(() -> {
+            if (enable) {
+                mN1ModeDisallowedReasons.remove(N1_MODE_DISALLOWED_REASON_IMS);
+            } else {
+                mN1ModeDisallowedReasons.add(N1_MODE_DISALLOWED_REASON_IMS);
+            }
+            if (mModemN1Mode == null) {
+                mCi.isN1ModeEnabled(obtainMessage(EVENT_GET_N1_MODE_ENABLED_DONE, result));
+            } else {
+                maybeUpdateModemN1Mode(result);
+            }
+        });
     }
 
     /** Only called on the handler thread. */
@@ -2504,8 +2499,6 @@
 
     /** Only called on the handler thread. */
     private void updateCarrierN1ModeSupported(@NonNull PersistableBundle b) {
-        if (!mFeatureFlags.enableCarrierConfigN1ControlAttempt2()) return;
-
         if (!CarrierConfigManager.isConfigForIdentifiedCarrier(b)) return;
 
         final int[] supportedNrModes = b.getIntArray(
@@ -3771,8 +3764,7 @@
                 }
 
                 CellularIdentifierDisclosure disclosure = (CellularIdentifierDisclosure) ar.result;
-                if (mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()
-                        && mIdentifierDisclosureNotifier != null
+                if (mIdentifierDisclosureNotifier != null
                         && disclosure != null) {
                     mIdentifierDisclosureNotifier.addDisclosure(mContext, getSubId(), disclosure);
                 }
@@ -3797,8 +3789,7 @@
                 ar = (AsyncResult) msg.obj;
                 SecurityAlgorithmUpdate update = (SecurityAlgorithmUpdate) ar.result;
 
-                if (mFeatureFlags.enableModemCipherTransparencyUnsolEvents()
-                        && mNullCipherNotifier != null) {
+                if (mNullCipherNotifier != null) {
                     mNullCipherNotifier.onSecurityAlgorithmUpdate(mContext, getPhoneId(),
                             getSubId(), update);
                 }
@@ -4578,6 +4569,10 @@
 
     protected void phoneObjectUpdater(int newVoiceRadioTech) {
         logd("phoneObjectUpdater: newVoiceRadioTech=" + newVoiceRadioTech);
+        if (mFeatureFlags.phoneTypeCleanup()) {
+            logd("phoneObjectUpdater: no-op as CDMA cleanup flag is set");
+            return;
+        }
 
         // Check for a voice over LTE/NR replacement
         if (ServiceState.isPsOnlyTech(newVoiceRadioTech)
@@ -5137,6 +5132,7 @@
     }
 
     public int getLteOnCdmaMode() {
+        if (mFeatureFlags.phoneTypeCleanup()) return PhoneConstants.LTE_ON_CDMA_FALSE;
         int currentConfig = TelephonyProperties.lte_on_cdma_device()
                 .orElse(PhoneConstants.LTE_ON_CDMA_FALSE);
         int lteOnCdmaModeDynamicValue = currentConfig;
@@ -5429,25 +5425,15 @@
 
     @Override
     public void handleIdentifierDisclosureNotificationPreferenceChange() {
-        if (!mFeatureFlags.enableIdentifierDisclosureTransparency()) {
-            logi("Not handling identifier disclosure preference change. Feature flag "
-                    + "enable_identifier_disclosure_transparency disabled");
-            return;
-        }
         boolean prefEnabled = getIdentifierDisclosureNotificationsPreferenceEnabled();
 
         // The notifier is tied to handling unsolicited updates from the modem, not the
         // enable/disable API, so we only toggle the enable state if the unsol events feature
         // flag is enabled.
-        if (mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()) {
-            if (prefEnabled) {
-                mIdentifierDisclosureNotifier.enable(mContext);
-            } else {
-                mIdentifierDisclosureNotifier.disable(mContext);
-            }
+        if (prefEnabled) {
+            mIdentifierDisclosureNotifier.enable(mContext);
         } else {
-            logi("Not toggling enable state for disclosure notifier. Feature flag "
-                    + "enable_identifier_disclosure_transparency_unsol_events is disabled");
+            mIdentifierDisclosureNotifier.disable(mContext);
         }
 
         mCi.setCellularIdentifierTransparencyEnabled(prefEnabled,
@@ -5456,25 +5442,14 @@
 
     @Override
     public void handleNullCipherNotificationPreferenceChanged() {
-        if (!mFeatureFlags.enableModemCipherTransparency()) {
-            logi("Not handling null cipher notification preference change. Feature flag "
-                    + "enable_modem_cipher_transparency disabled");
-            return;
-        }
         boolean prefEnabled = getNullCipherNotificationsPreferenceEnabled();
 
         // The notifier is tied to handling unsolicited updates from the modem, not the
         // enable/disable API.
-        if (mFeatureFlags.enableModemCipherTransparencyUnsolEvents()) {
-            if (prefEnabled) {
-                mNullCipherNotifier.enable(mContext);
-            } else {
-                mNullCipherNotifier.disable(mContext);
-            }
+        if (prefEnabled) {
+            mNullCipherNotifier.enable(mContext);
         } else {
-            logi(
-                    "Not toggling enable state for cipher notifier. Feature flag "
-                            + "enable_modem_cipher_transparency_unsol_events is disabled.");
+            mNullCipherNotifier.disable(mContext);
         }
 
         mCi.setSecurityAlgorithmsUpdatedEnabled(prefEnabled,
@@ -5486,10 +5461,6 @@
      */
     @VisibleForTesting
     public void updateNullCipherNotifier() {
-        if (!mFeatureFlags.enableModemCipherTransparencyUnsolEvents()) {
-            return;
-        }
-
         SubscriptionInfoInternal subInfo = mSubscriptionManagerService
                 .getSubscriptionInfoInternal(getSubId());
         boolean active = false;
@@ -5517,10 +5488,7 @@
 
     @Override
     public void refreshSafetySources(String refreshBroadcastId) {
-        if (mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()
-                || mFeatureFlags.enableModemCipherTransparencyUnsolEvents()) {
-            post(() -> mSafetySource.refresh(mContext, refreshBroadcastId));
-        }
+        post(() -> mSafetySource.refresh(mContext, refreshBroadcastId));
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
index 9eebc60..4a3e7b0 100644
--- a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -950,14 +950,6 @@
         return (boolean) setRequest.mResult;
     }
 
-    public boolean enableCellBroadcast(int messageIdentifier, int ranType) {
-        return enableCellBroadcastRange(messageIdentifier, messageIdentifier, ranType);
-    }
-
-    public boolean disableCellBroadcast(int messageIdentifier, int ranType) {
-        return disableCellBroadcastRange(messageIdentifier, messageIdentifier, ranType);
-    }
-
     public boolean enableCellBroadcastRange(int startMessageId, int endMessageId, int ranType) {
         mContext.enforceCallingPermission(android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST,
                 "enabling cell broadcast range [" + startMessageId + "-" + endMessageId + "]. "
diff --git a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
index 6955a55..76b3a17 100644
--- a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
+++ b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
@@ -248,7 +248,8 @@
                         tracker.mMessageId,
                         tracker.isFromDefaultSmsApplication(mContext),
                         tracker.getInterval(),
-                        mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
+                        mTelephonyManager.isEmergencyNumber(tracker.mDestAddress),
+                        tracker.isMtSmsPollingMessage(mContext));
                 if (mPhone != null) {
                     TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
                     if (telephonyAnalytics != null) {
@@ -666,7 +667,8 @@
                     tracker.mMessageId,
                     tracker.isFromDefaultSmsApplication(mContext),
                     tracker.getInterval(),
-                    mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
+                    mTelephonyManager.isEmergencyNumber(tracker.mDestAddress),
+                    tracker.isMtSmsPollingMessage(mContext));
             if (mPhone != null) {
                 TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
                 if (telephonyAnalytics != null) {
diff --git a/src/java/com/android/internal/telephony/LocaleTracker.java b/src/java/com/android/internal/telephony/LocaleTracker.java
index 42ec8d3..59a8885 100644
--- a/src/java/com/android/internal/telephony/LocaleTracker.java
+++ b/src/java/com/android/internal/telephony/LocaleTracker.java
@@ -565,10 +565,9 @@
                 TelephonyProperties.operator_iso_country(newProp);
             }
 
-            if (mFeatureFlags.oemEnabledSatelliteFlag()) {
-                TelephonyCountryDetector.getInstance(mPhone.getContext(), mFeatureFlags)
-                        .onNetworkCountryCodeChanged(mPhone, countryIso);
-            }
+            TelephonyCountryDetector.getInstance(mPhone.getContext(), mFeatureFlags)
+                    .onNetworkCountryCodeChanged(mPhone, countryIso);
+
             Intent intent = new Intent(TelephonyManager.ACTION_NETWORK_COUNTRY_CHANGED);
             intent.putExtra(TelephonyManager.EXTRA_NETWORK_COUNTRY, countryIso);
             intent.putExtra(TelephonyManager.EXTRA_LAST_KNOWN_NETWORK_COUNTRY,
diff --git a/src/java/com/android/internal/telephony/MccTable.java b/src/java/com/android/internal/telephony/MccTable.java
index b36a19e..211c88b 100644
--- a/src/java/com/android/internal/telephony/MccTable.java
+++ b/src/java/com/android/internal/telephony/MccTable.java
@@ -24,6 +24,7 @@
 import android.os.Build;
 import android.os.SystemProperties;
 import android.text.TextUtils;
+import android.timezone.MobileCountries;
 import android.timezone.TelephonyLookup;
 import android.timezone.TelephonyNetwork;
 import android.timezone.TelephonyNetworkFinder;
@@ -36,6 +37,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
@@ -53,12 +55,18 @@
 
     static ArrayList<MccEntry> sTable;
 
+    @VisibleForTesting
+    public static List<MccEntry> getAllMccEntries() {
+        return new ArrayList<>(sTable);
+    }
+
     /**
      * Container class for mcc and iso. This class implements compareTo so that it can be sorted
      * by mcc.
      */
     public static class MccEntry implements Comparable<MccEntry> {
-        final int mMcc;
+        @VisibleForTesting
+        public final int mMcc;
         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q,
                 publicAlternatives = "There is no alternative for {@code MccTable.MccEntry.mIso}, "
                         + "but it was included in hidden APIs due to a static analysis false "
@@ -87,7 +95,6 @@
      *
      * @hide
      */
-    @VisibleForTesting
     public static class MccMnc {
         @NonNull
         public final String mcc;
@@ -174,29 +181,46 @@
      * Given a GSM Mobile Country Code, returns a lower-case ISO 3166 alpha-2 country code if
      * available. Returns empty string if unavailable.
      */
-    @UnsupportedAppUsage
-    @NonNull
-    public static String countryCodeForMcc(int mcc) {
-        MccEntry entry = entryForMcc(mcc);
-
-        if (entry == null) {
-            return "";
-        } else {
-            return entry.mIso;
-        }
-    }
-
-    /**
-     * Given a GSM Mobile Country Code, returns a lower-case ISO 3166 alpha-2 country code if
-     * available. Returns empty string if unavailable.
-     */
     @NonNull
     public static String countryCodeForMcc(@NonNull String mcc) {
-        try {
-            return countryCodeForMcc(Integer.parseInt(mcc));
-        } catch (NumberFormatException ex) {
+        if (mcc == null) {
             return "";
         }
+
+        if (!isNewMccTableEnabled()) {
+            try {
+                MccEntry entry = entryForMcc(Integer.parseInt(mcc));
+
+                if (entry == null) {
+                    return "";
+                } else {
+                    return entry.mIso;
+                }
+            } catch (NumberFormatException ex) {
+                return "";
+            }
+        }
+
+        TelephonyNetworkFinder telephonyNetworkFinder;
+
+        synchronized (MccTable.class) {
+            if ((telephonyNetworkFinder = sTelephonyNetworkFinder) == null) {
+                sTelephonyNetworkFinder = telephonyNetworkFinder =
+                        TelephonyLookup.getInstance().getTelephonyNetworkFinder();
+            }
+        }
+
+        if (telephonyNetworkFinder == null) {
+            // This should not happen under normal circumstances, only when the data is missing.
+            return "";
+        }
+
+        MobileCountries mobileCountries = telephonyNetworkFinder.findCountriesByMcc(mcc);
+        if (mobileCountries == null) {
+            return "";
+        }
+
+        return mobileCountries.getDefaultCountryIsoCode();
     }
 
     /**
@@ -209,7 +233,7 @@
      * help distinguish, or the MCC assigned to a country isn't used for geopolitical reasons.
      * When the geographical country is needed  (e.g. time zone detection) this version can provide
      * more pragmatic results than the official MCC-only answer. This method falls back to calling
-     * {@link #countryCodeForMcc(int)} if no special MCC+MNC cases are found.
+     * {@link #countryCodeForMcc(String)} if no special MCC+MNC cases are found.
      * Returns empty string if no code can be determined.
      */
     @NonNull
@@ -220,7 +244,7 @@
         }
         if (TextUtils.isEmpty(countryCode)) {
             // Try the MCC-only fallback.
-            countryCode = MccTable.countryCodeForMcc(mccMnc.mcc);
+            countryCode = countryCodeForMcc(mccMnc.mcc);
         }
         return countryCode;
     }
@@ -244,7 +268,6 @@
         return network.getCountryIsoCode();
     }
 
-
     /**
      * Given a GSM Mobile Country Code, returns
      * the smallest number of digits that M if available.
@@ -312,6 +335,11 @@
      */
     public static final Map<Locale, Locale> FALLBACKS = new HashMap<Locale, Locale>();
 
+    public static boolean isNewMccTableEnabled() {
+        return com.android.icu.Flags.telephonyLookupMccExtension()
+                && com.android.internal.telephony.flags.Flags.useI18nForMccMapping();
+    }
+
     static {
         // If we have English (without a country) explicitly prioritize en_US. http://b/28998094
         FALLBACKS.put(Locale.ENGLISH, Locale.US);
diff --git a/src/java/com/android/internal/telephony/MultiSimSettingController.java b/src/java/com/android/internal/telephony/MultiSimSettingController.java
index 881adde..bdde74d 100644
--- a/src/java/com/android/internal/telephony/MultiSimSettingController.java
+++ b/src/java/com/android/internal/telephony/MultiSimSettingController.java
@@ -648,10 +648,7 @@
         // Otherwise, if user just inserted their first SIM, or there's one primary and one
         // opportunistic subscription active (activeSubInfos.size() > 1), we automatically
         // set the primary to be default SIM and return.
-        boolean conditionForOnePrimarySim =
-                mFeatureFlags.resetPrimarySimDefaultValues() ? mPrimarySubList.size() == 1
-                        : mPrimarySubList.size() == 1
-                        && (change != PRIMARY_SUB_REMOVED || mActiveModemCount == 1);
+        boolean conditionForOnePrimarySim = mPrimarySubList.size() == 1;
         if (conditionForOnePrimarySim) {
             int subId = mPrimarySubList.get(0);
             if (DBG) log("updateDefaultValues: to only primary sub " + subId);
diff --git a/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java b/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
index 9b2b847..039b77a 100644
--- a/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
+++ b/src/java/com/android/internal/telephony/NetworkScanRequestTracker.java
@@ -79,13 +79,16 @@
         @Override
         public void handleMessage(Message msg) {
             Log.d(TAG, "Received Event :" + msg.what);
+            AsyncResult ar;
             switch (msg.what) {
                 case CMD_START_NETWORK_SCAN:
                     mScheduler.doStartScan((NetworkScanRequestInfo) msg.obj);
                     break;
 
                 case EVENT_START_NETWORK_SCAN_DONE:
-                    mScheduler.startScanDone((AsyncResult) msg.obj);
+                    ar = (AsyncResult) msg.obj;
+                    mScheduler.startScanDone(ar);
+                    ((NetworkScanRequestInfo) ar.userObj).mPhone.setNetworkScanStarted(true);
                     break;
 
                 case EVENT_RECEIVE_NETWORK_SCAN_RESULT:
@@ -97,7 +100,9 @@
                     break;
 
                 case EVENT_STOP_NETWORK_SCAN_DONE:
-                    mScheduler.stopScanDone((AsyncResult) msg.obj);
+                    ar = (AsyncResult) msg.obj;
+                    mScheduler.stopScanDone(ar);
+                    ((NetworkScanRequestInfo) ar.userObj).mPhone.setNetworkScanStarted(false);
                     break;
 
                 case CMD_INTERRUPT_NETWORK_SCAN:
@@ -105,17 +110,20 @@
                     break;
 
                 case EVENT_INTERRUPT_NETWORK_SCAN_DONE:
-                    mScheduler.interruptScanDone((AsyncResult) msg.obj);
+                    ar = (AsyncResult) msg.obj;
+                    mScheduler.interruptScanDone(ar);
+                    ((NetworkScanRequestInfo) ar.userObj).mPhone.setNetworkScanStarted(false);
                     break;
 
                 case EVENT_RADIO_UNAVAILABLE:
                     // Fallthrough
                 case EVENT_MODEM_RESET:
-                    AsyncResult ar = (AsyncResult) msg.obj;
+                    ar = (AsyncResult) msg.obj;
                     mScheduler.deleteScanAndMayNotify(
                             (NetworkScanRequestInfo) ar.userObj,
                             NetworkScan.ERROR_MODEM_ERROR,
                             true);
+                    ((NetworkScanRequestInfo) ar.userObj).mPhone.setNetworkScanStarted(false);
                     break;
             }
         }
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index 82e0c6e..f05e002 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -213,8 +213,8 @@
     @NonNull private final Set<Integer> mAdditionalNrAdvancedBands = new HashSet<>();
     @NonNull private String mPrimaryTimerState;
     @NonNull private String mSecondaryTimerState;
-    // TODO(b/316425811 remove the workaround)
     private int mNrAdvancedBandsSecondaryTimer;
+    private int mNrAdvancedPciChangeSecondaryTimer;
     @NonNull private String mPreviousState;
     @LinkStatus private int mPhysicalLinkStatus;
     private boolean mIsPhysicalChannelConfig16Supported;
@@ -224,6 +224,7 @@
     private boolean mEnableNrAdvancedWhileRoaming = true;
     private boolean mIsDeviceIdleMode = false;
     private boolean mPrimaryCellChangedWhileIdle = false;
+    private boolean mPciChangedDuringPrimaryTimer = false;
 
     // Cached copies below to prevent race conditions
     @NonNull private ServiceState mServiceState;
@@ -485,6 +486,8 @@
                 CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL);
         mNrAdvancedBandsSecondaryTimer = config.getInt(
                 CarrierConfigManager.KEY_NR_ADVANCED_BANDS_SECONDARY_TIMER_SECONDS_INT);
+        mNrAdvancedPciChangeSecondaryTimer = config.getInt(
+                CarrierConfigManager.KEY_NR_ADVANCED_PCI_CHANGE_SECONDARY_TIMER_SECONDS_INT);
         String nrIconConfiguration = config.getString(
                 CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
         String overrideTimerRule = config.getString(
@@ -509,9 +512,6 @@
                     if (DBG) loge("Invalid 5G icon configuration, config = " + pair);
                     continue;
                 }
-                if (!mFeatureFlags.supportNrSaRrcIdle() && kv[0].equals(STATE_CONNECTED_RRC_IDLE)) {
-                    continue;
-                }
                 int icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
                 if (kv[1].equals(ICON_5G)) {
                     icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
@@ -539,9 +539,6 @@
                     if (DBG) loge("Invalid 5G icon timer configuration, config = " + triple);
                     continue;
                 }
-                if (!mFeatureFlags.supportNrSaRrcIdle() && kv[0].equals(STATE_CONNECTED_RRC_IDLE)) {
-                    continue;
-                }
                 int duration;
                 try {
                     duration = Integer.parseInt(kv[2]);
@@ -550,10 +547,6 @@
                 }
                 if (kv[0].equals(STATE_ANY)) {
                     for (String state : ALL_STATES) {
-                        if (!mFeatureFlags.supportNrSaRrcIdle()
-                                && state.equals(STATE_CONNECTED_RRC_IDLE)) {
-                            continue;
-                        }
                         OverrideTimerRule node = tempRules.get(state);
                         node.addTimer(kv[1], duration);
                     }
@@ -574,9 +567,6 @@
                     }
                     continue;
                 }
-                if (kv[0].equals(STATE_CONNECTED_RRC_IDLE) && !mFeatureFlags.supportNrSaRrcIdle()) {
-                    continue;
-                }
                 int duration;
                 try {
                     duration = Integer.parseInt(kv[2]);
@@ -585,10 +575,6 @@
                 }
                 if (kv[0].equals(STATE_ANY)) {
                     for (String state : ALL_STATES) {
-                        if (state.equals(STATE_CONNECTED_RRC_IDLE)
-                                && !mFeatureFlags.supportNrSaRrcIdle()) {
-                            continue;
-                        }
                         OverrideTimerRule node = tempRules.get(state);
                         node.addSecondaryTimer(kv[1], duration);
                     }
@@ -601,19 +587,17 @@
 
         // TODO: Remove this workaround to make STATE_CONNECTED_RRC_IDLE backwards compatible with
         //  STATE_CONNECTED once carrier configs are updated.
-        if (mFeatureFlags.supportNrSaRrcIdle()) {
-            OverrideTimerRule nrRules = tempRules.get(STATE_CONNECTED);
-            if (!tempRules.get(STATE_CONNECTED_RRC_IDLE).isDefined() && nrRules.isDefined()) {
-                OverrideTimerRule nrIdleRules =
-                        new OverrideTimerRule(STATE_CONNECTED_RRC_IDLE, nrRules.mOverrideType);
-                for (Map.Entry<String, Integer> entry : nrIdleRules.mPrimaryTimers.entrySet()) {
-                    nrIdleRules.addTimer(entry.getKey(), entry.getValue());
-                }
-                for (Map.Entry<String, Integer> entry : nrIdleRules.mSecondaryTimers.entrySet()) {
-                    nrIdleRules.addSecondaryTimer(entry.getKey(), entry.getValue());
-                }
-                tempRules.put(STATE_CONNECTED_RRC_IDLE, nrIdleRules);
+        OverrideTimerRule nrRules = tempRules.get(STATE_CONNECTED);
+        if (!tempRules.get(STATE_CONNECTED_RRC_IDLE).isDefined() && nrRules.isDefined()) {
+            OverrideTimerRule nrIdleRules =
+                    new OverrideTimerRule(STATE_CONNECTED_RRC_IDLE, nrRules.mOverrideType);
+            for (Map.Entry<String, Integer> entry : nrIdleRules.mPrimaryTimers.entrySet()) {
+                nrIdleRules.addTimer(entry.getKey(), entry.getValue());
             }
+            for (Map.Entry<String, Integer> entry : nrIdleRules.mSecondaryTimers.entrySet()) {
+                nrIdleRules.addSecondaryTimer(entry.getKey(), entry.getValue());
+            }
+            tempRules.put(STATE_CONNECTED_RRC_IDLE, nrIdleRules);
         }
 
         mOverrideTimerRules = tempRules;
@@ -795,6 +779,8 @@
                     mRatchetedNrBandwidths = 0;
                     mLastAnchorNrCellId = PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN;
                     mDoesPccListIndicateIdle = false;
+                    mIsNrAdvancedAllowedByPco = false;
+                    mInVoiceCall = false;
                     mPhysicalChannelConfigs = null;
                     transitionTo(mLegacyState);
                     break;
@@ -888,7 +874,6 @@
                             transitionTo(mNrConnectedAdvancedState);
                         } else {
                             transitionTo(isPhysicalLinkActive()
-                                    || !mFeatureFlags.supportNrSaRrcIdle()
                                     ? mNrConnectedState : mNrIdleState);
                         }
                     } else if (isLte(rat) && isNrNotRestricted()) {
@@ -971,7 +956,6 @@
                             transitionTo(mNrConnectedAdvancedState);
                         } else {
                             transitionTo(isPhysicalLinkActive()
-                                    || !mFeatureFlags.supportNrSaRrcIdle()
                                     ? mNrConnectedState : mNrIdleState);
                         }
                     } else if (!isLte(rat) || !isNrNotRestricted()) {
@@ -1055,7 +1039,6 @@
                             transitionTo(mNrConnectedAdvancedState);
                         } else {
                             transitionTo(isPhysicalLinkActive()
-                                    || !mFeatureFlags.supportNrSaRrcIdle()
                                     ? mNrConnectedState : mNrIdleState);
                         }
                     } else if (!isLte(rat) || !isNrNotRestricted()) {
@@ -1187,7 +1170,7 @@
 
         @Override
         public String getName() {
-            return mFeatureFlags.supportNrSaRrcIdle() ? STATE_CONNECTED_RRC_IDLE : STATE_CONNECTED;
+            return STATE_CONNECTED_RRC_IDLE;
         }
     }
 
@@ -1222,7 +1205,7 @@
                             || (isLte(rat) && isNrConnected())) {
                         if (isNrAdvanced()) {
                             transitionTo(mNrConnectedAdvancedState);
-                        } else if (!isPhysicalLinkActive() && mFeatureFlags.supportNrSaRrcIdle()) {
+                        } else if (!isPhysicalLinkActive()) {
                             transitionWithTimerTo(mNrIdleState);
                         } else {
                             // Update in case the override network type changed
@@ -1241,7 +1224,7 @@
                     if (isUsingPhysicalChannelConfigForRrcDetection()) {
                         mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig();
                     }
-                    if (!isPhysicalLinkActive() && mFeatureFlags.supportNrSaRrcIdle()) {
+                    if (!isPhysicalLinkActive()) {
                         transitionWithTimerTo(mNrIdleState);
                     } else if (isNrAdvanced()) {
                         transitionTo(mNrConnectedAdvancedState);
@@ -1249,7 +1232,7 @@
                     break;
                 case EVENT_PHYSICAL_LINK_STATUS_CHANGED:
                     mPhysicalLinkStatus = msg.arg1;
-                    if (!isPhysicalLinkActive() && mFeatureFlags.supportNrSaRrcIdle()) {
+                    if (!isPhysicalLinkActive()) {
                         transitionWithTimerTo(mNrIdleState);
                     }
                     break;
@@ -1314,7 +1297,6 @@
                                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
                             }
                             transitionWithTimerTo(isPhysicalLinkActive()
-                                    || !mFeatureFlags.supportNrSaRrcIdle()
                                     ? mNrConnectedState : mNrIdleState);
                         }
                     } else if (isLte(rat) && isNrNotRestricted()) {
@@ -1330,7 +1312,7 @@
                     if (isUsingPhysicalChannelConfigForRrcDetection()) {
                         mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig();
                     }
-                    if (!isPhysicalLinkActive() && mFeatureFlags.supportNrSaRrcIdle()) {
+                    if (!isPhysicalLinkActive()) {
                         transitionWithTimerTo(mNrIdleState);
                     } else if (!isNrAdvanced()) {
                         transitionWithTimerTo(mNrConnectedState);
@@ -1425,7 +1407,9 @@
             mRatchetedNrBandwidths = Math.max(mRatchetedNrBandwidths, nrBandwidths);
             mRatchetedNrBands.addAll(nrBands);
         } else {
-            if (mFeatureFlags.supportNrSaRrcIdle() && mDoesPccListIndicateIdle
+            mRatchetedNrBandwidths = nrBandwidths;
+            mRatchetedNrBands = nrBands;
+            if (mDoesPccListIndicateIdle
                     && anchorNrCellId != mLastAnchorNrCellId
                     && isUsingPhysicalChannelConfigForRrcDetection()
                     && !mPrimaryCellChangedWhileIdle
@@ -1441,13 +1425,12 @@
                 log("Not ratcheting physical channel config fields since anchor NR cell changed: "
                         + mLastAnchorNrCellId + " -> " + anchorNrCellId);
             }
-            mRatchetedNrBandwidths = nrBandwidths;
-            mRatchetedNrBands = nrBands;
         }
 
         mLastAnchorNrCellId = anchorNrCellId;
         mPhysicalChannelConfigs = physicalChannelConfigs;
         mDoesPccListIndicateIdle = false;
+        mPciChangedDuringPrimaryTimer = mIsPrimaryTimerActive;
         if (DBG) {
             log("Physical channel configs updated: anchorNrCell=" + mLastAnchorNrCellId
                     + ", nrBandwidths=" + mRatchetedNrBandwidths + ", nrBands=" +  mRatchetedNrBands
@@ -1505,6 +1488,7 @@
     private void transitionWithSecondaryTimerTo(IState destState) {
         String currentName = getCurrentState().getName();
         OverrideTimerRule rule = mOverrideTimerRules.get(mPrimaryTimerState);
+        int duration = -1;
         if (DBG) {
             log("Transition with secondary timer from " + currentName + " to "
                     + destState.getName());
@@ -1513,12 +1497,19 @@
             log("Skip secondary timer from " + currentName + " to "
                     + destState.getName() + " due to in call");
         } else if (!mIsDeviceIdleMode && rule != null && rule.getSecondaryTimer(currentName) > 0) {
-            int duration = rule.getSecondaryTimer(currentName);
+            duration = rule.getSecondaryTimer(currentName);
             if (mLastShownNrDueToAdvancedBand && mNrAdvancedBandsSecondaryTimer > 0) {
                 duration = mNrAdvancedBandsSecondaryTimer;
                 if (DBG) log("timer adjusted by nr_advanced_bands_secondary_timer_seconds_int");
             }
             if (DBG) log(duration + "s secondary timer started for state: " + currentName);
+        } else if (mNrAdvancedPciChangeSecondaryTimer > 0
+                && mPciChangedDuringPrimaryTimer) {
+            duration = mNrAdvancedPciChangeSecondaryTimer;
+            if (DBG) log(duration + "s secondary timer started for PCI changed");
+        }
+
+        if (duration > 0) {
             mSecondaryTimerState = currentName;
             mPreviousState = currentName;
             mIsSecondaryTimerActive = true;
@@ -1526,7 +1517,9 @@
             mSecondaryTimerExpireTimestamp = SystemClock.uptimeMillis() + durationMillis;
             sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, destState, durationMillis);
         }
+
         mIsPrimaryTimerActive = false;
+        mPciChangedDuringPrimaryTimer = false;
         transitionTo(getCurrentState());
     }
 
@@ -1534,7 +1527,7 @@
         int dataRat = getDataNetworkType();
         IState transitionState;
         if (dataRat == TelephonyManager.NETWORK_TYPE_NR || (isLte(dataRat) && isNrConnected())) {
-            if (!isPhysicalLinkActive() && mFeatureFlags.supportNrSaRrcIdle()) {
+            if (!isPhysicalLinkActive()) {
                 transitionState = mNrIdleState;
             } else if (isNrAdvanced()) {
                 transitionState = mNrConnectedAdvancedState;
@@ -1576,6 +1569,7 @@
             }
             removeMessages(EVENT_PRIMARY_TIMER_EXPIRED);
             mIsPrimaryTimerActive = false;
+            mPciChangedDuringPrimaryTimer = false;
             mPrimaryTimerState = "";
             transitionToCurrentState();
             return;
@@ -1619,6 +1613,7 @@
         removeMessages(EVENT_PRIMARY_TIMER_EXPIRED);
         removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
         mIsPrimaryTimerActive = false;
+        mPciChangedDuringPrimaryTimer = false;
         mIsSecondaryTimerActive = false;
         mSecondaryTimerExpireTimestamp = 0;
         mPrimaryTimerState = "";
@@ -1842,11 +1837,11 @@
         pw.flush();
         pw.increaseIndent();
         pw.println("mSubId=" + mPhone.getSubId());
-        pw.println("supportNrSaRrcIdle=" + mFeatureFlags.supportNrSaRrcIdle());
-        pw.println("mOverrideTimerRules=" + mOverrideTimerRules.toString());
+        pw.println("mOverrideTimerRules=" + mOverrideTimerRules);
         pw.println("mLteEnhancedPattern=" + mLteEnhancedPattern);
         pw.println("mIsPhysicalChannelConfigOn=" + mIsPhysicalChannelConfigOn);
         pw.println("mIsPrimaryTimerActive=" + mIsPrimaryTimerActive);
+        pw.println("mPciChangedDuringPrimaryTimer=" + mPciChangedDuringPrimaryTimer);
         pw.println("mIsSecondaryTimerActive=" + mIsSecondaryTimerActive);
         pw.println("mIsTimerResetEnabledForLegacyStateRrcIdle="
                 + mIsTimerResetEnabledForLegacyStateRrcIdle);
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 0c645a0..e136e5a 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -101,6 +101,7 @@
 import com.android.internal.telephony.imsphone.ImsPhoneCall;
 import com.android.internal.telephony.metrics.SmsStats;
 import com.android.internal.telephony.metrics.VoiceCallSessionStats;
+import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.internal.telephony.test.SimulatedRadioControl;
@@ -390,6 +391,7 @@
     private int mPreferredUsageSetting = SubscriptionManager.USAGE_SETTING_UNKNOWN;
     private int mUsageSettingFromModem = SubscriptionManager.USAGE_SETTING_UNKNOWN;
     private boolean mIsUsageSettingSupported = true;
+    private boolean mIsNetworkScanStarted = false;
 
     //IMS
     /**
@@ -671,9 +673,7 @@
             mCi.registerForSrvccStateChanged(this, EVENT_SRVCC_STATE_CHANGED, null);
         }
         //Initialize Telephony Analytics
-        if (mFeatureFlags.enableTelephonyAnalytics()) {
-            mTelephonyAnalytics = new TelephonyAnalytics(this);
-        }
+        mTelephonyAnalytics = new TelephonyAnalytics(this);
     }
 
     /**
@@ -1060,27 +1060,21 @@
     }
 
     /**
-     * Notify the phone that an SMS has been sent. This will be used determine if the SMS was sent
-     * to an emergency address.
+     * Notify the phone that an SMS has been sent. This will be used to determine if the SMS was
+     * sent to an emergency address.
+     *
      * @param destinationAddress the address that the SMS was sent to.
      */
     public void notifySmsSent(String destinationAddress) {
-        TelephonyManager m = (TelephonyManager) getContext().getSystemService(
-                Context.TELEPHONY_SERVICE);
-        if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()) {
+        TelephonyManager m =
+                (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
+        if (mContext.getPackageManager() != null
+                && mContext.getPackageManager()
+                                .hasSystemFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)) {
             if (m != null && m.isEmergencyNumber(destinationAddress)) {
                 mLocalLog.log("Emergency SMS detected, recording time.");
                 mTimeLastEmergencySmsSentMs = SystemClock.elapsedRealtime();
             }
-        } else {
-            if (mContext.getPackageManager() != null
-                    && mContext.getPackageManager().hasSystemFeature(
-                            PackageManager.FEATURE_TELEPHONY_CALLING)) {
-                if (m != null && m.isEmergencyNumber(destinationAddress)) {
-                    mLocalLog.log("Emergency SMS detected, recording time.");
-                    mTimeLastEmergencySmsSentMs = SystemClock.elapsedRealtime();
-                }
-            }
         }
     }
 
@@ -1974,6 +1968,13 @@
     }
 
     /**
+     * @return true if this device supports messaging, false otherwise.
+     */
+    public boolean hasMessaging() {
+        return TelephonyCapabilities.supportsTelephonyMessaging(mFeatureFlags, mContext);
+    }
+
+    /**
      * Retrieves the EmergencyNumberTracker of the phone instance.
      */
     public EmergencyNumberTracker getEmergencyNumberTracker() {
@@ -4166,6 +4167,24 @@
     }
 
     /**
+     * Sets the network scan started status.
+     *
+     * @param started {@code true} if the network scan has started, {@code false} otherwise.
+     */
+    public void setNetworkScanStarted(boolean started) {
+        mIsNetworkScanStarted = started;
+    }
+
+    /**
+     * Gets the network scan started status.
+     *
+     * @return {@code true} if the network scan has started, {@code false} otherwise.
+     */
+    public boolean getNetworkScanStarted() {
+        return mIsNetworkScanStarted;
+    }
+
+    /**
      * Override the roaming indicator for the current ICCID.
      */
     public boolean setRoamingOverride(List<String> gsmRoamingList,
@@ -5407,6 +5426,7 @@
     public void notifyCarrierRoamingNtnEligibleStateChanged(boolean eligible) {
         logd("notifyCarrierRoamingNtnEligibleStateChanged eligible:" + eligible);
         mNotifier.notifyCarrierRoamingNtnEligibleStateChanged(this, eligible);
+        ControllerMetricsStats.getInstance().reportP2PSmsEligibilityNotificationsCount(eligible);
     }
 
     /**
@@ -5432,6 +5452,52 @@
         mNotifier.notifyCarrierRoamingNtnSignalStrengthChanged(this, ntnSignalStrength);
     }
 
+    /**
+     * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
+     *
+     * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+     *                this information to determine the relevant carrier.
+     * @param carrierPlmnList The list of roaming PLMN used for connecting to satellite networks
+     *                        supported by user subscription.
+     * @param allSatellitePlmnList Modem should use the allSatellitePlmnList to identify satellite
+     *                             PLMNs that are not supported by the carrier and make sure not to
+     *                             attach to them.
+     * @param result Callback message to receive the result.
+     */
+    public void setSatellitePlmn(int simSlot,
+            @NonNull List<String> carrierPlmnList, @NonNull List<String> allSatellitePlmnList,
+            Message result) {
+        logd("setSatellitePlmn: simSlot=" + simSlot
+                + " carrierPlmnList=" + carrierPlmnList.toString()
+                + " allSatellitePlmnList=" + allSatellitePlmnList.toString());
+        mCi.setSatellitePlmn(simSlot, carrierPlmnList, allSatellitePlmnList, result);
+    }
+
+    /**
+     * Enable or disable satellite in the cellular modem associated with a carrier.
+     *
+     * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+     *                this information to determine the relevant carrier.
+     * @param satelliteEnabled {@code true} to enable satellite, {@code false} to disable satellite.
+     * @param result Callback message to receive the result.
+     */
+    public void setSatelliteEnabledForCarrier(int simSlot, boolean satelliteEnabled,
+            Message result) {
+        logd("setSatelliteEnabledForCarrier: simSlot=" + simSlot
+                + " satelliteEnabled=" + satelliteEnabled);
+        mCi.setSatelliteEnabledForCarrier(simSlot, satelliteEnabled, result);
+    }
+
+    /**
+     * Check whether satellite is enabled in the cellular modem associated with a carrier.
+     *
+     * @param simSlot Indicates the SIM slot to which this API will be applied.
+     * @param result Callback message to receive the result.
+     */
+    public void isSatelliteEnabledForCarrier(int simSlot, Message result) {
+        mCi.isSatelliteEnabledForCarrier(simSlot, result);
+    }
+
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("Phone: subId=" + getSubId());
         pw.println(" mPhoneId=" + mPhoneId);
diff --git a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
index dd96594..1e69e16 100644
--- a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
+++ b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
@@ -229,6 +229,17 @@
     }
 
     /**
+     * Listener for listening to events in the {@link android.telephony.TelephonyRegistryManager}
+     */
+    private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener =
+            new SubscriptionManager.OnSubscriptionsChangedListener() {
+                @Override
+                public void onSubscriptionsChanged() {
+                    updateSimultaneousSubIdsFromPhoneIdMappingAndNotify();
+                }
+            };
+
+    /**
      * If virtual DSDA is enabled for this UE, then increase maxActiveVoiceSubscriptions to 2.
      */
     private PhoneCapability maybeOverrideMaxActiveVoiceSubscriptions(
@@ -278,14 +289,11 @@
         // Register for subId updates to notify listeners when simultaneous calling is configured
         if (mFeatureFlags.simultaneousCallingIndications()
                 && (bkwdsCompatDsda || halSupportSimulCalling)) {
+            Log.d(LOG_TAG, "maybeEnableCellularDSDASupport: registering "
+                            + "mSubscriptionsChangedListener");
             mContext.getSystemService(TelephonyRegistryManager.class)
                     .addOnSubscriptionsChangedListener(
-                            new SubscriptionManager.OnSubscriptionsChangedListener() {
-                                @Override
-                                public void onSubscriptionsChanged() {
-                                    updateSimultaneousSubIdsFromPhoneIdMappingAndNotify();
-                                }
-                            }, mHandler::post);
+                            mSubscriptionsChangedListener, mHandler::post);
         }
     }
 
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index c077ca9..2212aca 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -20,6 +20,7 @@
 
 import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA;
 import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA_LTE;
+import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_GSM;
 
 import static java.util.Arrays.copyOf;
 
@@ -45,7 +46,6 @@
 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
 import com.android.internal.telephony.data.CellularNetworkValidator;
 import com.android.internal.telephony.data.PhoneSwitcher;
-import com.android.internal.telephony.data.TelephonyNetworkFactory;
 import com.android.internal.telephony.data.TelephonyNetworkProvider;
 import com.android.internal.telephony.euicc.EuiccCardController;
 import com.android.internal.telephony.euicc.EuiccController;
@@ -78,7 +78,7 @@
 
     //***** Class Variables
 
-    // lock sLockProxyPhones protects sPhones, sPhone and sTelephonyNetworkFactories
+    // lock sLockProxyPhones protects sPhones, sPhone
     final static Object sLockProxyPhones = new Object();
     static private Phone[] sPhones = null;
     static private Phone sPhone = null;
@@ -101,7 +101,6 @@
     static private PhoneConfigurationManager sPhoneConfigurationManager;
     static private SimultaneousCallingTracker sSimultaneousCallingTracker;
     static private PhoneSwitcher sPhoneSwitcher;
-    static private TelephonyNetworkFactory[] sTelephonyNetworkFactories;
     private static TelephonyNetworkProvider sTelephonyNetworkProvider;
     static private NotificationChannelController sNotificationChannelController;
     static private CellularNetworkValidator sCellularNetworkValidator;
@@ -179,7 +178,6 @@
                 int[] networkModes = new int[numPhones];
                 sPhones = new Phone[numPhones];
                 sCommandsInterfaces = new RIL[numPhones];
-                sTelephonyNetworkFactories = new TelephonyNetworkFactory[numPhones];
 
                 for (int i = 0; i < numPhones; i++) {
                     // reads the system properties and makes commandsinterface
@@ -271,7 +269,7 @@
                             SimultaneousCallingTracker.init(sContext, featureFlags);
                 }
 
-                sCellularNetworkValidator = CellularNetworkValidator.make(sContext);
+                sCellularNetworkValidator = CellularNetworkValidator.make(sContext, sFeatureFlags);
 
                 int maxActivePhones = sPhoneConfigurationManager
                         .getNumberOfModemsWithSimultaneousDataConnections();
@@ -287,16 +285,9 @@
 
                 sNotificationChannelController = new NotificationChannelController(context);
 
-                if (featureFlags.supportNetworkProvider()) {
-                    // Create the TelephonyNetworkProvider instance, which is a singleton.
-                    sTelephonyNetworkProvider = new TelephonyNetworkProvider(Looper.myLooper(),
-                            context, featureFlags);
-                } else {
-                    for (int i = 0; i < numPhones; i++) {
-                        sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
-                                Looper.myLooper(), sPhones[i], featureFlags);
-                    }
-                }
+                // Create the TelephonyNetworkProvider instance, which is a singleton.
+                sTelephonyNetworkProvider = new TelephonyNetworkProvider(Looper.myLooper(),
+                        context, featureFlags);
             }
         }
     }
@@ -313,7 +304,6 @@
             int prevActiveModemCount = sPhones.length;
             if (prevActiveModemCount == activeModemCount) return;
 
-            // TODO: clean up sPhones, sCommandsInterfaces and sTelephonyNetworkFactories objects.
             // Currently we will not clean up the 2nd Phone object, so that it can be re-used if
             // user switches back.
             if (prevActiveModemCount > activeModemCount) return;
@@ -321,10 +311,6 @@
             sPhones = copyOf(sPhones, activeModemCount);
             sCommandsInterfaces = copyOf(sCommandsInterfaces, activeModemCount);
 
-            if (!sFeatureFlags.supportNetworkProvider()) {
-                sTelephonyNetworkFactories = copyOf(sTelephonyNetworkFactories, activeModemCount);
-            }
-
             int cdmaSubscription = CdmaSubscriptionSourceManager.getDefault(context);
             for (int i = prevActiveModemCount; i < activeModemCount; i++) {
                 sCommandsInterfaces[i] = new RIL(context, RadioAccessFamily.getRafFromNetworkType(
@@ -335,21 +321,22 @@
                         PackageManager.FEATURE_TELEPHONY_IMS)) {
                     sPhones[i].createImsPhone();
                 }
-
-                if (!sFeatureFlags.supportNetworkProvider()) {
-                    sTelephonyNetworkFactories[i] = new TelephonyNetworkFactory(
-                            Looper.myLooper(), sPhones[i], sFeatureFlags);
-                }
             }
         }
     }
 
     private static Phone createPhone(Context context, int phoneId) {
-        int phoneType = TelephonyManager.getPhoneType(RILConstants.PREFERRED_NETWORK_MODE);
+        int phoneType;
+        if (sFeatureFlags.phoneTypeCleanup()) {
+            phoneType = PHONE_TYPE_GSM;
+        } else {
+            phoneType = TelephonyManager.getPhoneType(RILConstants.PREFERRED_NETWORK_MODE);
+            // We always use PHONE_TYPE_CDMA_LTE now.
+            if (phoneType == PHONE_TYPE_CDMA) phoneType = PHONE_TYPE_CDMA_LTE;
+        }
+
         Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " phoneId = " + phoneId);
 
-        // We always use PHONE_TYPE_CDMA_LTE now.
-        if (phoneType == PHONE_TYPE_CDMA) phoneType = PHONE_TYPE_CDMA_LTE;
         TelephonyComponentFactory injectedComponentFactory =
                 TelephonyComponentFactory.getInstance().inject(GsmCdmaPhone.class.getName());
 
@@ -412,36 +399,6 @@
     }
 
     /**
-     * Get the network factory associated with a given phone ID.
-     * @param phoneId the phone id
-     * @return a factory for this phone ID, or null if none.
-     */
-    public static TelephonyNetworkFactory getNetworkFactory(int phoneId) {
-        synchronized (sLockProxyPhones) {
-            if (!sMadeDefaults) {
-                throw new IllegalStateException("Default phones haven't been made yet!");
-            }
-            final String dbgInfo;
-            if (phoneId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
-                dbgInfo = "getNetworkFactory with DEFAULT_PHONE_ID => factory for sPhone";
-                phoneId = sPhone.getSubId();
-            } else {
-                dbgInfo = "getNetworkFactory with non-default, return factory for passed id";
-            }
-            // sTelephonyNetworkFactories is null in tests because in tests makeDefaultPhones()
-            // is not called.
-            final TelephonyNetworkFactory factory = (sTelephonyNetworkFactories != null
-                            && (phoneId >= 0 && phoneId < sTelephonyNetworkFactories.length))
-                            ? sTelephonyNetworkFactories[phoneId] : null;
-            if (DBG) {
-                Rlog.d(LOG_TAG, "getNetworkFactory:-" + dbgInfo + " phoneId=" + phoneId
-                        + " factory=" + factory);
-            }
-            return factory;
-        }
-    }
-
-    /**
      * Returns the preferred network type bitmask that should be set in the modem.
      *
      * @param phoneId The phone's id.
@@ -596,20 +553,10 @@
 
             pw.flush();
             pw.println("++++++++++++++++++++++++++++++++");
-
-            if (!sFeatureFlags.supportNetworkProvider()) {
-                sTelephonyNetworkFactories[i].dump(fd, pw, args);
-            }
-
-            pw.flush();
-            pw.decreaseIndent();
-            pw.println("++++++++++++++++++++++++++++++++");
         }
 
         pw.increaseIndent();
-        if (sFeatureFlags.supportNetworkProvider()) {
-            sTelephonyNetworkProvider.dump(fd, pw, args);
-        }
+        sTelephonyNetworkProvider.dump(fd, pw, args);
         pw.decreaseIndent();
         pw.println("++++++++++++++++++++++++++++++++");
 
diff --git a/src/java/com/android/internal/telephony/PhoneSubInfoController.java b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
index 9801542..c8cd242 100644
--- a/src/java/com/android/internal/telephony/PhoneSubInfoController.java
+++ b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
@@ -861,8 +861,7 @@
             return;
         }
 
-        if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
-                || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+        if (!CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
                 Binder.getCallingUserHandle())
                 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
             // Skip to check associated telephony feature,
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 39b6d37..f5d06db 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -94,6 +94,7 @@
 import com.android.internal.telephony.metrics.ModemRestartStats;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.nano.TelephonyProto.SmsSession;
+import com.android.internal.telephony.satellite.SatelliteModemInterface;
 import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
 import com.android.internal.telephony.uicc.IccUtils;
 import com.android.internal.telephony.uicc.SimPhonebookRecord;
@@ -393,27 +394,17 @@
                 case EVENT_AIDL_PROXY_DEAD:
                     int aidlService = msg.arg1;
                     long msgCookie = (long) msg.obj;
-                    if (mFeatureFlags.combineRilDeathHandle()) {
-                        if (msgCookie == mServiceCookies.get(aidlService).get()) {
-                            riljLog("handleMessage: EVENT_AIDL_PROXY_DEAD cookie = " + msgCookie
-                                    + ", service = " + serviceToString(aidlService) + ", cookie = "
-                                    + mServiceCookies.get(aidlService));
-                            mIsRadioProxyInitialized = false;
-                            resetProxyAndRequestList(aidlService);
-                            // Remove duplicate death message to avoid duplicate reset.
-                            mRilHandler.removeMessages(EVENT_AIDL_PROXY_DEAD);
-                        } else {
-                            riljLog("Ignore stale EVENT_AIDL_PROXY_DEAD for service "
-                                    + serviceToString(aidlService));
-                        }
-                    } else {
+                    if (msgCookie == mServiceCookies.get(aidlService).get()) {
                         riljLog("handleMessage: EVENT_AIDL_PROXY_DEAD cookie = " + msgCookie
                                 + ", service = " + serviceToString(aidlService) + ", cookie = "
                                 + mServiceCookies.get(aidlService));
-                        if (msgCookie == mServiceCookies.get(aidlService).get()) {
-                            mIsRadioProxyInitialized = false;
-                            resetProxyAndRequestList(aidlService);
-                        }
+                        mIsRadioProxyInitialized = false;
+                        resetProxyAndRequestList(aidlService);
+                        // Remove duplicate death message to avoid duplicate reset.
+                        mRilHandler.removeMessages(EVENT_AIDL_PROXY_DEAD);
+                    } else {
+                        riljLog("Ignore stale EVENT_AIDL_PROXY_DEAD for service "
+                                + serviceToString(aidlService));
                     }
                     break;
             }
@@ -458,14 +449,9 @@
         public void serviceDied(long cookie) {
             // Deal with service going away
             riljLog("serviceDied");
-            if (mFeatureFlags.combineRilDeathHandle()) {
-                mRilHandler.sendMessageAtFrontOfQueue(mRilHandler.obtainMessage(
-                        EVENT_RADIO_PROXY_DEAD,
-                        HAL_SERVICE_RADIO, 0 /* ignored arg2 */, cookie));
-            } else {
-                mRilHandler.sendMessage(mRilHandler.obtainMessage(EVENT_RADIO_PROXY_DEAD,
-                        HAL_SERVICE_RADIO, 0 /* ignored arg2 */, cookie));
-            }
+            mRilHandler.sendMessageAtFrontOfQueue(mRilHandler.obtainMessage(
+                    EVENT_RADIO_PROXY_DEAD,
+                    HAL_SERVICE_RADIO, 0 /* ignored arg2 */, cookie));
         }
     }
 
@@ -501,14 +487,9 @@
         @Override
         public void binderDied() {
             riljLog("Service " + serviceToString(mService) + " has died.");
-            if (mFeatureFlags.combineRilDeathHandle()) {
-                mRilHandler.sendMessageAtFrontOfQueue(mRilHandler.obtainMessage(
-                        EVENT_AIDL_PROXY_DEAD, mService, 0 /* ignored arg2 */,
-                        mLinkedFlags));
-            } else {
-                mRilHandler.sendMessage(mRilHandler.obtainMessage(EVENT_AIDL_PROXY_DEAD, mService,
-                        0 /* ignored arg2 */, mLinkedFlags));
-            }
+            mRilHandler.sendMessageAtFrontOfQueue(mRilHandler.obtainMessage(
+                    EVENT_AIDL_PROXY_DEAD, mService, 0 /* ignored arg2 */,
+                    mLinkedFlags));
             unlinkToDeath();
         }
     }
@@ -524,23 +505,17 @@
             // Increment the cookie so that death notification can be ignored
             mServiceCookies.get(service).incrementAndGet();
         } else {
-            if (mFeatureFlags.combineRilDeathHandle()) {
-                // Reset all aidl services.
-                for (int i = MIN_SERVICE_IDX; i <= MAX_SERVICE_IDX; i++) {
-                    if (i == HAL_SERVICE_RADIO) continue;
-                    if (mServiceProxies.get(i) == null) {
-                        // This should only happen in tests
-                        riljLoge("Null service proxy for service " + serviceToString(i));
-                        continue;
-                    }
-                    mServiceProxies.get(i).clear();
-                    // Increment the cookie so that death notification can be ignored
-                    mServiceCookies.get(i).incrementAndGet();
+            // Reset all aidl services.
+            for (int i = MIN_SERVICE_IDX; i <= MAX_SERVICE_IDX; i++) {
+                if (i == HAL_SERVICE_RADIO) continue;
+                if (mServiceProxies.get(i) == null) {
+                    // This should only happen in tests
+                    riljLoge("Null service proxy for service " + serviceToString(i));
+                    continue;
                 }
-            } else {
-                mServiceProxies.get(service).clear();
+                mServiceProxies.get(i).clear();
                 // Increment the cookie so that death notification can be ignored
-                mServiceCookies.get(service).incrementAndGet();
+                mServiceCookies.get(i).incrementAndGet();
             }
         }
 
@@ -553,19 +528,15 @@
         if (service == HAL_SERVICE_RADIO) {
             getRadioProxy();
         } else {
-            if (mFeatureFlags.combineRilDeathHandle()) {
-                // Reset all aidl services.
-                for (int i = MIN_SERVICE_IDX; i <= MAX_SERVICE_IDX; i++) {
-                    if (i == HAL_SERVICE_RADIO) continue;
-                    if (mServiceProxies.get(i) == null) {
-                        // This should only happen in tests
-                        riljLoge("Null service proxy for service " + serviceToString(i));
-                        continue;
-                    }
-                    getRadioServiceProxy(i);
+            // Reset all aidl services.
+            for (int i = MIN_SERVICE_IDX; i <= MAX_SERVICE_IDX; i++) {
+                if (i == HAL_SERVICE_RADIO) continue;
+                if (mServiceProxies.get(i) == null) {
+                    // This should only happen in tests
+                    riljLoge("Null service proxy for service " + serviceToString(i));
+                    continue;
                 }
-            } else {
-                getRadioServiceProxy(service);
+                getRadioServiceProxy(i);
             }
         }
     }
@@ -620,15 +591,9 @@
 
             if (serviceBound) {
                 mIsRadioProxyInitialized = false;
-                if (mFeatureFlags.combineRilDeathHandle()) {
-                    // Reset both hidl and aidl proxies.
-                    resetProxyAndRequestList(HAL_SERVICE_RADIO);
-                    resetProxyAndRequestList(HAL_SERVICE_DATA);
-                } else {
-                    for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) {
-                        resetProxyAndRequestList(service);
-                    }
-                }
+                // Reset both hidl and aidl proxies.
+                resetProxyAndRequestList(HAL_SERVICE_RADIO);
+                resetProxyAndRequestList(HAL_SERVICE_DATA);
             }
         }
 
@@ -655,16 +620,11 @@
                             mHalVersion.put(service, RADIO_HAL_VERSION_UNSUPPORTED);
                         }
                     }
-                    if (!mFeatureFlags.combineRilDeathHandle()) {
-                        resetProxyAndRequestList(service);
-                    }
                 }
-                if (mFeatureFlags.combineRilDeathHandle()) {
-                    // Reset both hidl and aidl proxies. Must be after cleaning mocked halVersion,
-                    // otherwise an aidl service will be incorrectly considered as disabled.
-                    resetProxyAndRequestList(HAL_SERVICE_RADIO);
-                    resetProxyAndRequestList(HAL_SERVICE_DATA);
-                }
+                // Reset both hidl and aidl proxies. Must be after cleaning mocked halVersion,
+                // otherwise an aidl service will be incorrectly considered as disabled.
+                resetProxyAndRequestList(HAL_SERVICE_RADIO);
+                resetProxyAndRequestList(HAL_SERVICE_DATA);
             }
         }
 
@@ -1081,34 +1041,19 @@
     @Override
     public synchronized void onSlotActiveStatusChange(boolean active) {
         mIsRadioProxyInitialized = false;
-        if (mFeatureFlags.combineRilDeathHandle()) {
-            if (active) {
-                for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) {
-                    // Try to connect to RIL services and set response functions.
-                    if (service == HAL_SERVICE_RADIO) {
-                        getRadioProxy();
-                    } else {
-                        getRadioServiceProxy(service);
-                    }
+        if (active) {
+            for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) {
+                // Try to connect to RIL services and set response functions.
+                if (service == HAL_SERVICE_RADIO) {
+                    getRadioProxy();
+                } else {
+                    getRadioServiceProxy(service);
                 }
-            } else {
-                // Reset both hidl and aidl proxies
-                resetProxyAndRequestList(HAL_SERVICE_RADIO);
-                resetProxyAndRequestList(HAL_SERVICE_DATA);
             }
         } else {
-            for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) {
-                if (active) {
-                    // Try to connect to RIL services and set response functions.
-                    if (service == HAL_SERVICE_RADIO) {
-                        getRadioProxy();
-                    } else {
-                        getRadioServiceProxy(service);
-                    }
-                } else {
-                    resetProxyAndRequestList(service);
-                }
-            }
+            // Reset both hidl and aidl proxies
+            resetProxyAndRequestList(HAL_SERVICE_RADIO);
+            resetProxyAndRequestList(HAL_SERVICE_DATA);
         }
     }
 
@@ -1386,7 +1331,12 @@
     }
 
     private boolean canMakeRequest(String request, RadioServiceProxy proxy, Message result,
-            HalVersion version) {
+            HalVersion minVersion) {
+        return canMakeRequest(request, proxy, result, minVersion, null /* maxVersion */);
+    }
+
+    private boolean canMakeRequest(String request, RadioServiceProxy proxy, Message result,
+            HalVersion minVersion, @Nullable HalVersion maxVersion) {
         int service = HAL_SERVICE_RADIO;
         if (proxy instanceof RadioDataProxy) {
             service = HAL_SERVICE_DATA;
@@ -1413,9 +1363,20 @@
             }
             return false;
         }
-        if (mHalVersion.get(service).less(version)) {
+        if (mHalVersion.get(service).less(minVersion)) {
             riljLoge(String.format("%s not supported on service %s < %s.",
-                    request, serviceToString(service), version));
+                    request, serviceToString(service), minVersion));
+            if (result != null) {
+                AsyncResult.forMessage(result, null,
+                        CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
+            }
+            return false;
+        }
+
+        if (maxVersion != null && mHalVersion.get(service).greater(maxVersion)) {
+            riljLoge(String.format("%s not supported on service %s > %s.",
+                    request, serviceToString(service), maxVersion));
             if (result != null) {
                 AsyncResult.forMessage(result, null,
                         CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
@@ -3682,7 +3643,8 @@
     @Override
     public void getDeviceIdentity(Message result) {
         RadioModemProxy modemProxy = getRadioServiceProxy(RadioModemProxy.class);
-        if (!canMakeRequest("getDeviceIdentity", modemProxy, result, RADIO_HAL_VERSION_1_4)) {
+        if (!canMakeRequest("getDeviceIdentity", modemProxy, result, RADIO_HAL_VERSION_1_4,
+                RADIO_HAL_VERSION_2_2)) {
             return;
         }
 
@@ -3937,7 +3899,7 @@
     public void getImsRegistrationState(Message result) {
         RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
         if (!canMakeRequest("getImsRegistrationState", networkProxy, result,
-                RADIO_HAL_VERSION_1_4)) {
+                RADIO_HAL_VERSION_1_4, RADIO_HAL_VERSION_2_2)) {
             return;
         }
 
@@ -4170,7 +4132,8 @@
 
     @Override
     public void nvResetConfig(int resetType, Message result) {
-        if (mFeatureFlags.cleanupCdma()) return;
+        // Disable all NV reset functions except modem restart.
+        if (mFeatureFlags.cleanupCdma() && resetType != 1) return;
 
         RadioModemProxy modemProxy = getRadioServiceProxy(RadioModemProxy.class);
         if (!canMakeRequest("nvResetConfig", modemProxy, result, RADIO_HAL_VERSION_1_4)) {
@@ -5399,11 +5362,10 @@
     public void setSatellitePlmn(int simSlot, @NonNull List<String> carrierPlmnList,
             @NonNull List<String> allSatellitePlmnList, Message result) {
         RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
-        if (!canMakeRequest(
-                "setSatellitePlmn",
-                networkProxy,
-                result,
-                RADIO_HAL_VERSION_2_4)) {
+        if (getHalVersion(HAL_SERVICE_NETWORK).less(RADIO_HAL_VERSION_2_3)) {
+            riljLog("setSatellitePlmn: SatelliteModemInterface is used.");
+            SatelliteModemInterface.getInstance().setSatellitePlmn(
+                    simSlot, carrierPlmnList, allSatellitePlmnList, result);
             return;
         }
 
@@ -5421,7 +5383,7 @@
                 rr,
                 "setSatellitePlmn",
                 () -> {
-                    networkProxy.setSatellitePlmn(rr.mSerial, simSlot, carrierPlmnList,
+                    networkProxy.setSatellitePlmn(rr.mSerial, carrierPlmnList,
                             allSatellitePlmnList);
                 });
     }
@@ -5433,11 +5395,10 @@
     public void setSatelliteEnabledForCarrier(int simSlot, boolean satelliteEnabled,
             Message result) {
         RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
-        if (!canMakeRequest(
-                "setSatelliteEnabledForCarrier",
-                networkProxy,
-                result,
-                RADIO_HAL_VERSION_2_4)) {
+        if (getHalVersion(HAL_SERVICE_NETWORK).less(RADIO_HAL_VERSION_2_3)) {
+            riljLog("setSatelliteEnabledForCarrier: SatelliteModemInterface is used.");
+            SatelliteModemInterface.getInstance().requestSetSatelliteEnabledForCarrier(
+                    simSlot, satelliteEnabled, result);
             return;
         }
 
@@ -5454,8 +5415,7 @@
                 rr,
                 "setSatelliteEnabledForCarrier",
                 () -> {
-                    networkProxy.setSatelliteEnabledForCarrier(rr.mSerial, simSlot,
-                            satelliteEnabled);
+                    networkProxy.setSatelliteEnabledForCarrier(rr.mSerial, satelliteEnabled);
                 });
     }
 
@@ -5465,11 +5425,10 @@
     @Override
     public void isSatelliteEnabledForCarrier(int simSlot, Message result) {
         RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
-        if (!canMakeRequest(
-                "isSatelliteEnabledForCarrier",
-                networkProxy,
-                result,
-                RADIO_HAL_VERSION_2_4)) {
+        if (getHalVersion(HAL_SERVICE_NETWORK).less(RADIO_HAL_VERSION_2_3)) {
+            riljLog("isSatelliteEnabledForCarrier: SatelliteModemInterface is used.");
+            SatelliteModemInterface.getInstance().requestIsSatelliteEnabledForCarrier(
+                    simSlot, result);
             return;
         }
 
@@ -5483,7 +5442,7 @@
 
         radioServiceInvokeHelper(
                 HAL_SERVICE_NETWORK, rr, "isSatelliteEnabledForCarrier", () -> {
-                    networkProxy.isSatelliteEnabledForCarrier(rr.mSerial, simSlot);
+                    networkProxy.isSatelliteEnabledForCarrier(rr.mSerial);
                 });
     }
 
@@ -6010,7 +5969,6 @@
             case RIL_REQUEST_GET_IMEISV:
             case RIL_REQUEST_SIM_OPEN_CHANNEL:
             case RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL:
-            case RIL_REQUEST_DEVICE_IMEI:
 
                 if (!RILJ_LOGV) {
                     // If not versbose logging just return and don't display IMSI and IMEI, IMEISV
@@ -6052,6 +6010,16 @@
             }
             sb.append("}");
             s = sb.toString();
+        } else if (req == RIL_REQUEST_DEVICE_IMEI) {
+            sb = new StringBuilder("{");
+            ImeiInfo imeiInfo = (ImeiInfo) ret;
+            if (imeiInfo != null) {
+                sb.append(Rlog.pii(RILJ_LOG_TAG, imeiInfo.imei)).append(", ");
+                sb.append(imeiInfo.type).append(", ");
+                sb.append(imeiInfo.svn);
+            }
+            sb.append("}");
+            s = sb.toString();
         } else if (req == RIL_REQUEST_GET_CURRENT_CALLS) {
             ArrayList<DriverCall> calls = (ArrayList<DriverCall>) ret;
             sb = new StringBuilder("{");
diff --git a/src/java/com/android/internal/telephony/RILUtils.java b/src/java/com/android/internal/telephony/RILUtils.java
index 15e2374..fb07fb3 100644
--- a/src/java/com/android/internal/telephony/RILUtils.java
+++ b/src/java/com/android/internal/telephony/RILUtils.java
@@ -1698,9 +1698,6 @@
         if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_NR) != 0) {
             raf |= android.hardware.radio.RadioAccessFamily.NR;
         }
-        if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_NB_IOT_NTN) != 0) {
-            raf |= android.hardware.radio.RadioAccessFamily.NB_IOT_NTN;
-        }
         return (raf == 0) ? android.hardware.radio.RadioAccessFamily.UNKNOWN : raf;
     }
 
diff --git a/src/java/com/android/internal/telephony/RadioIndication.java b/src/java/com/android/internal/telephony/RadioIndication.java
index aadfe62..26d3abd 100644
--- a/src/java/com/android/internal/telephony/RadioIndication.java
+++ b/src/java/com/android/internal/telephony/RadioIndication.java
@@ -112,6 +112,7 @@
 import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
 import com.android.internal.telephony.cdma.CdmaInformationRecords;
 import com.android.internal.telephony.data.KeepaliveStatus;
+import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.gsm.SsData;
 import com.android.internal.telephony.gsm.SuppServiceNotification;
 import com.android.internal.telephony.uicc.IccRefreshResponse;
@@ -571,6 +572,7 @@
     }
 
     public void cdmaCallWaiting(int indicationType, CdmaCallWaiting callWaitingRecord) {
+        if (Flags.phoneTypeCleanup()) return;
         mRil.processIndication(HAL_SERVICE_RADIO, indicationType);
 
         // todo: create a CdmaCallWaitingNotification constructor that takes in these fields to make
@@ -609,6 +611,7 @@
 
     public void cdmaInfoRec(int indicationType,
                             android.hardware.radio.V1_0.CdmaInformationRecords records) {
+        if (Flags.phoneTypeCleanup()) return;
         mRil.processIndication(HAL_SERVICE_RADIO, indicationType);
 
         int numberOfInfoRecs = records.infoRec.size();
diff --git a/src/java/com/android/internal/telephony/RadioInterfaceCapabilityController.java b/src/java/com/android/internal/telephony/RadioInterfaceCapabilityController.java
index 4d9196e..e681280 100644
--- a/src/java/com/android/internal/telephony/RadioInterfaceCapabilityController.java
+++ b/src/java/com/android/internal/telephony/RadioInterfaceCapabilityController.java
@@ -26,6 +26,8 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.Flags;
+import com.android.internal.telephony.util.WorkerThread;
 import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
@@ -55,10 +57,19 @@
             final CommandsInterface commandsInterface) {
         synchronized (RadioInterfaceCapabilityController.class) {
             if (sInstance == null) {
-                final HandlerThread handlerThread = new HandlerThread("RHC");
-                handlerThread.start();
-                sInstance = new RadioInterfaceCapabilityController(radioConfig, commandsInterface,
-                        handlerThread.getLooper());
+                if (Flags.threadShred()) {
+                    sInstance = new RadioInterfaceCapabilityController(
+                            radioConfig,
+                            commandsInterface,
+                            WorkerThread.get().getLooper());
+                } else {
+                    final HandlerThread handlerThread = new HandlerThread("RHC");
+                    handlerThread.start();
+                    sInstance = new RadioInterfaceCapabilityController(
+                            radioConfig,
+                            commandsInterface,
+                            handlerThread.getLooper());
+                }
             } else {
                 Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
             }
diff --git a/src/java/com/android/internal/telephony/RadioNetworkProxy.java b/src/java/com/android/internal/telephony/RadioNetworkProxy.java
index c4b6f76..5db7706 100644
--- a/src/java/com/android/internal/telephony/RadioNetworkProxy.java
+++ b/src/java/com/android/internal/telephony/RadioNetworkProxy.java
@@ -132,6 +132,7 @@
      * @throws RemoteException
      */
     public void getAvailableBandModes(int serial) throws RemoteException {
+        if (Flags.cleanupCdma()) return;
         if (isEmpty()) return;
         if (isAidl()) {
             mNetworkProxy.getAvailableBandModes(serial);
@@ -401,6 +402,7 @@
      * @throws RemoteException
      */
     public void setBandMode(int serial, int bandMode) throws RemoteException {
+        if (Flags.cleanupCdma()) return;
         if (isEmpty()) return;
         if (isAidl()) {
             mNetworkProxy.setBandMode(serial, bandMode);
@@ -525,6 +527,7 @@
      * @throws RemoteException
      */
     public void setLocationUpdates(int serial, boolean enable) throws RemoteException {
+        if (Flags.cleanupCdma()) return;
         if (isEmpty()) return;
         if (isAidl()) {
             mNetworkProxy.setLocationUpdates(serial, enable);
@@ -629,6 +632,7 @@
      * @throws RemoteException
      */
     public void setSuppServiceNotifications(int serial, boolean enable) throws RemoteException {
+        if (Flags.cleanupCdma()) return;
         if (isEmpty()) return;
         if (isAidl()) {
             mNetworkProxy.setSuppServiceNotifications(serial, enable);
@@ -988,22 +992,19 @@
      * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
      *
      * @param serial Serial number of request.
-     * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
-     *                this information to determine the relevant carrier.
      * @param carrierPlmnList The list of roaming PLMN used for connecting to satellite networks
      *                        supported by user subscription.
      * @param allSatellitePlmnList Modem should use the allSatellitePlmnList to identify satellite
      *                             PLMNs that are not supported by the carrier and make sure not to
      *                             attach to them.
      */
-    public void setSatellitePlmn(int serial, int simSlot, List<String> carrierPlmnList,
+    public void setSatellitePlmn(int serial, List<String> carrierPlmnList,
             List<String> allSatellitePlmnList) throws RemoteException {
         if (isEmpty()) return;
         if (isAidl()) {
             String[] carrierPlmnArray = carrierPlmnList.toArray(new String[0]);
             String[] allSatellitePlmnArray = allSatellitePlmnList.toArray(new String[0]);
-            mNetworkProxy.setSatellitePlmn(serial, simSlot, carrierPlmnArray,
-                    allSatellitePlmnArray);
+            mNetworkProxy.setSatellitePlmn(serial, carrierPlmnArray, allSatellitePlmnArray);
         }
         // Only supported on AIDL.
     }
@@ -1012,15 +1013,13 @@
      * Enable or disable satellite in the cellular modem associated with a carrier.
      *
      * @param serial Serial number of request.
-     * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
-     *                this information to determine the relevant carrier.
      * @param satelliteEnabled {@code true} to enable satellite, {@code false} to disable satellite.
      */
-    public void setSatelliteEnabledForCarrier(int serial, int simSlot,
-            boolean satelliteEnabled) throws RemoteException {
+    public void setSatelliteEnabledForCarrier(
+            int serial, boolean satelliteEnabled) throws RemoteException {
         if (isEmpty()) return;
         if (isAidl()) {
-            mNetworkProxy.setSatelliteEnabledForCarrier(serial, simSlot, satelliteEnabled);
+            mNetworkProxy.setSatelliteEnabledForCarrier(serial, satelliteEnabled);
         }
         // Only supported on AIDL.
     }
@@ -1029,13 +1028,12 @@
      * Check whether satellite is enabled in the cellular modem associated with a carrier.
      *
      * @param serial Serial number of request.
-     * @param simSlot Indicates the SIM slot to which this API will be applied.
      */
-    public void isSatelliteEnabledForCarrier(int serial, int simSlot)
+    public void isSatelliteEnabledForCarrier(int serial)
             throws RemoteException {
         if (isEmpty()) return;
         if (isAidl()) {
-            mNetworkProxy.isSatelliteEnabledForCarrier(serial, simSlot);
+            mNetworkProxy.isSatelliteEnabledForCarrier(serial);
         }
         // Only supported on AIDL.
     }
diff --git a/src/java/com/android/internal/telephony/RadioSimProxy.java b/src/java/com/android/internal/telephony/RadioSimProxy.java
index 9316ea4..65fbfa4 100644
--- a/src/java/com/android/internal/telephony/RadioSimProxy.java
+++ b/src/java/com/android/internal/telephony/RadioSimProxy.java
@@ -693,6 +693,7 @@
      */
     public void setUiccSubscription(int serial, int slotId, int appIndex, int subId, int subStatus)
             throws RemoteException {
+        if (Flags.cleanupCdma()) return;
         if (isEmpty()) return;
         if (isAidl()) {
             android.hardware.radio.sim.SelectUiccSub info =
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java
index fac4358..fd72c88 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -63,6 +63,7 @@
 import android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallback;
 import android.telephony.AnomalyReporter;
 import android.telephony.CarrierConfigManager;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
 import android.telephony.SmsManager;
@@ -90,9 +91,11 @@
 import com.android.internal.telephony.analytics.TelephonyAnalytics.SmsMmsAnalytics;
 import com.android.internal.telephony.cdma.sms.UserData;
 import com.android.internal.telephony.flags.Flags;
+import com.android.internal.telephony.satellite.SatelliteController;
 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.internal.telephony.uicc.IccRecords;
+import com.android.internal.telephony.util.ArrayUtils;
 import com.android.internal.telephony.util.TelephonyUtils;
 import com.android.telephony.Rlog;
 
@@ -1140,7 +1143,8 @@
                     tracker.mMessageId,
                     tracker.isFromDefaultSmsApplication(mContext),
                     tracker.getInterval(),
-                    mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
+                    mTelephonyManager.isEmergencyNumber(tracker.mDestAddress),
+                    tracker.isMtSmsPollingMessage(mContext));
             if (mPhone != null) {
                 TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
                 if (telephonyAnalytics != null) {
@@ -1201,7 +1205,8 @@
                         tracker.mMessageId,
                         tracker.isFromDefaultSmsApplication(mContext),
                         tracker.getInterval(),
-                        mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
+                        mTelephonyManager.isEmergencyNumber(tracker.mDestAddress),
+                        tracker.isMtSmsPollingMessage(mContext));
                 if (mPhone != null) {
                     TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
                     if (telephonyAnalytics != null) {
@@ -1238,7 +1243,8 @@
                         tracker.mMessageId,
                         tracker.isFromDefaultSmsApplication(mContext),
                         tracker.getInterval(),
-                        mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
+                        mTelephonyManager.isEmergencyNumber(tracker.mDestAddress),
+                        tracker.isMtSmsPollingMessage(mContext));
                 if (mPhone != null) {
                     TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
                     if (telephonyAnalytics != null) {
@@ -1265,7 +1271,8 @@
                         tracker.mMessageId,
                         tracker.isFromDefaultSmsApplication(mContext),
                         tracker.getInterval(),
-                        mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
+                        mTelephonyManager.isEmergencyNumber(tracker.mDestAddress),
+                        tracker.isMtSmsPollingMessage(mContext));
                 if (mPhone != null) {
                     TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
                     if (telephonyAnalytics != null) {
@@ -2222,6 +2229,7 @@
         if (mContext.checkCallingOrSelfPermission(SEND_SMS_NO_CONFIRMATION)
                 == PackageManager.PERMISSION_GRANTED || trackers[0].mIsForVvm
                 || trackers[0].mSkipShortCodeDestAddrCheck) {
+            Rlog.d(TAG, "checkDestination: app pre-approved");
             return true;            // app is pre-approved to send to short codes
         } else {
             int rule = mPremiumSmsRule.get();
@@ -2241,6 +2249,7 @@
                         mSmsDispatchersController
                                 .getUsageMonitor()
                                 .checkDestination(trackers[0].mDestAddress, simCountryIso);
+                Rlog.d(TAG, "checkDestination: simCountryIso=" + simCountryIso);
             }
             if (rule == PREMIUM_RULE_USE_NETWORK || rule == PREMIUM_RULE_USE_BOTH) {
                 String networkCountryIso =
@@ -2260,7 +2269,9 @@
                                         .getUsageMonitor()
                                         .checkDestination(
                                                 trackers[0].mDestAddress, networkCountryIso));
+                Rlog.d(TAG, "checkDestination: networkCountryIso=" + networkCountryIso);
             }
+            Rlog.d(TAG, "checkDestination: smsCategory=" + smsCategory);
 
             if (smsCategory != SmsManager.SMS_CATEGORY_NOT_SHORT_CODE) {
                 int xmlVersion = mSmsDispatchersController.getUsageMonitor()
@@ -2282,6 +2293,14 @@
                 return false;
             }
 
+            // Check whether to block premium sms in satellite mode.
+            if (shouldBlockPremiumSmsInSatelliteMode()) {
+                Rlog.d(TAG, "Block premium SMS in satellite mode."
+                        + " messageId=" + SmsController.formatCrossStackMessageId(
+                                getMultiTrackermessageId(trackers)));
+                return false;
+            }
+
             // Wait for user confirmation unless the user has set permission to always allow/deny
             int premiumSmsPermission =
                     mSmsDispatchersController
@@ -2321,6 +2340,32 @@
         }
     }
 
+    /** Block premium sms in satellite mode. */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public boolean shouldBlockPremiumSmsInSatelliteMode() {
+        SatelliteController sc = SatelliteController.getInstance();
+
+        if (sc.isSatelliteBeingEnabled()) {
+            Rlog.d(TAG, "shouldBlockPremiumSmsInSatelliteMode: block premium sms when "
+                    + "satellite is being enabled");
+            return true;
+        }
+
+        if (sc.isSatelliteEnabled()) {
+            int satelliteSubId = sc.getSelectedSatelliteSubId();
+            int[] services = sc.getSupportedServicesOnCarrierRoamingNtn(satelliteSubId);
+            boolean isSmsSupported = ArrayUtils.contains(
+                    services, NetworkRegistrationInfo.SERVICE_TYPE_SMS);
+            Rlog.d(TAG, "shouldBlockPremiumSmsInSatelliteMode: satelliteSubId="
+                    + satelliteSubId + " isSmsSupported=" + isSmsSupported
+                    + " services=" + Arrays.toString(services));
+            return !isSmsSupported;
+        }
+
+        Rlog.d(TAG, "shouldBlockPremiumSmsInSatelliteMode: return false.");
+        return false;
+    }
+
     /**
      * Deny sending a single or a multi-part SMS if the outgoing queue limit is reached. Used when
      * the message must be confirmed by the user due to excessive usage or potential premium SMS
@@ -2498,7 +2543,8 @@
                     trackers[0].mMessageId,
                     trackers[0].isFromDefaultSmsApplication(mContext),
                     trackers[0].getInterval(),
-                    mTelephonyManager.isEmergencyNumber(trackers[0].mDestAddress));
+                    mTelephonyManager.isEmergencyNumber(trackers[0].mDestAddress),
+                    trackers[0].isMtSmsPollingMessage(mContext));
             if (mPhone != null) {
                 TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
                 if (telephonyAnalytics != null) {
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index c32db3d..7ca291f 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -360,6 +360,9 @@
     private Pattern mOperatorNameStringPattern;
     private PersistableBundle mCarrierConfig;
 
+    @NonNull
+    private final FeatureFlags mFeatureFlags;
+
     private class SstSubscriptionsChangedListener extends OnSubscriptionsChangedListener {
 
         /**
@@ -705,13 +708,15 @@
                 .makeNitzStateMachine(phone);
         mPhone = phone;
         mCi = ci;
+        mFeatureFlags = featureFlags;
 
         mServiceStateStats = new ServiceStateStats(mPhone);
 
         mCdnr = new CarrierDisplayNameResolver(mPhone);
 
         // Create EriManager only if phone supports CDMA
-        if (UiccController.isCdmaSupported(mPhone.getContext())) {
+        if (!mFeatureFlags.phoneTypeCleanup()
+                && UiccController.isCdmaSupported(mPhone.getContext())) {
             mEriManager = TelephonyComponentFactory.getInstance().inject(EriManager.class.getName())
                     .makeEriManager(mPhone, EriManager.ERI_FROM_XML);
         } else {
@@ -891,19 +896,24 @@
                 mCdmaSSM.dispose(this);
             }
 
-            mCi.unregisterForCdmaPrlChanged(this);
-            mCi.unregisterForCdmaOtaProvision(this);
+            if (!mFeatureFlags.phoneTypeCleanup()) {
+                mCi.unregisterForCdmaPrlChanged(this);
+                mCi.unregisterForCdmaOtaProvision(this);
+            }
             mPhone.unregisterForSimRecordsLoaded(this);
 
         } else {
             mPhone.registerForSimRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
-            mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(mPhone.getContext(), mCi, this,
-                    EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
-            mIsSubscriptionFromRuim = (mCdmaSSM.getCdmaSubscriptionSource() ==
-                    CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM);
+            if (!mFeatureFlags.phoneTypeCleanup()) {
+                mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(mPhone.getContext(), mCi, this,
+                        EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
 
-            mCi.registerForCdmaPrlChanged(this, EVENT_CDMA_PRL_VERSION_CHANGED, null);
-            mCi.registerForCdmaOtaProvision(this, EVENT_OTA_PROVISION_STATUS_CHANGE, null);
+                mIsSubscriptionFromRuim = mCdmaSSM.getCdmaSubscriptionSource()
+                        == CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM;
+
+                mCi.registerForCdmaPrlChanged(this, EVENT_CDMA_PRL_VERSION_CHANGED, null);
+                mCi.registerForCdmaOtaProvision(this, EVENT_OTA_PROVISION_STATUS_CHANGE, null);
+            }
 
             mHbpcdUtils = new HbpcdUtils(mPhone.getContext());
             // update OTASP state in case previously set by another service
@@ -1309,7 +1319,9 @@
                     mIsMinInfoReady = false;
 
                     // Remove the EF records that come from UICC.
-                    mCdnr.updateEfFromRuim(null /* ruim */);
+                    if (!mFeatureFlags.phoneTypeCleanup()) {
+                        mCdnr.updateEfFromRuim(null /* ruim */);
+                    }
                     mCdnr.updateEfFromUsim(null /* Usim */);
                 }
                 onUpdateIccAvailability();
@@ -1993,6 +2005,7 @@
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     protected void updateOtaspState() {
+        if (mFeatureFlags.phoneTypeCleanup()) return;
         int otaspMode = getOtasp();
         int oldOtaspMode = mCurrentOtaspMode;
         mCurrentOtaspMode = otaspMode;
@@ -3798,7 +3811,11 @@
         mNewSS.setOutOfService(false);
 
         mCellIdentity = primaryCellIdentity;
-        if (mSS.getState() == ServiceState.STATE_IN_SERVICE && primaryCellIdentity != null) {
+        boolean isCsRegistered = mSS.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_CS,
+                AccessNetworkConstants.TRANSPORT_TYPE_WWAN).isNetworkRegistered();
+        boolean isPsRegistered = mSS.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
+                AccessNetworkConstants.TRANSPORT_TYPE_WWAN).isNetworkRegistered();
+        if (isCsRegistered || isPsRegistered) {
             mLastKnownCellIdentity = mCellIdentity;
             removeMessages(EVENT_RESET_LAST_KNOWN_CELL_IDENTITY);
         }
@@ -3870,23 +3887,26 @@
 
             tm.setNetworkOperatorNumericForPhone(mPhone.getPhoneId(), operatorNumeric);
 
-            // If the OPERATOR command hasn't returned a valid operator or the device is on IWLAN (
-            // because operatorNumeric would be SIM's mcc/mnc when device is on IWLAN), but if the
-            // device has camped on a cell either to attempt registration or for emergency services,
-            // then for purposes of setting the locale, we don't care if registration fails or is
-            // incomplete. Additionally, if there is no cellular service and ims is registered over
-            // the IWLAN, the locale will not be updated.
-            // CellIdentity can return a null MCC and MNC in CDMA
-            String localeOperator = operatorNumeric;
-            int dataNetworkType = mSS.getDataNetworkType();
-            if (dataNetworkType == TelephonyManager.NETWORK_TYPE_IWLAN
-                    || (dataNetworkType == TelephonyManager.NETWORK_TYPE_UNKNOWN
-                            && getImsRegistrationTech()
-                                    == ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN)) {
-                // TODO(b/333346537#comment10): Complete solution would be ignore mcc/mnc reported
-                //  by the unsolicited indication OPERATOR from RIL, but only relies on MCC/MNC from
-                //  data registration or voice registration.
-                localeOperator = null;
+            String localeOperator = null;
+            if (!mFeatureFlags.ignoreMccMncFromOperatorForLocale()) {
+                // If the OPERATOR command hasn't returned a valid operator or the device is on
+                // IWLAN (because operatorNumeric would be SIM's mcc/mnc when device is on IWLAN),
+                // but if the device has camped on a cell either to attempt registration or for
+                // emergency services, then for purposes of setting the locale, we don't care if
+                // registration fails or is incomplete. Additionally, if there is no cellular
+                // service and ims is registered over the IWLAN, the locale will not be updated.
+                // CellIdentity can return a null MCC and MNC in CDMA
+                localeOperator = operatorNumeric;
+                int dataNetworkType = mSS.getDataNetworkType();
+                if (dataNetworkType == TelephonyManager.NETWORK_TYPE_IWLAN
+                        || (dataNetworkType == TelephonyManager.NETWORK_TYPE_UNKNOWN
+                        && getImsRegistrationTech()
+                        == ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN)) {
+                    // TODO(b/333346537#comment10): Complete solution would be ignore mcc/mnc
+                    //  reported by the unsolicited indication OPERATOR from RIL, but only relies on
+                    //  MCC/MNC from data registration or voice registration.
+                    localeOperator = null;
+                }
             }
             if (isInvalidOperatorNumeric(localeOperator)) {
                 for (CellIdentity cid : prioritizedCids) {
@@ -5352,6 +5372,7 @@
     }
 
     private void handleCdmaSubscriptionSource(int newSubscriptionSource) {
+        if (mFeatureFlags.phoneTypeCleanup()) return;
         log("Subscription Source : " + newSubscriptionSource);
         mIsSubscriptionFromRuim =
                 (newSubscriptionSource == CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM);
@@ -5684,6 +5705,7 @@
                         .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
                         .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
                         .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+                        .setAvailableServices(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA))
                         .build();
                 mNewSS.addNetworkRegistrationInfo(nri);
                 mNewSS.setOperatorAlphaLong(operator);
diff --git a/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java b/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java
index 12cc2fa..b6df9b2 100644
--- a/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java
+++ b/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java
@@ -407,7 +407,7 @@
                 if (mPhoneConfigurationManager.isVirtualDsdaEnabled() ||
                         phone.isImsServiceSimultaneousCallingSupportCapable(mContext)) {
                     // Check if the transport types of each phone support simultaneous IMS calling:
-                    int phone1TransportType = ((ImsPhone) phone.getImsPhone()).getTransportType();
+                    int phone1TransportType = getImsTransportType(phone);
                     if (phone1TransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
                         // The transport type of this phone is WLAN so all combos are supported:
                         continue;
@@ -461,8 +461,7 @@
     }
 
     private boolean phonesSupportSimultaneousCallingViaCellularOrWlan(Phone phone1, Phone phone2) {
-        int phone2TransportType =
-                ((ImsPhone) phone2.getImsPhone()).getTransportType();
+        int phone2TransportType = getImsTransportType(phone2);
         return phone2TransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN ||
                 phonesSupportCellularSimultaneousCalling(phone1, phone2);
     }
@@ -497,6 +496,16 @@
         }
     }
 
+    private @AccessNetworkConstants.TransportType int getImsTransportType(Phone phone) {
+        ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
+        if (imsPhone != null) {
+            return imsPhone.getTransportType();
+        }
+        Log.d(LOG_TAG, "getImsTransportType: IMS not supported for phone = "
+            + phone);
+        return AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+    }
+
     private String getStringFromMap(Map<Integer, Set<Phone>> phoneMap) {
         StringBuilder sb = new StringBuilder();
         for (Map.Entry<Integer, Set<Phone>> entry : phoneMap.entrySet()) {
diff --git a/src/java/com/android/internal/telephony/SmsController.java b/src/java/com/android/internal/telephony/SmsController.java
index 051fbbd..ab1eb31 100644
--- a/src/java/com/android/internal/telephony/SmsController.java
+++ b/src/java/com/android/internal/telephony/SmsController.java
@@ -1254,8 +1254,7 @@
             return;
         }
 
-        if (!mFlags.enforceTelephonyFeatureMappingForPublicApis()
-                || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+        if (!CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
                 Binder.getCallingUserHandle())
                 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
             // Skip to check associated telephony feature,
diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java
index de5cc53..43d7eda 100644
--- a/src/java/com/android/internal/telephony/SmsDispatchersController.java
+++ b/src/java/com/android/internal/telephony/SmsDispatchersController.java
@@ -85,6 +85,7 @@
 public class SmsDispatchersController extends Handler {
     private static final String TAG = "SmsDispatchersController";
     private static final boolean VDBG = false; // STOPSHIP if true
+    private static final boolean ENABLE_CDMA_DISPATCHER = true; // see b/388540508
 
     /** Radio is ON */
     private static final int EVENT_RADIO_ON = 11;
@@ -411,7 +412,7 @@
         mImsSmsDispatcher = new ImsSmsDispatcher(phone, this, ImsManager::getConnector);
         mGsmInboundSmsHandler = GsmInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
                 storageMonitor, phone, looper, mFeatureFlags);
-        if (!mFeatureFlags.cleanupCdma()) {
+        if (ENABLE_CDMA_DISPATCHER) {
             mCdmaDispatcher = new CdmaSMSDispatcher(phone, this);
             mCdmaInboundSmsHandler = CdmaInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
                     storageMonitor, phone, (CdmaSMSDispatcher) mCdmaDispatcher, looper,
@@ -1002,7 +1003,7 @@
      * @return true if Cdma format should be used for MO SMS, false otherwise.
      */
     protected boolean isCdmaMo() {
-        if (mFeatureFlags.cleanupCdma()) return false;
+        if (!ENABLE_CDMA_DISPATCHER) return false;
         if (!isIms()) {
             // IMS is not registered, use Voice technology to determine SMS format.
             return (PhoneConstants.PHONE_TYPE_CDMA == mPhone.getPhoneType());
@@ -1018,7 +1019,7 @@
      * @return true if format given is CDMA format, false otherwise.
      */
     public boolean isCdmaFormat(String format) {
-        if (mFeatureFlags.cleanupCdma()) return false;
+        if (!ENABLE_CDMA_DISPATCHER) return false;
         return (mCdmaDispatcher.getFormat().equals(format));
     }
 
diff --git a/src/java/com/android/internal/telephony/TelephonyCapabilities.java b/src/java/com/android/internal/telephony/TelephonyCapabilities.java
index b650b43..35c862f 100644
--- a/src/java/com/android/internal/telephony/TelephonyCapabilities.java
+++ b/src/java/com/android/internal/telephony/TelephonyCapabilities.java
@@ -207,9 +207,7 @@
         // Check SDK version of the vendor partition.
         final int vendorApiLevel = SystemProperties.getInt(
                 "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT);
-        if (vendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) return false;
-
-        return featureFlags.minimalTelephonyCdmCheck();
+        return vendorApiLevel >= Build.VERSION_CODES.VANILLA_ICE_CREAM;
     }
 
     /**
@@ -221,4 +219,14 @@
         return context.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_TELEPHONY_CALLING);
     }
+
+    /**
+     * @return true if this device supports telephony messaging, false if it does not.
+     */
+    public static boolean supportsTelephonyMessaging(@NonNull FeatureFlags featureFlags,
+            Context context) {
+        if (!TelephonyCapabilities.minimalTelephonyCdmCheck(featureFlags)) return true;
+        return context.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_TELEPHONY_MESSAGING);
+    }
 }
diff --git a/src/java/com/android/internal/telephony/TelephonyCountryDetector.java b/src/java/com/android/internal/telephony/TelephonyCountryDetector.java
index 1e07bc3..542964c 100644
--- a/src/java/com/android/internal/telephony/TelephonyCountryDetector.java
+++ b/src/java/com/android/internal/telephony/TelephonyCountryDetector.java
@@ -43,6 +43,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.util.WorkerThread;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -205,12 +206,19 @@
     public static synchronized TelephonyCountryDetector getInstance(@NonNull Context context,
             FeatureFlags featureFlags) {
         if (sInstance == null) {
-            HandlerThread handlerThread = new HandlerThread("TelephonyCountryDetector");
-            handlerThread.start();
-            sInstance = new TelephonyCountryDetector(handlerThread.getLooper(), context,
-                    context.getSystemService(LocationManager.class),
-                    context.getSystemService(ConnectivityManager.class),
-                    featureFlags);
+            if (featureFlags.threadShred()) {
+                sInstance = new TelephonyCountryDetector(WorkerThread.get().getLooper(), context,
+                        context.getSystemService(LocationManager.class),
+                        context.getSystemService(ConnectivityManager.class),
+                        featureFlags);
+            } else {
+                HandlerThread handlerThread = new HandlerThread("TelephonyCountryDetector");
+                handlerThread.start();
+                sInstance = new TelephonyCountryDetector(handlerThread.getLooper(), context,
+                        context.getSystemService(LocationManager.class),
+                        context.getSystemService(ConnectivityManager.class),
+                        featureFlags);
+            }
         }
         return sInstance;
     }
@@ -482,12 +490,8 @@
             }
         }
         evaluateRequestingLocationUpdates();
-        if (mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("mCountryCodeChangedRegistrants.notifyRegistrants()");
-            mCountryCodeChangedRegistrants.notifyRegistrants();
-        } else {
-            logd("mCountryCodeChangedRegistrants.notifyRegistrants() is not called");
-        }
+        logd("mCountryCodeChangedRegistrants.notifyRegistrants()");
+        mCountryCodeChangedRegistrants.notifyRegistrants();
     }
 
     private void handleEventWifiConnectivityStateChanged(boolean connected) {
diff --git a/src/java/com/android/internal/telephony/VoiceIndication.java b/src/java/com/android/internal/telephony/VoiceIndication.java
index 9720bb7..6ae6470 100644
--- a/src/java/com/android/internal/telephony/VoiceIndication.java
+++ b/src/java/com/android/internal/telephony/VoiceIndication.java
@@ -40,6 +40,7 @@
 
 import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
 import com.android.internal.telephony.cdma.CdmaInformationRecords;
+import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.gsm.SsData;
 
 import java.util.ArrayList;
@@ -106,6 +107,7 @@
      */
     public void cdmaCallWaiting(int indicationType,
             android.hardware.radio.voice.CdmaCallWaiting callWaitingRecord) {
+        if (Flags.phoneTypeCleanup()) return;
         mRil.processIndication(HAL_SERVICE_VOICE, indicationType);
 
         // TODO: create a CdmaCallWaitingNotification constructor that takes in these fields to make
@@ -136,6 +138,7 @@
      */
     public void cdmaInfoRec(int indicationType,
             android.hardware.radio.voice.CdmaInformationRecord[] records) {
+        if (Flags.phoneTypeCleanup()) return;
         mRil.processIndication(HAL_SERVICE_VOICE, indicationType);
 
         for (int i = 0; i < records.length; i++) {
@@ -235,6 +238,7 @@
      * @param status CDMA OTA provision status
      */
     public void cdmaOtaProvisionStatus(int indicationType, int status) {
+        if (Flags.phoneTypeCleanup()) return;
         mRil.processIndication(HAL_SERVICE_VOICE, indicationType);
 
         int[] response = new int[] {status};
diff --git a/src/java/com/android/internal/telephony/analytics/TelephonyAnalytics.java b/src/java/com/android/internal/telephony/analytics/TelephonyAnalytics.java
index e74e40e..063ee45 100644
--- a/src/java/com/android/internal/telephony/analytics/TelephonyAnalytics.java
+++ b/src/java/com/android/internal/telephony/analytics/TelephonyAnalytics.java
@@ -47,10 +47,12 @@
 import android.telephony.ims.ImsReasonInfo;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
 
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.telephony.InboundSmsHandler;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.flags.Flags;
 import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
@@ -116,9 +118,14 @@
         mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
         mSlotIndex = mPhone.getPhoneId();
 
-        mHandlerThread = new HandlerThread(TelephonyAnalytics.class.getSimpleName());
-        mHandlerThread.start();
-        mHandler = new Handler(mHandlerThread.getLooper());
+        if (Flags.threadShred()) {
+            mHandlerThread = null; // TODO: maybe this doesn't need to be a member variable
+            mHandler = new Handler(BackgroundThread.get().getLooper());
+        } else {
+            mHandlerThread = new HandlerThread(TelephonyAnalytics.class.getSimpleName());
+            mHandlerThread.start();
+            mHandler = new Handler(mHandlerThread.getLooper());
+        }
         mExecutorService = Executors.newSingleThreadExecutor();
         mTelephonyAnalyticsUtil = TelephonyAnalyticsUtil.getInstance(mContext);
         initializeAnalyticsClasses();
diff --git a/src/java/com/android/internal/telephony/cat/CatService.java b/src/java/com/android/internal/telephony/cat/CatService.java
index 5fdb8ce..569a9c3 100644
--- a/src/java/com/android/internal/telephony/cat/CatService.java
+++ b/src/java/com/android/internal/telephony/cat/CatService.java
@@ -62,6 +62,7 @@
 import com.android.internal.telephony.uicc.UiccCardApplication;
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.telephony.uicc.UiccProfile;
+import com.android.internal.telephony.util.WorkerThread;
 
 import java.io.ByteArrayOutputStream;
 import java.util.List;
@@ -228,9 +229,11 @@
      */
     public static CatService getInstance(CommandsInterface ci,
             Context context, UiccProfile uiccProfile, int slotId) {
-        if (sCatServiceThread == null) {
-            sCatServiceThread = new HandlerThread("CatServiceThread");
-            sCatServiceThread.start();
+        if (!sFlags.threadShred()) {
+            if (sCatServiceThread == null) {
+                sCatServiceThread = new HandlerThread("CatServiceThread");
+                sCatServiceThread.start();
+            }
         }
         UiccCardApplication ca = null;
         IccFileHandler fh = null;
@@ -259,8 +262,13 @@
                         || uiccProfile == null) {
                     return null;
                 }
-                sInstance[slotId] = new CatService(ci, ca, ir, context, fh, uiccProfile, slotId,
-                        sCatServiceThread.getLooper());
+                if (sFlags.threadShred()) {
+                    sInstance[slotId] = new CatService(ci, ca, ir, context, fh, uiccProfile, slotId,
+                            WorkerThread.get().getLooper());
+                } else {
+                    sInstance[slotId] = new CatService(ci, ca, ir, context, fh, uiccProfile, slotId,
+                            sCatServiceThread.getLooper());
+                }
             } else if ((ir != null) && (mIccRecords != ir)) {
                 if (mIccRecords != null) {
                     mIccRecords.unregisterForRecordsLoaded(sInstance[slotId]);
diff --git a/src/java/com/android/internal/telephony/configupdate/ConfigParser.java b/src/java/com/android/internal/telephony/configupdate/ConfigParser.java
index 5c3ac86..f7691da 100644
--- a/src/java/com/android/internal/telephony/configupdate/ConfigParser.java
+++ b/src/java/com/android/internal/telephony/configupdate/ConfigParser.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.util.Log;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -25,6 +26,7 @@
 import java.io.InputStream;
 
 public abstract class ConfigParser<T> {
+    private static final String TAG = "ConfigParser";
 
     public static final int VERSION_UNKNOWN = -1;
 
@@ -97,4 +99,13 @@
      * @param data the config data
      */
     protected abstract void parseData(@Nullable byte[] data);
+
+
+    /**
+     * This API is used by CTS to override the version
+     */
+    protected void overrideVersion(int version) {
+        mVersion = version;
+        Log.d(TAG, "overrideVersion: mVersion=" + mVersion);
+    }
 }
diff --git a/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java b/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
index 85413f5..8a34ec1 100644
--- a/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
+++ b/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
@@ -34,6 +34,7 @@
 
 import libcore.io.IoUtils;
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.util.Iterator;
@@ -51,16 +52,21 @@
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected static final String NEW_CONFIG_CONTENT_PATH = "new_telephony_config.pb";
     protected static final String VALID_CONFIG_CONTENT_PATH = "valid_telephony_config.pb";
+    private static final String BACKUP_CONTENT_PATH = "backup_telephony_config.pb";
+
     protected static final String UPDATE_METADATA_PATH = "metadata/";
     public static final String VERSION = "version";
+    public static final String BACKUP_VERSION = "backup_version";
 
     private ConcurrentHashMap<Executor, Callback> mCallbackHashMap = new ConcurrentHashMap<>();
     @NonNull
     private final Object mConfigParserLock = new Object();
     @GuardedBy("mConfigParserLock")
     private ConfigParser mConfigParser;
-    @NonNull private final ConfigUpdaterMetricsStats mConfigUpdaterMetricsStats;
+    @NonNull
+    private final ConfigUpdaterMetricsStats mConfigUpdaterMetricsStats;
 
+    private int mOriginalVersion;
 
     public static TelephonyConfigUpdateInstallReceiver sReceiverAdaptorInstance =
             new TelephonyConfigUpdateInstallReceiver();
@@ -138,6 +144,10 @@
     @Override
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
     public void postInstall(Context context, Intent intent) {
+        postInstall();
+    }
+
+    private void postInstall() {
         Log.d(TAG, "Telephony config is updated in file partition");
 
         ConfigParser newConfigParser = getNewConfigParser(DOMAIN_SATELLITE,
@@ -157,17 +167,19 @@
             if (getInstance().mConfigParser != null) {
                 int updatedVersion = newConfigParser.mVersion;
                 int previousVersion = getInstance().mConfigParser.mVersion;
-                Log.d(TAG, "previous version is " + previousVersion + " | updated version is "
-                        + updatedVersion);
-                mConfigUpdaterMetricsStats.setConfigVersion(updatedVersion);
+                Log.d(TAG, "previous proto version is " + previousVersion
+                        + " | updated proto version is " + updatedVersion);
+
                 if (updatedVersion <= previousVersion) {
-                    Log.e(TAG, "updatedVersion is smaller than previousVersion");
+                    Log.e(TAG, "updated proto Version [" + updatedVersion
+                            + "] is smaller than previous proto Version [" + previousVersion + "]");
                     mConfigUpdaterMetricsStats.reportOemAndCarrierConfigError(
                             SatelliteConstants.CONFIG_UPDATE_RESULT_INVALID_VERSION);
                     return;
                 }
             }
             getInstance().mConfigParser = newConfigParser;
+            mConfigUpdaterMetricsStats.setConfigVersion(getInstance().mConfigParser.getVersion());
         }
 
         if (!getInstance().mCallbackHashMap.keySet().isEmpty()) {
@@ -246,8 +258,6 @@
     public ConfigParser getNewConfigParser(String domain, @Nullable byte[] data) {
         if (data == null) {
             Log.d(TAG, "content data is null");
-            mConfigUpdaterMetricsStats.reportOemAndCarrierConfigError(
-                    SatelliteConstants.CONFIG_UPDATE_RESULT_NO_DATA);
             return null;
         }
         switch (domain) {
@@ -291,4 +301,125 @@
         Log.d(TAG, "source file is not exist, no file to copy");
         return false;
     }
+
+    /**
+     * This API should be used by only CTS/unit tests to reset the telephony configs set through
+     * config updater
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public boolean cleanUpTelephonyConfigs() {
+        Log.d(TAG, "cleanTelephonyConfigs: resetting the telephony configs");
+        try {
+            // metadata/version
+            File updateMetadataDir = new File(updateDir, UPDATE_METADATA_PATH);
+            writeUpdate(
+                    updateMetadataDir,
+                    updateVersion,
+                    new ByteArrayInputStream(Integer.toString(-1).getBytes()));
+
+            // new_telephony_config.pb
+            writeUpdate(updateDir, updateContent, new ByteArrayInputStream(new byte[]{}));
+
+            // valid_telephony_config.pb
+            File validConfigContentPath = new File(updateDir, VALID_CONFIG_CONTENT_PATH);
+            writeUpdate(updateDir, validConfigContentPath, new ByteArrayInputStream(new byte[]{}));
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to clean telephony config files: " + e);
+            return false;
+        }
+
+        Log.d(TAG, "cleanTelephonyConfigs: resetting the config parser");
+        synchronized (getInstance().mConfigParserLock) {
+            getInstance().mConfigParser = null;
+        }
+        return true;
+    }
+
+
+    /**
+     * This API is used by CTS to override the version of the config data
+     *
+     * @param reset   Whether to restore the original version
+     * @param version The overriding version
+     * @return {@code true} if successful, {@code false} otherwise
+     */
+    public boolean overrideVersion(boolean reset, int version) {
+        Log.d(TAG, "overrideVersion: reset=" + reset + ", version=" + version);
+        if (reset) {
+            version = mOriginalVersion;
+            if (!restoreContentData()) {
+                return false;
+            }
+        } else {
+            mOriginalVersion = version;
+            if (!backupContentData()) {
+                return false;
+            }
+        }
+        return overrideVersion(version);
+    }
+
+    private boolean overrideVersion(int version) {
+        synchronized (getInstance().mConfigParserLock) {
+            try {
+                writeUpdate(updateDir, updateVersion,
+                        new ByteArrayInputStream(Long.toString(version).getBytes()));
+                if (getInstance().mConfigParser != null) {
+                    getInstance().mConfigParser.overrideVersion(version);
+                }
+            } catch (IOException e) {
+                Log.e(TAG, "overrideVersion: e=" + e);
+                return false;
+            }
+            return true;
+        }
+    }
+
+    private boolean isFileExists(@NonNull String fileName) {
+        Log.d(TAG, "isFileExists");
+        if (fileName == null) {
+            Log.d(TAG, "fileName cannot be null");
+            return false;
+        }
+        File sourceFile = new File(UPDATE_DIR, fileName);
+        return sourceFile.exists() && sourceFile.isFile();
+    }
+
+    private boolean backupContentData() {
+        if (!isFileExists(VALID_CONFIG_CONTENT_PATH)) {
+            Log.d(TAG, VALID_CONFIG_CONTENT_PATH + " is not exit, no need to backup");
+            return true;
+        }
+        if (!copySourceFileToTargetFile(VALID_CONFIG_CONTENT_PATH, BACKUP_CONTENT_PATH)) {
+            Log.e(TAG, "backupContentData: fail to backup the config data");
+            return false;
+        }
+        if (!copySourceFileToTargetFile(UPDATE_METADATA_PATH + VERSION,
+                UPDATE_METADATA_PATH + BACKUP_VERSION)) {
+            Log.e(TAG, "bakpuackupContentData: fail to backup the version");
+            return false;
+        }
+        Log.d(TAG, "backupContentData: backup success");
+        return true;
+    }
+
+    private boolean restoreContentData() {
+        if (!isFileExists(BACKUP_CONTENT_PATH)) {
+            Log.d(TAG, BACKUP_CONTENT_PATH + " is not exit, no need to restore");
+            return true;
+        }
+        if (!copySourceFileToTargetFile(BACKUP_CONTENT_PATH, NEW_CONFIG_CONTENT_PATH)) {
+            Log.e(TAG, "restoreContentData: fail to restore the config data");
+            return false;
+        }
+        if (!copySourceFileToTargetFile(UPDATE_METADATA_PATH + BACKUP_VERSION,
+                UPDATE_METADATA_PATH + VERSION)) {
+            Log.e(TAG, "restoreContentData: fail to restore the version");
+            return false;
+        }
+        Log.d(TAG, "restoreContentData: populate the data to SatelliteController");
+        postInstall();
+        Log.d(TAG, "restoreContentData: success");
+        return true;
+    }
 }
diff --git a/src/java/com/android/internal/telephony/data/AccessNetworksManager.java b/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
index 2691eab..65c462a 100644
--- a/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
+++ b/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
@@ -56,7 +56,6 @@
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.SlidingWindowEventCounter;
 import com.android.internal.telephony.flags.FeatureFlags;
-import com.android.internal.util.FunctionalUtils;
 import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
@@ -324,12 +323,6 @@
         public void onNetworkValidationRequested(@NetCapability int networkCapability,
                 @NonNull IIntegerConsumer resultCodeCallback) {
             DataNetworkController dnc = mPhone.getDataNetworkController();
-            if (!mFeatureFlags.networkValidation()) {
-                FunctionalUtils.ignoreRemoteException(resultCodeCallback::accept)
-                        .accept(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
-                return;
-            }
-
             log("onNetworkValidationRequested: networkCapability = ["
                     + DataUtils.networkCapabilityToString(networkCapability) + "]");
 
@@ -347,13 +340,11 @@
 
         @Override
         public void onReconnectQualifiedNetworkType(int apnTypes, int qualifiedNetworkType) {
-            if (mFeatureFlags.reconnectQualifiedNetwork()) {
-                log("onReconnectQualifiedNetworkType: apnTypes = ["
-                        + ApnSetting.getApnTypesStringFromBitmask(apnTypes)
-                        + "], networks = [" + AccessNetworkType.toString(qualifiedNetworkType)
-                        + "]");
-                handleQualifiedNetworksChanged(apnTypes, new int[]{qualifiedNetworkType}, true);
-            }
+            log("onReconnectQualifiedNetworkType: apnTypes = ["
+                    + ApnSetting.getApnTypesStringFromBitmask(apnTypes)
+                    + "], networks = [" + AccessNetworkType.toString(qualifiedNetworkType)
+                    + "]");
+            handleQualifiedNetworksChanged(apnTypes, new int[]{qualifiedNetworkType}, true);
         }
     }
 
diff --git a/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java b/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java
index 7131583..9c224dc 100644
--- a/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java
+++ b/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java
@@ -230,12 +230,6 @@
      * even if ping test fails.
      */
     private boolean mRequirePingTestBeforeSwitch = true;
-    /**
-     * TODO: remove after V.
-     * To indicate whether allow using roaming nDDS if user enabled its roaming when the DDS is not
-     * usable(OOS or disabled roaming)
-     */
-    private boolean mAllowNddsRoaming = true;
     /** The count of consecutive auto switch validation failure **/
     private int mAutoSwitchValidationFailedCount = 0;
     /**
@@ -308,22 +302,23 @@
          */
         private UsableState getUsableState() {
             ServiceState serviceState = mPhone.getServiceState();
-            boolean isUsingNonTerrestrialNetwork = sFeatureFlags.carrierEnabledSatelliteFlag()
-                    && (serviceState != null) && serviceState.isUsingNonTerrestrialNetwork();
+            boolean isUsingNonTerrestrialNetwork =
+                    (serviceState != null) && serviceState.isUsingNonTerrestrialNetwork();
 
             return switch (mDataRegState) {
-                case NetworkRegistrationInfo.REGISTRATION_STATE_HOME -> {
-                    if (isUsingNonTerrestrialNetwork) {
-                        yield UsableState.NON_TERRESTRIAL;
-                    }
-                    yield UsableState.HOME;
-                }
+                case NetworkRegistrationInfo.REGISTRATION_STATE_HOME ->
+                        isUsingNonTerrestrialNetwork
+                                ? UsableState.NON_TERRESTRIAL : UsableState.HOME;
                 case NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING -> {
+                    // Satellite may bypass User's roaming settings
+                    if (isUsingNonTerrestrialNetwork) {
+                        boolean byPassRoamingSettings = mPhone.getDataNetworkController()
+                                .getDataConfigManager().isIgnoringDataRoamingSettingForSatellite();
+                        if (byPassRoamingSettings) yield UsableState.NON_TERRESTRIAL;
+                    }
                     if (mPhone.getDataRoamingEnabled()) {
-                        if (isUsingNonTerrestrialNetwork) {
-                            yield UsableState.NON_TERRESTRIAL;
-                        }
-                        yield UsableState.ROAMING_ENABLED;
+                        yield isUsingNonTerrestrialNetwork
+                                ? UsableState.NON_TERRESTRIAL : UsableState.ROAMING_ENABLED;
                     }
                     yield UsableState.NOT_USABLE;
                 }
@@ -492,9 +487,8 @@
     private void readDeviceResourceConfig() {
         Phone phone = PhoneFactory.getDefaultPhone();
         DataConfigManager dataConfig = phone.getDataNetworkController().getDataConfigManager();
-        mScoreTolerance =  dataConfig.getAutoDataSwitchScoreTolerance();
+        mScoreTolerance = dataConfig.getAutoDataSwitchScoreTolerance();
         mRequirePingTestBeforeSwitch = dataConfig.isPingTestBeforeAutoDataSwitchRequired();
-        mAllowNddsRoaming = dataConfig.doesAutoDataSwitchAllowRoaming();
         STABILITY_CHECK_TIMER_MAP.put(STABILITY_CHECK_AVAILABILITY_SWITCH,
                 dataConfig.getAutoDataSwitchAvailabilityStabilityTimeThreshold());
         STABILITY_CHECK_TIMER_MAP.put(STABILITY_CHECK_PERFORMANCE_SWITCH,
@@ -513,29 +507,29 @@
         Object obj;
         int phoneId;
         switch (msg.what) {
-            case EVENT_SERVICE_STATE_CHANGED:
+            case EVENT_SERVICE_STATE_CHANGED -> {
                 ar = (AsyncResult) msg.obj;
                 phoneId = (int) ar.userObj;
                 onServiceStateChanged(phoneId);
-                break;
-            case EVENT_DISPLAY_INFO_CHANGED:
+            }
+            case EVENT_DISPLAY_INFO_CHANGED -> {
                 ar = (AsyncResult) msg.obj;
                 phoneId = (int) ar.userObj;
                 onDisplayInfoChanged(phoneId);
-                break;
-            case EVENT_SIGNAL_STRENGTH_CHANGED:
+            }
+            case EVENT_SIGNAL_STRENGTH_CHANGED -> {
                 ar = (AsyncResult) msg.obj;
                 phoneId = (int) ar.userObj;
                 onSignalStrengthChanged(phoneId);
-                break;
-            case EVENT_EVALUATE_AUTO_SWITCH:
+            }
+            case EVENT_EVALUATE_AUTO_SWITCH -> {
                 obj = mScheduledEventsToExtras.get(EVENT_EVALUATE_AUTO_SWITCH);
                 if (obj instanceof EvaluateEventExtra extra) {
                     mScheduledEventsToExtras.remove(EVENT_EVALUATE_AUTO_SWITCH);
                     onEvaluateAutoDataSwitch(extra.evaluateReason);
                 }
-                break;
-            case EVENT_STABILITY_CHECK_PASSED:
+            }
+            case EVENT_STABILITY_CHECK_PASSED -> {
                 obj = mScheduledEventsToExtras.get(EVENT_STABILITY_CHECK_PASSED);
                 if (obj instanceof StabilityEventExtra extra) {
                     int targetPhoneId = extra.targetPhoneId;
@@ -545,12 +539,9 @@
                     mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED);
                     mPhoneSwitcherCallback.onRequireValidation(targetPhoneId, needValidation);
                 }
-                break;
-            case EVENT_SUBSCRIPTIONS_CHANGED:
-                onSubscriptionsChanged();
-                break;
-            default:
-                loge("Unexpected event " + msg.what);
+            }
+            case EVENT_SUBSCRIPTIONS_CHANGED -> onSubscriptionsChanged();
+            default -> loge("Unexpected event " + msg.what);
         }
     }
 
@@ -648,7 +639,12 @@
             int currentScore = mPhonesSignalStatus[preferredPhoneId].getRatSignalScore();
             for (int phoneId = 0; phoneId < mPhonesSignalStatus.length; phoneId++) {
                 if (phoneId == preferredPhoneId) continue;
-                int candidateScore = mPhonesSignalStatus[phoneId].getRatSignalScore();
+                PhoneSignalStatus candidateStatus = mPhonesSignalStatus[phoneId];
+                // Ignore non-home phone.
+                if (candidateStatus.getUsableState() != PhoneSignalStatus.UsableState.HOME) {
+                    continue;
+                }
+                int candidateScore = candidateStatus.getRatSignalScore();
                 if ((candidateScore - currentScore) > mScoreTolerance
                         // Also reevaluate if DDS has the same score as the current phone.
                         || (candidateScore >= currentScore && phoneId == ddsPhoneId)) {
@@ -720,120 +716,87 @@
             }
 
             DataEvaluation internetEvaluation;
-            if (sFeatureFlags.autoDataSwitchUsesDataEnabled()) {
-                if (!defaultDataPhone.isUserDataEnabled()) {
-                    mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX,
-                            EVALUATION_REASON_DATA_SETTINGS_CHANGED);
-                    log(debugMessage.append(
-                            ", immediately back to default as user turns off default").toString());
-                    return;
-                } else if (!(internetEvaluation = getInternetEvaluation(backupDataPhone))
-                        .isSubsetOf(DataEvaluation.DataDisallowedReason.NOT_IN_SERVICE)) {
-                    mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(
-                            DEFAULT_PHONE_INDEX, EVALUATION_REASON_DATA_SETTINGS_CHANGED);
-                    log(debugMessage.append(
-                                    ", immediately back to default because backup ")
-                            .append(internetEvaluation).toString());
-                    return;
-                }
-            } else {
-                if (!defaultDataPhone.isUserDataEnabled() || !backupDataPhone.isDataAllowed()) {
-                    mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX,
-                            EVALUATION_REASON_DATA_SETTINGS_CHANGED);
-                    log(debugMessage.append(
-                            ", immediately back to default as user turns off settings").toString());
-                    return;
-                }
+            if (!defaultDataPhone.isUserDataEnabled()) {
+                mSelectedTargetPhoneId = INVALID_PHONE_INDEX;
+                mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX,
+                        EVALUATION_REASON_DATA_SETTINGS_CHANGED);
+                cancelAnyPendingSwitch();
+                log(debugMessage.append(
+                        ", immediately back to default as user turns off default").toString());
+                return;
+            } else if (!(internetEvaluation = getInternetEvaluation(backupDataPhone))
+                    .isSubsetOf(DataEvaluation.DataDisallowedReason.NOT_IN_SERVICE)) {
+                mSelectedTargetPhoneId = INVALID_PHONE_INDEX;
+                mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(
+                        DEFAULT_PHONE_INDEX, EVALUATION_REASON_DATA_SETTINGS_CHANGED);
+                cancelAnyPendingSwitch();
+                log(debugMessage.append(
+                                ", immediately back to default because backup ")
+                        .append(internetEvaluation).toString());
+                return;
             }
 
             boolean backToDefault = false;
             int switchType = STABILITY_CHECK_AVAILABILITY_SWITCH;
             boolean needValidation = true;
 
-            if (isNddsRoamingEnabled()) {
-                if (mDefaultNetworkIsOnNonCellular) {
-                    debugMessage.append(", back to default as default network")
-                            .append(" is active on nonCellular transport");
+            if (mDefaultNetworkIsOnNonCellular) {
+                debugMessage.append(", back to default as default network")
+                        .append(" is active on nonCellular transport");
+                backToDefault = true;
+                needValidation = false;
+            } else {
+                PhoneSignalStatus.UsableState defaultUsableState =
+                        mPhonesSignalStatus[defaultDataPhoneId].getUsableState();
+                PhoneSignalStatus.UsableState currentUsableState =
+                        mPhonesSignalStatus[preferredPhoneId].getUsableState();
+
+                boolean isCurrentUsable = currentUsableState.mScore
+                        > PhoneSignalStatus.UsableState.NOT_USABLE.mScore;
+
+                if (currentUsableState.mScore < defaultUsableState.mScore) {
+                    debugMessage.append(", back to default phone ").append(preferredPhoneId)
+                            .append(" : ").append(defaultUsableState)
+                            .append(" , backup phone: ").append(currentUsableState);
+
                     backToDefault = true;
-                    needValidation = false;
-                } else {
-                    PhoneSignalStatus.UsableState defaultUsableState =
-                            mPhonesSignalStatus[defaultDataPhoneId].getUsableState();
-                    PhoneSignalStatus.UsableState currentUsableState =
-                            mPhonesSignalStatus[preferredPhoneId].getUsableState();
+                    // Require validation if the current preferred phone is usable.
+                    needValidation = isCurrentUsable && mRequirePingTestBeforeSwitch;
+                } else if (defaultUsableState.mScore == currentUsableState.mScore) {
+                    debugMessage.append(", default phone ").append(preferredPhoneId)
+                            .append(" : ").append(defaultUsableState)
+                            .append(" , backup phone: ").append(currentUsableState);
 
-                    boolean isCurrentUsable = currentUsableState.mScore
-                            > PhoneSignalStatus.UsableState.NOT_USABLE.mScore;
-
-                    if (currentUsableState.mScore < defaultUsableState.mScore) {
-                        debugMessage.append(", back to default phone ").append(preferredPhoneId)
-                                .append(" : ").append(defaultUsableState)
-                                .append(" , backup phone: ").append(currentUsableState);
-
-                        backToDefault = true;
-                        // Require validation if the current preferred phone is usable.
-                        needValidation = isCurrentUsable && mRequirePingTestBeforeSwitch;
-                    } else if (defaultUsableState.mScore == currentUsableState.mScore) {
-                        debugMessage.append(", default phone ").append(preferredPhoneId)
-                                .append(" : ").append(defaultUsableState)
-                                .append(" , backup phone: ").append(currentUsableState);
-
-                        if (isCurrentUsable) {
-                            // Both phones are usable.
-                            if (isRatSignalStrengthBasedSwitchEnabled()) {
-                                int defaultScore = mPhonesSignalStatus[defaultDataPhoneId]
-                                        .getRatSignalScore();
-                                int currentScore = mPhonesSignalStatus[preferredPhoneId]
-                                        .getRatSignalScore();
-                                if (defaultScore >= currentScore) {
-                                    debugMessage
-                                            .append(", back to default for higher or equal score ")
-                                            .append(defaultScore).append(" versus current ")
-                                            .append(currentScore);
-                                    backToDefault = true;
-                                    switchType = STABILITY_CHECK_PERFORMANCE_SWITCH;
-                                    needValidation = mRequirePingTestBeforeSwitch;
-                                }
-                            } else {
-                                // Only OOS/in service switch is enabled, switch back.
-                                debugMessage.append(", back to default as it's usable. ");
+                    if (isCurrentUsable) {
+                        // Both phones are usable.
+                        if (isRatSignalStrengthBasedSwitchEnabled()
+                                && currentUsableState == PhoneSignalStatus.UsableState.HOME
+                                && defaultUsableState == PhoneSignalStatus.UsableState.HOME) {
+                            int defaultScore = mPhonesSignalStatus[defaultDataPhoneId]
+                                    .getRatSignalScore();
+                            int currentScore = mPhonesSignalStatus[preferredPhoneId]
+                                    .getRatSignalScore();
+                            if (defaultScore >= currentScore) {
+                                debugMessage
+                                        .append(", back to default for higher or equal score ")
+                                        .append(defaultScore).append(" versus current ")
+                                        .append(currentScore);
                                 backToDefault = true;
+                                switchType = STABILITY_CHECK_PERFORMANCE_SWITCH;
                                 needValidation = mRequirePingTestBeforeSwitch;
                             }
                         } else {
-                            debugMessage.append(", back to default as both phones are unusable.");
+                            // Only OOS/in service switch is enabled, switch back.
+                            debugMessage.append(", back to default as it's usable. ");
                             backToDefault = true;
-                            switchType = STABILITY_CHECK_AVAILABILITY_SWITCH_BACK;
-                            needValidation = false;
+                            needValidation = mRequirePingTestBeforeSwitch;
                         }
-                    }
-                }
-            } else {
-                if (mDefaultNetworkIsOnNonCellular) {
-                    debugMessage.append(", back to default as default network")
-                            .append(" is active on nonCellular transport");
-                    backToDefault = true;
-                    needValidation = false;
-                } else if (!isHomeService(mPhonesSignalStatus[preferredPhoneId].mDataRegState)) {
-                    debugMessage.append(", back to default as backup phone lost HOME registration");
-                    backToDefault = true;
-                    needValidation = false;
-                } else if (isRatSignalStrengthBasedSwitchEnabled()) {
-                    int defaultScore = mPhonesSignalStatus[defaultDataPhoneId].getRatSignalScore();
-                    int currentScore = mPhonesSignalStatus[preferredPhoneId].getRatSignalScore();
-                    if (defaultScore >= currentScore) {
-                        debugMessage
-                                .append(", back to default as default has higher or equal score ")
-                                .append(defaultScore).append(" versus current ")
-                                .append(currentScore);
+                    } else {
+                        debugMessage.append(", back to default as both phones are unusable.");
                         backToDefault = true;
-                        switchType = STABILITY_CHECK_PERFORMANCE_SWITCH;
-                        needValidation = mRequirePingTestBeforeSwitch;
+                        switchType = STABILITY_CHECK_AVAILABILITY_SWITCH_BACK;
+                        needValidation = false;
                     }
-                } else if (isInService(mPhonesSignalStatus[defaultDataPhoneId].mDataRegState)) {
-                    debugMessage.append(", back to default as the default is back to service ");
-                    backToDefault = true;
-                    needValidation = mRequirePingTestBeforeSwitch;
                 }
             }
 
@@ -877,20 +840,11 @@
             return invalidResult;
         }
 
-        if (isNddsRoamingEnabled()) {
-            // check whether primary and secondary signal status are worth switching
-            if (!isRatSignalStrengthBasedSwitchEnabled()
-                    && isHomeService(mPhonesSignalStatus[defaultPhoneId].mDataRegState)) {
-                debugMessage.append(", no candidate as default phone is in HOME service");
-                return invalidResult;
-            }
-        } else {
-            // check whether primary and secondary signal status are worth switching
-            if (!isRatSignalStrengthBasedSwitchEnabled()
-                    && isInService(mPhonesSignalStatus[defaultPhoneId].mDataRegState)) {
-                debugMessage.append(", no candidate as default phone is in service");
-                return invalidResult;
-            }
+        // check whether primary and secondary signal status are worth switching
+        if (!isRatSignalStrengthBasedSwitchEnabled()
+                && isHomeService(mPhonesSignalStatus[defaultPhoneId].mDataRegState)) {
+            debugMessage.append(", no candidate as default phone is in HOME service");
+            return invalidResult;
         }
 
         PhoneSignalStatus defaultPhoneStatus = mPhonesSignalStatus[defaultPhoneId];
@@ -899,57 +853,31 @@
 
             Phone secondaryDataPhone = null;
             PhoneSignalStatus candidatePhoneStatus = mPhonesSignalStatus[phoneId];
-            if (isNddsRoamingEnabled()) {
-                PhoneSignalStatus.UsableState currentUsableState =
-                        mPhonesSignalStatus[defaultPhoneId].getUsableState();
-                PhoneSignalStatus.UsableState candidateUsableState =
-                        mPhonesSignalStatus[phoneId].getUsableState();
-                debugMessage.append(", found phone ").append(phoneId).append(" ")
-                        .append(candidateUsableState)
-                        .append(", default is ").append(currentUsableState);
-                if (candidateUsableState.mScore > currentUsableState.mScore) {
+            PhoneSignalStatus.UsableState currentUsableState =
+                    mPhonesSignalStatus[defaultPhoneId].getUsableState();
+            PhoneSignalStatus.UsableState candidateUsableState =
+                    mPhonesSignalStatus[phoneId].getUsableState();
+            debugMessage.append(", found phone ").append(phoneId).append(" ")
+                    .append(candidateUsableState)
+                    .append(", default is ").append(currentUsableState);
+            if (candidateUsableState.mScore > currentUsableState.mScore) {
+                secondaryDataPhone = PhoneFactory.getPhone(phoneId);
+            } else if (isRatSignalStrengthBasedSwitchEnabled()
+                    && currentUsableState == PhoneSignalStatus.UsableState.HOME
+                    && candidateUsableState == PhoneSignalStatus.UsableState.HOME) {
+                // Both phones are home, so compare RAT/signal score.
+
+                int defaultScore = defaultPhoneStatus.getRatSignalScore();
+                int candidateScore = candidatePhoneStatus.getRatSignalScore();
+                if ((candidateScore - defaultScore) > mScoreTolerance) {
+                    debugMessage.append(" with ").append(defaultScore)
+                            .append(" versus candidate higher score ").append(candidateScore);
                     secondaryDataPhone = PhoneFactory.getPhone(phoneId);
-                } else if (isRatSignalStrengthBasedSwitchEnabled()
-                        && currentUsableState.mScore == candidateUsableState.mScore) {
-                    // Both phones are home or both roaming enabled, so compare RAT/signal score.
-
-                    int defaultScore = defaultPhoneStatus.getRatSignalScore();
-                    int candidateScore = candidatePhoneStatus.getRatSignalScore();
-                    if ((candidateScore - defaultScore) > mScoreTolerance) {
-                        debugMessage.append(" with ").append(defaultScore)
-                                .append(" versus candidate higher score ").append(candidateScore);
-                        secondaryDataPhone = PhoneFactory.getPhone(phoneId);
-                        switchType = STABILITY_CHECK_PERFORMANCE_SWITCH;
-                    } else {
-                        debugMessage.append(", candidate's score ").append(candidateScore)
-                                .append(" doesn't justify the switch given the current ")
-                                .append(defaultScore);
-                    }
-                }
-            } else if (isHomeService(candidatePhoneStatus.mDataRegState)) {
-                // the alternative phone must have HOME availability
-                debugMessage.append(", found phone ").append(phoneId).append(" in HOME service");
-
-                if (isInService(defaultPhoneStatus.mDataRegState)) {
-                    // Use score if RAT/signal strength based switch is enabled and both phone are
-                    // in service.
-                    if (isRatSignalStrengthBasedSwitchEnabled()) {
-                        int defaultScore = mPhonesSignalStatus[defaultPhoneId].getRatSignalScore();
-                        int candidateScore = mPhonesSignalStatus[phoneId].getRatSignalScore();
-                        if ((candidateScore - defaultScore) > mScoreTolerance) {
-                            debugMessage.append(" with higher score ").append(candidateScore)
-                                    .append(" versus current ").append(defaultScore);
-                            secondaryDataPhone = PhoneFactory.getPhone(phoneId);
-                            switchType = STABILITY_CHECK_PERFORMANCE_SWITCH;
-                        } else {
-                            debugMessage.append(", but its score ").append(candidateScore)
-                                    .append(" doesn't meet the bar to switch given the current ")
-                                    .append(defaultScore);
-                        }
-                    }
+                    switchType = STABILITY_CHECK_PERFORMANCE_SWITCH;
                 } else {
-                    // Only OOS/in service switch is enabled.
-                    secondaryDataPhone = PhoneFactory.getPhone(phoneId);
+                    debugMessage.append(", candidate's score ").append(candidateScore)
+                            .append(" doesn't justify the switch given the current ")
+                            .append(defaultScore);
                 }
             }
 
@@ -994,14 +922,8 @@
      */
     private boolean isRatSignalStrengthBasedSwitchEnabled() {
         return mScoreTolerance >= 0
-                && STABILITY_CHECK_TIMER_MAP.get(STABILITY_CHECK_PERFORMANCE_SWITCH) >= 0;
-    }
-
-    /**
-     * @return {@code true} If the feature of switching to roaming non DDS is enabled.
-     */
-    private boolean isNddsRoamingEnabled() {
-        return sFeatureFlags.autoDataSwitchAllowRoaming() && mAllowNddsRoaming;
+                && STABILITY_CHECK_TIMER_MAP.get(STABILITY_CHECK_PERFORMANCE_SWITCH) >= 0
+                && sFeatureFlags.autoDataSwitchEnhanced();
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/data/CellularNetworkValidator.java b/src/java/com/android/internal/telephony/data/CellularNetworkValidator.java
index 026fbf4..cf3e7d7 100644
--- a/src/java/com/android/internal/telephony/data/CellularNetworkValidator.java
+++ b/src/java/com/android/internal/telephony/data/CellularNetworkValidator.java
@@ -41,15 +41,15 @@
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConfigurationManager;
 import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent;
 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 
-import java.util.Comparator;
+import java.util.ArrayDeque;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.PriorityQueue;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -77,7 +77,7 @@
 
     private int mState = STATE_IDLE;
     private int mSubId;
-    private boolean mReleaseAfterValidation;
+    private boolean mRequireTestPass;
 
     private ValidationCallback mValidationCallback;
     private final Context mContext;
@@ -88,12 +88,13 @@
     public ConnectivityNetworkCallback mNetworkCallback;
     private final ValidatedNetworkCache mValidatedNetworkCache = new ValidatedNetworkCache();
 
+    @NonNull
+    private final FeatureFlags mFlags;
     private class ValidatedNetworkCache {
         // A cache with fixed size. It remembers 10 most recently successfully validated networks.
         private static final int VALIDATED_NETWORK_CACHE_SIZE = 10;
-        private final PriorityQueue<ValidatedNetwork> mValidatedNetworkPQ =
-                new PriorityQueue<>((Comparator<ValidatedNetwork>) Comparator.comparingLong(
-                        (ValidatedNetwork n) -> n.mValidationTimeStamp));
+
+        private final ArrayDeque<ValidatedNetwork> mValidatedNetworkAQ = new ArrayDeque<>();
         private final Map<String, ValidatedNetwork> mValidatedNetworkMap = new HashMap<>();
 
         private static final class ValidatedNetwork {
@@ -128,7 +129,7 @@
 
             if (!validated) {
                 // If validation failed, clear it from the cache.
-                mValidatedNetworkPQ.remove(mValidatedNetworkMap.get(networkIdentity));
+                mValidatedNetworkAQ.remove(mValidatedNetworkMap.get(networkIdentity));
                 mValidatedNetworkMap.remove(networkIdentity);
                 return;
             }
@@ -138,16 +139,16 @@
                 // Already existed in cache, update.
                 network.update(time);
                 // Re-add to re-sort.
-                mValidatedNetworkPQ.remove(network);
-                mValidatedNetworkPQ.add(network);
+                mValidatedNetworkAQ.remove(network);
+                mValidatedNetworkAQ.add(network);
             } else {
                 network = new ValidatedNetwork(networkIdentity, time);
                 mValidatedNetworkMap.put(networkIdentity, network);
-                mValidatedNetworkPQ.add(network);
+                mValidatedNetworkAQ.add(network);
             }
             // If exceeded max size, remove the one with smallest validation timestamp.
-            if (mValidatedNetworkPQ.size() > VALIDATED_NETWORK_CACHE_SIZE) {
-                ValidatedNetwork networkToRemove = mValidatedNetworkPQ.poll();
+            if (mValidatedNetworkAQ.size() > VALIDATED_NETWORK_CACHE_SIZE) {
+                ValidatedNetwork networkToRemove = mValidatedNetworkAQ.poll();
                 mValidatedNetworkMap.remove(networkToRemove.mValidationIdentity);
             }
         }
@@ -206,11 +207,12 @@
     /**
      * Create instance.
      */
-    public static CellularNetworkValidator make(Context context) {
+    public static CellularNetworkValidator make(Context context,
+            @NonNull FeatureFlags featureFlags) {
         if (sInstance != null) {
             logd("createCellularNetworkValidator failed. Instance already exists.");
         } else {
-            sInstance = new CellularNetworkValidator(context);
+            sInstance = new CellularNetworkValidator(context, featureFlags);
         }
 
         return sInstance;
@@ -232,8 +234,9 @@
     }
 
     @VisibleForTesting
-    public CellularNetworkValidator(Context context) {
+    public CellularNetworkValidator(Context context, @NonNull FeatureFlags featureFlags) {
         mContext = context;
+        mFlags = featureFlags;
         mConnectivityManager = (ConnectivityManager)
                 mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
     }
@@ -242,7 +245,7 @@
      * API to start a validation
      */
     public synchronized void validate(int subId, long timeoutInMs,
-            boolean releaseAfterValidation, ValidationCallback callback) {
+            boolean requireTestPass, ValidationCallback callback) {
         // If it's already validating the same subscription, do nothing.
         if (subId == mSubId) return;
 
@@ -261,10 +264,10 @@
         mState = STATE_VALIDATING;
         mSubId = subId;
         mValidationCallback = callback;
-        mReleaseAfterValidation = releaseAfterValidation;
+        mRequireTestPass = requireTestPass;
 
         logd("Start validating subId " + mSubId + " timeoutInMs " + timeoutInMs
-                + " mReleaseAfterValidation " + mReleaseAfterValidation);
+                + " mRequireTestPass " + mRequireTestPass);
 
         mNetworkCallback = new ConnectivityNetworkCallback(subId);
 
@@ -339,9 +342,10 @@
         if (mState == STATE_VALIDATING) {
             mValidationCallback.onValidationDone(passed, mSubId);
             mState = STATE_VALIDATED;
+            boolean keepRequest = passed || !mRequireTestPass;
             // If validation passed and per request to NOT release after validation, delay cleanup.
-            if (!mReleaseAfterValidation && passed) {
-                mHandler.postDelayed(this::stopValidation, 500);
+            if (keepRequest) {
+                mHandler.postDelayed(this::stopValidation, 5000);
             } else {
                 stopValidation();
             }
diff --git a/src/java/com/android/internal/telephony/data/DataConfigManager.java b/src/java/com/android/internal/telephony/data/DataConfigManager.java
index 6dec224..a2859f3 100644
--- a/src/java/com/android/internal/telephony/data/DataConfigManager.java
+++ b/src/java/com/android/internal/telephony/data/DataConfigManager.java
@@ -892,6 +892,17 @@
     }
 
     /**
+     * Returns whether the data roaming setting for satellite connection is ignored.
+     *
+     * @return {@code true} if data roaming setting for satellite connection is ignored,
+     * {@code false} otherwise.
+     */
+    public boolean isIgnoringDataRoamingSettingForSatellite() {
+        return mCarrierConfig.getBoolean(
+            CarrierConfigManager.KEY_SATELLITE_IGNORE_DATA_ROAMING_SETTING_BOOL);
+    }
+
+    /**
      * @return Whether data throttling should be reset when the TAC changes from the carrier config.
      */
     public boolean shouldResetDataThrottlingWhenTacChanges() {
@@ -1114,15 +1125,6 @@
     }
 
     /**
-     * TODO: remove after V.
-     * @return To indicate whether allow using roaming nDDS if user enabled its roaming when the DDS
-     * is not usable(OOS or disabled roaming)
-     */
-    public boolean doesAutoDataSwitchAllowRoaming() {
-        return mResources.getBoolean(com.android.internal.R.bool.auto_data_switch_allow_roaming);
-    }
-
-    /**
      * @return The maximum number of retries when a validation for switching failed.
      */
     public int getAutoDataSwitchValidationMaxRetry() {
@@ -1273,6 +1275,20 @@
         }
     }
 
+    /**
+     * @return The unsupported network capabilities. The unsupported capabilities will be removed
+     * from the default network capabilities that {@link TelephonyNetworkProvider} use to inform
+     * connectivity service what network capabilities are supported by telephony.
+     */
+    @NonNull
+    @NetCapability
+    public Set<Integer> getUnsupportedNetworkCapabilities() {
+        return Arrays.stream(mResources.getStringArray(com.android.internal.R.array
+                        .config_unsupported_network_capabilities))
+                .map(DataUtils::getNetworkCapabilityFromString)
+                .collect(Collectors.toSet());
+    }
+
     /** Update handover rules from carrier config. */
     private void updateHandoverRules() {
         synchronized (this) {
@@ -1282,7 +1298,7 @@
             if (handoverRulesStrings != null) {
                 for (String ruleString : handoverRulesStrings) {
                     try {
-                        mHandoverRuleList.add(new HandoverRule(ruleString));
+                        mHandoverRuleList.add(new HandoverRule(ruleString, mFeatureFlags));
                     } catch (IllegalArgumentException e) {
                         loge("updateHandoverRules: " + e.getMessage());
                     }
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java
index 738c60f..d8e6f6a 100644
--- a/src/java/com/android/internal/telephony/data/DataNetwork.java
+++ b/src/java/com/android/internal/telephony/data/DataNetwork.java
@@ -29,7 +29,6 @@
 import android.net.NetworkAgent;
 import android.net.NetworkAgentConfig;
 import android.net.NetworkCapabilities;
-import android.net.NetworkFactory;
 import android.net.NetworkProvider;
 import android.net.NetworkRequest;
 import android.net.NetworkScore;
@@ -106,6 +105,7 @@
 import com.android.internal.telephony.metrics.DataCallSessionStats;
 import com.android.internal.telephony.metrics.DataNetworkValidationStats;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
+import com.android.internal.telephony.satellite.SatelliteController;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FunctionalUtils;
 import com.android.internal.util.IState;
@@ -1180,21 +1180,13 @@
         }
 
         NetworkProvider provider;
-        if (mFlags.supportNetworkProvider()) {
-            provider = PhoneFactory.getNetworkProvider();
-        } else {
-            final NetworkFactory factory = PhoneFactory.getNetworkFactory(
-                    mPhone.getPhoneId());
-            provider = (null == factory) ? null : factory.getProvider();
-        }
+        provider = PhoneFactory.getNetworkProvider();
 
         NetworkScore.Builder builder = new NetworkScore.Builder()
                 .setKeepConnectedReason(isHandoverInProgress()
                         ? NetworkScore.KEEP_CONNECTED_FOR_HANDOVER
                         : NetworkScore.KEEP_CONNECTED_NONE);
-        if (mFlags.supportNetworkProvider()) {
-            builder.setTransportPrimary(mOnPreferredDataPhone);
-        }
+        builder.setTransportPrimary(mOnPreferredDataPhone);
         mNetworkScore = builder.build();
         logl("mNetworkScore: isPrimary=" + mNetworkScore.isTransportPrimary()
                 + ", keepConnectedReason=" + mNetworkScore.getKeepConnectedReason());
@@ -1259,15 +1251,13 @@
             mDataNetworkController.getDataSettingsManager()
                     .registerCallback(mDataSettingsManagerCallback);
 
-            if (mFlags.supportNetworkProvider()) {
-                mPhoneSwitcherCallback = new PhoneSwitcherCallback(Runnable::run) {
-                    @Override
-                    public void onPreferredDataPhoneIdChanged(int phoneId) {
-                        sendMessage(EVENT_PREFERRED_DATA_SUBSCRIPTION_CHANGED, phoneId, 0);
-                    }
-                };
-                mPhoneSwitcher.registerCallback(mPhoneSwitcherCallback);
-            }
+            mPhoneSwitcherCallback = new PhoneSwitcherCallback(Runnable::run) {
+                @Override
+                public void onPreferredDataPhoneIdChanged(int phoneId) {
+                    sendMessage(EVENT_PREFERRED_DATA_SUBSCRIPTION_CHANGED, phoneId, 0);
+                }
+            };
+            mPhoneSwitcher.registerCallback(mPhoneSwitcherCallback);
 
             mPhone.getDisplayInfoController().registerForTelephonyDisplayInfoChanged(
                     getHandler(), EVENT_DISPLAY_INFO_CHANGED, null);
@@ -1325,6 +1315,8 @@
                 mAccessNetworksManager.registerCallback(mAccessNetworksManagerCallback);
             }
 
+            mRil.registerForNotAvailable(getHandler(), EVENT_RADIO_NOT_AVAILABLE, null);
+
             // Only add symmetric code here, for example, registering and unregistering.
             // DefaultState.enter() is the starting point in the life cycle of the DataNetwork,
             // and DefaultState.exit() is the end. For non-symmetric initializing works, put them
@@ -1360,13 +1352,12 @@
             mPhone.getServiceStateTracker().unregisterForServiceStateChanged(getHandler());
             mPhone.getDisplayInfoController().unregisterForTelephonyDisplayInfoChanged(
                     getHandler());
-            if (mFlags.supportNetworkProvider()) {
-                mPhoneSwitcher.unregisterCallback(mPhoneSwitcherCallback);
-            }
+            mPhoneSwitcher.unregisterCallback(mPhoneSwitcherCallback);
             mDataNetworkController.getDataSettingsManager()
                     .unregisterCallback(mDataSettingsManagerCallback);
             mRil.unregisterForPcoData(getHandler());
             mDataConfigManager.unregisterCallback(mDataConfigManagerCallback);
+            mRil.unregisterForNotAvailable(getHandler());
         }
 
         @Override
@@ -1407,8 +1398,14 @@
                 }
                 case EVENT_DETACH_ALL_NETWORK_REQUESTS: {
                     for (TelephonyNetworkRequest networkRequest : mAttachedNetworkRequestList) {
-                        networkRequest.setState(TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
-                        networkRequest.setAttachedNetwork(null);
+                        // Check if the network request still belongs to this network, because
+                        // during data switch, the network request can be attached to other network
+                        // on a different SIM.
+                        if (networkRequest.getAttachedNetwork() == DataNetwork.this) {
+                            networkRequest.setState(
+                                    TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
+                            networkRequest.setAttachedNetwork(null);
+                        }
                     }
                     log("All network requests detached.");
                     mAttachedNetworkRequestList.clear();
@@ -1461,6 +1458,12 @@
                             .transportTypeToString(msg.arg1) + " request.");
                     break;
                 case EVENT_RADIO_NOT_AVAILABLE:
+                    // Ignore this event when it isn't a WWAN data network.
+                    if (mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
+                        loge(eventToString(msg.what)
+                                + ": ignored on IWLAN");
+                        break;
+                    }
                     mFailCause = DataFailCause.RADIO_NOT_AVAILABLE;
                     loge(eventToString(msg.what) + ": transition to disconnected state");
                     transitionTo(mDisconnectedState);
@@ -1541,10 +1544,6 @@
                         setupData();
                     } else {
                         mRetryDelayMillis = DataCallResponse.RETRY_DURATION_UNDEFINED;
-                        if (!mFlags.keepEmptyRequestsNetwork()) {
-                            // This will mark the data profile as no retry perm failure.
-                            mFailCause = DataFailCause.NO_RETRY_FAILURE;
-                        }
                         transitionTo(mDisconnectedState);
                     }
                     break;
@@ -1670,15 +1669,6 @@
 
                 updateDataNetwork(response);
 
-                if (!mFlags.keepEmptyRequestsNetwork() && mAttachedNetworkRequestList.isEmpty()) {
-                    log("Tear down the network since there is no live network request.");
-                    // Directly call onTearDown here. Calling tearDown will cause deadlock because
-                    // EVENT_TEAR_DOWN_NETWORK is deferred until state machine enters connected
-                    // state, which will never happen in this case.
-                    onTearDown(TEAR_DOWN_REASON_NO_LIVE_REQUEST);
-                    return;
-                }
-
                 if (mVcnManager != null && mVcnManager.applyVcnNetworkPolicy(mNetworkCapabilities,
                         mLinkProperties).isTeardownRequested()) {
                     log("VCN service requested to tear down the network.");
@@ -1897,6 +1887,19 @@
                     log("Defer message " + eventToString(msg.what));
                     deferMessage(msg);
                     break;
+                case EVENT_RADIO_NOT_AVAILABLE:
+                    if (mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
+                        // Defer the request until handover to IWLAN succeeds or fails.
+                        log("Defer message " + eventToString(msg.what));
+                        deferMessage(msg);
+                    } else {
+                        // If this is during handover to cellular, always tear down the network as
+                        // we will never get success or failed response from the modem.
+                        mFailCause = DataFailCause.RADIO_NOT_AVAILABLE;
+                        loge(eventToString(msg.what) + ": transition to disconnected state");
+                        transitionTo(mDisconnectedState);
+                    }
+                    break;
                 case EVENT_NOTIFY_HANDOVER_STARTED_RESPONSE:
                     onStartHandover(msg.arg2, (DataHandoverRetryEntry) msg.obj);
                     break;
@@ -2073,7 +2076,6 @@
     private void registerForWwanEvents() {
         registerForBandwidthUpdate();
         mKeepaliveTracker.registerForKeepaliveStatus();
-        mRil.registerForNotAvailable(this.getHandler(), EVENT_RADIO_NOT_AVAILABLE, null);
     }
 
     /**
@@ -2082,7 +2084,6 @@
     private void unregisterForWwanEvents() {
         unregisterForBandwidthUpdate();
         mKeepaliveTracker.unregisterForKeepaliveStatus();
-        mRil.unregisterForNotAvailable(this.getHandler());
     }
 
     @Override
@@ -2154,14 +2155,19 @@
     private void onDetachNetworkRequest(@NonNull TelephonyNetworkRequest networkRequest,
             boolean shouldRetry) {
         mAttachedNetworkRequestList.remove(networkRequest);
-        networkRequest.setState(TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
-        networkRequest.setAttachedNetwork(null);
+        // Check if the network request still belongs to this network, because
+        // during data switch, the network request can be attached to other network
+        // on a different SIM.
+        if (networkRequest.getAttachedNetwork() == DataNetwork.this) {
+            networkRequest.setState(TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
+            networkRequest.setAttachedNetwork(null);
 
-        if (shouldRetry) {
-            // Inform DataNetworkController that a network request was detached and should be
-            // scheduled to retry.
-            mDataNetworkCallback.invokeFromExecutor(
-                    () -> mDataNetworkCallback.onRetryUnsatisfiedNetworkRequest(networkRequest));
+            if (shouldRetry) {
+                // Inform DataNetworkController that a network request was detached and should be
+                // scheduled to retry.
+                mDataNetworkCallback.invokeFromExecutor(() ->
+                        mDataNetworkCallback.onRetryUnsatisfiedNetworkRequest(networkRequest));
+            }
         }
 
         if (mAttachedNetworkRequestList.isEmpty()) {
@@ -2357,16 +2363,9 @@
     private void updateNetworkCapabilities() {
         final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder();
 
-        if (mFlags.satelliteInternet() && mIsSatellite
-                && mDataConfigManager.getForcedCellularTransportCapabilities().stream()
+        if (mIsSatellite && mDataConfigManager.getForcedCellularTransportCapabilities().stream()
                 .noneMatch(this::hasNetworkCapabilityInNetworkRequests)) {
-            // TODO: b/328622096 remove the try/catch
-            try {
-                builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
-            } catch (IllegalArgumentException exception) {
-                loge("TRANSPORT_SATELLITE is not supported.");
-                builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
-            }
+            builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
         } else {
             builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
         }
@@ -2572,9 +2571,18 @@
         builder.setLinkUpstreamBandwidthKbps(mNetworkBandwidth.uplinkBandwidthKbps);
 
         // Configure the network as restricted/constrained for unrestricted satellite network.
-        if (mFlags.satelliteInternet() && mIsSatellite && builder.build()
-                .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) {
-            switch (mDataConfigManager.getSatelliteDataSupportMode()) {
+        if (mIsSatellite && builder.build().hasCapability(
+                NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) {
+
+            int dataPolicy;
+            if (mFlags.dataServiceCheck()) {
+                final SatelliteController satelliteController = SatelliteController.getInstance();
+                dataPolicy = satelliteController.getSatelliteDataServicePolicyForPlmn(mSubId,
+                        mPhone.getServiceState().getOperatorNumeric());
+            } else {
+                dataPolicy = mDataConfigManager.getSatelliteDataSupportMode();
+            }
+            switch (dataPolicy) {
                 case CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED
                         -> builder.removeCapability(
                                 NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
@@ -3373,13 +3381,10 @@
         int connectedReason = keepConnectedForHandover
                 ? NetworkScore.KEEP_CONNECTED_FOR_HANDOVER : NetworkScore.KEEP_CONNECTED_NONE;
         if (mNetworkScore.getKeepConnectedReason() != connectedReason
-                || (mFlags.supportNetworkProvider()
-                && mNetworkScore.isTransportPrimary() != mOnPreferredDataPhone)) {
+                || mNetworkScore.isTransportPrimary() != mOnPreferredDataPhone) {
             NetworkScore.Builder builder = new NetworkScore.Builder()
                     .setKeepConnectedReason(connectedReason);
-            if (mFlags.supportNetworkProvider()) {
-                builder.setTransportPrimary(mOnPreferredDataPhone);
-            }
+            builder.setTransportPrimary(mOnPreferredDataPhone);
             mNetworkScore = builder.build();
             mNetworkAgent.sendNetworkScore(mNetworkScore);
             logl("updateNetworkScore: isPrimary=" + mNetworkScore.isTransportPrimary()
@@ -3914,11 +3919,6 @@
      */
     private void updateValidationStatus(
             @PreciseDataConnectionState.NetworkValidationStatus int networkValidationStatus) {
-        if (!mFlags.networkValidation()) {
-            // Do nothing, if network validation feature is disabled
-            return;
-        }
-
         // if network validation status is changed, notify preciseDataConnectionState.
         if (mNetworkValidationStatus != networkValidationStatus) {
             log("updateValidationStatus:"
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index b5bfc1d..6b916f2 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -111,6 +111,7 @@
 import com.android.internal.telephony.data.LinkBandwidthEstimator.LinkBandwidthEstimatorCallback;
 import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.ims.ImsResolver;
+import com.android.internal.telephony.satellite.SatelliteController;
 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.internal.telephony.util.TelephonyUtils;
@@ -696,13 +697,6 @@
         public void onDataServiceBound(@TransportType int transport) {}
 
         /**
-         * Called when SIM load state changed.
-         *
-         * @param simState The current SIM state
-         */
-        public void onSimStateChanged(@SimState int simState) {}
-
-        /**
          * Called when QosBearerSessions changed.
          *
          * @param qosBearerSessions The latest QOS bearer sessions.
@@ -741,6 +735,8 @@
 
         private static final String RULE_TAG_ROAMING = "roaming";
 
+        private static final String RULE_TAG_INCALL = "incall";
+
         /** Handover rule type. */
         @HandoverRuleType
         public final int type;
@@ -766,6 +762,9 @@
         /** {@code true} indicates this policy is only applicable when the device is roaming. */
         public final boolean isOnlyForRoaming;
 
+        /** {@code true} indicates this policy is only applicable when the device is incall. */
+        public final boolean isOnlyForIncall;
+
         /**
          * Constructor
          *
@@ -773,7 +772,7 @@
          *
          * @see CarrierConfigManager#KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY
          */
-        public HandoverRule(@NonNull String ruleString) {
+        public HandoverRule(@NonNull String ruleString, @NonNull FeatureFlags featureFlags) {
             if (TextUtils.isEmpty(ruleString)) {
                 throw new IllegalArgumentException("illegal rule " + ruleString);
             }
@@ -781,6 +780,7 @@
             Set<Integer> source = null, target = null, capabilities = Collections.emptySet();
             int type = 0;
             boolean roaming = false;
+            boolean incall = false;
 
             ruleString = ruleString.trim().toLowerCase(Locale.ROOT);
             String[] expressions = ruleString.split("\\s*,\\s*");
@@ -821,6 +821,11 @@
                         case RULE_TAG_ROAMING:
                             roaming = Boolean.parseBoolean(value);
                             break;
+                        case RULE_TAG_INCALL:
+                            if (featureFlags.incallHandoverPolicy()) {
+                                incall = Boolean.parseBoolean(value);
+                            }
+                            break;
                         default:
                             throw new IllegalArgumentException("unexpected key " + key);
                     }
@@ -867,6 +872,7 @@
             this.type = type;
             networkCapabilities = capabilities;
             isOnlyForRoaming = roaming;
+            isOnlyForIncall = incall;
         }
 
         @Override
@@ -876,8 +882,8 @@
                     .map(AccessNetworkType::toString).collect(Collectors.joining("|"))
                     + ", target=" + targetAccessNetworks.stream().map(AccessNetworkType::toString)
                     .collect(Collectors.joining("|")) + ", isRoaming=" + isOnlyForRoaming
-                    + ", capabilities=" + DataUtils.networkCapabilitiesToString(networkCapabilities)
-                    + "]";
+                    + ", isIncall=" + isOnlyForIncall + ", capabilities="
+                    + DataUtils.networkCapabilitiesToString(networkCapabilities) + "]";
         }
     }
 
@@ -1588,8 +1594,7 @@
                 networkRequest.getHighestPriorityApnTypeNetworkCapability());
 
         // Check if the request can be satisfied by cellular network or satellite network.
-        if (mFeatureFlags.satelliteInternet()
-                && !canConnectivityTransportSatisfyNetworkRequest(networkRequest, transport)) {
+        if (!canConnectivityTransportSatisfyNetworkRequest(networkRequest, transport)) {
             evaluation.addDataDisallowedReason(
                     DataDisallowedReason.DATA_NETWORK_TRANSPORT_NOT_ALLOWED);
         }
@@ -1635,6 +1640,16 @@
             evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_CONFIG_NOT_READY);
         }
 
+        if (mFeatureFlags.dataServiceCheck()) {
+            NetworkRegistrationInfo nri = mServiceState.getNetworkRegistrationInfo(
+                    NetworkRegistrationInfo.DOMAIN_PS, transport);
+            if (nri != null && !nri.getAvailableServices().contains(
+                    NetworkRegistrationInfo.SERVICE_TYPE_DATA)) {
+                evaluation.addDataDisallowedReason(
+                        DataDisallowedReason.SERVICE_OPTION_NOT_SUPPORTED);
+            }
+        }
+
         // Check CS call state and see if concurrent voice/data is allowed.
         if (hasCalling() && mPhone.getCallTracker().getState() != PhoneConstants.State.IDLE
                 && !mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
@@ -1665,7 +1680,11 @@
         }
 
         // Check if data roaming is disabled.
-        if (mServiceState.getDataRoaming() && !mDataSettingsManager.isDataRoamingEnabled()) {
+        // But if the data roaming setting for satellite connection is ignored as the satellite
+        // data plan is included in the user mobile plan, then we should not disallow data due to
+        // roaming disabled.
+        if (mServiceState.getDataRoaming() && !mDataSettingsManager.isDataRoamingEnabled()
+                    && !shouldIgnoreDataRoamingSettingForSatellite()) {
             evaluation.addDataDisallowedReason(DataDisallowedReason.ROAMING_DISABLED);
         }
 
@@ -1812,6 +1831,18 @@
     }
 
     /**
+     * Returns whether the data roaming setting should be ignored for satellite connection,
+     * as the satellite data plan is included in the user mobile plan.
+     *
+     * @return {@code true} if the data roaming setting should be ignored for satellite connection.
+     * {@code false} otherwise.
+     */
+    private boolean shouldIgnoreDataRoamingSettingForSatellite() {
+        return mServiceState.isUsingNonTerrestrialNetwork()
+                && mDataConfigManager.isIgnoringDataRoamingSettingForSatellite();
+    }
+
+    /**
      * This method
      *  - At evaluation network request and evaluation data network determines, if
      *    bootstrap sim current data usage reached bootstrap sim max data limit allowed set
@@ -1952,18 +1983,26 @@
             evaluation.addDataDisallowedReason(DataDisallowedReason.CDMA_EMERGENCY_CALLBACK_MODE);
         }
 
-        // If the network is satellite, then the network must be restricted.
-        if (mFeatureFlags.satelliteInternet()) {
-            // The IWLAN data network should remain intact even when satellite is connected.
-            if (dataNetwork.getTransport() != AccessNetworkConstants.TRANSPORT_TYPE_WLAN
-                    && mServiceState.isUsingNonTerrestrialNetwork() != dataNetwork.isSatellite()) {
-                // Since we don't support satellite/cellular network handover, we should always
-                // tear down the network when transport changes.
+        if (mFeatureFlags.dataServiceCheck()) {
+            NetworkRegistrationInfo nri = mServiceState.getNetworkRegistrationInfo(
+                    NetworkRegistrationInfo.DOMAIN_PS, dataNetwork.getTransport());
+            if (nri != null && nri.isInService() && !nri.getAvailableServices().contains(
+                    NetworkRegistrationInfo.SERVICE_TYPE_DATA)) {
                 evaluation.addDataDisallowedReason(
-                        DataDisallowedReason.DATA_NETWORK_TRANSPORT_NOT_ALLOWED);
+                        DataDisallowedReason.SERVICE_OPTION_NOT_SUPPORTED);
             }
         }
 
+        // If the network is satellite, then the network must be restricted.
+        // The IWLAN data network should remain intact even when satellite is connected.
+        if (dataNetwork.getTransport() != AccessNetworkConstants.TRANSPORT_TYPE_WLAN
+                && mServiceState.isUsingNonTerrestrialNetwork() != dataNetwork.isSatellite()) {
+            // Since we don't support satellite/cellular network handover, we should always
+            // tear down the network when transport changes.
+            evaluation.addDataDisallowedReason(
+                    DataDisallowedReason.DATA_NETWORK_TRANSPORT_NOT_ALLOWED);
+        }
+
         // Check whether data limit reached for bootstrap sim, else re-evaluate based on the timer
         // set.
         if (isEsimBootStrapProvisioningActivated()
@@ -2169,11 +2208,20 @@
             return true;
         }
 
-        // When the device is on satellite, only restricted/constrained network request can request
-        // network.
+        // When the device is on satellite, allow network request without bandwidth not constrained
+        // to enable data connection with constrained network.
         if (mServiceState.isUsingNonTerrestrialNetwork() && networkRequest.hasCapability(
                 NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) {
-            switch (mDataConfigManager.getSatelliteDataSupportMode()) {
+
+            int dataPolicy;
+            if (mFeatureFlags.dataServiceCheck()) {
+                final SatelliteController satelliteController = SatelliteController.getInstance();
+                dataPolicy = satelliteController.getSatelliteDataServicePolicyForPlmn(mSubId,
+                        mPhone.getServiceState().getOperatorNumeric());
+            } else {
+                dataPolicy = mDataConfigManager.getSatelliteDataSupportMode();
+            }
+            switch (dataPolicy) {
                 case CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED -> {
                     return false;
                 }
@@ -2222,27 +2270,20 @@
      * that can bypass any soft disallowed reasons, otherwise {@code false}.
      */
     private boolean isValidRestrictedRequest(@NonNull TelephonyNetworkRequest networkRequest) {
-
-        if (!mFeatureFlags.satelliteInternet()) {
-            return !(networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
-                    || networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE));
-        } else {
-            // tethering, enterprise and mms with restricted capabilities always honor soft
-            // disallowed reasons and not respected as restricted request
-            if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
-                    || networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
-                    || networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
-                return false;
-            }
-            // When the device is on satellite, internet with restricted capabilities always honor
-            // soft disallowed reasons and not respected as restricted request
-            // Note - ping test are performed with restricted request on satellite assuming they cannot
-            // bypass any checks. If below is removed, reevaluate the ping request in
-            // CellularNetworkValidator and the getInternetEvaluation in AutoDataSwitchController
-            return !(mServiceState.isUsingNonTerrestrialNetwork()
-                    && networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET));
-
+        // tethering, enterprise and mms with restricted capabilities always honor soft
+        // disallowed reasons and not respected as restricted request
+        if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
+                || networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
+                || networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+            return false;
         }
+        // When the device is on satellite, internet with restricted capabilities always honor
+        // soft disallowed reasons and not respected as restricted request
+        // Note - ping test are performed with restricted request on satellite assuming they cannot
+        // bypass any checks. If below is removed, reevaluate the ping request in
+        // CellularNetworkValidator and the getInternetEvaluation in AutoDataSwitchController
+        return !(mServiceState.isUsingNonTerrestrialNetwork()
+                && networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET));
     }
 
     /**
@@ -2341,6 +2382,9 @@
             // in data network.
             boolean isRoaming = isWwanInService ? mServiceState.getDataRoamingFromRegistration()
                     : dataNetwork.getLastKnownRoamingState();
+            Phone imsPhone = mPhone.getImsPhone();
+            boolean isIncall = mFeatureFlags.incallHandoverPolicy() && imsPhone != null
+                    && (imsPhone.getCallTracker().getState() != PhoneConstants.State.IDLE);
             int targetAccessNetwork = DataUtils.networkTypeToAccessNetworkType(
                     getDataNetworkType(DataUtils.getTargetTransport(dataNetwork.getTransport())));
             NetworkCapabilities capabilities = dataNetwork.getNetworkCapabilities();
@@ -2348,17 +2392,23 @@
                     + "source=" + AccessNetworkType.toString(sourceAccessNetwork)
                     + ", target=" + AccessNetworkType.toString(targetAccessNetwork)
                     + ", roaming=" + isRoaming
+                    + ", incall=" + isIncall
                     + ", ServiceState=" + mServiceState
                     + ", capabilities=" + capabilities);
 
             // Matching the rules by the configured order. Bail out if find first matching rule.
             for (HandoverRule rule : handoverRules) {
-                // Check if the rule is only for roaming and we are not roaming.
+                // Check if the rule is only for roaming and we are not  aroaming.
                 if (rule.isOnlyForRoaming && !isRoaming) {
                     // If the rule is for roaming only, and the device is not roaming, then bypass
                     // this rule.
                     continue;
                 }
+                if (rule.isOnlyForIncall && (!mFeatureFlags.incallHandoverPolicy() || !isIncall)) {
+                    // If the rule is for incall only, and the device is not incall, then bypass
+                    // this rule.
+                    continue;
+                }
 
                 if (rule.sourceAccessNetworks.contains(sourceAccessNetwork)
                         && rule.targetAccessNetworks.contains(targetAccessNetwork)) {
@@ -2518,53 +2568,27 @@
     }
 
     private void onRemoveNetworkRequest(@NonNull TelephonyNetworkRequest request) {
-        if (mFeatureFlags.supportNetworkProvider()) {
-            if (!mAllNetworkRequestList.remove(request)) {
-                loge("onRemoveNetworkRequest: Network request does not exist. " + request);
-                return;
-            }
-
-            if (request.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
-                mImsThrottleCounter.addOccurrence();
-                mLastReleasedImsRequestCapabilities = request.getCapabilities();
-                mLastImsOperationIsRelease = true;
-            }
-
-            if (request.getAttachedNetwork() != null) {
-                request.getAttachedNetwork().detachNetworkRequest(
-                        request, false /* shouldRetry */);
-            }
-
-            request.setState(TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
-            request.setEvaluation(null);
-
-            log("onRemoveNetworkRequest: Removed " + request);
+        if (!mAllNetworkRequestList.remove(request)) {
+            loge("onRemoveNetworkRequest: Network request does not exist. " + request);
             return;
         }
 
-        // The request generated from telephony network factory does not contain the information
-        // the original request has, for example, attached data network. We need to find the
-        // original one.
-        TelephonyNetworkRequest networkRequest = mAllNetworkRequestList.stream()
-                .filter(r -> r.equals(request))
-                .findFirst()
-                .orElse(null);
-        if (networkRequest == null || !mAllNetworkRequestList.remove(networkRequest)) {
-            loge("onRemoveNetworkRequest: Network request does not exist. " + networkRequest);
-            return;
-        }
-
-        if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
+        if (request.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
             mImsThrottleCounter.addOccurrence();
-            mLastReleasedImsRequestCapabilities = networkRequest.getCapabilities();
+            mLastReleasedImsRequestCapabilities = request.getCapabilities();
             mLastImsOperationIsRelease = true;
         }
 
-        if (networkRequest.getAttachedNetwork() != null) {
-            networkRequest.getAttachedNetwork().detachNetworkRequest(
-                    networkRequest, false /* shouldRetry */);
+        if (request.getAttachedNetwork() != null) {
+            request.getAttachedNetwork().detachNetworkRequest(
+                    request, false /* shouldRetry */);
         }
-        log("onRemoveNetworkRequest: Removed " + networkRequest);
+
+        request.setState(TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
+        request.setEvaluation(null);
+
+        log("onRemoveNetworkRequest: Removed " + request);
+        return;
     }
 
     /**
@@ -3363,6 +3387,7 @@
         mPendingImsDeregDataNetworks.remove(dataNetwork);
         mDataRetryManager.cancelPendingHandoverRetry(dataNetwork);
         if (dataNetwork.isInternetSupported()) updateOverallInternetDataState();
+        onPcoDataChanged(dataNetwork);
 
         if (dataNetwork.getNetworkCapabilities().hasCapability(
                 NetworkCapabilities.NET_CAPABILITY_IMS)) {
@@ -3570,8 +3595,6 @@
                 sendMessage(obtainMessage(EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS,
                         DataEvaluationReason.SIM_LOADED));
             }
-            mDataNetworkControllerCallbacks.forEach(callback -> callback.invokeFromExecutor(
-                    () -> callback.onSimStateChanged(mSimState)));
         }
     }
 
@@ -3776,6 +3799,22 @@
     }
 
     /**
+     * Check if network available services list is changed
+     *
+     * @param oldNri Previous network registration info.
+     * @param newNri Current network registration info.
+     * @return {@code true} if available services list is changed else return false
+     */
+    private boolean areNetworkAvailableServicesChanged(@NonNull NetworkRegistrationInfo oldNri,
+            @NonNull NetworkRegistrationInfo newNri) {
+        List<Integer> oldAvailableServicesList = oldNri.getAvailableServices();
+        List<Integer> newAvailableServicesList = newNri.getAvailableServices();
+
+        return !(oldAvailableServicesList.size() == newAvailableServicesList.size()
+                && oldAvailableServicesList.stream().allMatch(newAvailableServicesList::contains));
+    }
+
+    /**
      * Check if needed to re-evaluate the existing data networks.
      *
      * @param oldNri Previous network registration info.
@@ -3791,6 +3830,10 @@
             return false;
         }
 
+        if (areNetworkAvailableServicesChanged(oldNri, newNri)) {
+            return true;
+        }
+
         if (oldNri.getAccessNetworkTechnology() != newNri.getAccessNetworkTechnology()
                 // Some CarrierConfig disallows vops in nonVops area for specified home/roaming.
                 || (oldNri.isRoaming() != newNri.isRoaming())) {
@@ -3836,6 +3879,10 @@
             return false;
         }
 
+        if (areNetworkAvailableServicesChanged(oldPsNri, newPsNri)) {
+            return true;
+        }
+
         if (oldPsNri == null
                 || oldPsNri.getAccessNetworkTechnology() != newPsNri.getAccessNetworkTechnology()
                 || (!oldPsNri.isInService() && newPsNri.isInService())
diff --git a/src/java/com/android/internal/telephony/data/DataProfileManager.java b/src/java/com/android/internal/telephony/data/DataProfileManager.java
index 28fe935..0138aa0 100644
--- a/src/java/com/android/internal/telephony/data/DataProfileManager.java
+++ b/src/java/com/android/internal/telephony/data/DataProfileManager.java
@@ -37,7 +37,6 @@
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.TelephonyManager.SimState;
 import android.telephony.data.ApnSetting;
 import android.telephony.data.DataProfile;
 import android.telephony.data.TrafficDescriptor;
@@ -47,6 +46,7 @@
 import android.util.LocalLog;
 import android.util.LruCache;
 
+import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback;
 import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback;
@@ -120,10 +120,6 @@
     @NonNull
     private final Set<DataProfileManagerCallback> mDataProfileManagerCallbacks = new ArraySet<>();
 
-    /** SIM state. */
-    @SimState
-    private int mSimState = TelephonyManager.SIM_STATE_UNKNOWN;
-
     /** Feature flags controlling which feature is enabled. */
     @NonNull
     private final FeatureFlags mFeatureFlags;
@@ -186,11 +182,6 @@
                         if (internetNetworks.isEmpty()) return;
                         DataProfileManager.this.onInternetDataNetworkConnected(internetNetworks);
                     }
-
-                    @Override
-                    public void onSimStateChanged(@SimState int simState) {
-                        DataProfileManager.this.mSimState = simState;
-                    }
                 });
         mDataConfigManager.registerCallback(new DataConfigManagerCallback(this::post) {
             @Override
@@ -315,7 +306,7 @@
 
         DataProfile dataProfile;
 
-        if (mSimState == TelephonyManager.SIM_STATE_LOADED) {
+        if (IccCardConstants.State.LOADED.equals(mPhone.getIccCard().getState())) {
             // Check if any of the profile already supports IMS, if not, add the default one.
             dataProfile = profiles.stream()
                     .filter(dp -> dp.canSatisfy(NetworkCapabilities.NET_CAPABILITY_IMS))
@@ -743,7 +734,6 @@
 
         // if esim bootstrap provisioning in progress, do not apply preferred data profile
         if (!isEsimBootStrapProvisioning) {
-            if (mFeatureFlags.carrierEnabledSatelliteFlag()) {
                 // If the preferred data profile can be used, always use it if it can satisfy the
                 // network request with current network type (even though it's been marked as
                 // permanent failed.)
@@ -763,24 +753,6 @@
                             + "retry can happen.");
                     return null;
                 }
-            } else {
-                // If the preferred data profile can be used, always use it if it can satisfy the
-                // network request with current network type (even though it's been marked as
-                // permanent failed.)
-                if (mPreferredDataProfile != null
-                        && networkRequest.canBeSatisfiedBy(mPreferredDataProfile)
-                        && mPreferredDataProfile.getApnSetting() != null
-                        && mPreferredDataProfile.getApnSetting()
-                        .canSupportNetworkType(networkType)) {
-                    if (ignorePermanentFailure || !mPreferredDataProfile.getApnSetting()
-                            .getPermanentFailed()) {
-                        return mPreferredDataProfile.getApnSetting();
-                    }
-                    log("The preferred data profile is permanently failed. Only condition based "
-                            + "retry can happen.");
-                    return null;
-                }
-            }
         }
 
         // Filter out the data profile that can't satisfy the request.
@@ -807,26 +779,18 @@
                     if (!dp.getApnSetting().canSupportNetworkType(networkType)) return false;
                     if (isEsimBootStrapProvisioning
                             != dp.getApnSetting().isEsimBootstrapProvisioning()) return false;
-                    if (mFeatureFlags.carrierEnabledSatelliteFlag()) {
-                        if (isNtn && !dp.getApnSetting().isForInfrastructure(
-                                ApnSetting.INFRASTRUCTURE_SATELLITE)) {
-                            return false;
-                        }
-                        return isNtn || dp.getApnSetting().isForInfrastructure(
-                                ApnSetting.INFRASTRUCTURE_CELLULAR);
+                    if (isNtn && !dp.getApnSetting().isForInfrastructure(
+                            ApnSetting.INFRASTRUCTURE_SATELLITE)) {
+                        return false;
                     }
-
-                    return true;
+                    return isNtn || dp.getApnSetting().isForInfrastructure(
+                            ApnSetting.INFRASTRUCTURE_CELLULAR);
                 })
                 .collect(Collectors.toList());
         if (dataProfiles.isEmpty()) {
-            String ntnReason = "";
-            if (mFeatureFlags.carrierEnabledSatelliteFlag()) {
-                ntnReason = " and infrastructure for "
-                        + NetworkRegistrationInfo.isNonTerrestrialNetworkToString(isNtn);
-            }
             log("Can't find any data profile for network type "
-                    + TelephonyManager.getNetworkTypeName(networkType) + ntnReason);
+                    + TelephonyManager.getNetworkTypeName(networkType) + " and infrastructure for "
+                    + NetworkRegistrationInfo.isNonTerrestrialNetworkToString(isNtn));
             return null;
         }
 
diff --git a/src/java/com/android/internal/telephony/data/DataSettingsManager.java b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
index 0b9ac27..cf748ff 100644
--- a/src/java/com/android/internal/telephony/data/DataSettingsManager.java
+++ b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
@@ -216,7 +216,6 @@
                 break;
             }
             case EVENT_SUBSCRIPTIONS_CHANGED: {
-                mSubId = (int) msg.obj;
                 refreshEnabledMobileDataPolicy();
                 updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_USER,
                         mPhone.getContext().getOpPackageName(),
@@ -313,11 +312,12 @@
                     public void onSubscriptionsChanged() {
                         if (mSubId != mPhone.getSubId()) {
                             log("onSubscriptionsChanged: " + mSubId + " to " + mPhone.getSubId());
+                            mSubId = mPhone.getSubId();
                             obtainMessage(EVENT_SUBSCRIPTIONS_CHANGED, mPhone.getSubId())
                                     .sendToTarget();
                         }
                     }
-                }, this::post);
+                }, Runnable::run);
         // some overall mobile data override policy depend on whether DDS is user data enabled.
         for (Phone phone : PhoneFactory.getPhones()) {
             if (phone.getPhoneId() != mPhone.getPhoneId()) {
@@ -467,8 +467,8 @@
         if (isStandAloneOpportunistic(mSubId) && !enabled) return;
         boolean changed = GlobalSettingsHelper.setInt(mPhone.getContext(),
                 Settings.Global.MOBILE_DATA, mSubId, (enabled ? 1 : 0));
-        log("Set user data enabled to " + enabled + ", changed=" + changed + ", callingPackage="
-                + callingPackage);
+        logl("Set user data enabled to " + enabled + " on sub " + mSubId + ", changed="
+                + changed + ", callingPackage=" + callingPackage);
         if (changed) {
             logl("UserDataEnabled changed to " + enabled);
             mPhone.notifyUserMobileDataStateChanged(enabled);
@@ -555,8 +555,9 @@
         // Will trigger handleDataOnRoamingChange() through observer
         boolean changed = GlobalSettingsHelper.setBoolean(mPhone.getContext(),
                 Settings.Global.DATA_ROAMING, mSubId, enabled);
+        logl("DataRoamingEnabled set to " + enabled + " on sub " + mSubId
+                + ", changed=" + changed);
         if (changed) {
-            logl("DataRoamingEnabled changed to " + enabled);
             mDataSettingsManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
                     () -> callback.onDataRoamingEnabledChanged(enabled)));
         }
diff --git a/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java b/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
index 42e1a78..e3060e5 100644
--- a/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
+++ b/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
@@ -46,6 +46,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback;
 import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback;
 import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback;
@@ -571,16 +572,12 @@
     private void onInternetValidationStatusChanged(@ValidationStatus int status) {
         logl("onInternetValidationStatusChanged: " + DataUtils.validationStatusToString(status));
         final boolean isValid = status == NetworkAgent.VALIDATION_STATUS_VALID;
-        if (mFeatureFlags.dsrsDiagnosticsEnabled()) {
-            mValidationCount += 1;
-            mActionValidationCount += 1;
-        }
+        mValidationCount += 1;
+        mActionValidationCount += 1;
         setNetworkValidationState(isValid);
         if (isValid) {
-            if (mFeatureFlags.dsrsDiagnosticsEnabled()) {
-                // Broadcast intent that data stall recovered.
-                broadcastDataStallDetected(mLastAction);
-            }
+            // Broadcast intent that data stall recovered.
+            broadcastDataStallDetected(mLastAction);
             reset();
         } else if (isRecoveryNeeded(true)) {
             // Set the network as invalid, because recovery is needed
@@ -620,7 +617,7 @@
     @VisibleForTesting
     public void setRecoveryAction(@RecoveryAction int action) {
         // Reset the validation count for action change
-        if (mFeatureFlags.dsrsDiagnosticsEnabled() && mRecoveryAction != action) {
+        if (mRecoveryAction != action) {
             mActionValidationCount = 0;
         }
         mRecoveryAction = action;
@@ -702,10 +699,8 @@
         final int duration = (int) (SystemClock.elapsedRealtime() - mDataStallStartMs);
         @RecoveredReason final int reason = getRecoveredReason(mIsValidNetwork);
         final int durationOfAction = (int) getDurationOfCurrentRecoveryMs();
-        if (mFeatureFlags.dsrsDiagnosticsEnabled()) {
-            log("mValidationCount=" + mValidationCount
-                    + ", mActionValidationCount=" + mActionValidationCount);
-        }
+        log("mValidationCount=" + mValidationCount
+                + ", mActionValidationCount=" + mActionValidationCount);
 
         // Get the bundled DSRS stats.
         Bundle bundle = mStats.getDataStallRecoveryMetricsData(
@@ -806,12 +801,17 @@
         }
 
         // Skip recovery if it can cause a call to drop
-        if (mPhone.getState() != PhoneConstants.State.IDLE
-                && getRecoveryAction() > RECOVERY_ACTION_CLEANUP) {
+        if (!isPhoneStateIdle() && getRecoveryAction() > RECOVERY_ACTION_CLEANUP) {
             logl("skip data stall recovery as there is an active call");
             return false;
         }
 
+        // Skip when network scan started
+        if (isAnyPhoneNetworkScanStarted()) {
+            logl("skip data stall recovery as network scan started");
+            return false;
+        }
+
         // Skip when poor signal strength
         if (mPhone.getSignalStrength().getLevel() <= CellSignalStrength.SIGNAL_STRENGTH_POOR) {
             logl("skip data stall recovery as in poor signal condition");
@@ -831,6 +831,38 @@
     }
 
     /**
+     * Checks if any network scan is currently started on any of the available phones.
+     *
+     * @return {@code true} if any network scan is started on any phone; {@code false} otherwise.
+     */
+    private boolean isAnyPhoneNetworkScanStarted() {
+        for (Phone phone : PhoneFactory.getPhones()) {
+            logl("NetworkScanStarted: " + phone.getNetworkScanStarted()
+                    + " on phone" + phone.getPhoneId());
+            if (phone.getNetworkScanStarted()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Check whether the phone state is {@link PhoneConstants.State#IDLE} for all phones.
+     * If any phone is not IDLE (voice call active on any phone), do not trigger recovery.
+     *
+     * @return {@code true} if all phones are IDLE and {@code false} if any phones are not IDLE.
+     */
+    private boolean isPhoneStateIdle() {
+        for (Phone phone : PhoneFactory.getPhones()) {
+            logl("Phone State: " + phone.getState() + " on phone" + phone.getPhoneId());
+            if (phone.getState() != PhoneConstants.State.IDLE) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
      * Set the validation status into metrics.
      *
      * @param isValid true for validation passed & false for validation failed
diff --git a/src/java/com/android/internal/telephony/data/DataUtils.java b/src/java/com/android/internal/telephony/data/DataUtils.java
index c88e0b3..c266428 100644
--- a/src/java/com/android/internal/telephony/data/DataUtils.java
+++ b/src/java/com/android/internal/telephony/data/DataUtils.java
@@ -404,52 +404,24 @@
     public static List<NetworkRequestList> getGroupedNetworkRequestList(
             @NonNull NetworkRequestList networkRequestList, @NonNull FeatureFlags featureFlags) {
         List<NetworkRequestList> requests = new ArrayList<>();
-        if (featureFlags.satelliteInternet()) {
-            record NetworkCapabilitiesKey(Set<Integer> caps, Set<Integer> enterpriseIds,
-                                          Set<Integer> transportTypes) { }
+        record NetworkCapabilitiesKey(Set<Integer> caps, Set<Integer> enterpriseIds,
+                                      Set<Integer> transportTypes) { }
 
-            // Key is the combination of capabilities, enterprise ids, and transport types.
-            Map<NetworkCapabilitiesKey, NetworkRequestList> requestsMap = new ArrayMap<>();
-            for (TelephonyNetworkRequest networkRequest : networkRequestList) {
-                requestsMap.computeIfAbsent(new NetworkCapabilitiesKey(
-                                Arrays.stream(networkRequest.getCapabilities())
-                                        .boxed().collect(Collectors.toSet()),
-                                Arrays.stream(networkRequest.getNativeNetworkRequest()
-                                                .getEnterpriseIds())
-                                        .boxed().collect(Collectors.toSet()),
-                                Arrays.stream(networkRequest.getTransportTypes())
-                                        .boxed().collect(Collectors.toSet())
-                                ),
-                        v -> new NetworkRequestList()).add(networkRequest);
-            }
-            requests.addAll(requestsMap.values());
-        } else {
-            // Key is the capabilities set.
-            Map<Set<Integer>, NetworkRequestList> requestsMap = new ArrayMap<>();
-            for (TelephonyNetworkRequest networkRequest : networkRequestList) {
-                requestsMap.computeIfAbsent(Arrays.stream(networkRequest.getCapabilities())
-                                .boxed().collect(Collectors.toSet()),
-                        v -> new NetworkRequestList()).add(networkRequest);
-            }
-            // Create separate groups for enterprise requests with different enterprise IDs.
-            for (NetworkRequestList requestList : requestsMap.values()) {
-                List<TelephonyNetworkRequest> enterpriseRequests = requestList.stream()
-                        .filter(request -> request.hasCapability(
-                                NetworkCapabilities.NET_CAPABILITY_ENTERPRISE))
-                        .toList();
-                if (enterpriseRequests.isEmpty()) {
-                    requests.add(requestList);
-                    continue;
-                }
-                // Key is the enterprise ID
-                Map<Integer, NetworkRequestList> enterpriseRequestsMap = new ArrayMap<>();
-                for (TelephonyNetworkRequest request : enterpriseRequests) {
-                    enterpriseRequestsMap.computeIfAbsent(request.getCapabilityDifferentiator(),
-                            v -> new NetworkRequestList()).add(request);
-                }
-                requests.addAll(enterpriseRequestsMap.values());
-            }
+        // Key is the combination of capabilities, enterprise ids, and transport types.
+        Map<NetworkCapabilitiesKey, NetworkRequestList> requestsMap = new ArrayMap<>();
+        for (TelephonyNetworkRequest networkRequest : networkRequestList) {
+            requestsMap.computeIfAbsent(new NetworkCapabilitiesKey(
+                            Arrays.stream(networkRequest.getCapabilities())
+                                    .boxed().collect(Collectors.toSet()),
+                            Arrays.stream(networkRequest.getNativeNetworkRequest()
+                                            .getEnterpriseIds())
+                                    .boxed().collect(Collectors.toSet()),
+                            Arrays.stream(networkRequest.getTransportTypes())
+                                    .boxed().collect(Collectors.toSet())
+                            ),
+                    v -> new NetworkRequestList()).add(networkRequest);
         }
+        requests.addAll(requestsMap.values());
         // Sort the requests so the network request list with higher priority will be at the front.
         return requests.stream()
                 .sorted((list1, list2) -> Integer.compare(
diff --git a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
index 079e705..f76db08 100644
--- a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
@@ -38,10 +38,8 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.ConnectivityManager;
-import android.net.MatchAllNetworkSpecifier;
 import android.net.Network;
 import android.net.NetworkCapabilities;
-import android.net.NetworkFactory;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
 import android.net.TelephonyNetworkSpecifier;
@@ -50,7 +48,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.PersistableBundle;
-import android.os.Registrant;
 import android.os.RegistrantList;
 import android.os.RemoteException;
 import android.telephony.CarrierConfigManager;
@@ -88,7 +85,6 @@
 import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.DataSwitch;
-import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.OnDemandDataSwitch;
 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.internal.telephony.subscription.SubscriptionManagerService.SubscriptionManagerServiceCallback;
@@ -267,7 +263,7 @@
     @VisibleForTesting
     // It decides:
     // 1. In modem layer, which modem is DDS (preferred to have data traffic on)
-    // 2. In TelephonyNetworkFactory, which subscription will apply default network requests, which
+    // 2. In TelephonyNetworkProvider, which subscription will apply default network requests, which
     //    are requests without specifying a subId.
     // Corresponding phoneId after considering mOpptDataSubId, mPrimaryDataSubId and
     // mPhoneIdInVoiceCall above.
@@ -290,8 +286,6 @@
 
     private static final int EVENT_PRIMARY_DATA_SUB_CHANGED       = 101;
     protected static final int EVENT_SUBSCRIPTION_CHANGED         = 102;
-    private static final int EVENT_REQUEST_NETWORK                = 103;
-    private static final int EVENT_RELEASE_NETWORK                = 104;
     // ECBM has started/ended. If we just ended an emergency call and mEmergencyOverride is not
     // null, we will wait for EVENT_EMERGENCY_TOGGLE again with ECBM ending to send the message
     // EVENT_REMOVE_DDS_EMERGENCY_OVERRIDE to remove the override after the mEmergencyOverride
@@ -651,37 +645,6 @@
                 this, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
 
         mConnectivityManager.registerDefaultNetworkCallback(mDefaultNetworkCallback, this);
-
-        if (!mFlags.supportNetworkProvider()) {
-            final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
-                    .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
-                    .addCapability(NetworkCapabilities.NET_CAPABILITY_IA)
-                    .addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL)
-                    .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
-                    .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_1)
-                    .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_2)
-                    .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_3)
-                    .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_4)
-                    .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_5)
-                    .setNetworkSpecifier(new MatchAllNetworkSpecifier());
-            TelephonyNetworkRequest.getAllSupportedNetworkCapabilities()
-                    .forEach(builder::addCapability);
-
-            if (mFlags.satelliteInternet()) {
-                // TODO: b/328622096 remove the try/catch
-                try {
-                    builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
-                } catch (IllegalArgumentException exception) {
-                    loge("TRANSPORT_SATELLITE is not supported.");
-                }
-            }
-
-            NetworkFactory networkFactory = new PhoneSwitcherNetworkRequestListener(looper, context,
-                    builder.build(), this);
-            // we want to see all requests
-            networkFactory.registerIgnoringScore();
-        }
-
         updateHalCommandToUse();
 
         logl("PhoneSwitcher started");
@@ -750,14 +713,6 @@
                         DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL);
                 break;
             }
-            case EVENT_REQUEST_NETWORK: {
-                onRequestNetwork((NetworkRequest)msg.obj);
-                break;
-            }
-            case EVENT_RELEASE_NETWORK: {
-                onReleaseNetwork((NetworkRequest)msg.obj);
-                break;
-            }
             case EVENT_EMERGENCY_TOGGLE: {
                 boolean isInEcm = isInEmergencyCallbackMode();
                 if (mEmergencyOverride != null) {
@@ -1100,43 +1055,15 @@
         return false;
     }
 
-    // TODO: Remove after removing TelephonyNetworkFactory
-    private static class PhoneSwitcherNetworkRequestListener extends NetworkFactory {
-        private final PhoneSwitcher mPhoneSwitcher;
-        public PhoneSwitcherNetworkRequestListener (Looper l, Context c,
-                NetworkCapabilities nc, PhoneSwitcher ps) {
-            super(l, c, "PhoneSwitcherNetworkRequestListener", nc);
-            mPhoneSwitcher = ps;
-        }
-
-        @Override
-        protected void needNetworkFor(@NonNull NetworkRequest networkRequest) {
-            if (VDBG) log("needNetworkFor " + networkRequest);
-            Message msg = mPhoneSwitcher.obtainMessage(EVENT_REQUEST_NETWORK);
-            msg.obj = networkRequest;
-            msg.sendToTarget();
-        }
-
-        @Override
-        protected void releaseNetworkFor(@NonNull NetworkRequest networkRequest) {
-            if (VDBG) log("releaseNetworkFor " + networkRequest);
-            Message msg = mPhoneSwitcher.obtainMessage(EVENT_RELEASE_NETWORK);
-            msg.obj = networkRequest;
-            msg.sendToTarget();
-        }
-    }
-
     /**
      * Called when receiving a network request.
      *
      * @param networkRequest The network request.
      */
     // TODO: Transform to TelephonyNetworkRequest after removing TelephonyNetworkFactory
-    public void onRequestNetwork(@NonNull NetworkRequest networkRequest) {
-        TelephonyNetworkRequest telephonyNetworkRequest = new TelephonyNetworkRequest(
-                networkRequest, PhoneFactory.getDefaultPhone(), mFlags);
-        if (!mNetworkRequestList.contains(telephonyNetworkRequest)) {
-            mNetworkRequestList.add(telephonyNetworkRequest);
+    public void onRequestNetwork(@NonNull TelephonyNetworkRequest networkRequest) {
+        if (!mNetworkRequestList.contains(networkRequest)) {
+            mNetworkRequestList.add(networkRequest);
             onEvaluate(REQUESTS_CHANGED, "netRequest");
         }
     }
@@ -1146,13 +1073,9 @@
      *
      * @param networkRequest The network request to release.
      */
-    // TODO: Transform to TelephonyNetworkRequest after removing TelephonyNetworkFactory
-    public void onReleaseNetwork(@NonNull NetworkRequest networkRequest) {
-        TelephonyNetworkRequest telephonyNetworkRequest = new TelephonyNetworkRequest(
-                networkRequest, PhoneFactory.getDefaultPhone(), mFlags);
-        if (mNetworkRequestList.remove(telephonyNetworkRequest)) {
+    public void onReleaseNetwork(@NonNull TelephonyNetworkRequest networkRequest) {
+        if (mNetworkRequestList.remove(networkRequest)) {
             onEvaluate(REQUESTS_CHANGED, "netReleased");
-            collectReleaseNetworkMetrics(networkRequest);
         }
     }
 
@@ -1161,18 +1084,6 @@
         mDefaultNetworkCallback.mSwitchReason = reason;
     }
 
-    private void collectReleaseNetworkMetrics(NetworkRequest networkRequest) {
-        // Release network for MMS will recover the network on default data subscription, this only
-        // happen on multi-sim device.
-        if (mActiveModemCount > 1 && networkRequest.hasCapability(
-                NetworkCapabilities.NET_CAPABILITY_MMS)) {
-            OnDemandDataSwitch onDemandDataSwitch = new OnDemandDataSwitch();
-            onDemandDataSwitch.apn = TelephonyEvent.ApnType.APN_TYPE_MMS;
-            onDemandDataSwitch.state = TelephonyEvent.EventState.EVENT_STATE_END;
-            TelephonyMetrics.getInstance().writeOnDemandDataSwitch(onDemandDataSwitch);
-        }
-    }
-
     /**
      * Cancel any auto switch attempts when the current environment is not suitable for auto switch.
      */
@@ -1610,17 +1521,6 @@
     }
 
     /**
-     * If preferred phone changes, or phone activation status changes, registrants
-     * will be notified.
-     */
-    // TODO: Remove after removing TelephonyNetworkFactory
-    public void registerForActivePhoneSwitch(Handler h, int what, Object o) {
-        Registrant r = new Registrant(h, what, o);
-        mActivePhoneRegistrants.add(r);
-        r.notifyRegistrant();
-    }
-
-    /**
      * Set opportunistic data subscription. It's an indication to switch Internet data to this
      * subscription. It has to be an active subscription, and PhoneSwitcher will try to validate
      * it first if needed. If subId is DEFAULT_SUBSCRIPTION_ID, it means we are un-setting
@@ -1717,7 +1617,8 @@
         mPendingSwitchNeedValidation = needValidation;
         mSetOpptSubCallback = callback;
         long validationTimeout = getValidationTimeout(subIdToValidate, needValidation);
-        mValidator.validate(subIdToValidate, validationTimeout, false, mValidationCallback);
+        mValidator.validate(subIdToValidate, validationTimeout,
+                mPendingSwitchNeedValidation, mValidationCallback);
     }
 
     private long getValidationTimeout(int subId, boolean needValidation) {
@@ -2037,10 +1938,8 @@
         // Notify all registrants
         mActivePhoneRegistrants.notifyRegistrants();
         notifyPreferredDataSubIdChanged();
-        if (mFlags.supportNetworkProvider()) {
-            mPhoneSwitcherCallbacks.forEach(callback -> callback.invokeFromExecutor(
-                    () -> callback.onPreferredDataPhoneIdChanged(phoneId)));
-        }
+        mPhoneSwitcherCallbacks.forEach(callback -> callback.invokeFromExecutor(
+                () -> callback.onPreferredDataPhoneIdChanged(phoneId)));
     }
 
     private boolean isPhoneIdValidForRetry(int phoneId) {
diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java
deleted file mode 100644
index 7d1746c..0000000
--- a/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.data;
-
-import android.annotation.NonNull;
-import android.net.NetworkCapabilities;
-import android.net.NetworkFactory;
-import android.net.NetworkRequest;
-import android.net.TelephonyNetworkSpecifier;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.telephony.AccessNetworkConstants;
-import android.telephony.SubscriptionManager;
-import android.util.LocalLog;
-
-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.NetworkRequestsStats;
-import com.android.internal.util.IndentingPrintWriter;
-import com.android.telephony.Rlog;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Telephony network factory is responsible for dispatching network requests from the connectivity
- * service to the data network controller.
- */
-public class TelephonyNetworkFactory extends NetworkFactory {
-    public final String LOG_TAG;
-    protected static final boolean DBG = true;
-
-    private static final int REQUEST_LOG_SIZE = 256;
-
-    private static final int ACTION_NO_OP   = 0;
-    private static final int ACTION_REQUEST = 1;
-    private static final int ACTION_RELEASE = 2;
-
-    private static final int TELEPHONY_NETWORK_SCORE = 50;
-
-    @VisibleForTesting
-    public static final int EVENT_ACTIVE_PHONE_SWITCH               = 1;
-    @VisibleForTesting
-    public static final int EVENT_SUBSCRIPTION_CHANGED              = 2;
-    private static final int EVENT_NETWORK_REQUEST                  = 3;
-    private static final int EVENT_NETWORK_RELEASE                  = 4;
-
-    private final PhoneSwitcher mPhoneSwitcher;
-    private final LocalLog mLocalLog = new LocalLog(REQUEST_LOG_SIZE);
-
-    // Key: network request. Value: the transport of the network request applies to,
-    // AccessNetworkConstants.TRANSPORT_TYPE_INVALID if not applied.
-    private final Map<TelephonyNetworkRequest, Integer> mNetworkRequests = new HashMap<>();
-
-    private final Phone mPhone;
-
-    private final AccessNetworksManager mAccessNetworksManager;
-
-    private int mSubscriptionId;
-
-    @VisibleForTesting
-    public final Handler mInternalHandler;
-
-    @NonNull
-    private final FeatureFlags mFlags;
-
-
-    /**
-     * Constructor
-     *
-     * @param looper The looper for the handler
-     * @param phone The phone instance
-     * @param featureFlags The feature flags
-     */
-    public TelephonyNetworkFactory(@NonNull Looper looper, @NonNull Phone phone,
-            @NonNull FeatureFlags featureFlags) {
-        super(looper, phone.getContext(), "TelephonyNetworkFactory[" + phone.getPhoneId()
-                + "]", null);
-        mPhone = phone;
-        mFlags = featureFlags;
-        mInternalHandler = new InternalHandler(looper);
-
-        mAccessNetworksManager = mPhone.getAccessNetworksManager();
-
-        setCapabilityFilter(makeNetworkFilterByPhoneId(mPhone.getPhoneId()));
-        setScoreFilter(TELEPHONY_NETWORK_SCORE);
-
-        mPhoneSwitcher = PhoneSwitcher.getInstance();
-        LOG_TAG = "TelephonyNetworkFactory[" + mPhone.getPhoneId() + "]";
-
-        mPhoneSwitcher.registerForActivePhoneSwitch(mInternalHandler, EVENT_ACTIVE_PHONE_SWITCH,
-                null);
-
-        mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-        SubscriptionManager.OnSubscriptionsChangedListener subscriptionsChangedListener =
-                new SubscriptionManager.OnSubscriptionsChangedListener() {
-                    @Override
-                    public void onSubscriptionsChanged() {
-                        mInternalHandler.sendEmptyMessage(EVENT_SUBSCRIPTION_CHANGED);
-                    }};
-
-        mPhone.getContext().getSystemService(SubscriptionManager.class)
-                .addOnSubscriptionsChangedListener(subscriptionsChangedListener);
-
-        register();
-    }
-
-    private NetworkCapabilities makeNetworkFilterByPhoneId(int phoneId) {
-        return makeNetworkFilter(SubscriptionManager.getSubscriptionId(phoneId));
-    }
-
-    /**
-     * Build the network request filter used by this factory.
-     * @param subscriptionId the subscription ID to listen to
-     * @return the filter to send to the system server
-     */
-    // This is used by the test to simulate the behavior of the system server, which is to
-    // send requests that match the network filter.
-    @VisibleForTesting
-    public NetworkCapabilities makeNetworkFilter(int subscriptionId) {
-        final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
-                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
-                .addCapability(NetworkCapabilities.NET_CAPABILITY_IA)
-                .addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL)
-                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
-                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
-                .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_1)
-                .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_2)
-                .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_3)
-                .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_4)
-                .addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_5)
-                .setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
-                                .setSubscriptionId(subscriptionId).build());
-        TelephonyNetworkRequest.getAllSupportedNetworkCapabilities()
-                .forEach(builder::addCapability);
-
-        if (mFlags.satelliteInternet()) {
-            // TODO: b/328622096 remove the try/catch
-            try {
-                builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
-            } catch (IllegalArgumentException exception) {
-                log("TRANSPORT_SATELLITE is not supported.");
-            }
-        }
-
-        return builder.build();
-    }
-
-    private class InternalHandler extends Handler {
-        InternalHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case EVENT_ACTIVE_PHONE_SWITCH: {
-                    onActivePhoneSwitch();
-                    break;
-                }
-                case EVENT_SUBSCRIPTION_CHANGED: {
-                    onSubIdChange();
-                    break;
-                }
-                case EVENT_NETWORK_REQUEST: {
-                    onNeedNetworkFor(msg);
-                    break;
-                }
-                case EVENT_NETWORK_RELEASE: {
-                    onReleaseNetworkFor(msg);
-                    break;
-                }
-            }
-        }
-    }
-
-    private int getTransportTypeFromNetworkRequest(TelephonyNetworkRequest networkRequest) {
-        int transport = AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
-        int capability = networkRequest.getHighestPriorityApnTypeNetworkCapability();
-        if (capability >= 0) {
-            transport = mAccessNetworksManager
-                    .getPreferredTransportByNetworkCapability(capability);
-        }
-        return transport;
-    }
-
-    private static int getAction(boolean wasActive, boolean isActive) {
-        if (!wasActive && isActive) {
-            return ACTION_REQUEST;
-        } else if (wasActive && !isActive) {
-            return ACTION_RELEASE;
-        } else {
-            return ACTION_NO_OP;
-        }
-    }
-
-    // apply or revoke requests if our active-ness changes
-    private void onActivePhoneSwitch() {
-        logl("onActivePhoneSwitch");
-        for (Map.Entry<TelephonyNetworkRequest, Integer> entry : mNetworkRequests.entrySet()) {
-            TelephonyNetworkRequest networkRequest = entry.getKey();
-            boolean applied = entry.getValue() != AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
-
-            boolean shouldApply = mPhoneSwitcher.shouldApplyNetworkRequest(
-                    networkRequest, mPhone.getPhoneId());
-
-            int action = getAction(applied, shouldApply);
-            if (action == ACTION_NO_OP) continue;
-
-            logl("onActivePhoneSwitch: " + ((action == ACTION_REQUEST)
-                    ? "Requesting" : "Releasing") + " network request " + networkRequest);
-            int transportType = getTransportTypeFromNetworkRequest(networkRequest);
-            if (action == ACTION_REQUEST) {
-                NetworkRequestsStats.addNetworkRequest(networkRequest.getNativeNetworkRequest(),
-                        mSubscriptionId);
-                mPhone.getDataNetworkController().addNetworkRequest(networkRequest);
-            } else if (action == ACTION_RELEASE) {
-                mPhone.getDataNetworkController().removeNetworkRequest(networkRequest);
-            }
-
-            mNetworkRequests.put(networkRequest,
-                    shouldApply ? transportType : AccessNetworkConstants.TRANSPORT_TYPE_INVALID);
-        }
-    }
-
-    // watch for phone->subId changes, reapply new filter and let
-    // that flow through to apply/revoke of requests
-    private void onSubIdChange() {
-        int newSubscriptionId = SubscriptionManager.getSubscriptionId(mPhone.getPhoneId());
-        if (mSubscriptionId != newSubscriptionId) {
-            if (DBG) logl("onSubIdChange " + mSubscriptionId + "->" + newSubscriptionId);
-            mSubscriptionId = newSubscriptionId;
-            setCapabilityFilter(makeNetworkFilter(mSubscriptionId));
-        }
-    }
-
-    @Override
-    public void needNetworkFor(@NonNull NetworkRequest networkRequest) {
-        Message msg = mInternalHandler.obtainMessage(EVENT_NETWORK_REQUEST);
-        msg.obj = networkRequest;
-        msg.sendToTarget();
-    }
-
-    private void onNeedNetworkFor(@NonNull Message msg) {
-        TelephonyNetworkRequest networkRequest =
-                new TelephonyNetworkRequest((NetworkRequest) msg.obj, mPhone, mFlags);
-        boolean shouldApply = mPhoneSwitcher.shouldApplyNetworkRequest(
-                networkRequest, mPhone.getPhoneId());
-
-        mNetworkRequests.put(networkRequest, shouldApply
-                ? getTransportTypeFromNetworkRequest(networkRequest)
-                : AccessNetworkConstants.TRANSPORT_TYPE_INVALID);
-
-        logl("onNeedNetworkFor " + networkRequest + " shouldApply " + shouldApply);
-
-        if (shouldApply) {
-            NetworkRequestsStats.addNetworkRequest(networkRequest.getNativeNetworkRequest(),
-                    mSubscriptionId);
-            mPhone.getDataNetworkController().addNetworkRequest(networkRequest);
-        }
-    }
-
-    @Override
-    public void releaseNetworkFor(@NonNull NetworkRequest networkRequest) {
-        Message msg = mInternalHandler.obtainMessage(EVENT_NETWORK_RELEASE);
-        msg.obj = networkRequest;
-        msg.sendToTarget();
-    }
-
-    private void onReleaseNetworkFor(@NonNull Message msg) {
-        TelephonyNetworkRequest networkRequest =
-                new TelephonyNetworkRequest((NetworkRequest) msg.obj, mPhone, mFlags);
-        boolean applied = mNetworkRequests.get(networkRequest)
-                != AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
-
-        mNetworkRequests.remove(networkRequest);
-
-        logl("onReleaseNetworkFor " + networkRequest + " applied " + applied);
-
-        if (applied) {
-            mPhone.getDataNetworkController().removeNetworkRequest(networkRequest);
-        }
-    }
-
-    protected void log(String s) {
-        Rlog.d(LOG_TAG, s);
-    }
-
-    protected void logl(String s) {
-        log(s);
-        mLocalLog.log(s);
-    }
-
-    /**
-     * Dump the state of telephony network factory
-     *
-     * @param fd File descriptor
-     * @param writer Print writer
-     * @param args Arguments
-     */
-    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
-        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
-        pw.println("TelephonyNetworkFactory-" + mPhone.getPhoneId());
-        pw.increaseIndent();
-        pw.println("Network Requests:");
-        pw.increaseIndent();
-        for (Map.Entry<TelephonyNetworkRequest, Integer> entry : mNetworkRequests.entrySet()) {
-            TelephonyNetworkRequest nr = entry.getKey();
-            int transport = entry.getValue();
-            pw.println(nr + (transport != AccessNetworkConstants.TRANSPORT_TYPE_INVALID
-                    ? (" applied on " + transport) : " not applied"));
-        }
-        pw.decreaseIndent();
-        pw.print("Local logs:");
-        pw.increaseIndent();
-        mLocalLog.dump(fd, pw, args);
-        pw.decreaseIndent();
-        pw.decreaseIndent();
-    }
-}
diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkProvider.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkProvider.java
index 63edefa..fb81658 100644
--- a/src/java/com/android/internal/telephony/data/TelephonyNetworkProvider.java
+++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkProvider.java
@@ -32,6 +32,7 @@
 import android.util.ArrayMap;
 import android.util.LocalLog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.data.PhoneSwitcher.PhoneSwitcherCallback;
@@ -152,7 +153,7 @@
             return;
         }
 
-        mPhoneSwitcher.onRequestNetwork(request);
+        mPhoneSwitcher.onRequestNetwork(networkRequest);
 
         // Check with PhoneSwitcher to see where to route the request.
         int phoneId = getPhoneIdForNetworkRequest(networkRequest);
@@ -187,7 +188,7 @@
             return;
         }
 
-        mPhoneSwitcher.onReleaseNetwork(request);
+        mPhoneSwitcher.onReleaseNetwork(networkRequest);
         int phoneId = mNetworkRequests.remove(networkRequest);
         Phone phone = PhoneFactory.getPhone(phoneId);
         if (phone != null) {
@@ -233,10 +234,12 @@
     /**
      * @return The maximal network capabilities that telephony can support.
      */
+    @VisibleForTesting
     @NonNull
-    private NetworkCapabilities makeNetworkFilter() {
+    public NetworkCapabilities makeNetworkFilter() {
         final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
                 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+                .addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE)
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_IA)
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL)
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
@@ -254,13 +257,6 @@
         TelephonyNetworkRequest.getAllSupportedNetworkCapabilities()
                 .forEach(builder::addCapability);
 
-        // TODO: b/328622096 remove the try/catch
-        try {
-            builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
-        } catch (IllegalArgumentException exception) {
-            log("TRANSPORT_SATELLITE is not supported.");
-        }
-
         return builder.build();
     }
 
diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java
index ca1ca21..fc37f58 100644
--- a/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java
+++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java
@@ -32,6 +32,7 @@
 import android.telephony.data.TrafficDescriptor.OsAppId;
 
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.flags.FeatureFlags;
 
 import java.lang.annotation.Retention;
@@ -41,6 +42,7 @@
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -327,31 +329,29 @@
         if ((hasAttribute(CAPABILITY_ATTRIBUTE_APN_SETTING)
                 || hasAttribute(CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN))
                 && dataProfile.getApnSetting() != null) {
-            if (mFeatureFlags.satelliteInternet()) {
-                if (mNativeNetworkRequest.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
-                        && !mNativeNetworkRequest.hasTransport(
-                                NetworkCapabilities.TRANSPORT_SATELLITE)) {
-                    if (mDataConfigManager != null) {
-                        if (Arrays.stream(getCapabilities()).noneMatch(mDataConfigManager
-                                .getForcedCellularTransportCapabilities()::contains)) {
-                            // If the request is explicitly for the cellular, then the data profile
-                            // needs to support cellular.
-                            if (!dataProfile.getApnSetting().isForInfrastructure(
-                                    ApnSetting.INFRASTRUCTURE_CELLULAR)) {
-                                return false;
-                            }
+            if (mNativeNetworkRequest.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+                    && !mNativeNetworkRequest.hasTransport(
+                            NetworkCapabilities.TRANSPORT_SATELLITE)) {
+                if (mDataConfigManager != null) {
+                    if (Arrays.stream(getCapabilities()).noneMatch(mDataConfigManager
+                            .getForcedCellularTransportCapabilities()::contains)) {
+                        // If the request is explicitly for the cellular, then the data profile
+                        // needs to support cellular.
+                        if (!dataProfile.getApnSetting().isForInfrastructure(
+                                ApnSetting.INFRASTRUCTURE_CELLULAR)) {
+                            return false;
                         }
                     }
-                } else if (mNativeNetworkRequest.hasTransport(
-                        NetworkCapabilities.TRANSPORT_SATELLITE)
-                        && !mNativeNetworkRequest.hasTransport(
-                                NetworkCapabilities.TRANSPORT_CELLULAR)) {
-                    // If the request is explicitly for the satellite, then the data profile needs
-                    // to support satellite.
-                    if (!dataProfile.getApnSetting().isForInfrastructure(
-                            ApnSetting.INFRASTRUCTURE_SATELLITE)) {
-                        return false;
-                    }
+                }
+            } else if (mNativeNetworkRequest.hasTransport(
+                    NetworkCapabilities.TRANSPORT_SATELLITE)
+                    && !mNativeNetworkRequest.hasTransport(
+                            NetworkCapabilities.TRANSPORT_CELLULAR)) {
+                // If the request is explicitly for the satellite, then the data profile needs
+                // to support satellite.
+                if (!dataProfile.getApnSetting().isForInfrastructure(
+                        ApnSetting.INFRASTRUCTURE_SATELLITE)) {
+                    return false;
                 }
             }
             // Fallback to the legacy APN type matching.
@@ -437,7 +437,11 @@
     @NonNull
     @NetCapability
     public static List<Integer> getAllSupportedNetworkCapabilities() {
-        return CAPABILITY_ATTRIBUTE_MAP.keySet().stream().toList();
+        Set<Integer> unsupportedCaps = PhoneFactory.getDefaultPhone()
+                .getDataNetworkController().getDataConfigManager()
+                .getUnsupportedNetworkCapabilities();
+        return CAPABILITY_ATTRIBUTE_MAP.keySet().stream()
+                .filter(cap -> !unsupportedCaps.contains(cap)).toList();
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java b/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java
index e4ae592..a8fead4 100644
--- a/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java
+++ b/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java
@@ -44,7 +44,9 @@
 import com.android.internal.telephony.IDomainSelectionServiceController;
 import com.android.internal.telephony.ITransportSelectorCallback;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.internal.telephony.util.WorkerThread;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -80,10 +82,9 @@
         long getMaximumDelay();
     }
 
-    private final HandlerThread mHandlerThread =
-            new HandlerThread("DomainSelectionControllerHandler");
-
+    private HandlerThread mHandlerThread; // effectively final
     private final Handler mHandler;
+
     // Only added or removed, never accessed on purpose.
     private final LocalLog mLocalLog = new LocalLog(30);
 
@@ -255,9 +256,15 @@
             @Nullable Looper looper, @Nullable BindRetry bindRetry) {
         mContext = context;
 
+        mHandlerThread = null;
         if (looper == null) {
-            mHandlerThread.start();
-            looper = mHandlerThread.getLooper();
+            if (Flags.threadShred()) {
+                looper = WorkerThread.get().getLooper();
+            } else {
+                mHandlerThread = new HandlerThread("DomainSelectionControllerHandler");
+                mHandlerThread.start();
+                looper = mHandlerThread.getLooper();
+            }
         }
         mHandler = new DomainSelectionControllerHandler(looper);
 
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
index 06ebff2..e2b36f0 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
@@ -187,10 +187,14 @@
         mFeatureFlags = featureFlags;
         mResources = ctx.getResources();
 
-        if (TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)
-                && !ctx.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_TELEPHONY_CALLING)) {
-            throw new UnsupportedOperationException("EmergencyNumberTracker requires calling");
+        if (TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) {
+            if (!ctx.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
+                    && !ctx.getPackageManager()
+                            .hasSystemFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)) {
+                throw new UnsupportedOperationException(
+                        "EmergencyNumberTracker requires telephony calling or messaging feature to"
+                                + " be enabled");
+            }
         }
 
         if (mPhone != null) {
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
index b3e8095..4a3ab21 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
@@ -74,6 +74,8 @@
 import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.imsphone.ImsPhoneConnection;
 import com.android.internal.telephony.satellite.SatelliteController;
+import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.telephony.Rlog;
 
 import java.lang.annotation.Retention;
@@ -141,6 +143,8 @@
     private final Handler mHandler;
     private final boolean mIsSuplDdsSwitchRequiredForEmergencyCall;
     private final int mWaitForInServiceTimeoutMs;
+    private final boolean mTurnOffOemEnabledSatelliteDuringEmergencyCall;
+    private final boolean mTurnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall;
     private final PowerManager.WakeLock mWakeLock;
     private RadioOnHelper mRadioOnHelper;
     @EmergencyConstants.EmergencyMode
@@ -163,6 +167,8 @@
     private android.telecom.Connection mOngoingConnection;
     // Domain of the active emergency call. Assuming here that there will only be one domain active.
     private int mEmergencyCallDomain = NetworkRegistrationInfo.DOMAIN_UNKNOWN;
+    // Phone type of the active emergency call. Assuming that there will only be one phone active.
+    private int mEmergencyCallPhoneType = PhoneConstants.PHONE_TYPE_NONE;
     private CompletableFuture<Integer> mCallEmergencyModeFuture;
     private boolean mIsInEmergencyCall;
     private boolean mIsInEcm;
@@ -310,8 +316,24 @@
                     maybeNotifyTransportChangeCompleted(emergencyType, false);
 
                     if (emergencyType == EMERGENCY_TYPE_CALL) {
-                        setIsInEmergencyCall(true);
-                        completeEmergencyMode(emergencyType);
+                        // If the emergency registration result(mLastEmergencyRegistrationResult) is
+                        // null, it means that the emergency mode is not set properly on the modem.
+                        // Therefore, based on the emergency registration result and current
+                        // subscription status, the current phone is not available for an emergency
+                        // call, so we check if an emergency call is possible through cross stack.
+                        if (mFeatureFlags.performCrossStackRedialCheckForEmergencyCall()
+                                && mLastEmergencyRegistrationResult == null
+                                && mPhone != null
+                                && !SubscriptionManager.isValidSubscriptionId(mPhone.getSubId())
+                                && needToSwitchPhone(mPhone)) {
+                            Rlog.i(TAG, "setEmergencyMode failed: need to switch stacks.");
+                            mEmergencyMode = MODE_EMERGENCY_NONE;
+                            completeEmergencyMode(emergencyType,
+                                    DisconnectCause.EMERGENCY_PERM_FAILURE);
+                        } else {
+                            setIsInEmergencyCall(true);
+                            completeEmergencyMode(emergencyType);
+                        }
 
                         // Case 1) When the emergency call is setting the emergency mode and
                         // the emergency SMS is being sent, completes the SMS future also.
@@ -470,13 +492,24 @@
      * @param context                                 The context of the application.
      * @param isSuplDdsSwitchRequiredForEmergencyCall Whether gnss supl requires default data for
      *                                                emergency call.
+     * @param turnOffOemEnabledSatelliteDuringEmergencyCall Specifying whether OEM enabled satellite
+     *                                                      should be turned off during emergency
+     *                                                      call.
+     * @param turnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall Specifying whether non-emergency
+     *                                                             NB-IOT NTN satellite should be
+     *                                                             turned off for emergency call.
      * @param featureFlags                            The telephony feature flags.
      */
     public static void make(Context context, boolean isSuplDdsSwitchRequiredForEmergencyCall,
-            int waitForInServiceTimeout, @NonNull FeatureFlags featureFlags) {
+            int waitForInServiceTimeout, boolean turnOffOemEnabledSatelliteDuringEmergencyCall,
+            boolean turnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall,
+            @NonNull FeatureFlags featureFlags) {
         if (INSTANCE == null) {
             INSTANCE = new EmergencyStateTracker(context, Looper.myLooper(),
-                    isSuplDdsSwitchRequiredForEmergencyCall, waitForInServiceTimeout, featureFlags);
+                    isSuplDdsSwitchRequiredForEmergencyCall, waitForInServiceTimeout,
+                    turnOffOemEnabledSatelliteDuringEmergencyCall,
+                    turnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall,
+                    featureFlags);
         }
     }
 
@@ -497,12 +530,18 @@
      */
     private EmergencyStateTracker(Context context, Looper looper,
             boolean isSuplDdsSwitchRequiredForEmergencyCall, int waitForInServiceTimeout,
+            boolean turnOffOemEnabledSatelliteDuringEmergencyCall,
+            boolean turnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall,
             @NonNull FeatureFlags featureFlags) {
         mEcmExitTimeoutMs = DEFAULT_ECM_EXIT_TIMEOUT_MS;
         mContext = context;
         mHandler = new MyHandler(looper);
         mIsSuplDdsSwitchRequiredForEmergencyCall = isSuplDdsSwitchRequiredForEmergencyCall;
         mWaitForInServiceTimeoutMs = waitForInServiceTimeout;
+        mTurnOffOemEnabledSatelliteDuringEmergencyCall =
+                turnOffOemEnabledSatelliteDuringEmergencyCall;
+        mTurnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall =
+                turnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall;
         mFeatureFlags = featureFlags;
         PowerManager pm = context.getSystemService(PowerManager.class);
         mWakeLock = (pm != null) ? pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
@@ -539,6 +578,12 @@
      *                                                modem to get in-service state when emergency
      *                                                call is dialed in airplane mode before
      *                                                starting the emergency call.
+     * @param turnOffOemEnabledSatelliteDuringEmergencyCall Specifying whether OEM enabled satellite
+     *                                                      should be turned off during emergency
+     *                                                      call.
+     * @param turnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall Specifying whether non-emergency
+     *                                                             NB-IOT NTN satellite should be
+     *                                                             turned off for emergency call.
      * @param phoneFactoryProxy                       The {@link PhoneFactoryProxy} to be injected.
      * @param phoneSwitcherProxy                      The {@link PhoneSwitcherProxy} to be injected.
      * @param telephonyManagerProxy                   The {@link TelephonyManagerProxy} to be
@@ -549,6 +594,8 @@
     @VisibleForTesting
     public EmergencyStateTracker(Context context, Looper looper,
             boolean isSuplDdsSwitchRequiredForEmergencyCall, int waitForInServiceTimeout,
+            boolean turnOffOemEnabledSatelliteDuringEmergencyCall,
+            boolean turnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall,
             PhoneFactoryProxy phoneFactoryProxy, PhoneSwitcherProxy phoneSwitcherProxy,
             TelephonyManagerProxy telephonyManagerProxy, RadioOnHelper radioOnHelper,
             long ecmExitTimeoutMs, FeatureFlags featureFlags) {
@@ -556,6 +603,10 @@
         mHandler = new MyHandler(looper);
         mIsSuplDdsSwitchRequiredForEmergencyCall = isSuplDdsSwitchRequiredForEmergencyCall;
         mWaitForInServiceTimeoutMs = waitForInServiceTimeout;
+        mTurnOffOemEnabledSatelliteDuringEmergencyCall =
+                turnOffOemEnabledSatelliteDuringEmergencyCall;
+        mTurnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall =
+                turnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall;
         mPhoneFactoryProxy = phoneFactoryProxy;
         mPhoneSwitcherProxy = phoneSwitcherProxy;
         mTelephonyManagerProxy = telephonyManagerProxy;
@@ -702,7 +753,7 @@
         }
 
         if (wasActive && mActiveEmergencyCalls.isEmpty()
-                && isEmergencyCallbackModeSupported(mPhone)) {
+                && isEmergencyCallbackModeSupported(mPhone, true)) {
             enterEmergencyCallbackMode();
 
             if (mOngoingConnection == null) {
@@ -713,10 +764,17 @@
             if (isInEcm()) {
                 mIsEmergencyCallStartedDuringEmergencySms = false;
                 mCallEmergencyModeFuture = null;
-                // If the emergency call was initiated during the emergency callback mode,
-                // the emergency callback mode should be restored when the emergency call is ended.
+
                 if (mActiveEmergencyCalls.isEmpty()) {
-                    enterEmergencyCallbackMode();
+                    // If the emergency call was initiated during the emergency callback mode,
+                    // the emergency callback mode should be restored when the emergency call is
+                    // ended.
+                    if (isEmergencyCallbackModeSupported(mPhone, true)) {
+                        enterEmergencyCallbackMode();
+                    } else {
+                        exitEmergencyCallbackMode();
+                        clearEmergencyCallInfo();
+                    }
                 }
             } else {
                 if (isInScbm()) {
@@ -735,6 +793,7 @@
 
     private void clearEmergencyCallInfo() {
         mEmergencyCallDomain = NetworkRegistrationInfo.DOMAIN_UNKNOWN;
+        mEmergencyCallPhoneType = PhoneConstants.PHONE_TYPE_NONE;
         mIsTestEmergencyNumber = false;
         mIsEmergencyCallStartedDuringEmergencySms = false;
         mCallEmergencyModeFuture = null;
@@ -851,23 +910,25 @@
 
     private void completeEmergencyMode(@EmergencyType int emergencyType,
             @DisconnectCauses int result) {
+        CompletableFuture<Integer> emergencyModeFuture = null;
+
         if (emergencyType == EMERGENCY_TYPE_CALL) {
-            if (mCallEmergencyModeFuture != null && !mCallEmergencyModeFuture.isDone()) {
-                mCallEmergencyModeFuture.complete(result);
-            }
+            emergencyModeFuture = mCallEmergencyModeFuture;
 
             if (result != DisconnectCause.NOT_DISCONNECTED) {
                 clearEmergencyCallInfo();
             }
         } else if (emergencyType == EMERGENCY_TYPE_SMS) {
-            if (mSmsEmergencyModeFuture != null && !mSmsEmergencyModeFuture.isDone()) {
-                mSmsEmergencyModeFuture.complete(result);
-            }
+            emergencyModeFuture = mSmsEmergencyModeFuture;
 
             if (result != DisconnectCause.NOT_DISCONNECTED) {
                 clearEmergencySmsInfo();
             }
         }
+
+        if (emergencyModeFuture != null && !emergencyModeFuture.isDone()) {
+            emergencyModeFuture.complete(result);
+        }
     }
 
     /**
@@ -1075,9 +1136,16 @@
                 Rlog.w(TAG, "domain updated: Unexpected phoneType:" + phoneType);
             }
         }
-        if (mEmergencyCallDomain == domain) return;
-        Rlog.i(TAG, "domain updated: from " + mEmergencyCallDomain + " to " + domain);
-        mEmergencyCallDomain = domain;
+
+        if (mEmergencyCallPhoneType != phoneType) {
+            Rlog.i(TAG, "phoneType updated: from " + mEmergencyCallPhoneType + " to " + phoneType);
+            mEmergencyCallPhoneType = phoneType;
+        }
+
+        if (mEmergencyCallDomain != domain) {
+            Rlog.i(TAG, "domain updated: from " + mEmergencyCallDomain + " to " + domain);
+            mEmergencyCallDomain = domain;
+        }
     }
 
     /**
@@ -1127,12 +1195,27 @@
     }
 
     /**
-     * Returns {@code true} if device and carrier support emergency callback mode.
+     * Returns {@code true} if device and carrier support emergency callback mode. If
+     * {@code forEcbm} is {@code true}, it also checks RAT used when the emergency call ended.
      *
      * @param phone The {@link Phone} instance to be checked.
+     * @param forEcbm {@code true} if it's for the ECBM. {@code false} if it's for the SCBM.
      */
     @VisibleForTesting
-    public boolean isEmergencyCallbackModeSupported(Phone phone) {
+    public boolean isEmergencyCallbackModeSupported(Phone phone, boolean forEcbm) {
+        // TODO(b/399787802): Remove the forEcbm parameter and related logic when the CDMA-related
+        // APIs are deprecated. Replace this logic with a check that utilizes the domain parameter
+        // to determine ECBM and SCBM support.
+        if (forEcbm) {
+            if (mFeatureFlags.disableEcbmBasedOnRat()) {
+                if ((mEmergencyCallPhoneType == PhoneConstants.PHONE_TYPE_GSM)
+                        || (mEmergencyCallPhoneType == PhoneConstants.PHONE_TYPE_NONE)) {
+                    Rlog.d(TAG, "ecbmUnavailableRat");
+                    return false;
+                }
+            }
+        }
+
         if (phone == null) {
             return false;
         }
@@ -1251,9 +1334,15 @@
             exitEmergencyMode(gsmCdmaPhone, EMERGENCY_TYPE_CALL);
         }
 
-        mEmergencyCallDomain = NetworkRegistrationInfo.DOMAIN_UNKNOWN;
-        mIsTestEmergencyNumber = false;
-        mPhone = null;
+        // If an emergency call is in progress, even if this method is called for any reason,
+        // we should not initialize the Phone object so that the application can normally end
+        // the emergency call.
+        if (mOngoingConnection == null) {
+            mEmergencyCallDomain = NetworkRegistrationInfo.DOMAIN_UNKNOWN;
+            mEmergencyCallPhoneType = PhoneConstants.PHONE_TYPE_NONE;
+            mIsTestEmergencyNumber = false;
+            mPhone = null;
+        }
     }
 
     private void releaseWakeLock() {
@@ -1470,7 +1559,7 @@
 
             // If SCBM supports, SCBM will be entered here regardless of ECBM state.
             if (success && domain == NetworkRegistrationInfo.DOMAIN_PS
-                    && (isInScbm() || isEmergencyCallbackModeSupported(mSmsPhone))) {
+                    && (isInScbm() || isEmergencyCallbackModeSupported(mSmsPhone, false))) {
                 enterEmergencySmsCallbackMode();
             } else if (isInScbm()) {
                 // Sets the emergency mode to CALLBACK without re-initiating SCBM timer.
@@ -1676,8 +1765,7 @@
             boolean isTestEmergencyNumber) {
         final boolean isAirplaneModeOn = isAirplaneModeOn(mContext);
         boolean needToTurnOnRadio = !isRadioOn() || isAirplaneModeOn;
-        final SatelliteController satelliteController = SatelliteController.getInstance();
-        boolean needToTurnOffSatellite = satelliteController.isSatelliteEnabledOrBeingEnabled();
+        boolean needToTurnOffSatellite = shouldExitSatelliteMode();
 
         if (isAirplaneModeOn && !isPowerOff()
                 && !phone.getServiceStateTracker().getDesiredPowerState()) {
@@ -1713,7 +1801,7 @@
                         return;
                     }
                     if (!isRadioReady) {
-                        if (satelliteController.isSatelliteEnabledOrBeingEnabled()) {
+                        if (shouldExitSatelliteMode()) {
                             // Could not turn satellite off
                             Rlog.e(TAG, "Failed to turn off satellite modem.");
                             completeEmergencyMode(emergencyType, DisconnectCause.SATELLITE_ENABLED);
@@ -1746,7 +1834,7 @@
                         return false;
                     }
                     return phone.getServiceStateTracker().isRadioOn()
-                            && !satelliteController.isSatelliteEnabledOrBeingEnabled();
+                            && !shouldExitSatelliteMode();
                 }
 
                 @Override
@@ -1758,7 +1846,7 @@
                     }
                     // onTimeout shall be called only with the Phone for emergency
                     return phone.getServiceStateTracker().isRadioOn()
-                            && !satelliteController.isSatelliteEnabledOrBeingEnabled();
+                            && !shouldExitSatelliteMode();
                 }
             }, !isTestEmergencyNumber, phone, isTestEmergencyNumber, waitForInServiceTimeout);
         } else {
@@ -2268,4 +2356,55 @@
 
         return false;
     }
+
+    /**
+     * Checks whether the satellite mode should be turned off to proceed with an emergency call
+     * when satellite mode is enabled or an NTN(Non Terrestrial Network) session is in progress.
+     *
+     * @return {@code true} if satellite mode should be exited before an emergency call is being
+     *         processed, {@code false} otherwise.
+     */
+    @VisibleForTesting
+    public boolean shouldExitSatelliteMode() {
+        final SatelliteController satelliteController = SatelliteController.getInstance();
+
+        if (!satelliteController.isSatelliteEnabledOrBeingEnabled()) {
+            return false;
+        }
+
+        if (!mTurnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall) {
+            // Carrier
+            return false;
+        }
+
+        if (satelliteController.isDemoModeEnabled()) {
+            // If user makes emergency call in demo mode, end the satellite session
+            return true;
+        } else if (mFeatureFlags.carrierRoamingNbIotNtn()
+                && !satelliteController.getRequestIsEmergency()) {
+            // If satellite is not for emergency, end the satellite session
+            return true;
+        } else { // satellite is for emergency
+            if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+                int subId = satelliteController.getSelectedSatelliteSubId();
+                SubscriptionInfoInternal info = SubscriptionManagerService.getInstance()
+                        .getSubscriptionInfoInternal(subId);
+                if (info == null) {
+                    Rlog.e(TAG, "satellite is/being enabled, but satellite sub "
+                            + subId + " is null");
+                    return false;
+                }
+
+                if (info.getOnlyNonTerrestrialNetwork() == 1) {
+                    // OEM
+                    return mTurnOffOemEnabledSatelliteDuringEmergencyCall;
+                } else {
+                    // Carrier
+                    return satelliteController.shouldTurnOffCarrierSatelliteForEmergencyCall();
+                }
+            } else {
+                return mTurnOffOemEnabledSatelliteDuringEmergencyCall;
+            }
+        }
+    }
 }
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccCardController.java b/src/java/com/android/internal/telephony/euicc/EuiccCardController.java
index e511e8f..96107a2 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccCardController.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccCardController.java
@@ -1544,8 +1544,7 @@
             return;
         }
 
-        if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
-                || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+        if (!CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
                 Binder.getCallingUserHandle())
                 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
             // Skip to check associated telephony feature,
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccConnector.java b/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
index c5cc769..b919bdd 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccConnector.java
@@ -749,12 +749,12 @@
         @Override
         public boolean processMessage(Message message) {
             if (message.what == CMD_SERVICE_DISCONNECTED) {
-                EuiccSession.get().endAllSessions();
+                EuiccSession.get(mContext).endAllSessions();
                 mEuiccService = null;
                 transitionTo(mDisconnectedState);
                 return HANDLED;
             } else if (message.what == CMD_LINGER_TIMEOUT) {
-                EuiccSession.get().endAllSessions();
+                EuiccSession.get(mContext).endAllSessions();
                 unbind();
                 transitionTo(mAvailableState);
                 return HANDLED;
@@ -833,7 +833,7 @@
                         }
                         case CMD_DOWNLOAD_SUBSCRIPTION: {
                             DownloadRequest request = (DownloadRequest) message.obj;
-                            EuiccSession.get().startSession(EuiccSession.DOWNLOAD);
+                            EuiccSession.get(mContext).startSession(EuiccSession.DOWNLOAD);
                             mEuiccService.downloadSubscription(slotId,
                                     request.mPortIndex,
                                     request.mSubscription,
@@ -848,7 +848,8 @@
                                                     .onDownloadComplete(result);
                                                 onCommandEnd(callback);
                                             });
-                                            EuiccSession.get().endSession(EuiccSession.DOWNLOAD);
+                                            EuiccSession.get(mContext)
+                                                    .endSession(EuiccSession.DOWNLOAD);
                                         }
                                     });
                             break;
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccController.java b/src/java/com/android/internal/telephony/euicc/EuiccController.java
index cc9d793..58eb4f2 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccController.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccController.java
@@ -2377,8 +2377,7 @@
             return;
         }
 
-        if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
-                || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+        if (!CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
                 Binder.getCallingUserHandle())
                 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
             // Skip to check associated telephony feature,
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccSession.java b/src/java/com/android/internal/telephony/euicc/EuiccSession.java
index f17789f..790ca89 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccSession.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccSession.java
@@ -16,6 +16,7 @@
 package com.android.internal.telephony.euicc;
 
 import android.annotation.Nullable;
+import android.content.Context;
 import android.util.ArraySet;
 
 import com.android.internal.annotations.GuardedBy;
@@ -41,9 +42,9 @@
     @GuardedBy("EuiccSession.class")
     private static EuiccSession sInstance;
 
-    public static synchronized EuiccSession get() {
+    public static synchronized EuiccSession get(Context context) {
         if (sInstance == null) {
-            sInstance = new EuiccSession();
+            sInstance = new EuiccSession(context);
         }
         return sInstance;
     }
@@ -53,6 +54,18 @@
 
     @GuardedBy("this")
     private final Set<ApduSender> mApduSenders = new ArraySet<>();
+    private final Context mContext;
+
+    /**
+     * Returns true if the ApduSender optimization is enabled i.e. a logical channel is opened
+     * and kept open for multiple APDU commands within one session.
+     *
+     * This is gated by both an aconfig flag and a device-specific flag.
+     */
+    private boolean optimizeApduSender() {
+        return Flags.optimizationApduSender() && mContext.getResources().getBoolean(
+                com.android.internal.R.bool.euicc_optimize_apdu_sender);
+    }
 
     /**
      * Marks the start of a eUICC transaction session.
@@ -72,7 +85,7 @@
      * @param sessionId The session ID.
      */
     public void startSession(String sessionId) {
-        if (!Flags.optimizationApduSender()) {
+        if (!optimizeApduSender()) {
             // Other methods in this class is no-op if no session started.
             // Do not add flag to other methods, so if the flag gets turned off,
             // the session can be ended properly.
@@ -179,5 +192,7 @@
     }
 
     @VisibleForTesting
-    public EuiccSession() {}
+    public EuiccSession(Context context) {
+        mContext = context;
+    }
 }
diff --git a/src/java/com/android/internal/telephony/ims/ImsResolver.java b/src/java/com/android/internal/telephony/ims/ImsResolver.java
index b95911f..73ea190 100644
--- a/src/java/com/android/internal/telephony/ims/ImsResolver.java
+++ b/src/java/com/android/internal/telephony/ims/ImsResolver.java
@@ -63,6 +63,7 @@
 import com.android.internal.os.SomeArgs;
 import com.android.internal.telephony.PhoneConfigurationManager;
 import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.util.WorkerThread;
 import com.android.internal.util.IndentingPrintWriter;
 
 import java.io.FileDescriptor;
@@ -138,7 +139,8 @@
 
     // Delay between dynamic ImsService queries.
     private static final int DELAY_DYNAMIC_QUERY_MS = 5000;
-    private static final HandlerThread sHandlerThread = new HandlerThread(TAG);
+
+    private static HandlerThread sHandlerThread;
 
     private static ImsResolver sInstance;
 
@@ -149,9 +151,15 @@
             String defaultRcsPackageName, int numSlots, ImsFeatureBinderRepository repo,
             FeatureFlags featureFlags) {
         if (sInstance == null) {
-            sHandlerThread.start();
-            sInstance = new ImsResolver(context, defaultMmTelPackageName, defaultRcsPackageName,
-                    numSlots, repo, sHandlerThread.getLooper(), featureFlags);
+            if (featureFlags.threadShred()) {
+                sInstance = new ImsResolver(context, defaultMmTelPackageName, defaultRcsPackageName,
+                        numSlots, repo, WorkerThread.get().getLooper(), featureFlags);
+            } else {
+                sHandlerThread = new HandlerThread(TAG);
+                sHandlerThread.start();
+                sInstance = new ImsResolver(context, defaultMmTelPackageName, defaultRcsPackageName,
+                        numSlots, repo, sHandlerThread.getLooper(), featureFlags);
+            }
         }
     }
 
diff --git a/src/java/com/android/internal/telephony/ims/ImsServiceController.java b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
index 37c10eb..c61c7eb 100644
--- a/src/java/com/android/internal/telephony/ims/ImsServiceController.java
+++ b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
@@ -28,6 +28,7 @@
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.IInterface;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.permission.LegacyPermissionManager;
@@ -51,6 +52,7 @@
 import com.android.internal.telephony.ExponentialBackoff;
 import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.internal.telephony.util.WorkerThread;
 
 import java.io.PrintWriter;
 import java.util.HashSet;
@@ -264,7 +266,7 @@
     // Enable ImsServiceControllerTest and SipDelegateManagerTest cases if this is re-enabled.
     private static final boolean ENFORCE_SINGLE_SERVICE_FOR_SIP_TRANSPORT = false;
     private final ComponentName mComponentName;
-    private final HandlerThread mHandlerThread = new HandlerThread("ImsServiceControllerHandler");
+    private final HandlerThread mHandlerThread;
     private final Handler mHandler;
     private final LegacyPermissionManager mPermissionManager;
     private final FeatureFlags mFeatureFlags;
@@ -362,8 +364,17 @@
         mContext = context;
         mComponentName = componentName;
         mCallbacks = callbacks;
-        mHandlerThread.start();
-        mHandler = new Handler(mHandlerThread.getLooper());
+        Looper looper;
+        if (featureFlags.threadShred()) {
+            mHandlerThread = null;
+            mHandler = new Handler(WorkerThread.get().getLooper());
+            looper = WorkerThread.get().getLooper();
+        } else {
+            mHandlerThread = new HandlerThread("ImsServiceControllerHandler");
+            mHandlerThread.start();
+            mHandler = new Handler(mHandlerThread.getLooper());
+            looper = mHandlerThread.getLooper();
+        }
         mBackoff = new ExponentialBackoff(
                 mRebindRetry.getStartDelay(),
                 mRebindRetry.getMaximumDelay(),
@@ -373,7 +384,7 @@
         mPermissionManager = (LegacyPermissionManager) mContext.getSystemService(
                 Context.LEGACY_PERMISSION_SERVICE);
         mRepo = repo;
-        mImsEnablementTracker = new ImsEnablementTracker(mHandlerThread.getLooper(), componentName);
+        mImsEnablementTracker = new ImsEnablementTracker(looper, componentName);
         mFeatureFlags = featureFlags;
         mPackageManager = mContext.getPackageManager();
         if (mPackageManager != null) {
@@ -404,6 +415,7 @@
         mRepo = repo;
         mFeatureFlags = featureFlags;
         mImsEnablementTracker = new ImsEnablementTracker(handler.getLooper(), componentName);
+        mHandlerThread = null;
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsCallInfo.java b/src/java/com/android/internal/telephony/imsphone/ImsCallInfo.java
index 79ab9c5..12c6d96 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsCallInfo.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsCallInfo.java
@@ -18,7 +18,8 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.telephony.AccessNetworkConstants;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
 import android.telephony.ServiceState;
 
 import com.android.internal.telephony.Call;
@@ -32,6 +33,8 @@
     private @Nullable ImsPhoneConnection mConnection = null;
     private Call.State mState = Call.State.IDLE;
     private boolean mIsHeldByRemote = false;
+    private boolean mShouldIgnoreUpdate = false;
+    private @RadioAccessNetworkType int mCallRadioTech = AccessNetworkType.UNKNOWN;
 
     public ImsCallInfo(int index) {
         mIndex = index;
@@ -42,16 +45,22 @@
         mConnection = null;
         mState = Call.State.IDLE;
         mIsHeldByRemote = false;
+        mShouldIgnoreUpdate = false;
+        mCallRadioTech = AccessNetworkType.UNKNOWN;
     }
 
     /**
-     * Updates the state of the IMS call.
+     * Initializes the state of the IMS call when this object is just created or re-used.
      *
      * @param c The instance of {@link ImsPhoneConnection}.
      */
-    public void update(@NonNull ImsPhoneConnection c) {
+    public void init(@NonNull ImsPhoneConnection c) {
         mConnection = c;
         mState = c.getState();
+        mCallRadioTech = getCallRadioTech(c);
+        // MO call: Need to wait for any state changes from ImsCall.
+        // MT call: Ready to update the state.
+        mShouldIgnoreUpdate = !isIncoming();
     }
 
     /**
@@ -64,8 +73,11 @@
     public boolean update(@NonNull ImsPhoneConnection c,
             boolean holdReceived, boolean resumeReceived) {
         Call.State state = c.getState();
-        boolean changed = mState != state;
+        int callRadioTech = getCallRadioTech(c);
+        boolean changed = mState != state || mCallRadioTech != callRadioTech;
+
         mState = state;
+        mCallRadioTech = callRadioTech;
 
         if (holdReceived && !mIsHeldByRemote) {
             changed = true;
@@ -75,6 +87,22 @@
             mIsHeldByRemote = false;
         }
 
+        if (shouldIgnoreUpdate()) {
+            if (!c.isAlive()) {
+                // Even if the call state or attributes are updated,
+                // there is no need to update the call state
+                // because the call state has never been updated to the modem.
+                //
+                // For example, the call has created and cancelled by user immediately
+                // before receiving any state changes from ImsCall.
+                changed = false;
+            } else {
+                // Enforce IMS call state update even if the call state is the same.
+                changed = true;
+                mShouldIgnoreUpdate = false;
+            }
+        }
+
         return changed;
     }
 
@@ -108,14 +136,24 @@
         return mConnection.isEmergencyCall();
     }
 
+    /** @return {@code true} if the update should be ignored. */
+    public boolean shouldIgnoreUpdate() {
+        return mShouldIgnoreUpdate;
+    }
+
     /** @return the radio technology used for current connection. */
-    public @AccessNetworkConstants.RadioAccessNetworkType int getCallRadioTech() {
-        return ServiceState.rilRadioTechnologyToAccessNetworkType(mConnection.getCallRadioTech());
+    public @RadioAccessNetworkType int getCallRadioTech() {
+        return mCallRadioTech;
     }
 
     @Override
     public String toString() {
         return "[ id=" + mIndex + ", state=" + mState
+                + ", callRadioTech=" + AccessNetworkType.toString(mCallRadioTech)
                 + ", isMT=" + isIncoming() + ", heldByRemote=" + mIsHeldByRemote + " ]";
     }
+
+    private static @RadioAccessNetworkType int getCallRadioTech(ImsPhoneConnection c) {
+        return ServiceState.rilRadioTechnologyToAccessNetworkType(c.getCallRadioTech());
+    }
 }
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsCallInfoTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsCallInfoTracker.java
index 5783e48..5798847 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsCallInfoTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsCallInfoTracker.java
@@ -70,10 +70,12 @@
             ImsCallInfo imsCallInfo = it.next();
             mQueue.remove(imsCallInfo);
 
-            imsCallInfo.update(c);
+            imsCallInfo.init(c);
             mImsCallInfo.put(c, imsCallInfo);
 
-            notifyImsCallStatus();
+            if (!imsCallInfo.shouldIgnoreUpdate()) {
+                notifyImsCallStatus();
+            }
 
             if (DBG) dump();
         }
@@ -170,7 +172,8 @@
     }
 
     private void notifyImsCallStatus() {
-        Collection<ImsCallInfo> infos = mImsCallInfo.values();
+        Collection<ImsCallInfo> infos = mImsCallInfo.values()
+                .stream().filter(info -> !info.shouldIgnoreUpdate()).toList();
         ArrayList<ImsCallInfo> imsCallInfo = new ArrayList<ImsCallInfo>(infos);
         sort(imsCallInfo);
         mPhone.updateImsCallStatus(imsCallInfo, null);
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsNrSaModeHandler.java b/src/java/com/android/internal/telephony/imsphone/ImsNrSaModeHandler.java
index f2b5dee..243c63d 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsNrSaModeHandler.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsNrSaModeHandler.java
@@ -51,7 +51,7 @@
  * IMS is registered over WiFi in order to improve the delay or voice mute issue when the handover
  * from ePDG to NR is not supported in UE or network.
  */
-public class ImsNrSaModeHandler extends Handler{
+public class ImsNrSaModeHandler extends Handler {
 
     public static final String TAG = "ImsNrSaModeHandler";
 
@@ -61,6 +61,14 @@
     private final @NonNull ImsPhone mPhone;
     private @Nullable CarrierConfigManager mCarrierConfigManager;
 
+    @FunctionalInterface
+    public interface N1ModeSetter {
+        /** Override-able for testing */
+        void setN1ModeEnabled(boolean enabled, @Nullable Message message);
+    }
+
+    private N1ModeSetter mN1ModeSetter;
+
     private @NrSaDisablePolicy int mNrSaDisablePolicy;
     private boolean mIsNrSaDisabledForWfc;
     private boolean mIsWifiRegistered;
@@ -73,7 +81,10 @@
 
     public ImsNrSaModeHandler(@NonNull ImsPhone phone, Looper looper) {
         super(looper);
+
         mPhone = phone;
+        mN1ModeSetter = mPhone.getDefaultPhone()::setN1ModeEnabled;
+
         mCarrierConfigManager = (CarrierConfigManager) mPhone.getContext()
                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
 
@@ -257,8 +268,13 @@
         }
     }
 
+    @VisibleForTesting
+    public void setN1ModeSetter(N1ModeSetter setter) {
+        mN1ModeSetter = setter;
+    }
+
     private void setNrSaMode(boolean onOrOff) {
-        mPhone.getDefaultPhone().setN1ModeEnabled(onOrOff, null);
+        mN1ModeSetter.setN1ModeEnabled(onOrOff, null);
         Log.i(TAG, "setNrSaMode : " + onOrOff);
 
         setNrSaDisabledForWfc(!onOrOff);
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index 22b8a75..ca18098 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -1000,9 +1000,16 @@
         // Need to make sure dialString gets parsed properly
         String newDialString = PhoneNumberUtils.stripSeparators(dialString);
 
-        // handle in-call MMI first if applicable
-        if (handleInCallMmiCommands(newDialString)) {
-            return null;
+        if (mFeatureFlags.skipMmiCodeCheckForEmergencyCall()) {
+            // If not emergency number, handle in-call MMI first if applicable
+            if (!dialArgs.isEmergency && handleInCallMmiCommands(newDialString)) {
+                return null;
+            }
+        } else {
+            // handle in-call MMI first if applicable
+            if (handleInCallMmiCommands(newDialString)) {
+                return null;
+            }
         }
 
         ImsDialArgs.Builder imsDialArgsBuilder;
@@ -1014,6 +1021,14 @@
             return mCT.dial(dialString, imsDialArgsBuilder.build());
         }
 
+        if (mFeatureFlags.skipMmiCodeCheckForEmergencyCall()) {
+            // Skip to check mmi code if outgoing call is emergency
+            if (dialArgs.isEmergency) {
+                logd("dialInternal: emergency number, skip to check mmi code");
+                return mCT.dial(dialString, imsDialArgsBuilder.build());
+            }
+        }
+
         // Only look at the Network portion for mmi
         String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString);
         ImsPhoneMmiCode mmi =  ImsPhoneMmiCode.newFromDialString(networkPortion, this,
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index d47f05b..f4475b5 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -259,6 +259,8 @@
     private Optional<Integer> mCurrentlyConnectedSubId = Optional.empty();
 
     private final MmTelFeatureListener mMmTelFeatureListener = new MmTelFeatureListener();
+    private com.android.server.telecom.flags.FeatureFlags mTelecomFlags =
+            new com.android.server.telecom.flags.FeatureFlagsImpl();
     private class MmTelFeatureListener extends MmTelFeature.Listener {
 
         private IImsCallSessionListener processIncomingCall(@NonNull IImsCallSession c,
@@ -312,11 +314,8 @@
                         // activeCall could be null if the foreground call is in a disconnected
                         // state.  If either of the calls is null there is no need to check if
                         // one will be disconnected on answer.
-                        // Use VideoProfile.STATE_BIDIRECTIONAL to not affect existing
-                        // implementation. Video state of user response is handled in acceptCall().
                         boolean answeringWillDisconnect =
-                                shouldDisconnectActiveCallOnAnswer(activeCall, imsCall,
-                                        VideoProfile.STATE_BIDIRECTIONAL);
+                                shouldDisconnectActiveCallOnAnswer(activeCall, imsCall);
                         conn.setActiveCallDisconnectedOnAnswer(answeringWillDisconnect);
                     }
                 }
@@ -2223,7 +2222,7 @@
             ImsCall ringingCall = mRingingCall.getImsCall();
             if (mForegroundCall.hasConnections() && mRingingCall.hasConnections()) {
                 answeringWillDisconnect =
-                        shouldDisconnectActiveCallOnAnswer(activeCall, ringingCall, videoState);
+                        shouldDisconnectActiveCallOnAnswer(activeCall, ringingCall);
             }
 
             // Cache video state for pending MT call.
@@ -3119,6 +3118,8 @@
             conn.maybeChangeRingbackState();
 
             maybeSetVideoCallProvider(conn, imsCall);
+            // Update IMS call status if the call attributes are changed - i.e. call network type.
+            mImsCallInfoTracker.updateImsCallStatus(conn);
             // IMS call profile might be changed while call state is maintained. In this case, it's
             // required to notify to CallAttributesListener.
             // Since call state is not changed, TelephonyRegistry will not notify to
@@ -4084,6 +4085,13 @@
                             + " in the single call unhold case");
                 }
             }
+            ImsPhoneConnection conn = findConnection(imsCall);
+            // Send connection event so that Telecom can unhold the call the bg call that was held
+            // for calls across phone accounts.
+            if (mTelecomFlags.enableCallSequencing() && conn != null
+                    && conn.getState() != ImsPhoneCall.State.DISCONNECTED) {
+                conn.onConnectionEvent(android.telecom.Connection.EVENT_CALL_RESUME_FAILED, null);
+            }
             mPhone.notifySuppServiceFailed(Phone.SuppService.RESUME);
             mMetrics.writeOnImsCallResumeFailed(mPhone.getPhoneId(), imsCall.getCallSession(),
                     reasonInfo);
@@ -5533,13 +5541,11 @@
      *
      * @param activeCall The active call.
      * @param incomingCall The incoming call.
-     * @param incomingCallVideoState The media type of incoming call acceptance.
-     *                              {@link VideoProfile.VideoState}
      * @return {@code true} if answering the incoming call will cause the active call to be
      *      disconnected, {@code false} otherwise.
      */
     private boolean shouldDisconnectActiveCallOnAnswer(ImsCall activeCall,
-            ImsCall incomingCall, int incomingCallVideoState) {
+            ImsCall incomingCall) {
 
         if (activeCall == null || incomingCall == null) {
             return false;
@@ -5554,14 +5560,7 @@
         boolean isActiveCallOnWifi = activeCall.isWifiCall();
         boolean isVoWifiEnabled = mImsManager.isWfcEnabledByPlatform()
                 && mImsManager.isWfcEnabledByUser();
-        boolean isIncomingCallAudio = true;
-        if (!mFeatureFlags.terminateActiveVideoCallWhenAcceptingSecondVideoCallAsAudioOnly()) {
-            isIncomingCallAudio = !incomingCall.isVideoCall();
-        } else {
-            isIncomingCallAudio = !incomingCall.isVideoCall()
-                    || incomingCallVideoState == VideoProfile.STATE_AUDIO_ONLY;
-        }
-
+        boolean isIncomingCallAudio = !incomingCall.isVideoCall();
         log("shouldDisconnectActiveCallOnAnswer : isActiveCallVideo=" + isActiveCallVideo +
                 " isActiveCallOnWifi=" + isActiveCallOnWifi + " isIncomingCallAudio=" +
                 isIncomingCallAudio + " isVowifiEnabled=" + isVoWifiEnabled);
diff --git a/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java b/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java
index 175f5e4..f3a111c 100644
--- a/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java
+++ b/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java
@@ -310,6 +310,7 @@
         copy.isNtn = call.isNtn;
         copy.isSatelliteTransport = call.isSatelliteTransport;
         copy.isProvisioningProfile = call.isProvisioningProfile;
+        copy.isNbIotNtn = call.isNbIotNtn;
         return copy;
     }
 
@@ -337,8 +338,13 @@
         proto.handoverFailureRat = new int[0];
         proto.isNonDds = false;
         proto.isIwlanCrossSim = false;
-        proto.isNtn = mSatelliteController != null
-                ? mSatelliteController.isInSatelliteModeForCarrierRoaming(mPhone) : false;
+        if (mSatelliteController != null) {
+            proto.isNtn = mSatelliteController.isInSatelliteModeForCarrierRoaming(mPhone);
+            proto.isNbIotNtn = mSatelliteController.isInCarrierRoamingNbIotNtn(mPhone);
+        } else {
+            proto.isNtn = false;
+            proto.isNbIotNtn = false;
+        }
         proto.isSatelliteTransport = isSatellite;
         proto.isProvisioningProfile = getIsProvisioningProfile();
         return proto;
diff --git a/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java b/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java
index 079ff03..4f46c39 100644
--- a/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java
+++ b/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java
@@ -16,8 +16,6 @@
 
 package com.android.internal.telephony.metrics;
 
-import static com.android.internal.telephony.flags.Flags.dataRatMetricEnabled;
-
 import android.os.Handler;
 import android.os.HandlerExecutor;
 import android.os.HandlerThread;
@@ -29,8 +27,10 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.TelephonyStatsLog;
+import com.android.internal.telephony.flags.Flags;
 
 import java.util.HashMap;
 import java.util.List;
@@ -76,10 +76,14 @@
             };
 
     private DataConnectionStateTracker() {
-        HandlerThread handlerThread =
-                new HandlerThread(DataConnectionStateTracker.class.getSimpleName());
-        handlerThread.start();
-        mExecutor = new HandlerExecutor(new Handler(handlerThread.getLooper()));
+        if (Flags.threadShred()) {
+            mExecutor = BackgroundThread.getExecutor();
+        } else {
+            HandlerThread handlerThread =
+                    new HandlerThread(DataConnectionStateTracker.class.getSimpleName());
+            handlerThread.start();
+            mExecutor = new HandlerExecutor(new Handler(handlerThread.getLooper()));
+        }
     }
 
     /** Getting or Creating DataConnectionStateTracker based on phoneId */
@@ -229,9 +233,7 @@
 
         @Override
         public void onActiveDataSubscriptionIdChanged(int subId) {
-            if (dataRatMetricEnabled()) {
-                logRATChanges(subId);
-            }
+            logRATChanges(subId);
             mActiveDataSubId = subId;
         }
 
diff --git a/src/java/com/android/internal/telephony/metrics/DataStallRecoveryStats.java b/src/java/com/android/internal/telephony/metrics/DataStallRecoveryStats.java
index cd5b7d6..ba851d3 100644
--- a/src/java/com/android/internal/telephony/metrics/DataStallRecoveryStats.java
+++ b/src/java/com/android/internal/telephony/metrics/DataStallRecoveryStats.java
@@ -47,6 +47,7 @@
 import android.telephony.data.DataCallResponse.LinkStatus;
 import android.text.TextUtils;
 
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.TelephonyStatsLog;
@@ -88,9 +89,6 @@
     private final @NonNull TelephonyManager mTelephonyManager;
     private final @NonNull FeatureFlags mFeatureFlags;
 
-    // Flag to control the DSRS diagnostics
-    private final boolean mIsDsrsDiagnosticsEnabled;
-
     // The interface name of the internet network.
     private @Nullable String mIfaceName = null;
 
@@ -143,9 +141,14 @@
         mPhone = phone;
         mFeatureFlags = featureFlags;
 
-        HandlerThread handlerThread = new HandlerThread(mTag + "-thread");
-        handlerThread.start();
-        mHandler = new Handler(handlerThread.getLooper());
+        if (mFeatureFlags.threadShred()) {
+            mHandler = new Handler(BackgroundThread.get().getLooper());
+        } else {
+            HandlerThread handlerThread = new HandlerThread(mTag + "-thread");
+            handlerThread.start();
+            mHandler = new Handler(handlerThread.getLooper());
+        }
+
         mTelephonyManager = mPhone.getContext().getSystemService(TelephonyManager.class);
 
         dataNetworkController.registerDataNetworkControllerCallback(
@@ -166,43 +169,40 @@
                 }
             });
 
-        mIsDsrsDiagnosticsEnabled = mFeatureFlags.dsrsDiagnosticsEnabled();
-        if (mIsDsrsDiagnosticsEnabled) {
-            try {
-                // Register ConnectivityDiagnosticsCallback to get diagnostics states
-                mConnectivityDiagnosticsManager =
-                    mPhone.getContext().getSystemService(ConnectivityDiagnosticsManager.class);
-                mConnectivityDiagnosticsCallback = new ConnectivityDiagnosticsCallback() {
-                    @Override
-                    public void onConnectivityReportAvailable(@NonNull ConnectivityReport report) {
-                        PersistableBundle bundle = report.getAdditionalInfo();
-                        mNetworkProbesResult = bundle.getInt(KEY_NETWORK_PROBES_SUCCEEDED_BITMASK);
-                        mNetworkProbesType = bundle.getInt(KEY_NETWORK_PROBES_ATTEMPTED_BITMASK);
-                        mNetworkValidationResult = bundle.getInt(KEY_NETWORK_VALIDATION_RESULT);
-                    }
+        try {
+            // Register ConnectivityDiagnosticsCallback to get diagnostics states
+            mConnectivityDiagnosticsManager =
+                mPhone.getContext().getSystemService(ConnectivityDiagnosticsManager.class);
+            mConnectivityDiagnosticsCallback = new ConnectivityDiagnosticsCallback() {
+                @Override
+                public void onConnectivityReportAvailable(@NonNull ConnectivityReport report) {
+                    PersistableBundle bundle = report.getAdditionalInfo();
+                    mNetworkProbesResult = bundle.getInt(KEY_NETWORK_PROBES_SUCCEEDED_BITMASK);
+                    mNetworkProbesType = bundle.getInt(KEY_NETWORK_PROBES_ATTEMPTED_BITMASK);
+                    mNetworkValidationResult = bundle.getInt(KEY_NETWORK_VALIDATION_RESULT);
+                }
 
-                    @Override
-                    public void onDataStallSuspected(@NonNull DataStallReport report) {
-                        PersistableBundle bundle = report.getStallDetails();
-                        mTcpMetricsCollectionPeriodMillis =
-                            bundle.getInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS);
-                        mTcpPacketFailRate = bundle.getInt(KEY_TCP_PACKET_FAIL_RATE);
-                        mDnsConsecutiveTimeouts = bundle.getInt(KEY_DNS_CONSECUTIVE_TIMEOUTS);
-                    }
-                };
-                mConnectivityDiagnosticsManager.registerConnectivityDiagnosticsCallback(
-                    new NetworkRequest.Builder()
-                        .clearCapabilities()
-                        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
-                        .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
-                        .build(),
-                        INLINE_EXECUTOR,
-                        mConnectivityDiagnosticsCallback
-                );
-            } catch (Exception e) {
-                mConnectivityDiagnosticsManager = null;
-                mConnectivityDiagnosticsCallback = null;
-            }
+                @Override
+                public void onDataStallSuspected(@NonNull DataStallReport report) {
+                    PersistableBundle bundle = report.getStallDetails();
+                    mTcpMetricsCollectionPeriodMillis =
+                        bundle.getInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS);
+                    mTcpPacketFailRate = bundle.getInt(KEY_TCP_PACKET_FAIL_RATE);
+                    mDnsConsecutiveTimeouts = bundle.getInt(KEY_DNS_CONSECUTIVE_TIMEOUTS);
+                }
+            };
+            mConnectivityDiagnosticsManager.registerConnectivityDiagnosticsCallback(
+                new NetworkRequest.Builder()
+                    .clearCapabilities()
+                    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                    .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+                    .build(),
+                    INLINE_EXECUTOR,
+                    mConnectivityDiagnosticsCallback
+            );
+        } catch (Exception e) {
+            mConnectivityDiagnosticsManager = null;
+            mConnectivityDiagnosticsCallback = null;
         }
     }
 
@@ -287,19 +287,17 @@
         mPhoneId = mPhone.getPhoneId() + 1;
         mCarrierId = mPhone.getCarrierId();
         mSignalStrength = mPhone.getSignalStrength().getLevel();
-        if (mIsDsrsDiagnosticsEnabled) {
-            // Get the MCCMNC and convert it to an int
-            String networkOperator = mTelephonyManager.getNetworkOperator();
-            if (!TextUtils.isEmpty(networkOperator)) {
-                try {
-                    mConvertedMccMnc = Integer.parseInt(networkOperator);
-                } catch (NumberFormatException e) {
-                    loge("Invalid MCCMNC format: " + networkOperator);
-                    mConvertedMccMnc = -1;
-                }
-            } else {
+        // Get the MCCMNC and convert it to an int
+        String networkOperator = mTelephonyManager.getNetworkOperator();
+        if (!TextUtils.isEmpty(networkOperator)) {
+            try {
+                mConvertedMccMnc = Integer.parseInt(networkOperator);
+            } catch (NumberFormatException e) {
+                loge("Invalid MCCMNC format: " + networkOperator);
                 mConvertedMccMnc = -1;
             }
+        } else {
+            mConvertedMccMnc = -1;
         }
 
         // Update the bandwidth.
@@ -424,71 +422,46 @@
             int actionValidationCount,
             int durationOfAction) {
 
-        if (mIsDsrsDiagnosticsEnabled) {
-            // Refresh data if the data has not been updated within 3 minutes
-            final long refreshDuration = SystemClock.elapsedRealtime() - mMetricsReflashTime;
-            if (refreshDuration > REFRESH_DURATION_IN_MILLIS) {
-                // Refreshes the metrics data.
-                try {
-                    refreshMetricsData();
-                } catch (Exception e) {
-                    loge("The metrics data cannot be refreshed.", e);
-                }
+        // Refresh data if the data has not been updated within 3 minutes
+        final long refreshDuration = SystemClock.elapsedRealtime() - mMetricsReflashTime;
+        if (refreshDuration > REFRESH_DURATION_IN_MILLIS) {
+            // Refreshes the metrics data.
+            try {
+                refreshMetricsData();
+            } catch (Exception e) {
+                loge("The metrics data cannot be refreshed.", e);
             }
         }
 
         Bundle bundle = new Bundle();
 
-        if (mIsDsrsDiagnosticsEnabled) {
-            bundle.putInt("Action", action);
-            bundle.putInt("IsRecovered", isRecovered ? 1 : 0);
-            bundle.putInt("Duration", duration);
-            bundle.putInt("Reason", reason);
-            bundle.putInt("DurationOfAction", durationOfAction);
-            bundle.putInt("ValidationCount", validationCount);
-            bundle.putInt("ActionValidationCount", actionValidationCount);
-            bundle.putInt("PhoneId", mPhoneId);
-            bundle.putInt("CarrierId", mCarrierId);
-            bundle.putInt("MccMnc", mConvertedMccMnc);
-            bundle.putInt("SignalStrength", mSignalStrength);
-            bundle.putInt("Band", mBand);
-            bundle.putInt("Rat", mRat);
-            bundle.putInt("IsOpportunistic", mIsOpportunistic ? 1 : 0);
-            bundle.putInt("IsMultiSim", mIsMultiSim ? 1 : 0);
-            bundle.putInt("NetworkRegState", mNetworkRegState);
-            bundle.putInt("OtherSignalStrength", mOtherSignalStrength);
-            bundle.putInt("OtherNetworkRegState", mOtherNetworkRegState);
-            bundle.putInt("InternetLinkStatus", mInternetLinkStatus);
-            bundle.putInt("LinkDownBandwidthKbps", mLinkDownBandwidthKbps);
-            bundle.putInt("LinkUpBandwidthKbps", mLinkUpBandwidthKbps);
-            bundle.putInt("NetworkProbesResult", mNetworkProbesResult);
-            bundle.putInt("NetworkProbesType", mNetworkProbesType);
-            bundle.putInt("NetworkValidationResult", mNetworkValidationResult);
-            bundle.putInt("TcpMetricsCollectionPeriodMillis", mTcpMetricsCollectionPeriodMillis);
-            bundle.putInt("TcpPacketFailRate", mTcpPacketFailRate);
-            bundle.putInt("DnsConsecutiveTimeouts", mDnsConsecutiveTimeouts);
-        } else {
-            bundle.putInt("Action", action);
-            bundle.putBoolean("IsRecovered", isRecovered);
-            bundle.putInt("Duration", duration);
-            bundle.putInt("Reason", reason);
-            bundle.putBoolean("IsFirstValidation", validationCount == 1);
-            bundle.putInt("DurationOfAction", durationOfAction);
-            bundle.putInt("PhoneId", mPhoneId);
-            bundle.putInt("CarrierId", mCarrierId);
-            bundle.putInt("SignalStrength", mSignalStrength);
-            bundle.putInt("Band", mBand);
-            bundle.putInt("Rat", mRat);
-            bundle.putBoolean("IsOpportunistic", mIsOpportunistic);
-            bundle.putBoolean("IsMultiSim", mIsMultiSim);
-            bundle.putInt("NetworkRegState", mNetworkRegState);
-            bundle.putInt("OtherSignalStrength", mOtherSignalStrength);
-            bundle.putInt("OtherNetworkRegState", mOtherNetworkRegState);
-            bundle.putInt("InternetLinkStatus", mInternetLinkStatus);
-            bundle.putInt("LinkDownBandwidthKbps", mLinkDownBandwidthKbps);
-            bundle.putInt("LinkUpBandwidthKbps", mLinkUpBandwidthKbps);
-        }
-
+        bundle.putInt("Action", action);
+        bundle.putInt("IsRecovered", isRecovered ? 1 : 0);
+        bundle.putInt("Duration", duration);
+        bundle.putInt("Reason", reason);
+        bundle.putInt("DurationOfAction", durationOfAction);
+        bundle.putInt("ValidationCount", validationCount);
+        bundle.putInt("ActionValidationCount", actionValidationCount);
+        bundle.putInt("PhoneId", mPhoneId);
+        bundle.putInt("CarrierId", mCarrierId);
+        bundle.putInt("MccMnc", mConvertedMccMnc);
+        bundle.putInt("SignalStrength", mSignalStrength);
+        bundle.putInt("Band", mBand);
+        bundle.putInt("Rat", mRat);
+        bundle.putInt("IsOpportunistic", mIsOpportunistic ? 1 : 0);
+        bundle.putInt("IsMultiSim", mIsMultiSim ? 1 : 0);
+        bundle.putInt("NetworkRegState", mNetworkRegState);
+        bundle.putInt("OtherSignalStrength", mOtherSignalStrength);
+        bundle.putInt("OtherNetworkRegState", mOtherNetworkRegState);
+        bundle.putInt("InternetLinkStatus", mInternetLinkStatus);
+        bundle.putInt("LinkDownBandwidthKbps", mLinkDownBandwidthKbps);
+        bundle.putInt("LinkUpBandwidthKbps", mLinkUpBandwidthKbps);
+        bundle.putInt("NetworkProbesResult", mNetworkProbesResult);
+        bundle.putInt("NetworkProbesType", mNetworkProbesType);
+        bundle.putInt("NetworkValidationResult", mNetworkValidationResult);
+        bundle.putInt("TcpMetricsCollectionPeriodMillis", mTcpMetricsCollectionPeriodMillis);
+        bundle.putInt("TcpPacketFailRate", mTcpPacketFailRate);
+        bundle.putInt("DnsConsecutiveTimeouts", mDnsConsecutiveTimeouts);
         return bundle;
     }
 
diff --git a/src/java/com/android/internal/telephony/metrics/DefaultNetworkMonitor.java b/src/java/com/android/internal/telephony/metrics/DefaultNetworkMonitor.java
index 1dab10b..cb7ada7 100644
--- a/src/java/com/android/internal/telephony/metrics/DefaultNetworkMonitor.java
+++ b/src/java/com/android/internal/telephony/metrics/DefaultNetworkMonitor.java
@@ -64,9 +64,7 @@
 
     DefaultNetworkMonitor(@NonNull Context context, @NonNull FeatureFlags featureFlags) {
         super(Looper.myLooper());
-        if (featureFlags.dataCallSessionStatsCapturesCrossSimCalling()) {
-            registerSystemDefaultNetworkCallback(context);
-        }
+        registerSystemDefaultNetworkCallback(context);
     }
 
     private void registerSystemDefaultNetworkCallback(@NonNull Context context) {
diff --git a/src/java/com/android/internal/telephony/metrics/DeviceStateHelper.java b/src/java/com/android/internal/telephony/metrics/DeviceStateHelper.java
index 9ab52fb..dc0ee4e 100644
--- a/src/java/com/android/internal/telephony/metrics/DeviceStateHelper.java
+++ b/src/java/com/android/internal/telephony/metrics/DeviceStateHelper.java
@@ -28,21 +28,32 @@
 import android.os.HandlerExecutor;
 import android.os.HandlerThread;
 
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.Flags;
 
 /** Device state information like the fold state. */
 public class DeviceStateHelper {
     private int mFoldState = CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_UNKNOWN;
 
     public DeviceStateHelper(Context context) {
-        HandlerThread mHandlerThread = new HandlerThread("DeviceStateHelperThread");
-        mHandlerThread.start();
-        context.getSystemService(DeviceStateManager.class)
-                .registerCallback(
-                        new HandlerExecutor(new Handler(mHandlerThread.getLooper())),
-                        state -> {
-                            updateFoldState(state.getIdentifier());
-                        });
+        if (Flags.threadShred()) {
+            context.getSystemService(DeviceStateManager.class)
+                    .registerCallback(
+                            BackgroundThread.getExecutor(),
+                            state -> {
+                                updateFoldState(state.getIdentifier());
+                            });
+        } else {
+            HandlerThread mHandlerThread = new HandlerThread("DeviceStateHelperThread");
+            mHandlerThread.start();
+            context.getSystemService(DeviceStateManager.class)
+                    .registerCallback(
+                            new HandlerExecutor(new Handler(mHandlerThread.getLooper())),
+                            state -> {
+                                updateFoldState(state.getIdentifier());
+                            });
+        }
     }
 
     private void updateFoldState(int posture) {
diff --git a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
index 8ef5a8f..1bbfddb 100644
--- a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+++ b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
@@ -1064,7 +1064,8 @@
                 serviceSwitch.simSlotIndex,
                 serviceSwitch.isMultiSim,
                 serviceSwitch.carrierId,
-                serviceSwitch.switchCount);
+                serviceSwitch.switchCount,
+                serviceSwitch.isOpportunistic);
     }
 
     private static StatsEvent buildStatsEvent(CellularServiceState state) {
@@ -1086,7 +1087,9 @@
                 state.overrideVoiceService,
                 state.isDataEnabled,
                 state.isIwlanCrossSim,
-                state.isNtn);
+                state.isNtn,
+                state.isNbIotNtn,
+                state.isOpportunistic);
     }
 
     private static StatsEvent buildStatsEvent(VoiceCallRatUsage usage) {
@@ -1172,7 +1175,8 @@
                 sms.count,
                 sms.isManagedProfile,
                 sms.isNtn,
-                sms.isEmergency);
+                sms.isEmergency,
+                sms.isNbIotNtn);
     }
 
     private static StatsEvent buildStatsEvent(OutgoingSms sms) {
@@ -1197,7 +1201,9 @@
                 sms.networkErrorCode,
                 sms.isManagedProfile,
                 sms.isEmergency,
-                sms.isNtn);
+                sms.isNtn,
+                sms.isMtSmsPolling,
+                sms.isNbIotNtn);
     }
 
     private static StatsEvent buildStatsEvent(DataCallSession dataCallSession) {
@@ -1229,7 +1235,8 @@
                 dataCallSession.isIwlanCrossSim,
                 dataCallSession.isNtn,
                 dataCallSession.isSatelliteTransport,
-                dataCallSession.isProvisioningProfile);
+                dataCallSession.isProvisioningProfile,
+                dataCallSession.isNbIotNtn);
     }
 
     private static StatsEvent buildStatsEvent(ImsRegistrationStats stats) {
@@ -1483,7 +1490,14 @@
                 satelliteController.countOfFailedLocationQueries,
                 satelliteController.countOfP2PSmsAvailableNotificationShown,
                 satelliteController.countOfP2PSmsAvailableNotificationRemoved,
-                satelliteController.isNtnOnlyCarrier);
+                satelliteController.isNtnOnlyCarrier,
+                satelliteController.versionOfSatelliteAccessConfig,
+                satelliteController.countOfIncomingDatagramTypeSosSmsSuccess,
+                satelliteController.countOfIncomingDatagramTypeSosSmsFail,
+                satelliteController.countOfOutgoingDatagramTypeSmsSuccess,
+                satelliteController.countOfOutgoingDatagramTypeSmsFail,
+                satelliteController.countOfIncomingDatagramTypeSmsSuccess,
+                satelliteController.countOfIncomingDatagramTypeSmsFail);
     }
 
     private static StatsEvent buildStatsEvent(SatelliteSession satelliteSession) {
@@ -1591,7 +1605,12 @@
                 stats.countOfIncomingSms,
                 stats.countOfOutgoingSms,
                 stats.countOfIncomingMms,
-                stats.countOfOutgoingMms);
+                stats.countOfOutgoingMms,
+                stats.supportedSatelliteServices,
+                stats.serviceDataPolicy,
+                stats.satelliteDataConsumedBytes,
+                stats.isMultiSim,
+                stats.isNbIotNtn);
     }
 
     private static StatsEvent buildStatsEvent(CarrierRoamingSatelliteControllerStats stats) {
@@ -1605,7 +1624,10 @@
                 stats.satelliteSessionGapAvgSec,
                 stats.satelliteSessionGapMaxSec,
                 stats.carrierId,
-                stats.isDeviceEntitled);
+                stats.isDeviceEntitled,
+                stats.isMultiSim,
+                stats.countOfSatelliteSessions,
+                stats.isNbIotNtn);
     }
 
     private static StatsEvent buildStatsEvent(SatelliteEntitlement stats) {
@@ -1615,7 +1637,10 @@
                 stats.result,
                 stats.entitlementStatus,
                 stats.isRetry,
-                stats.count);
+                stats.count,
+                stats.isAllowedServiceEntitlement,
+                stats.entitlementServiceType,
+                stats.entitlementDataPolicy);
     }
 
     private static StatsEvent buildStatsEvent(SatelliteConfigUpdater stats) {
diff --git a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
index 2ddc604..a0fb57f 100644
--- a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
+++ b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
@@ -29,6 +29,8 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.nano.PersistAtomsProto.CarrierIdMismatch;
 import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteControllerStats;
 import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteSession;
@@ -263,9 +265,15 @@
         mAtoms = loadAtomsFromFile();
         mVoiceCallRatTracker = VoiceCallRatTracker.fromProto(mAtoms.voiceCallRatUsage);
 
-        mHandlerThread = new HandlerThread("PersistAtomsThread");
-        mHandlerThread.start();
-        mHandler = new Handler(mHandlerThread.getLooper());
+        if (Flags.threadShred()) {
+            mHandlerThread = null;
+            mHandler = new Handler(BackgroundThread.get().getLooper());
+        } else {
+            // TODO: we might be able to make mHandlerThread a local variable
+            mHandlerThread = new HandlerThread("PersistAtomsThread");
+            mHandlerThread.start();
+            mHandler = new Handler(mHandlerThread.getLooper());
+        }
         mSaveImmediately = false;
     }
 
@@ -777,6 +785,19 @@
             existingStats.countOfP2PSmsAvailableNotificationRemoved
                     += stats.countOfP2PSmsAvailableNotificationRemoved;
             // Does not update isNtnOnlyCarrier due to it is a dimension field.
+            existingStats.versionOfSatelliteAccessConfig = stats.versionOfSatelliteAccessConfig;
+            existingStats.countOfIncomingDatagramTypeSosSmsSuccess
+                    += stats.countOfIncomingDatagramTypeSosSmsSuccess;
+            existingStats.countOfIncomingDatagramTypeSosSmsFail
+                    += stats.countOfIncomingDatagramTypeSosSmsFail;
+            existingStats.countOfOutgoingDatagramTypeSmsSuccess
+                    += stats.countOfOutgoingDatagramTypeSmsSuccess;
+            existingStats.countOfOutgoingDatagramTypeSmsFail
+                    += stats.countOfOutgoingDatagramTypeSmsFail;
+            existingStats.countOfIncomingDatagramTypeSmsSuccess
+                    += stats.countOfIncomingDatagramTypeSmsSuccess;
+            existingStats.countOfIncomingDatagramTypeSmsFail
+                    += stats.countOfIncomingDatagramTypeSmsFail;
         } else {
             mAtoms.satelliteController = insertAtRandomPlace(mAtoms.satelliteController, stats,
                     mMaxNumSatelliteStats);
@@ -876,6 +897,9 @@
             // Does not update configDataSource, carrierId, isDeviceEntitled, due to  they are
             // dimension fields.
             existingStats.isDeviceEntitled = stats.isDeviceEntitled;
+            existingStats.isMultiSim = stats.isMultiSim;
+            existingStats.countOfSatelliteSessions += stats.countOfSatelliteSessions;
+            existingStats.isNbIotNtn = stats.isNbIotNtn;
         } else {
             mAtoms.carrierRoamingSatelliteControllerStats = insertAtRandomPlace(
                     mAtoms.carrierRoamingSatelliteControllerStats, stats, mMaxNumSatelliteStats);
@@ -1625,6 +1649,7 @@
                     mAtoms.carrierRoamingSatelliteControllerStats;
             mAtoms.carrierRoamingSatelliteControllerStats =
                     new CarrierRoamingSatelliteControllerStats[0];
+            SatelliteStats.getInstance().resetCarrierRoamingSatelliteControllerStats();
             saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS);
             return statsArray;
         } else {
@@ -1987,7 +2012,9 @@
                     && state.overrideVoiceService == key.overrideVoiceService
                     && state.isDataEnabled == key.isDataEnabled
                     && state.isIwlanCrossSim == key.isIwlanCrossSim
-                    && state.isNtn == key.isNtn) {
+                    && state.isNtn == key.isNtn
+                    && state.isNbIotNtn == key.isNbIotNtn
+                    && state.isOpportunistic == key.isOpportunistic) {
                 return state;
             }
         }
@@ -2004,7 +2031,8 @@
                     && serviceSwitch.ratTo == key.ratTo
                     && serviceSwitch.simSlotIndex == key.simSlotIndex
                     && serviceSwitch.isMultiSim == key.isMultiSim
-                    && serviceSwitch.carrierId == key.carrierId) {
+                    && serviceSwitch.carrierId == key.carrierId
+                    && serviceSwitch.isOpportunistic == key.isOpportunistic) {
                 return serviceSwitch;
             }
         }
@@ -2418,9 +2446,7 @@
             CarrierRoamingSatelliteControllerStats key) {
         for (CarrierRoamingSatelliteControllerStats stats :
                 mAtoms.carrierRoamingSatelliteControllerStats) {
-            if (stats.carrierId == key.carrierId
-                    && stats.configDataSource == key.configDataSource
-                    && stats.isDeviceEntitled == key.isDeviceEntitled) {
+            if (stats.carrierId == key.carrierId) {
                 return stats;
             }
         }
diff --git a/src/java/com/android/internal/telephony/metrics/SatelliteStats.java b/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
index c17c8ab..2ccd8b5 100644
--- a/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
+++ b/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
@@ -16,8 +16,8 @@
 
 package com.android.internal.telephony.metrics;
 
-import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
 import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
+import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
 
 import static com.android.internal.telephony.satellite.SatelliteConstants.TRIGGERING_EVENT_UNKNOWN;
 
@@ -40,11 +40,13 @@
 import com.android.telephony.Rlog;
 
 import java.util.Arrays;
+import java.util.Objects;
 import java.util.Optional;
 
 /** Tracks Satellite metrics for each phone */
 public class SatelliteStats {
     private static final String TAG = SatelliteStats.class.getSimpleName();
+    private static final boolean DBG = false;
 
     private final PersistAtomsStorage mAtomsStorage =
             PhoneFactory.getMetricsCollector().getAtomsStorage();
@@ -103,6 +105,13 @@
         private final int mCountOfP2PSmsAvailableNotificationShown;
         private final int mCountOfP2PSmsAvailableNotificationRemoved;
         private static boolean sIsNtnOnlyCarrier;
+        private static int sVersionOfSatelliteAccessConfig;
+        private final int mCountOfIncomingDatagramTypeSosSmsSuccess;
+        private final int mCountOfIncomingDatagramTypeSosSmsFail;
+        private final int mCountOfOutgoingDatagramTypeSmsSuccess;
+        private final int mCountOfOutgoingDatagramTypeSmsFail;
+        private final int mCountOfIncomingDatagramTypeSmsSuccess;
+        private final int mCountOfIncomingDatagramTypeSmsFail;
 
         private SatelliteControllerParams(Builder builder) {
             this.mCountOfSatelliteServiceEnablementsSuccess =
@@ -170,10 +179,26 @@
             this.mCountOfP2PSmsAvailableNotificationRemoved =
                     builder.mCountOfP2PSmsAvailableNotificationRemoved;
 
-            // Carrier ID value should be updated only when it is meaningful.
+            // Ntn only carrier value should be updated only when it is meaningful.
             if (builder.mIsNtnOnlyCarrier.isPresent()) {
                 this.sIsNtnOnlyCarrier = builder.mIsNtnOnlyCarrier.get();
             }
+            // version satellite access config value should be updated only when it is meaningful.
+            if (builder.mVersionOfSatelliteAccessConfig.isPresent()) {
+                this.sVersionOfSatelliteAccessConfig =
+                        builder.mVersionOfSatelliteAccessConfig.get();
+            }
+
+            this.mCountOfIncomingDatagramTypeSosSmsSuccess =
+                    builder.mCountOfIncomingDatagramTypeSosSmsSuccess;
+            this.mCountOfIncomingDatagramTypeSosSmsFail =
+                    builder.mCountOfIncomingDatagramTypeSosSmsFail;
+            this.mCountOfOutgoingDatagramTypeSmsSuccess =
+                    builder.mCountOfOutgoingDatagramTypeSmsSuccess;
+            this.mCountOfOutgoingDatagramTypeSmsFail = builder.mCountOfOutgoingDatagramTypeSmsFail;
+            this.mCountOfIncomingDatagramTypeSmsSuccess =
+                    builder.mCountOfIncomingDatagramTypeSmsSuccess;
+            this.mCountOfIncomingDatagramTypeSmsFail = builder.mCountOfIncomingDatagramTypeSmsFail;
         }
 
         public int getCountOfSatelliteServiceEnablementsSuccess() {
@@ -320,6 +345,34 @@
             return sIsNtnOnlyCarrier;
         }
 
+        public static int getVersionSatelliteAccessConfig() {
+            return sVersionOfSatelliteAccessConfig;
+        }
+
+        public int getCountOfIncomingDatagramTypeSosSmsSuccess() {
+            return mCountOfIncomingDatagramTypeSosSmsSuccess;
+        }
+
+        public int getCountOfIncomingDatagramTypeSosSmsFail() {
+            return mCountOfIncomingDatagramTypeSosSmsFail;
+        }
+
+        public int getCountOfOutgoingDatagramTypeSmsSuccess() {
+            return mCountOfOutgoingDatagramTypeSmsSuccess;
+        }
+
+        public int getCountOfOutgoingDatagramTypeSmsFail() {
+            return mCountOfOutgoingDatagramTypeSmsFail;
+        }
+
+        public int getCountOfIncomingDatagramTypeSmsSuccess() {
+            return mCountOfIncomingDatagramTypeSmsSuccess;
+        }
+
+        public int getCountOfIncomingDatagramTypeSmsFail() {
+            return mCountOfIncomingDatagramTypeSmsFail;
+        }
+
         /**
          * A builder class to create {@link SatelliteControllerParams} data structure class
          */
@@ -360,6 +413,13 @@
             private int mCountOfP2PSmsAvailableNotificationShown = 0;
             private int mCountOfP2PSmsAvailableNotificationRemoved = 0;
             private Optional<Boolean> mIsNtnOnlyCarrier = Optional.empty();
+            private Optional<Integer> mVersionOfSatelliteAccessConfig = Optional.empty();
+            private int mCountOfIncomingDatagramTypeSosSmsSuccess;
+            private int mCountOfIncomingDatagramTypeSosSmsFail;
+            private int mCountOfOutgoingDatagramTypeSmsSuccess;
+            private int mCountOfOutgoingDatagramTypeSmsFail;
+            private int mCountOfIncomingDatagramTypeSmsSuccess;
+            private int mCountOfIncomingDatagramTypeSmsFail;
 
             /**
              * Sets countOfSatelliteServiceEnablementsSuccess value of {@link SatelliteController}
@@ -719,6 +779,76 @@
             }
 
             /**
+             * Sets versionOfSatelliteAccessConfig value of {@link SatelliteController} atom
+             * then returns Builder class
+             */
+            public Builder setVersionOfSatelliteAccessControl(int version) {
+                this.mVersionOfSatelliteAccessConfig = Optional.of(version);
+                return this;
+            }
+
+            /**
+             * Sets countOfIncomingDatagramTypeSosSmsSuccess value of {@link SatelliteController}
+             * atom then returns Builder class
+             */
+            public Builder setCountOfIncomingDatagramTypeSosSmsSuccess(
+                    int countOfIncomingDatagramTypeSosSmsSuccess) {
+                this.mCountOfIncomingDatagramTypeSosSmsSuccess =
+                        countOfIncomingDatagramTypeSosSmsSuccess;
+                return this;
+            }
+
+            /**
+             * Sets countOfIncomingDatagramTypeSosSmsFail value of {@link SatelliteController} atom
+             * then returns Builder class
+             */
+            public Builder setCountOfIncomingDatagramTypeSosSmsFail(
+                    int countOfIncomingDatagramTypeSosSmsFail) {
+                this.mCountOfIncomingDatagramTypeSosSmsFail = countOfIncomingDatagramTypeSosSmsFail;
+                return this;
+            }
+
+            /**
+             * Sets countOfOutgoingDatagramTypeSmsSuccess value of {@link SatelliteController} atom
+             * then returns Builder class
+             */
+            public Builder setCountOfOutgoingDatagramTypeSmsSuccess(
+                    int countOfOutgoingDatagramTypeSmsSuccess) {
+                this.mCountOfOutgoingDatagramTypeSmsSuccess = countOfOutgoingDatagramTypeSmsSuccess;
+                return this;
+            }
+
+            /**
+             * Sets countOfOutgoingDatagramTypeSmsFail value of {@link SatelliteController} atom
+             * then returns Builder class
+             */
+            public Builder setCountOfOutgoingDatagramTypeSmsFail(
+                    int countOfOutgoingDatagramTypeSmsFail) {
+                this.mCountOfOutgoingDatagramTypeSmsFail = countOfOutgoingDatagramTypeSmsFail;
+                return this;
+            }
+
+            /**
+             * Sets countOfIncomingDatagramTypeSmsSuccess value of {@link SatelliteController} atom
+             * then returns Builder class
+             */
+            public Builder setCountOfIncomingDatagramTypeSmsSuccess(
+                    int countOfIncomingDatagramTypeSmsSuccess) {
+                this.mCountOfIncomingDatagramTypeSmsSuccess = countOfIncomingDatagramTypeSmsSuccess;
+                return this;
+            }
+
+            /**
+             * Sets countOfIncomingDatagramTypeSmsFail value of {@link SatelliteController} atom
+             * then returns Builder class
+             */
+            public Builder setCountOfIncomingDatagramTypeSmsFail(
+                    int countOfIncomingDatagramTypeSmsFail) {
+                this.mCountOfIncomingDatagramTypeSmsFail = countOfIncomingDatagramTypeSmsFail;
+                return this;
+            }
+
+            /**
              * Returns ControllerParams, which contains whole component of
              * {@link SatelliteController} atom
              */
@@ -777,7 +907,17 @@
                     + mCountOfP2PSmsAvailableNotificationShown
                     + ", countOfP2PSmsAvailableNotificationRemoved="
                     + mCountOfP2PSmsAvailableNotificationRemoved
-                    + ", isNtnOnlyCarrier=" + sIsNtnOnlyCarrier
+                    + ", versionOfSatelliteAccessConfig=" + sVersionOfSatelliteAccessConfig
+                    + ", countOfIncomingDatagramTypeSosSmsSuccess="
+                    + mCountOfIncomingDatagramTypeSosSmsSuccess
+                    + ", countOfIncomingDatagramTypeSosSmsFail="
+                    + mCountOfIncomingDatagramTypeSosSmsFail
+                    + ", countOfOutgoingDatagramTypeSmsSuccess="
+                    + mCountOfOutgoingDatagramTypeSmsSuccess
+                    + ", countOfOutgoingDatagramTypeSmsFail=" + mCountOfOutgoingDatagramTypeSmsFail
+                    + ", countOfIncomingDatagramTypeSmsSuccess="
+                    + mCountOfIncomingDatagramTypeSmsSuccess
+                    + ", countOfIncomingDatagramTypeSmsFail=" + mCountOfIncomingDatagramTypeSmsFail
                     + ")";
         }
     }
@@ -1742,6 +1882,11 @@
         private final int mCountOfOutgoingSms;
         private final int mCountOfIncomingMms;
         private final int mCountOfOutgoingMms;
+        private final int[] mSupportedSatelliteServices;
+        private final int mServiceDataPolicy;
+        private final long mSatelliteDataConsumedBytes;
+        private final boolean mIsMultiSim;
+        private final boolean mIsNbIotNtn;
 
         private CarrierRoamingSatelliteSessionParams(Builder builder) {
             this.mCarrierId = builder.mCarrierId;
@@ -1761,6 +1906,12 @@
             this.mCountOfOutgoingSms = builder.mCountOfOutgoingSms;
             this.mCountOfIncomingMms = builder.mCountOfIncomingMms;
             this.mCountOfOutgoingMms = builder.mCountOfOutgoingMms;
+            this.mSupportedSatelliteServices = builder.mSupportedSatelliteServices;
+            this.mServiceDataPolicy = builder.mServiceDataPolicy;
+            this.mSatelliteDataConsumedBytes =
+                    builder.mSatelliteDataConsumedBytes;
+            this.mIsMultiSim = builder.mIsMultiSim;
+            this.mIsNbIotNtn = builder.mIsNbIotNtn;
         }
 
         public int getCarrierId() {
@@ -1827,6 +1978,26 @@
             return mCountOfOutgoingMms;
         }
 
+        public int[] getSupportedSatelliteServices() {
+            return mSupportedSatelliteServices;
+        }
+
+        public int getServiceDataPolicy() {
+            return mServiceDataPolicy;
+        }
+
+        public long getSatelliteDataConsumedBytes() {
+            return mSatelliteDataConsumedBytes;
+        }
+
+        public boolean isMultiSim() {
+            return mIsMultiSim;
+        }
+
+        public boolean isNbIotNtn() {
+            return mIsNbIotNtn;
+        }
+
         /**
          * A builder class to create {@link CarrierRoamingSatelliteSessionParams} data structure
          * class
@@ -1848,6 +2019,12 @@
             private int mCountOfOutgoingSms = 0;
             private int mCountOfIncomingMms = 0;
             private int mCountOfOutgoingMms = 0;
+            private int[] mSupportedSatelliteServices = new int[0];
+            int mServiceDataPolicy =
+                    SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN;
+            long mSatelliteDataConsumedBytes = 0L;
+            private boolean mIsMultiSim = false;
+            private boolean mIsNbIotNtn = false;
 
             /**
              * Sets carrierId value of {@link CarrierRoamingSatelliteSession} atom
@@ -1997,6 +2174,44 @@
             }
 
             /**
+             * Sets supportedSatelliteServices value of {@link CarrierRoamingSatelliteSession}
+             * atom then returns Builder class
+             */
+            public Builder setSupportedSatelliteServices(int[] supportedSatelliteServices) {
+                this.mSupportedSatelliteServices = supportedSatelliteServices;
+                Arrays.sort(this.mSupportedSatelliteServices);
+                return this;
+            }
+
+            /**
+             * Sets serviceDataPolicy value of {@link CarrierRoamingSatelliteSession}
+             * atom then returns Builder class
+             */
+            public Builder setServiceDataPolicy(int serviceDataPolicy) {
+                this.mServiceDataPolicy = serviceDataPolicy;
+                return this;
+            }
+
+            /**
+             * Sets satelliteDataConsumedPerSessionBytes value of
+             * {@link CarrierRoamingSatelliteSession} atom then returns Builder class
+             */
+            public Builder setSatelliteDataConsumedBytes(
+                    long satelliteDataConsumedPerSessionBytes) {
+                this.mSatelliteDataConsumedBytes = satelliteDataConsumedPerSessionBytes;
+                return this;
+            }
+
+            /**
+             * Sets isMultiSim value of {@link CarrierRoamingSatelliteSession} atom, which indicates
+             * whether multi sim are activated or not, then returns Builder class
+             */
+            public Builder setIsMultiSim(boolean isMultiSim) {
+                this.mIsMultiSim = isMultiSim;
+                return this;
+            }
+
+            /**
              * Returns CarrierRoamingSatelliteSessionParams, which contains whole component of
              * {@link CarrierRoamingSatelliteSession} atom
              */
@@ -2004,6 +2219,15 @@
                 return new SatelliteStats()
                         .new CarrierRoamingSatelliteSessionParams(Builder.this);
             }
+
+            /**
+             * Sets isNbIotNtn value of {@link CarrierRoamingSatelliteSession} atom, which indicates
+             * whether satellite service tech is NB-IoT-NTN or not
+             */
+            public Builder setIsNbIotNtn(boolean isNbIotNtn) {
+                this.mIsNbIotNtn = isNbIotNtn;
+                return this;
+            }
         }
 
         @Override
@@ -2026,6 +2250,11 @@
                     + ", countOfOutgoingSms=" + mCountOfOutgoingSms
                     + ", countOfIncomingMms=" + mCountOfIncomingMms
                     + ", countOfOutgoingMms=" + mCountOfOutgoingMms
+                    + ", supportedSatelliteServices=" + Arrays.toString(mSupportedSatelliteServices)
+                    + ", serviceDataPolicy=" + mServiceDataPolicy
+                    + ", SatelliteDataConsumedBytes=" + mSatelliteDataConsumedBytes
+                    + ", isMultiSim=" + mIsMultiSim
+                    + ", isNbIotNtn=" + mIsNbIotNtn
                     + ")";
         }
     }
@@ -2040,11 +2269,14 @@
         private final int mCountOfEntitlementStatusQueryRequest;
         private final int mCountOfSatelliteConfigUpdateRequest;
         private final int mCountOfSatelliteNotificationDisplayed;
-        private final int mSatelliteSessionGapMinSec;
-        private final int mSatelliteSessionGapAvgSec;
-        private final int mSatelliteSessionGapMaxSec;
+        private static int sSatelliteSessionGapMinSec;
+        private static int sSatelliteSessionGapAvgSec;
+        private static int sSatelliteSessionGapMaxSec;
         private static int sCarrierId;
         private static boolean sIsDeviceEntitled;
+        private static boolean sIsMultiSim;
+        private final int mCountOfSatelliteSessions;
+        private static boolean sIsNbIotNtn;
 
         private CarrierRoamingSatelliteControllerStatsParams(Builder builder) {
             this.mConfigDataSource = builder.mConfigDataSource;
@@ -2054,18 +2286,38 @@
                     builder.mCountOfSatelliteConfigUpdateRequest;
             this.mCountOfSatelliteNotificationDisplayed =
                     builder.mCountOfSatelliteNotificationDisplayed;
-            this.mSatelliteSessionGapMinSec = builder.mSatelliteSessionGapMinSec;
-            this.mSatelliteSessionGapAvgSec = builder.mSatelliteSessionGapAvgSec;
-            this.mSatelliteSessionGapMaxSec = builder.mSatelliteSessionGapMaxSec;
+
+            // Update session gap params only when they are explicitly provided
+            if (builder.mSatelliteSessionGapMinSec.isPresent()) {
+                sSatelliteSessionGapMinSec = builder.mSatelliteSessionGapMinSec.get();
+            }
+            if (builder.mSatelliteSessionGapAvgSec.isPresent()) {
+                sSatelliteSessionGapAvgSec = builder.mSatelliteSessionGapAvgSec.get();
+            }
+            if (builder.mSatelliteSessionGapMaxSec.isPresent()) {
+                sSatelliteSessionGapMaxSec = builder.mSatelliteSessionGapMaxSec.get();
+            }
 
             // Carrier ID value should be updated only when it is meaningful.
             if (builder.mCarrierId.isPresent()) {
-                this.sCarrierId = builder.mCarrierId.get();
+                sCarrierId = builder.mCarrierId.get();
             }
 
             // isDeviceEntitled value should be updated only when it is meaningful.
             if (builder.mIsDeviceEntitled.isPresent()) {
-                this.sIsDeviceEntitled = builder.mIsDeviceEntitled.get();
+                sIsDeviceEntitled = builder.mIsDeviceEntitled.get();
+            }
+
+            // isMulti value should be updated only when it is meaningful.
+            if (builder.mIsMultiSim.isPresent()) {
+                sIsMultiSim = builder.mIsMultiSim.get();
+            }
+
+            this.mCountOfSatelliteSessions = builder.mCountOfSatelliteSessions;
+
+            // isNbIotNtn value should be updated only when it is meaningful.
+            if (builder.mIsNbIotNtn.isPresent()) {
+                sIsNbIotNtn = builder.mIsNbIotNtn.get();
             }
         }
 
@@ -2073,7 +2325,6 @@
             return mConfigDataSource;
         }
 
-
         public int getCountOfEntitlementStatusQueryRequest() {
             return mCountOfEntitlementStatusQueryRequest;
         }
@@ -2087,15 +2338,15 @@
         }
 
         public int getSatelliteSessionGapMinSec() {
-            return mSatelliteSessionGapMinSec;
+            return sSatelliteSessionGapMinSec;
         }
 
         public int getSatelliteSessionGapAvgSec() {
-            return mSatelliteSessionGapAvgSec;
+            return sSatelliteSessionGapAvgSec;
         }
 
         public int getSatelliteSessionGapMaxSec() {
-            return mSatelliteSessionGapMaxSec;
+            return sSatelliteSessionGapMaxSec;
         }
 
         public int getCarrierId() {
@@ -2106,6 +2357,18 @@
             return sIsDeviceEntitled;
         }
 
+        public boolean isMultiSim() {
+            return sIsMultiSim;
+        }
+
+        public int getCountOfSatelliteSessions() {
+            return mCountOfSatelliteSessions;
+        }
+
+        public boolean isNbIotNtn() {
+            return sIsNbIotNtn;
+        }
+
         /**
          * A builder class to create {@link CarrierRoamingSatelliteControllerStatsParams}
          * data structure class
@@ -2115,11 +2378,14 @@
             private int mCountOfEntitlementStatusQueryRequest = 0;
             private int mCountOfSatelliteConfigUpdateRequest = 0;
             private int mCountOfSatelliteNotificationDisplayed = 0;
-            private int mSatelliteSessionGapMinSec = 0;
-            private int mSatelliteSessionGapAvgSec = 0;
-            private int mSatelliteSessionGapMaxSec = 0;
+            private Optional<Integer> mSatelliteSessionGapMinSec = Optional.empty();
+            private Optional<Integer> mSatelliteSessionGapAvgSec = Optional.empty();
+            private Optional<Integer> mSatelliteSessionGapMaxSec = Optional.empty();
             private Optional<Integer> mCarrierId = Optional.empty();
             private Optional<Boolean> mIsDeviceEntitled = Optional.empty();
+            private Optional<Boolean> mIsMultiSim = Optional.empty();
+            private int mCountOfSatelliteSessions = 0;
+            private Optional<Boolean> mIsNbIotNtn = Optional.empty();
 
             /**
              * Sets configDataSource value of {@link CarrierRoamingSatelliteControllerStats} atom
@@ -2165,7 +2431,7 @@
              * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class
              */
             public Builder setSatelliteSessionGapMinSec(int satelliteSessionGapMinSec) {
-                this.mSatelliteSessionGapMinSec = satelliteSessionGapMinSec;
+                this.mSatelliteSessionGapMinSec = Optional.of(satelliteSessionGapMinSec);
                 return this;
             }
 
@@ -2174,7 +2440,7 @@
              * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class
              */
             public Builder setSatelliteSessionGapAvgSec(int satelliteSessionGapAvgSec) {
-                this.mSatelliteSessionGapAvgSec = satelliteSessionGapAvgSec;
+                this.mSatelliteSessionGapAvgSec = Optional.of(satelliteSessionGapAvgSec);
                 return this;
             }
 
@@ -2183,7 +2449,7 @@
              * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class
              */
             public Builder setSatelliteSessionGapMaxSec(int satelliteSessionGapMaxSec) {
-                this.mSatelliteSessionGapMaxSec = satelliteSessionGapMaxSec;
+                this.mSatelliteSessionGapMaxSec = Optional.of(satelliteSessionGapMaxSec);
                 return this;
             }
 
@@ -2199,6 +2465,27 @@
                 return this;
             }
 
+            /** Sets whether the device is in DSDS state or not. */
+            public Builder setIsMultiSim(boolean isMultiSim) {
+                this.mIsMultiSim = Optional.of(isMultiSim);
+                return this;
+            }
+
+            /**
+             * Increase the countOfSatelliteSession value of
+             * {@link CarrierRoamingSatelliteControllerStats} atom by one then returns Builder class
+             */
+            public Builder increaseCountOfSatelliteSessions() {
+                this.mCountOfSatelliteSessions++;
+                return this;
+            }
+
+            /** Sets whether the device is in NB-NoT-NTN state or not. */
+            public Builder setIsNbIotNtn(boolean isNbIotNtn) {
+                this.mIsNbIotNtn = Optional.of(isNbIotNtn);
+                return this;
+            }
+
             /**
              * Returns CarrierRoamingSatelliteControllerStatsParams, which contains whole component
              * of {@link CarrierRoamingSatelliteControllerStats} atom
@@ -2210,6 +2497,38 @@
         }
 
         @Override
+        public boolean equals(Object obj) {
+            if (this == obj) return true;
+            if (obj == null || getClass() != obj.getClass()) return false;
+            CarrierRoamingSatelliteControllerStatsParams that =
+                    (CarrierRoamingSatelliteControllerStatsParams) obj;
+            return mConfigDataSource == that.getConfigDataSource()
+                    && mCountOfEntitlementStatusQueryRequest
+                    == that.getCountOfEntitlementStatusQueryRequest()
+                    && mCountOfSatelliteConfigUpdateRequest
+                    == that.getCountOfSatelliteConfigUpdateRequest()
+                    && mCountOfSatelliteNotificationDisplayed
+                    == that.getCountOfSatelliteNotificationDisplayed()
+                    && sSatelliteSessionGapMinSec == that.getSatelliteSessionGapMinSec()
+                    && sSatelliteSessionGapAvgSec == that.getSatelliteSessionGapAvgSec()
+                    && sSatelliteSessionGapMaxSec == that.getSatelliteSessionGapMaxSec()
+                    && sCarrierId == that.getCarrierId()
+                    && sIsDeviceEntitled == that.isDeviceEntitled()
+                    && sIsMultiSim == that.isMultiSim()
+                    && mCountOfSatelliteSessions == that.getCountOfSatelliteSessions()
+                    && sIsNbIotNtn == that.isNbIotNtn();
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mConfigDataSource, mCountOfEntitlementStatusQueryRequest,
+                    mCountOfSatelliteConfigUpdateRequest, mCountOfSatelliteNotificationDisplayed,
+                    sSatelliteSessionGapMinSec, sSatelliteSessionGapAvgSec,
+                    sSatelliteSessionGapMaxSec, sCarrierId, sIsDeviceEntitled, sIsMultiSim,
+                    mCountOfSatelliteSessions, sIsNbIotNtn);
+        }
+
+        @Override
         public String toString() {
             return "CarrierRoamingSatelliteControllerStatsParams("
                     + "configDataSource=" + mConfigDataSource
@@ -2219,11 +2538,14 @@
                     + mCountOfSatelliteConfigUpdateRequest
                     + ", countOfSatelliteNotificationDisplayed="
                     + mCountOfSatelliteNotificationDisplayed
-                    + ", satelliteSessionGapMinSec=" + mSatelliteSessionGapMinSec
-                    + ", satelliteSessionGapAvgSec=" + mSatelliteSessionGapAvgSec
-                    + ", satelliteSessionGapMaxSec=" + mSatelliteSessionGapMaxSec
+                    + ", satelliteSessionGapMinSec=" + sSatelliteSessionGapMinSec
+                    + ", satelliteSessionGapAvgSec=" + sSatelliteSessionGapAvgSec
+                    + ", satelliteSessionGapMaxSec=" + sSatelliteSessionGapMaxSec
                     + ", carrierId=" + sCarrierId
                     + ", isDeviceEntitled=" + sIsDeviceEntitled
+                    + ", isMultiSim=" + sIsMultiSim
+                    + ", countOfSatelliteSession=" + mCountOfSatelliteSessions
+                    + ", isNbIotNtn=" + sIsNbIotNtn
                     + ")";
         }
     }
@@ -2238,6 +2560,9 @@
         private final int mEntitlementStatus;
         private final boolean mIsRetry;
         private final int mCount;
+        private final boolean mIsAllowedServiceEntitlement;
+        private final int[] mEntitlementServiceType;
+        private final int mEntitlementDataPolicy;
 
         private SatelliteEntitlementParams(Builder builder) {
             this.mCarrierId = builder.mCarrierId;
@@ -2245,6 +2570,9 @@
             this.mEntitlementStatus = builder.mEntitlementStatus;
             this.mIsRetry = builder.mIsRetry;
             this.mCount = builder.mCount;
+            this.mIsAllowedServiceEntitlement = builder.mIsAllowedServiceEntitlement;
+            this.mEntitlementServiceType = builder.mEntitlementServiceType;
+            this.mEntitlementDataPolicy = builder.mEntitlementDataPolicy;
         }
 
         public int getCarrierId() {
@@ -2267,6 +2595,18 @@
             return mCount;
         }
 
+        public boolean getIsAllowedServiceEntitlement() {
+            return mIsAllowedServiceEntitlement;
+        }
+
+        public int[] getEntitlementServiceType() {
+            return mEntitlementServiceType;
+        }
+
+        public int getEntitlementDataPolicy() {
+            return mEntitlementDataPolicy;
+        }
+
         /**
          * A builder class to create {@link SatelliteEntitlementParams} data structure class
          */
@@ -2276,6 +2616,10 @@
             private int mEntitlementStatus = -1;
             private boolean mIsRetry = false;
             private int mCount = -1;
+            private boolean mIsAllowedServiceEntitlement = false;
+            private int[] mEntitlementServiceType = new int[0];
+            private int mEntitlementDataPolicy =
+                    SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN;
 
             /**
              * Sets carrierId value of {@link SatelliteEntitlement} atom
@@ -2323,6 +2667,34 @@
             }
 
             /**
+             * Sets isAllowedServiceEntitlement value of {@link SatelliteEntitlement} atom
+             * then returns Builder class
+             */
+            public Builder setIsAllowedServiceEntitlement(boolean isAllowedServiceEntitlement) {
+                this.mIsAllowedServiceEntitlement = isAllowedServiceEntitlement;
+                return this;
+            }
+
+            /**
+             * Sets entitlementServiceType value of {@link SatelliteEntitlement} atom
+             * then returns Builder class
+             */
+            public Builder setEntitlementServiceType(int[] entitlementServiceType) {
+                this.mEntitlementServiceType = entitlementServiceType;
+                Arrays.sort(this.mEntitlementServiceType);
+                return this;
+            }
+
+            /**
+             * Sets entitlementDataPolicy value of {@link SatelliteEntitlement} atom
+             * then returns Builder class
+             */
+            public Builder setEntitlementDataPolicy(int entitlementDataPolicy) {
+                this.mEntitlementDataPolicy = entitlementDataPolicy;
+                return this;
+            }
+
+            /**
              * Returns SatelliteEntitlementParams, which contains whole component of
              * {@link SatelliteEntitlement} atom
              */
@@ -2339,7 +2711,10 @@
                     + ", result=" + mResult
                     + ", entitlementStatus=" + mEntitlementStatus
                     + ", isRetry=" + mIsRetry
-                    + ", count=" + mCount + ")";
+                    + ", count=" + mCount
+                    + ",isAllowedServiceEntitlement=" + mIsAllowedServiceEntitlement
+                    + ",entitlementServiceType=" + Arrays.toString(mEntitlementServiceType)
+                    + ",entitlementServicePolicy=" + mEntitlementDataPolicy + ")";
         }
     }
 
@@ -2701,7 +3076,18 @@
         proto.countOfP2PSmsAvailableNotificationRemoved =
                 param.getCountOfP2PSmsAvailableNotificationRemoved();
         proto.isNtnOnlyCarrier = param.isNtnOnlyCarrier();
-
+        proto.versionOfSatelliteAccessConfig = param.getVersionSatelliteAccessConfig();
+        proto.countOfIncomingDatagramTypeSosSmsSuccess =
+                param.getCountOfIncomingDatagramTypeSosSmsSuccess();
+        proto.countOfIncomingDatagramTypeSosSmsFail =
+                param.getCountOfIncomingDatagramTypeSosSmsFail();
+        proto.countOfOutgoingDatagramTypeSmsSuccess =
+                param.getCountOfOutgoingDatagramTypeSmsSuccess();
+        proto.countOfOutgoingDatagramTypeSmsFail = param.getCountOfOutgoingDatagramTypeSmsFail();
+        proto.countOfIncomingDatagramTypeSmsSuccess =
+                param.getCountOfIncomingDatagramTypeSmsSuccess();
+        proto.countOfIncomingDatagramTypeSmsFail = param.getCountOfIncomingDatagramTypeSmsFail();
+        if (DBG) logd("onSatelliteControllerMetrics" + param);
         mAtomsStorage.addSatelliteControllerStats(proto);
     }
 
@@ -2730,6 +3116,7 @@
         proto.isEmergency = param.getIsEmergency();
         proto.isNtnOnlyCarrier = param.isNtnOnlyCarrier();
         proto.maxInactivityDurationSec = param.getMaxInactivityDurationSec();
+        if (DBG) logd("onSatelliteSessionMetrics" + param);
         mAtomsStorage.addSatelliteSessionStats(proto);
     }
 
@@ -2743,6 +3130,7 @@
         proto.isDemoMode = param.getIsDemoMode();
         proto.carrierId = param.getCarrierId();
         proto.isNtnOnlyCarrier = param.isNtnOnlyCarrier();
+        if (DBG) logd("onSatelliteIncomingDatagramMetrics" + param);
         mAtomsStorage.addSatelliteIncomingDatagramStats(proto);
     }
 
@@ -2757,6 +3145,7 @@
         proto.isDemoMode = param.getIsDemoMode();
         proto.carrierId = param.getCarrierId();
         proto.isNtnOnlyCarrier = param.isNtnOnlyCarrier();
+        if (DBG) logd("onSatelliteOutgoingDatagramMetrics: " + param);
         mAtomsStorage.addSatelliteOutgoingDatagramStats(proto);
     }
 
@@ -2769,6 +3158,7 @@
         proto.isCanceled = param.getIsCanceled();
         proto.carrierId = param.getCarrierId();
         proto.isNtnOnlyCarrier = param.isNtnOnlyCarrier();
+        if (DBG) logd("onSatelliteProvisionMetrics: " + param);
         mAtomsStorage.addSatelliteProvisionStats(proto);
     }
 
@@ -2787,6 +3177,7 @@
         proto.carrierId = param.getCarrierId();
         proto.isNtnOnlyCarrier = param.isNtnOnlyCarrier();
         proto.count = 1;
+        if (DBG) logd("onSatelliteSosMessageRecommender: " + param);
         mAtomsStorage.addSatelliteSosMessageRecommenderStats(proto);
     }
 
@@ -2810,6 +3201,12 @@
         proto.countOfOutgoingSms = param.mCountOfOutgoingSms;
         proto.countOfIncomingMms = param.mCountOfIncomingMms;
         proto.countOfOutgoingMms = param.mCountOfOutgoingMms;
+        proto.supportedSatelliteServices = param.mSupportedSatelliteServices;
+        proto.serviceDataPolicy = param.mServiceDataPolicy;
+        proto.satelliteDataConsumedBytes = param.mSatelliteDataConsumedBytes;
+        proto.isMultiSim = param.isMultiSim();
+        proto.isNbIotNtn = param.isNbIotNtn();
+        if (DBG) logd("onCarrierRoamingSatelliteSessionMetrics: " + param);
         mAtomsStorage.addCarrierRoamingSatelliteSessionStats(proto);
     }
 
@@ -2821,14 +3218,26 @@
         proto.countOfEntitlementStatusQueryRequest = param.mCountOfEntitlementStatusQueryRequest;
         proto.countOfSatelliteConfigUpdateRequest = param.mCountOfSatelliteConfigUpdateRequest;
         proto.countOfSatelliteNotificationDisplayed = param.mCountOfSatelliteNotificationDisplayed;
-        proto.satelliteSessionGapMinSec = param.mSatelliteSessionGapMinSec;
-        proto.satelliteSessionGapAvgSec = param.mSatelliteSessionGapAvgSec;
-        proto.satelliteSessionGapMaxSec = param.mSatelliteSessionGapMaxSec;
+        proto.satelliteSessionGapMinSec = param.getSatelliteSessionGapMinSec();
+        proto.satelliteSessionGapAvgSec = param.getSatelliteSessionGapAvgSec();
+        proto.satelliteSessionGapMaxSec = param.getSatelliteSessionGapMaxSec();
         proto.carrierId = param.getCarrierId();
         proto.isDeviceEntitled = param.isDeviceEntitled();
+        proto.isMultiSim = param.isMultiSim();
+        proto.countOfSatelliteSessions = param.getCountOfSatelliteSessions();
+        proto.isNbIotNtn = param.isNbIotNtn();
+        if (DBG) logd("onCarrierRoamingSatelliteControllerStatsMetrics: " + param);
         mAtomsStorage.addCarrierRoamingSatelliteControllerStats(proto);
     }
 
+    /** Reset carrier roaming satellite controller stats after atom is pulled. */
+    public synchronized void resetCarrierRoamingSatelliteControllerStats() {
+        if (DBG) logd("resetCarrierRoamingSatelliteControllerStats:");
+        com.android.internal.telephony.satellite.metrics
+                .CarrierRoamingSatelliteControllerStats.getOrCreateInstance()
+                .resetSessionGapLists();
+    }
+
     /**  Create a new atom for SatelliteEntitlement metrics */
     public synchronized  void onSatelliteEntitlementMetrics(SatelliteEntitlementParams param) {
         SatelliteEntitlement proto = new SatelliteEntitlement();
@@ -2837,6 +3246,10 @@
         proto.entitlementStatus = param.getEntitlementStatus();
         proto.isRetry = param.getIsRetry();
         proto.count = param.getCount();
+        proto.isAllowedServiceEntitlement = param.getIsAllowedServiceEntitlement();
+        proto.entitlementServiceType = param.getEntitlementServiceType();
+        proto.entitlementDataPolicy = param.getEntitlementDataPolicy();
+        if (DBG) logd("onSatelliteEntitlementMetrics: " + param);
         mAtomsStorage.addSatelliteEntitlementStats(proto);
     }
 
@@ -2847,6 +3260,7 @@
         proto.oemConfigResult = param.getOemConfigResult();
         proto.carrierConfigResult = param.getCarrierConfigResult();
         proto.count = param.getCount();
+        if (DBG) logd("onSatelliteConfigUpdaterMetrics: " + param);
         mAtomsStorage.addSatelliteConfigUpdaterStats(proto);
     }
 
@@ -2866,6 +3280,11 @@
         proto.carrierId = param.getCarrierId();
         proto.triggeringEvent = param.getTriggeringEvent();
         proto.isNtnOnlyCarrier = param.isNtnOnlyCarrier();
+        if (DBG) logd("onSatelliteAccessControllerMetrics: " + param);
         mAtomsStorage.addSatelliteAccessControllerStats(proto);
     }
+
+    private static void logd(String msg) {
+        Rlog.d(TAG, msg);
+    }
 }
diff --git a/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
index 3f24968..1d4c316 100644
--- a/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
+++ b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
@@ -21,7 +21,6 @@
 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS;
 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS;
 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_UNKNOWN;
-import static com.android.internal.telephony.flags.Flags.dataRatMetricEnabled;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -142,17 +141,20 @@
             newState.overrideVoiceService = mOverrideVoiceService.get();
             newState.isDataEnabled = mPhone.getDataSettingsManager().isDataEnabled();
             newState.isIwlanCrossSim = isCrossSimCallingRegistered(mPhone);
-            newState.isNtn = satelliteController != null
-                    && satelliteController.isInSatelliteModeForCarrierRoaming(mPhone);
+            if (satelliteController != null) {
+                newState.isNtn = satelliteController.isInSatelliteModeForCarrierRoaming(mPhone);
+                newState.isNbIotNtn = satelliteController.isInCarrierRoamingNbIotNtn(mPhone);
+            } else {
+                newState.isNtn = false;
+                newState.isNbIotNtn = false;
+            }
             TimestampedServiceState prevState =
                     mLastState.getAndSet(new TimestampedServiceState(newState, now));
             addServiceStateAndSwitch(
                     prevState, now, getDataServiceSwitch(prevState.mServiceState, newState));
         }
 
-        if (dataRatMetricEnabled()) {
-            writeDataRatAtom(serviceState);
-        }
+        writeDataRatAtom(serviceState);
     }
 
     /** Updates the fold state of the device for the current service state. */
@@ -320,6 +322,7 @@
         copy.isDataEnabled = state.isDataEnabled;
         copy.isIwlanCrossSim = state.isIwlanCrossSim;
         copy.isNtn = state.isNtn;
+        copy.isNbIotNtn = state.isNbIotNtn;
         return copy;
     }
 
diff --git a/src/java/com/android/internal/telephony/metrics/SmsStats.java b/src/java/com/android/internal/telephony/metrics/SmsStats.java
index b62114c..fdbb20b 100644
--- a/src/java/com/android/internal/telephony/metrics/SmsStats.java
+++ b/src/java/com/android/internal/telephony/metrics/SmsStats.java
@@ -57,10 +57,10 @@
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms;
 import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingShortCodeSms;
 import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
+import com.android.internal.telephony.satellite.SatelliteController;
 import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteSessionStats;
 import com.android.telephony.Rlog;
 
@@ -160,18 +160,19 @@
     /** Create a new atom when an outgoing SMS is sent. */
     public void onOutgoingSms(boolean isOverIms, boolean is3gpp2, boolean fallbackToCs,
             @SmsManager.Result int sendErrorCode, long messageId, boolean isFromDefaultApp,
-            long intervalMillis, boolean isEmergency) {
+            long intervalMillis, boolean isEmergency, boolean isMtSmsPolling) {
         onOutgoingSms(isOverIms, is3gpp2, fallbackToCs, sendErrorCode, NO_ERROR_CODE,
-                messageId, isFromDefaultApp, intervalMillis, isEmergency);
+                messageId, isFromDefaultApp, intervalMillis, isEmergency, isMtSmsPolling);
     }
 
     /** Create a new atom when an outgoing SMS is sent. */
     public void onOutgoingSms(boolean isOverIms, boolean is3gpp2, boolean fallbackToCs,
             @SmsManager.Result int sendErrorCode, int networkErrorCode, long messageId,
-            boolean isFromDefaultApp, long intervalMillis, boolean isEmergency) {
+            boolean isFromDefaultApp, long intervalMillis, boolean isEmergency,
+            boolean isMtSmsPolling) {
         OutgoingSms proto =
                 getOutgoingDefaultProto(is3gpp2, isOverIms, messageId, isFromDefaultApp,
-                        intervalMillis, isEmergency);
+                        intervalMillis, isEmergency, isMtSmsPolling);
 
         // The field errorCode is used for up-to-Android-13 devices. From Android 14, sendErrorCode
         // and networkErrorCode will be used. The field errorCode will be deprecated when most
@@ -242,12 +243,14 @@
         proto.isManagedProfile = mPhone.isManagedProfile();
         proto.isNtn = isNonTerrestrialNetwork();
         proto.isEmergency = isEmergency;
+        proto.isNbIotNtn = isNbIotNtn(mPhone);
         return proto;
     }
 
     /** Create a proto for a normal {@code OutgoingSms} with default values. */
     private OutgoingSms getOutgoingDefaultProto(boolean is3gpp2, boolean isOverIms,
-            long messageId, boolean isFromDefaultApp, long intervalMillis, boolean isEmergency) {
+            long messageId, boolean isFromDefaultApp, long intervalMillis, boolean isEmergency,
+            boolean isMtSmsPolling) {
         OutgoingSms proto = new OutgoingSms();
         proto.smsFormat = getSmsFormat(is3gpp2);
         proto.smsTech = getSmsTech(isOverIms, is3gpp2);
@@ -270,6 +273,8 @@
         proto.isManagedProfile = mPhone.isManagedProfile();
         proto.isEmergency = isEmergency;
         proto.isNtn = isNonTerrestrialNetwork();
+        proto.isMtSmsPolling = isMtSmsPolling;
+        proto.isNbIotNtn = isNbIotNtn(mPhone);
         return proto;
     }
 
@@ -342,8 +347,8 @@
      */
     static int getSmsHashCode(OutgoingSms sms) {
         return Objects.hash(sms.smsFormat, sms.smsTech, sms.rat, sms.sendResult, sms.errorCode,
-                    sms.isRoaming, sms.isFromDefaultApp, sms.simSlotIndex, sms.isMultiSim,
-                    sms.isEsim, sms.carrierId);
+                sms.isRoaming, sms.isFromDefaultApp, sms.simSlotIndex, sms.isMultiSim, sms.isEsim,
+                sms.carrierId, sms.isEmergency, sms.isNtn, sms.isMtSmsPolling, sms.isNbIotNtn);
     }
 
     /**
@@ -353,7 +358,8 @@
     static int getSmsHashCode(IncomingSms sms) {
         return Objects.hash(sms.smsFormat, sms.smsTech, sms.rat, sms.smsType,
             sms.totalParts, sms.receivedParts, sms.blocked, sms.error,
-            sms.isRoaming, sms.simSlotIndex, sms.isMultiSim, sms.isEsim, sms.carrierId);
+                sms.isRoaming, sms.simSlotIndex, sms.isMultiSim, sms.isEsim, sms.carrierId,
+                sms.isNtn, sms.isNbIotNtn);
     }
 
     private int getPhoneId() {
@@ -408,10 +414,6 @@
     }
 
     private boolean isNonTerrestrialNetwork() {
-        if (!Flags.carrierEnabledSatelliteFlag()) {
-            return false;
-        }
-
         ServiceState ss = getServiceState();
         if (ss != null) {
             return ss.isUsingNonTerrestrialNetwork();
@@ -421,6 +423,10 @@
         }
     }
 
+    private boolean isNbIotNtn(Phone phone) {
+        return SatelliteController.getInstance().isInCarrierRoamingNbIotNtn(phone);
+    }
+
     private void loge(String format, Object... args) {
         Rlog.e(TAG, "[" + mPhone.getPhoneId() + "]" + String.format(format, args));
     }
diff --git a/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java b/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
index b6a26c6..dcacb4e 100644
--- a/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
+++ b/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
@@ -478,9 +478,7 @@
         @VideoState int videoState = conn.getVideoState();
         VoiceCallSession proto = new VoiceCallSession();
 
-        if (mFlags.vonrEnabledMetric()) {
-            mVonrHelper.updateVonrEnabledState();
-        }
+        mVonrHelper.updateVonrEnabledState();
 
         proto.bearerAtStart = bearer;
         proto.bearerAtEnd = bearer;
@@ -582,9 +580,7 @@
         // Set device fold state
         proto.foldState = mDeviceStateHelper.getFoldState();
 
-        if (mFlags.vonrEnabledMetric()) {
-            proto.vonrEnabled = mVonrHelper.getVonrEnabled(mPhone.getSubId());
-        }
+        proto.vonrEnabled = mVonrHelper.getVonrEnabled(mPhone.getSubId());
 
         proto.supportsBusinessCallComposer = isBusinessCallSupported();
         // 0 is defined as UNKNOWN in Enum
diff --git a/src/java/com/android/internal/telephony/metrics/VonrHelper.java b/src/java/com/android/internal/telephony/metrics/VonrHelper.java
index 8f14a86..0c1c111 100644
--- a/src/java/com/android/internal/telephony/metrics/VonrHelper.java
+++ b/src/java/com/android/internal/telephony/metrics/VonrHelper.java
@@ -24,6 +24,7 @@
 import android.os.HandlerThread;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.flags.FeatureFlags;
 
@@ -39,11 +40,14 @@
     private final @NonNull FeatureFlags mFlags;
 
     private Handler mHandler;
+    private Handler mHandlerThread;
     private Map<Integer, Boolean> mPhoneVonrState = new ConcurrentHashMap<>();
 
     public VonrHelper(@NonNull FeatureFlags featureFlags) {
         this.mFlags = featureFlags;
-        if (mFlags.vonrEnabledMetric()) {
+        if (mFlags.threadShred()) {
+            mHandler = new Handler(BackgroundThread.get().getLooper());
+        } else {
             HandlerThread mHandlerThread = new HandlerThread("VonrHelperThread");
             mHandlerThread.start();
             mHandler = new Handler(mHandlerThread.getLooper());
@@ -52,9 +56,7 @@
 
     /** Update vonr_enabled state */
     public void updateVonrEnabledState() {
-        if (mFlags.vonrEnabledMetric()) {
-            mHandler.post(mVonrRunnable);
-        }
+        mHandler.post(mVonrRunnable);
     }
 
     @VisibleForTesting
@@ -71,10 +73,6 @@
 
     /** Get vonr_enabled per subId */
     public boolean getVonrEnabled(int subId) {
-        if (mFlags.vonrEnabledMetric()) {
-            return mPhoneVonrState.getOrDefault(subId, false);
-        } else {
-            return false;
-        }
+        return mPhoneVonrState.getOrDefault(subId, false);
     }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramController.java b/src/java/com/android/internal/telephony/satellite/DatagramController.java
index acd3fd1..05aef83 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramController.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramController.java
@@ -34,12 +34,11 @@
 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;
 import android.telephony.satellite.SatelliteManager;
+import android.util.Log;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -180,11 +179,7 @@
         mDatagramWaitTimeForConnectedStateForLastMessage =
                 getDatagramWaitForConnectedStateForLastMessageTimeoutMillis();
         mDemoModeDatagramList = new ArrayList<>();
-
-        if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
-            mPersistentLogger = new PersistentLogger(
-                    DropBoxManagerLoggerBackend.getInstance(context));
-        }
+        mPersistentLogger = SatelliteServiceUtils.getPersistentLogger(context);
     }
 
     /**
@@ -687,35 +682,22 @@
     }
 
     private static void logd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
     }
 
     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;
-        }
+        Log.e(TAG, log);
     }
 
     private void plogd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.debug(TAG, log);
         }
     }
 
     private void ploge(@NonNull String log) {
-        Rlog.e(TAG, log);
+        Log.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 d1d8726..dc6be3a 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -28,8 +28,8 @@
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
 
-import static com.android.internal.telephony.satellite.DatagramController.ROUNDING_UNIT;
 import static com.android.internal.telephony.SmsDispatchersController.PendingRequest;
+import static com.android.internal.telephony.satellite.DatagramController.ROUNDING_UNIT;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -39,9 +39,7 @@
 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.satellite.SatelliteDatagram;
 import android.telephony.satellite.SatelliteManager;
 import android.telephony.satellite.SatelliteSessionStats;
@@ -82,6 +80,8 @@
     private static final int CMD_SEND_SMS = 8;
     private static final int EVENT_SEND_SMS_DONE = 9;
     private static final int EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT = 10;
+    private static final int CMD_SEND_MT_SMS_POLLING_MESSAGE = 11;
+
     private static final Long TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE = TimeUnit.SECONDS.toMillis(10);
     @NonNull private static DatagramDispatcher sInstance;
     @NonNull private final Context mContext;
@@ -194,10 +194,7 @@
         mDatagramController = datagramController;
         mControllerMetricsStats = ControllerMetricsStats.getInstance();
         mSessionMetricsStats = SessionMetricsStats.getInstance();
-        if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
-            mPersistentLogger = new PersistentLogger(
-                    DropBoxManagerLoggerBackend.getInstance(context));
-        }
+        mPersistentLogger = SatelliteServiceUtils.getPersistentLogger(context);
 
         synchronized (mLock) {
             mSendingInProgress = false;
@@ -426,10 +423,16 @@
             case EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT: {
                 synchronized (mLock) {
                     mIsMtSmsPollingThrottled = false;
-                    if (allowMtSmsPolling()) {
-                        sendMtSmsPollingMessage();
-                    }
                 }
+                if (allowMtSmsPolling()) {
+                    sendMessage(obtainMessage(CMD_SEND_MT_SMS_POLLING_MESSAGE));
+                }
+                break;
+            }
+
+            case CMD_SEND_MT_SMS_POLLING_MESSAGE: {
+                plogd("CMD_SEND_MT_SMS_POLLING_MESSAGE");
+                handleCmdSendMtSmsPollingMessage();
                 break;
             }
 
@@ -521,9 +524,9 @@
             mIsAligned = isAligned;
             plogd("setDeviceAlignedWithSatellite: " + mIsAligned);
             if (isAligned && mIsDemoMode) handleEventSatelliteAligned();
-            if (allowMtSmsPolling()) {
-                sendMtSmsPollingMessage();
-            }
+        }
+        if (allowMtSmsPolling()) {
+            sendMessage(obtainMessage(CMD_SEND_MT_SMS_POLLING_MESSAGE));
         }
     }
 
@@ -763,9 +766,11 @@
         if (resultCode == SATELLITE_RESULT_SUCCESS) {
             long smsTransmissionTime = mSmsTransmissionStartTime > 0
                     ? (System.currentTimeMillis() - mSmsTransmissionStartTime) : 0;
+            mControllerMetricsStats.reportOutgoingDatagramSuccessCount(datagramType, false);
             mSessionMetricsStats.addCountOfSuccessfulOutgoingDatagram(
                     datagramType, smsTransmissionTime);
         } else {
+            mControllerMetricsStats.reportOutgoingDatagramFailCount(datagramType, false);
             mSessionMetricsStats.addCountOfFailedOutgoingDatagram(
                     datagramType, resultCode);
         }
@@ -845,10 +850,9 @@
                     mShouldPollMtSms = shouldPollMtSms();
                 }
             }
-
-            if (allowMtSmsPolling()) {
-                sendMtSmsPollingMessage();
-            }
+        }
+        if (allowMtSmsPolling()) {
+            sendMessage(obtainMessage(CMD_SEND_MT_SMS_POLLING_MESSAGE));
         }
     }
 
@@ -1325,23 +1329,26 @@
                 && satelliteController.shouldSendSmsToDatagramDispatcher(satellitePhone);
     }
 
-    @GuardedBy("mLock")
-    private void sendMtSmsPollingMessage() {
-        if (!mShouldPollMtSms) {
-            return;
-        }
-
-        plogd("sendMtSmsPollingMessage");
-        if (!allowCheckMessageInNotConnected()) {
-            mShouldPollMtSms = false;
-        }
-
-        for (Entry<Long, PendingRequest> entry : mPendingSmsMap.entrySet()) {
-            PendingRequest pendingRequest = entry.getValue();
-            if (pendingRequest.isMtSmsPolling) {
-                plogd("sendMtSmsPollingMessage: mPendingSmsMap already has the polling message.");
+    private void handleCmdSendMtSmsPollingMessage() {
+        synchronized (mLock) {
+            if (!mShouldPollMtSms) {
+                plogd("sendMtSmsPollingMessage: mShouldPollMtSms=" + mShouldPollMtSms);
                 return;
             }
+
+            plogd("sendMtSmsPollingMessage");
+            if (!allowCheckMessageInNotConnected()) {
+                mShouldPollMtSms = false;
+            }
+
+            for (Entry<Long, PendingRequest> entry : mPendingSmsMap.entrySet()) {
+                PendingRequest pendingRequest = entry.getValue();
+                if (pendingRequest.isMtSmsPolling) {
+                    plogd("sendMtSmsPollingMessage: mPendingSmsMap already "
+                            + "has the polling message.");
+                    return;
+                }
+            }
         }
 
         Phone satellitePhone = SatelliteController.getInstance().getSatellitePhone();
@@ -1374,23 +1381,44 @@
         removeMessages(EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT);
     }
 
-    @GuardedBy("mLock")
     private boolean allowMtSmsPolling() {
-        if (!mFeatureFlags.carrierRoamingNbIotNtn()) return false;
-
-        if (mIsMtSmsPollingThrottled) return false;
-
-        if (!mIsAligned) return false;
-
-        boolean isModemStateConnectedOrTransferring =
-                mModemState == SATELLITE_MODEM_STATE_CONNECTED
-                        || mModemState == SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING;
-        if (!isModemStateConnectedOrTransferring && !allowCheckMessageInNotConnected()) {
-            plogd("EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT:"
-                    + " allow_check_message_in_not_connected is disabled");
+        SatelliteController satelliteController = SatelliteController.getInstance();
+        int subId = satelliteController.getSelectedSatelliteSubId();
+        boolean isP2PSmsDisallowed =
+                satelliteController.isP2PSmsDisallowedOnCarrierRoamingNtn(subId);
+        if (isP2PSmsDisallowed) {
+            plogd("allowMtSmsPolling: P2P SMS disallowed, subId = " + subId);
             return false;
         }
 
+        boolean isModemStateConnectedOrTransferring;
+        boolean isAligned;
+        boolean isMtSmsPollingThrottled;
+        synchronized (mLock) {
+            isMtSmsPollingThrottled = mIsMtSmsPollingThrottled;
+            isAligned = mIsAligned;
+            isModemStateConnectedOrTransferring =
+                    mModemState == SATELLITE_MODEM_STATE_CONNECTED
+                            || mModemState == SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING;
+        }
+
+        if (isMtSmsPollingThrottled) {
+            plogd("allowMtSmsPolling: polling is throttled");
+            return false;
+        }
+
+        if (!isAligned) {
+            plogd("allowMtSmsPolling: not aligned");
+            return false;
+        }
+
+        if (!isModemStateConnectedOrTransferring && !allowCheckMessageInNotConnected()) {
+            plogd("allowMtSmsPolling: not in service and "
+                    + "allow_check_message_in_not_connected is disabled");
+            return false;
+        }
+
+        plogd("allowMtSmsPolling: return true");
         return true;
     }
 
@@ -1400,44 +1428,31 @@
     }
 
     private static void logd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
     }
 
     private static void loge(@NonNull String log) {
-        Rlog.e(TAG, log);
+        Log.e(TAG, log);
     }
 
-    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 static void logw(@NonNull String log) { Log.w(TAG, log); }
 
     private void plogd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.debug(TAG, log);
         }
     }
 
     private void plogw(@NonNull String log) {
-        Rlog.w(TAG, log);
+        Log.w(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.warn(TAG, log);
         }
     }
 
     private void ploge(@NonNull String log) {
-        Rlog.e(TAG, log);
+        Log.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 c01f10d..26d456b 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
@@ -37,13 +37,12 @@
 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;
 import android.telephony.satellite.SatelliteDatagram;
 import android.telephony.satellite.SatelliteManager;
+import android.util.Log;
 import android.util.Pair;
 
 import com.android.internal.R;
@@ -152,10 +151,7 @@
         mDatagramController = datagramController;
         mControllerMetricsStats = ControllerMetricsStats.getInstance();
         mSessionMetricsStats = SessionMetricsStats.getInstance();
-        if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
-            mPersistentLogger = new PersistentLogger(
-                    DropBoxManagerLoggerBackend.getInstance(context));
-        }
+        mPersistentLogger = SatelliteServiceUtils.getPersistentLogger(context);
         try {
             mSharedPreferences =
                     mContext.getSharedPreferences(SatelliteController.SATELLITE_SHARED_PREF,
@@ -896,46 +892,33 @@
     }
 
     private static void logd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
     }
 
     private static void loge(@NonNull String log) {
-        Rlog.e(TAG, log);
+        Log.e(TAG, log);
     }
 
     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;
-        }
+        Log.w(TAG, log);
     }
 
     private void plogd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.debug(TAG, log);
         }
     }
 
     private void plogw(@NonNull String log) {
-        Rlog.w(TAG, log);
+        Log.w(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.warn(TAG, log);
         }
     }
 
     private void ploge(@NonNull String log) {
-        Rlog.e(TAG, log);
+        Log.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 4b53178..0e6233a 100644
--- a/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
+++ b/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
@@ -18,8 +18,8 @@
 
 import android.annotation.NonNull;
 import android.telephony.NetworkRegistrationInfo;
-import android.telephony.Rlog;
 import android.text.TextUtils;
+import android.util.Log;
 
 import java.util.List;
 
@@ -60,6 +60,6 @@
     }
 
     private static void logd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
     }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/PointingAppController.java b/src/java/com/android/internal/telephony/satellite/PointingAppController.java
index 9606150..4846323 100644
--- a/src/java/com/android/internal/telephony/satellite/PointingAppController.java
+++ b/src/java/com/android/internal/telephony/satellite/PointingAppController.java
@@ -35,16 +35,16 @@
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.os.UserHandle;
-import android.telephony.DropBoxManagerLoggerBackend;
 import android.telephony.PersistentLogger;
-import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
 import android.telephony.satellite.PointingInfo;
 import android.telephony.satellite.SatelliteManager;
 import android.text.TextUtils;
+import android.util.Log;
 
 import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.flags.FeatureFlags;
 
@@ -70,6 +70,9 @@
     private boolean mLastNeedFullScreenPointingUI;
     private boolean mLastIsDemoMode;
     private boolean mLastIsEmergency;
+
+    private final Object mListenerForPointingUIRegisteredLock = new Object();
+    @GuardedBy("mListenerForPointingUIRegisteredLock")
     private boolean mListenerForPointingUIRegistered;
     @NonNull private String mPointingUiPackageName = "";
     @NonNull private String mPointingUiClassName = "";
@@ -122,10 +125,7 @@
         mLastIsEmergency = false;
         mListenerForPointingUIRegistered = false;
         mActivityManager = mContext.getSystemService(ActivityManager.class);
-        if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
-            mPersistentLogger = new PersistentLogger(
-                    DropBoxManagerLoggerBackend.getInstance(context));
-        }
+        mPersistentLogger = SatelliteServiceUtils.getPersistentLogger(context);
     }
 
     /**
@@ -419,17 +419,20 @@
         launchIntent.putExtra("isEmergency", isEmergency);
 
         try {
-            if (!mListenerForPointingUIRegistered) {
-                mActivityManager.addOnUidImportanceListener(mUidImportanceListener,
-                        IMPORTANCE_GONE);
-                mListenerForPointingUIRegistered = true;
+            synchronized (mListenerForPointingUIRegisteredLock) {
+                if (!mListenerForPointingUIRegistered) {
+                    mActivityManager.addOnUidImportanceListener(mUidImportanceListener,
+                            IMPORTANCE_GONE);
+                    mListenerForPointingUIRegistered = true;
+                }
             }
             mLastNeedFullScreenPointingUI = needFullScreenPointingUI;
             mLastIsDemoMode = isDemoMode;
             mLastIsEmergency = isEmergency;
             mContext.startActivityAsUser(launchIntent, UserHandle.CURRENT);
-        } catch (ActivityNotFoundException ex) {
-            ploge("startPointingUI: Pointing UI app activity is not found, ex=" + ex);
+        } catch (ActivityNotFoundException | IllegalArgumentException ex) {
+            ploge("startPointingUI: Unable to start Pointing UI activity due to an exception, ex="
+                    + ex);
         }
     }
 
@@ -437,9 +440,11 @@
      * Remove the Importance Listener For Pointing UI App once the satellite is disabled
      */
     public void removeListenerForPointingUI() {
-        if (mListenerForPointingUIRegistered) {
-            mActivityManager.removeOnUidImportanceListener(mUidImportanceListener);
-            mListenerForPointingUIRegistered = false;
+        synchronized (mListenerForPointingUIRegisteredLock) {
+            if (mListenerForPointingUIRegistered) {
+                mActivityManager.removeOnUidImportanceListener(mUidImportanceListener);
+                mListenerForPointingUIRegistered = false;
+            }
         }
     }
 
@@ -558,35 +563,22 @@
     }
 
     private static void logd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
     }
 
     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;
-        }
+        Log.e(TAG, log);
     }
 
     private void plogd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.debug(TAG, log);
         }
     }
 
     private void ploge(@NonNull String log) {
-        Rlog.e(TAG, log);
+        Log.e(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.error(TAG, log);
         }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java b/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
index 0568d86..cfade30 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
+import android.os.FileUtils;
 import android.util.ArraySet;
 import android.util.Log;
 
@@ -48,11 +49,14 @@
     private static final String TAG = "SatelliteConfig";
     private static final String SATELLITE_DIR_NAME = "satellite";
     private static final String S2_CELL_FILE_NAME = "s2_cell_file";
+    private static final String SATELLITE_ACCESS_CONFIG_JSON_FILE_NAME =
+            "satelltie_access_config.json";
     private int mVersion;
     private Map<Integer, Map<String, Set<Integer>>> mSupportedServicesPerCarrier;
     private List<String> mSatelliteRegionCountryCodes;
     private Boolean mIsSatelliteRegionAllowed;
     private File mSatS2File;
+    private File mSatelliteAccessConfigJsonFile;
     private SatelliteConfigData.SatelliteConfigProto mConfigData;
 
     public SatelliteConfig(SatelliteConfigData.SatelliteConfigProto configData) {
@@ -63,13 +67,16 @@
                 mConfigData.deviceSatelliteRegion.countryCodes);
         mIsSatelliteRegionAllowed = mConfigData.deviceSatelliteRegion.isAllowed;
         mSatS2File = null;
+        mSatelliteAccessConfigJsonFile = null;
 
         Log.d(TAG, "mVersion:" + mVersion + " | "
                 + "mSupportedServicesPerCarrier:" + mSupportedServicesPerCarrier + " | "
                 + "mSatelliteRegionCountryCodes:"
                 + String.join(",", mSatelliteRegionCountryCodes) + " | "
                 + "mIsSatelliteRegionAllowed:" + mIsSatelliteRegionAllowed + " | "
-                + " | s2CellFile size:" + mConfigData.deviceSatelliteRegion.s2CellFile.length);
+                + "s2CellFile size:" + mConfigData.deviceSatelliteRegion.s2CellFile.length  + " | "
+                + "satellite_access_config_json size:"
+                + mConfigData.deviceSatelliteRegion.satelliteAccessConfigFile.length);
     }
 
     /**
@@ -194,8 +201,8 @@
         }
 
         if (mConfigData != null && mConfigData.deviceSatelliteRegion != null) {
-            mSatS2File = copySatS2FileToPhoneDirectory(
-                    context, mConfigData.deviceSatelliteRegion.s2CellFile);
+            mSatS2File = copySatelliteFileToPhoneDirectory(
+                    context, mConfigData.deviceSatelliteRegion.s2CellFile, S2_CELL_FILE_NAME);
             return mSatS2File;
         }
         Log.d(TAG, "getSatelliteS2CellFile: "
@@ -204,38 +211,108 @@
     }
 
     /**
-     * @param context       the Context
-     * @param byteArrayFile byte array type of protobuffer config data
-     * @return the satellite_cell_file path
+     * @param context the Context
+     * @return satellite access config json path
      */
     @Nullable
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
-    public File copySatS2FileToPhoneDirectory(@Nullable Context context,
-            @Nullable byte[] byteArrayFile) {
-
-        if (context == null || byteArrayFile == null) {
-            Log.d(TAG, "copySatS2FileToPhoneDirectory : context or byteArrayFile are null");
+    public File getSatelliteAccessConfigJsonFile(@Nullable Context context) {
+        if (context == null) {
+            Log.d(TAG, "getSatelliteAccessConfigJsonFile : context is null");
             return null;
         }
 
-        File satS2FileDir = context.getDir(SATELLITE_DIR_NAME, Context.MODE_PRIVATE);
-        if (!satS2FileDir.exists()) {
-            satS2FileDir.mkdirs();
+        if (isFileExist(mSatelliteAccessConfigJsonFile)) {
+            Log.d(TAG, "File mSatelliteAccessConfigJsonFile is already exist");
+            return mSatelliteAccessConfigJsonFile;
         }
 
-        Path targetSatS2FilePath = satS2FileDir.toPath().resolve(S2_CELL_FILE_NAME);
+        if (mConfigData != null && mConfigData.deviceSatelliteRegion != null) {
+            mSatelliteAccessConfigJsonFile = copySatelliteFileToPhoneDirectory(context,
+                    mConfigData.deviceSatelliteRegion.satelliteAccessConfigFile,
+                    SATELLITE_ACCESS_CONFIG_JSON_FILE_NAME);
+            return mSatelliteAccessConfigJsonFile;
+        }
+        Log.d(TAG, "mSatelliteAccessConfigJsonFile: "
+                + "mConfigData is null or mConfigData.deviceSatelliteRegion is null");
+        return null;
+    }
+
+    /**
+     * Get the version of satellite config data
+     *
+     * @return version corresponding version number of satellite config data.
+     */
+    @NonNull
+    public int getSatelliteConfigDataVersion() {
+        Log.d(TAG, "getSatelliteConfigDataVersion: mVersion: " + mVersion);
+        return mVersion;
+    }
+
+    /**
+     * @param context       the Context
+     * @param byteArrayFile byte array type of protobuffer config data
+     * @return the path for satellite_file in phone process
+     */
+    @Nullable
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public File copySatelliteFileToPhoneDirectory(@Nullable Context context,
+            @Nullable byte[] byteArrayFile, String fileName) {
+
+        if (context == null || byteArrayFile == null) {
+            Log.d(TAG, "copySatelliteFileToPhoneDirectory : context or byteArrayFile are null");
+            return null;
+        }
+
+        File satelliteFileDir = context.getDir(SATELLITE_DIR_NAME, Context.MODE_PRIVATE);
+        if (!satelliteFileDir.exists()) {
+            satelliteFileDir.mkdirs();
+        }
+
+        Path targetSatelliteFilePath = satelliteFileDir.toPath().resolve(fileName);
         try {
             InputStream inputStream = new ByteArrayInputStream(byteArrayFile);
             if (inputStream == null) {
-                Log.d(TAG, "copySatS2FileToPhoneDirectory: Resource=" + S2_CELL_FILE_NAME
+                Log.d(TAG, "copySatelliteFileToPhoneDirectory: Resource=" + fileName
                         + " not found");
             } else {
-                Files.copy(inputStream, targetSatS2FilePath, StandardCopyOption.REPLACE_EXISTING);
+                Files.copy(inputStream, targetSatelliteFilePath,
+                        StandardCopyOption.REPLACE_EXISTING);
             }
         } catch (IOException ex) {
-            Log.e(TAG, "copySatS2FileToPhoneDirectory: ex=" + ex);
+            Log.e(TAG, "copySatelliteFileToPhoneDirectory: ex=" + ex);
         }
-        return targetSatS2FilePath.toFile();
+        Log.d(
+                TAG,
+                "targetSatelliteFilePath's path: "
+                        + targetSatelliteFilePath.toAbsolutePath().toString());
+        return targetSatelliteFilePath.toFile();
+    }
+
+    /**
+     * This method cleans the Satellite Config OTA resources and it should be used only in CTS/Unit
+     * tests
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public void cleanOtaResources(@Nullable Context context) {
+        if (context == null) {
+            Log.d(TAG, "cleanOtaResources : context is null");
+            return;
+        }
+        try {
+            File satelliteFileDir = context.getDir(SATELLITE_DIR_NAME, Context.MODE_PRIVATE);
+            if (!satelliteFileDir.exists()) {
+                Log.d(
+                        TAG,
+                        "cleanOtaResources: "
+                                + SATELLITE_DIR_NAME
+                                + " does not exist. No need to clean.");
+                return;
+            }
+            Log.d(TAG, "cleanOtaResources: Deleting contents under " + SATELLITE_DIR_NAME);
+            FileUtils.deleteContents(satelliteFileDir);
+        } catch (Exception e) {
+            Log.e(TAG, "cleanOtaResources error : " + e);
+        }
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java b/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java
index a5afe4a..7fbba14 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java
@@ -66,6 +66,7 @@
     public static final int CONFIG_UPDATE_RESULT_DEVICE_DATA_INVALID_COUNTRY_CODE = 9;
     public static final int CONFIG_UPDATE_RESULT_DEVICE_DATA_INVALID_S2_CELL_FILE = 10;
     public static final int CONFIG_UPDATE_RESULT_IO_ERROR = 11;
+    public static final int CONFIG_UPDATE_RESULT_INVALID_SATELLITE_ACCESS_CONFIG_FILE = 12;
 
     @IntDef(prefix = {"CONFIG_UPDATE_RESULT_"}, value = {
             CONFIG_UPDATE_RESULT_UNKNOWN,
@@ -79,7 +80,8 @@
             CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_SUPPORTED_SERVICES,
             CONFIG_UPDATE_RESULT_DEVICE_DATA_INVALID_COUNTRY_CODE,
             CONFIG_UPDATE_RESULT_DEVICE_DATA_INVALID_S2_CELL_FILE,
-            CONFIG_UPDATE_RESULT_IO_ERROR
+            CONFIG_UPDATE_RESULT_IO_ERROR,
+            CONFIG_UPDATE_RESULT_INVALID_SATELLITE_ACCESS_CONFIG_FILE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ConfigUpdateResult {}
@@ -111,15 +113,35 @@
     public static final int TRIGGERING_EVENT_EXTERNAL_REQUEST = 1;
     // Satellite Access Controller has been triggered by an MCC change event.
     public static final int TRIGGERING_EVENT_MCC_CHANGED = 2;
-    //Satellite Access Controller has been triggered due to the location setting being enabled.
+    // Satellite Access Controller has been triggered due to the location setting being enabled.
     public static final int TRIGGERING_EVENT_LOCATION_SETTINGS_ENABLED = 3;
+    // Satellite Access Controller has been triggered due to the location setting being disabled.
+    public static final int TRIGGERING_EVENT_LOCATION_SETTINGS_DISABLED = 4;
+    // Satellite Access Controller has been triggered due to the config data updated.
+    public static final int TRIGGERING_EVENT_CONFIG_DATA_UPDATED = 5;
 
     @IntDef(prefix = {"TRIGGERING_EVENT_"}, value = {
             TRIGGERING_EVENT_UNKNOWN,
             TRIGGERING_EVENT_EXTERNAL_REQUEST,
             TRIGGERING_EVENT_MCC_CHANGED,
-            TRIGGERING_EVENT_LOCATION_SETTINGS_ENABLED
+            TRIGGERING_EVENT_LOCATION_SETTINGS_ENABLED,
+            TRIGGERING_EVENT_LOCATION_SETTINGS_DISABLED,
+            TRIGGERING_EVENT_CONFIG_DATA_UPDATED
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface TriggeringEvent {}
+
+    public static final int SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN = 0;
+    public static final int SATELLITE_ENTITLEMENT_SERVICE_POLICY_RESTRICTED = 1;
+    public static final int SATELLITE_ENTITLEMENT_SERVICE_POLICY_CONSTRAINED = 2;
+    public static final int SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNCONSTRAINED = 3;
+
+    @IntDef(prefix = {"SATELLITE_ENTITLEMENT_SERVICE_POLICY_"}, value = {
+            SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN,
+            SATELLITE_ENTITLEMENT_SERVICE_POLICY_RESTRICTED,
+            SATELLITE_ENTITLEMENT_SERVICE_POLICY_CONSTRAINED,
+            SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNCONSTRAINED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SatelliteEntitlementServicePolicy {}
 }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index d455863..7689763 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -32,6 +32,7 @@
 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_CONNECTED_NOTIFICATION_THROTTLE_MILLIS_INT;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_DISPLAY_NAME_STRING;
@@ -56,6 +57,7 @@
 import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_ENTITLEMENT;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
 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;
@@ -66,6 +68,7 @@
 import static com.android.internal.telephony.configupdate.ConfigProviderAdaptor.DOMAIN_SATELLITE;
 
 import android.annotation.ArrayRes;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AlertDialog;
@@ -89,6 +92,7 @@
 import android.database.ContentObserver;
 import android.hardware.devicestate.DeviceState;
 import android.hardware.devicestate.DeviceStateManager;
+import android.location.LocationManager;
 import android.net.Uri;
 import android.net.wifi.WifiManager;
 import android.nfc.NfcAdapter;
@@ -133,13 +137,12 @@
 import android.telephony.satellite.ISatelliteDatagramCallback;
 import android.telephony.satellite.ISatelliteModemStateCallback;
 import android.telephony.satellite.ISatelliteProvisionStateCallback;
-import android.telephony.satellite.ISatelliteSupportedStateCallback;
 import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
 import android.telephony.satellite.ISelectedNbIotSatelliteSubscriptionCallback;
 import android.telephony.satellite.NtnSignalStrength;
 import android.telephony.satellite.SatelliteAccessConfiguration;
 import android.telephony.satellite.SatelliteCapabilities;
-import android.telephony.satellite.SatelliteCommunicationAllowedStateCallback;
+import android.telephony.satellite.SatelliteCommunicationAccessStateCallback;
 import android.telephony.satellite.SatelliteDatagram;
 import android.telephony.satellite.SatelliteManager;
 import android.telephony.satellite.SatelliteModemEnableRequestAttributes;
@@ -160,6 +163,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.DeviceStateMonitor;
+import com.android.internal.telephony.IBooleanConsumer;
 import com.android.internal.telephony.IIntegerConsumer;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
@@ -168,6 +172,7 @@
 import com.android.internal.telephony.configupdate.ConfigProviderAdaptor;
 import com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver;
 import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteControllerStats;
 import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteSessionStats;
 import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
@@ -177,8 +182,11 @@
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.internal.telephony.util.ArrayUtils;
 import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.internal.telephony.util.WorkerThread;
 import com.android.internal.util.FunctionalUtils;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -234,6 +242,8 @@
     @VisibleForTesting(visibility =  VisibleForTesting.Visibility.PRIVATE)
     public static final String NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY =
             "ntn_sms_supported_by_messages_app_key";
+    public static final String CARRIER_ROAMING_NTN_ALL_SATELLITE_PLMN_SET_KEY =
+            "carrier_roaming_ntn_all_satellite_plmn_set_key";
 
     public static final long DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS =
             TimeUnit.SECONDS.toMillis(30);
@@ -308,6 +318,11 @@
     private static final int EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE = 59;
     private static final int EVENT_SELECTED_NB_IOT_SATELLITE_SUBSCRIPTION_CHANGED = 60;
     private static final int CMD_EVALUATE_CARRIER_ROAMING_NTN_ELIGIBILITY_CHANGE = 61;
+    private static final int CMD_LOCATION_SERVICE_STATE_CHANGED = 62;
+    protected static final int
+        EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT = 63;
+    private static final int CMD_GET_SATELLITE_ENABLED_FOR_CARRIER = 64;
+    private static final int EVENT_GET_SATELLITE_ENABLED_FOR_CARRIER_DONE = 65;
 
     @NonNull private static SatelliteController sInstance;
     @NonNull private final Context mContext;
@@ -332,7 +347,7 @@
     @GuardedBy("mSatellitePhoneLock")
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected Phone mSatellitePhone = null;
-
+    private SatelliteOptimizedApplicationsTracker mSatelliteOptimizedApplicationsTracker;
     private final Object mRadioStateLock = new Object();
 
     /** Flags to indicate whether the respective radio is enabled */
@@ -350,6 +365,7 @@
     private boolean mDisableNFCOnSatelliteEnabled = false;
     private boolean mDisableUWBOnSatelliteEnabled = false;
     private boolean mDisableWifiOnSatelliteEnabled = false;
+    private AtomicBoolean mIgnorePlmnListFromStorage = new AtomicBoolean(false);
 
     private final Object mSatelliteEnabledRequestLock = new Object();
     /* This variable is used to store the first enable request that framework has received in the
@@ -393,7 +409,7 @@
             new AtomicBoolean(false);
     private final AtomicBoolean mRegisteredForTerrestrialNetworkAvailableChanged =
             new AtomicBoolean(false);
-    private final AtomicBoolean mRegisteredForSatelliteCommunicationAllowedStateChanged =
+    private final AtomicBoolean mRegisteredForSatelliteCommunicationAccessStateChanged =
         new AtomicBoolean(false);
     /**
      * Map key: subId, value: callback to get error code of the provision request.
@@ -421,7 +437,7 @@
     /**
      * Map key: binder of the callback, value: callback to receive supported state changed events.
      */
-    private final ConcurrentHashMap<IBinder, ISatelliteSupportedStateCallback>
+    private final ConcurrentHashMap<IBinder, IBooleanConsumer>
             mSatelliteSupportedStateChangedListeners = new ConcurrentHashMap<>();
 
     /**
@@ -479,7 +495,7 @@
      */
     @GuardedBy("mSupportedSatelliteServicesLock")
     @NonNull private final Map<Integer, Map<String, Set<Integer>>>
-            mSatelliteServicesSupportedByCarriers = new HashMap<>();
+            mSatelliteServicesSupportedByCarriersFromConfig = new HashMap<>();
     @NonNull private final Object mSupportedSatelliteServicesLock = new Object();
     @NonNull private final List<String> mSatellitePlmnListFromOverlayConfig;
     @NonNull private final CarrierConfigManager mCarrierConfigManager;
@@ -597,6 +613,7 @@
     SparseArray<Map<String, Integer>> mEntitlementVoiceServicePolicyMapPerCarrier =
             new SparseArray<>();
     private static AtomicLong sNextSatelliteEnableRequestId = new AtomicLong(0);
+    private static AtomicLong sNextSystemSelectionChannelsUpdateRequestId = new AtomicLong(0);
     // key : subscriberId, value : provisioned or not.
     @GuardedBy("mSatelliteTokenProvisionedLock")
     private Map<String, Boolean> mProvisionedSubscriberId = new HashMap<>();
@@ -614,7 +631,6 @@
     private List<SatelliteSubscriberProvisionStatus> mLastEvaluatedSubscriberProvisionStatus =
             new ArrayList<>();
     // The ID of the satellite subscription that has highest priority and is provisioned.
-    @GuardedBy("mSatelliteTokenProvisionedLock")
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected int mSelectedSatelliteSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     // The last ICC ID that framework configured to modem.
@@ -636,6 +652,8 @@
     /** Key used to read/write satellite system notification done in shared preferences. */
     private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY =
             "satellite_system_notification_done_key";
+    private static final String SATELLITE_SYSTEM_NOTIFICATION_TIME =
+            "satellite_system_notification_time";
     // The notification tag used when showing a notification. The combination of notification tag
     // and notification id should be unique within the phone app.
     private static final String NOTIFICATION_TAG = "SatelliteController";
@@ -644,8 +662,10 @@
     private static final String NOTIFICATION_CHANNEL_ID = "satellite";
 
     private final RegistrantList mSatelliteConfigUpdateChangedRegistrants = new RegistrantList();
+    private final RegistrantList mSatelliteSubIdChangedRegistrants = new RegistrantList();
     private final BTWifiNFCStateReceiver mBTWifiNFCSateReceiver;
     private final UwbAdapterStateCallback mUwbAdapterStateCallback;
+    private final List<Integer> mCtsSatelliteAccessAllowedSubIds = new ArrayList<>();
 
     private long mSessionStartTimeStamp;
     private long mSessionProcessingTimeStamp;
@@ -673,11 +693,16 @@
     private AtomicBoolean mOverrideNtnEligibility;
     private String mDefaultSmsPackageName = "";
     private String mSatelliteGatewayServicePackageName = "";
+    private Boolean mOverriddenDisableSatelliteWhileEnableInProgressSupported = null;
 
     private final Object mNtnSmsSupportedByMessagesAppLock = new Object();
     @GuardedBy("mNtnSmsSupportedByMessagesAppLock")
     private Boolean mNtnSmsSupportedByMessagesApp = null;
 
+    private final Object mCarrierRoamingNtnAllSatellitePlmnSetLock = new Object();
+    @GuardedBy("mCarrierRoamingNtnAllSatellitePlmnSetLock")
+    private Set<String> mCarrierRoamingNtnAllSatellitePlmnSet = null;
+
     private final Object mSatelliteModemStateLock = new Object();
     @GuardedBy("mSatelliteModemStateLock")
     @SatelliteManager.SatelliteModemState
@@ -686,6 +711,12 @@
     // Data Plan types at entitlement for the plmn allowed
     public static final int SATELLITE_DATA_PLAN_METERED = 0;
     public static final int SATELLITE_DATA_PLAN_UNMETERED = 1;
+    @IntDef(prefix = {"SATELLITE_DATA_PLAN_"}, value = {
+            SATELLITE_DATA_PLAN_METERED,
+            SATELLITE_DATA_PLAN_UNMETERED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SatelliteDataPlan {}
     private BroadcastReceiver
             mDefaultSmsSubscriptionChangedBroadcastReceiver = new BroadcastReceiver() {
                 @Override
@@ -724,6 +755,17 @@
         }
     };
 
+    protected BroadcastReceiver mLocationServiceStateChangedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // Check whether user has turned on/off location manager from settings menu
+            if (intent.getAction().equals(LocationManager.MODE_CHANGED_ACTION)) {
+                plogd("mLocationServiceStateChangedReceiver");
+                sendRequestAsync(CMD_LOCATION_SERVICE_STATE_CHANGED, null, null);
+            }
+        }
+    };
+
     // List of device states returned from DeviceStateManager to determine if running on a foldable
     // device.
     private List<DeviceState> mDeviceStates = new ArrayList();
@@ -828,9 +870,15 @@
      */
     public static void make(@NonNull Context context, @NonNull FeatureFlags featureFlags) {
         if (sInstance == null) {
-            HandlerThread satelliteThread = new HandlerThread(TAG);
-            satelliteThread.start();
-            sInstance = new SatelliteController(context, satelliteThread.getLooper(), featureFlags);
+            if (featureFlags.threadShred()) {
+                sInstance = new SatelliteController(
+                        context, WorkerThread.get().getLooper(), featureFlags);
+            } else {
+                HandlerThread satelliteThread = new HandlerThread(TAG);
+                satelliteThread.start();
+                sInstance = new SatelliteController(
+                        context, satelliteThread.getLooper(), featureFlags);
+            }
         }
     }
 
@@ -847,11 +895,7 @@
             @NonNull Context context, @NonNull Looper looper, @NonNull FeatureFlags featureFlags) {
         super(looper);
 
-        if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
-            mPersistentLogger = new PersistentLogger(
-                    DropBoxManagerLoggerBackend.getInstance(context));
-        }
-
+        mPersistentLogger = SatelliteServiceUtils.getPersistentLogger(context);
         mContext = context;
         mFeatureFlags = featureFlags;
         Phone phone = SatelliteServiceUtils.getPhone();
@@ -896,7 +940,7 @@
         registerForSatelliteModemStateChanged();
         registerForServiceStateChanged();
         registerForSignalStrengthChanged();
-        registerForSatelliteCommunicationAllowedStateChanged();
+        registerForSatelliteCommunicationAccessStateChanged();
         mContentResolver = mContext.getContentResolver();
         mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
 
@@ -918,6 +962,7 @@
 
         mSatellitePlmnListFromOverlayConfig = readSatellitePlmnsFromOverlayConfig();
         registerApplicationStateChanged();
+        registerLocationServiceStateChanged();
         updateSupportedSatelliteServicesForActiveSubscriptions();
         mCarrierConfigChangeListener =
                 (slotIndex, subId, carrierId, specificCarrierId) ->
@@ -944,9 +989,19 @@
 
         loadSatelliteSharedPreferences();
         if (mSharedPreferences != null) {
-            synchronized (mNtnSmsSupportedByMessagesAppLock) {
-                mNtnSmsSupportedByMessagesApp = mSharedPreferences.getBoolean(
-                        NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY, false);
+            try {
+                synchronized (mNtnSmsSupportedByMessagesAppLock) {
+                    mNtnSmsSupportedByMessagesApp = mSharedPreferences.getBoolean(
+                            NTN_SMS_SUPPORTED_BY_MESSAGES_APP_KEY, false);
+                }
+
+                synchronized (mCarrierRoamingNtnAllSatellitePlmnSetLock) {
+                    mCarrierRoamingNtnAllSatellitePlmnSet = mSharedPreferences.getStringSet(
+                            CARRIER_ROAMING_NTN_ALL_SATELLITE_PLMN_SET_KEY, new HashSet<>());
+                }
+            } catch (Exception ex) {
+                plogd("SatelliteController constructor: "
+                        + "cannot get default shared preferences. e" + ex);
             }
         }
 
@@ -973,6 +1028,16 @@
         if (android.hardware.devicestate.feature.flags.Flags.deviceStatePropertyMigration()) {
             mDeviceStates = getSupportedDeviceStates();
         }
+
+        mSatelliteOptimizedApplicationsTracker = new SatelliteOptimizedApplicationsTracker(
+                getLooper(), mContext
+        );
+
+        for (Phone phoneToSendRequest : PhoneFactory.getPhones()) {
+            sendRequestAsync(CMD_GET_SATELLITE_ENABLED_FOR_CARRIER, null, phoneToSendRequest);
+        }
+
+        logd("Satellite Tracker is created");
     }
 
     class SatelliteSubscriptionsChangedListener
@@ -1007,6 +1072,24 @@
     }
 
     /**
+     * Register a callback to change the satelliteSubId.
+     * @param h Handler to notify
+     * @param what msg.what when the message is delivered
+     * @param obj AsyncResult.userObj when the message is delivered
+     */
+    public void registerForSatelliteSubIdChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        mSatelliteSubIdChangedRegistrants.add(r);
+    }
+
+    /**
+     * Unregister a callback to get a updated satellite config data.
+     * @param h Handler to notify
+     */
+    public void unregisterForSatelliteSubIdChanged(Handler h) {
+        mSatelliteSubIdChangedRegistrants.remove(h);
+    }
+    /**
      * Get satelliteConfig from SatelliteConfigParser
      */
     public SatelliteConfig getSatelliteConfig() {
@@ -1019,6 +1102,15 @@
     }
 
     /**
+     * This API should be used by only CTS/unit tests to reset the telephony configs set through
+     * config updater
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public void cleanUpTelephonyConfigs() {
+        TelephonyConfigUpdateInstallReceiver.getInstance().cleanUpTelephonyConfigs();
+    }
+
+    /**
      * Get SatelliteConfigParser from TelephonyConfigUpdateInstallReceiver
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@@ -1216,7 +1308,8 @@
         }
     }
 
-    private static final class SatelliteControllerHandlerRequest {
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public static final class SatelliteControllerHandlerRequest {
         /** The argument to use for the request */
         public @NonNull Object argument;
         /** The caller needs to specify the phone to be used for the request */
@@ -1224,7 +1317,7 @@
         /** The result of the request that is run on the main thread */
         public @Nullable Object result;
 
-        SatelliteControllerHandlerRequest(Object argument, Phone phone) {
+        public SatelliteControllerHandlerRequest(Object argument, Phone phone) {
             this.argument = argument;
             this.phone = phone;
         }
@@ -1279,14 +1372,17 @@
     }
 
     private static final class UpdateSystemSelectionChannelsArgument {
-        @NonNull List<SystemSelectionSpecifier> mSystemSelectionSpecifiers;
-        @NonNull ResultReceiver mResult;
+        public @NonNull List<SystemSelectionSpecifier> systemSelectionSpecifiers;
+        public @NonNull ResultReceiver result;
+        public long requestId;
 
         UpdateSystemSelectionChannelsArgument(
                 @NonNull List<SystemSelectionSpecifier> systemSelectionSpecifiers,
                 @NonNull ResultReceiver result) {
-            this.mSystemSelectionSpecifiers = systemSelectionSpecifiers;
-            this.mResult = result;
+            this.systemSelectionSpecifiers = systemSelectionSpecifiers;
+            this.result = result;
+            this.requestId = sNextSystemSelectionChannelsUpdateRequestId.getAndUpdate(
+                    n -> ((n + 1) % Long.MAX_VALUE));
         }
     }
 
@@ -1474,7 +1570,7 @@
                     mSessionMetricsStats.setInitializationResult(error)
                             .setSatelliteTechnology(getSupportedNtnRadioTechnology())
                             .setInitializationProcessingTime(
-                                    System.currentTimeMillis() - mSessionProcessingTimeStamp)
+                                    getElapsedRealtime() - mSessionProcessingTimeStamp)
                             .setIsDemoMode(mIsDemoModeEnabled)
                             .setCarrierId(getSatelliteCarrierId())
                             .setIsEmergency(argument.isEmergency);
@@ -1490,7 +1586,7 @@
                     }
                 } else {
                     mSessionMetricsStats.setTerminationResult(error)
-                            .setTerminationProcessingTime(System.currentTimeMillis()
+                            .setTerminationProcessingTime(getElapsedRealtime()
                                     - mSessionProcessingTimeStamp)
                             .setSessionDurationSec(calculateSessionDurationTimeSec())
                             .reportSessionMetrics();
@@ -1825,10 +1921,14 @@
                 int error =  SatelliteServiceUtils.getSatelliteError(ar,
                         "requestSetSatelliteEnabledForCarrier");
 
+                plogd("EVENT_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE_DONE: subId="
+                        + subId + " error:" + error);
                 synchronized (mIsSatelliteEnabledLock) {
                     if (error == SATELLITE_RESULT_SUCCESS) {
                         boolean enableSatellite = mSatelliteAttachRestrictionForCarrierArray
                                 .getOrDefault(argument.subId, Collections.emptySet()).isEmpty();
+                        plogd("EVENT_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE_DONE: "
+                                + "satelliteAttachEnabledForCarrier=" + enableSatellite);
                         mIsSatelliteAttachEnabledForCarrierArrayPerSub.put(subId, enableSatellite);
                     } else {
                         mIsSatelliteAttachEnabledForCarrierArrayPerSub.remove(subId);
@@ -2070,7 +2170,8 @@
                     int defaultSubId = mSubscriptionManagerService.getDefaultSubId();
                     boolean isEntitled = mSatelliteEntitlementStatusPerCarrier.get(defaultSubId,
                             false);
-                    mCarrierRoamingSatelliteControllerStats.reportIsDeviceEntitled(isEntitled);
+                    mCarrierRoamingSatelliteControllerStats.reportIsDeviceEntitled(defaultSubId,
+                            isEntitled);
                 }
                 sendMessageDelayed(obtainMessage(
                                 EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT),
@@ -2115,11 +2216,13 @@
             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);
+                onCompleted =
+                    obtainMessage(EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE, request);
+                UpdateSystemSelectionChannelsArgument argument =
+                        (UpdateSystemSelectionChannelsArgument) request.argument;
                 mSatelliteModemInterface.updateSystemSelectionChannels(
-                        ((UpdateSystemSelectionChannelsArgument) (request.argument))
-                                .mSystemSelectionSpecifiers,
-                        onCompleted);
+                        argument.systemSelectionSpecifiers, onCompleted);
+                startWaitForUpdateSystemSelectionChannelsResponseTimer(argument);
                 break;
             }
 
@@ -2129,8 +2232,25 @@
                 int error =  SatelliteServiceUtils.getSatelliteError(
                         ar, "updateSystemSelectionChannel");
                 plogd("EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE = " + error);
-                ((UpdateSystemSelectionChannelsArgument) (request.argument)).mResult.send(error,
-                        null);
+                UpdateSystemSelectionChannelsArgument argument =
+                        (UpdateSystemSelectionChannelsArgument) request.argument;
+                if (shouldProcessEventUpdateSystemSelectionChannelsDone(argument)) {
+                    argument.result.send(error, null);
+                    stopWaitForUpdateSystemSelectionChannelsResponseTimer(argument);
+                } else {
+                    plogd("EVENT_UPDATE_SYSTEM_SELECTION_CHANNELS_DONE: the timer of "
+                              + "the request ID " + argument.requestId
+                              + " has already expired.");
+                }
+                break;
+            }
+
+            case EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT: {
+                UpdateSystemSelectionChannelsArgument argument =
+                        (UpdateSystemSelectionChannelsArgument) msg.obj;
+                argument.result.send(SATELLITE_RESULT_MODEM_TIMEOUT, null);
+                plogd("Timed out to wait for response of the system selection channels"
+                          + " update request ID " + argument.requestId);
                 break;
             }
 
@@ -2144,6 +2264,9 @@
                 break;
             }
 
+            case CMD_LOCATION_SERVICE_STATE_CHANGED:
+                plogd("CMD_LOCATION_SERVICE_STATE_CHANGED");
+                // Fall through
             case CMD_EVALUATE_CARRIER_ROAMING_NTN_ELIGIBILITY_CHANGE: {
                 plogd("CMD_EVALUATE_CARRIER_ROAMING_NTN_ELIGIBILITY_CHANGE");
                 evaluateCarrierRoamingNtnEligibilityChange();
@@ -2152,11 +2275,51 @@
                 int selectedSatelliteSubId = getSelectedSatelliteSubId();
                 Phone phone = SatelliteServiceUtils.getPhone(selectedSatelliteSubId);
                 if (eligible) {
+                    synchronized (mSatellitePhoneLock) {
+                        mLastNotifiedNtnEligibility = eligible;
+                    }
                     phone.notifyCarrierRoamingNtnEligibleStateChanged(eligible);
                 }
                 break;
             }
 
+            case CMD_GET_SATELLITE_ENABLED_FOR_CARRIER: {
+                request = (SatelliteControllerHandlerRequest) msg.obj;
+                Phone phone = request.phone;
+                int subId = phone.getSubId();
+                onCompleted = obtainMessage(EVENT_GET_SATELLITE_ENABLED_FOR_CARRIER_DONE,
+                        subId);
+                int simSlot = SubscriptionManager.getSlotIndex(subId);
+                plogd("CMD_GET_SATELLITE_ENABLED_FOR_CARRIER: subId=" + subId);
+                phone.isSatelliteEnabledForCarrier(simSlot, onCompleted);
+                break;
+            }
+
+            case EVENT_GET_SATELLITE_ENABLED_FOR_CARRIER_DONE: {
+                ar = (AsyncResult) msg.obj;
+
+                if (ar.result == null) {
+                    loge("EVENT_GET_SATELLITE_ENABLED_FOR_CARRIER_DONE: result is null");
+                } else {
+                    int subId = (int) ar.userObj;
+                    int error = SatelliteServiceUtils.getSatelliteError(
+                            ar, "isSatelliteEnabledForCarrier");
+                    boolean satelliteEnabled = (Boolean) ar.result;
+                    plogd("EVENT_GET_SATELLITE_ENABLED_FOR_CARRIER_DONE: subId=" + subId
+                            + " error=" + error + " satelliteEnabled=" + satelliteEnabled);
+
+                    if (error == SATELLITE_RESULT_SUCCESS) {
+                        synchronized (mIsSatelliteEnabledLock) {
+                            mIsSatelliteAttachEnabledForCarrierArrayPerSub.put(
+                                    subId, satelliteEnabled);
+                        }
+                        evaluateEnablingSatelliteForCarrier(subId,
+                                SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, null);
+                    }
+                }
+                break;
+            }
+
             default:
                 Log.w(TAG, "SatelliteControllerHandler: unexpected message code: " +
                         msg.what);
@@ -2343,6 +2506,13 @@
                                 SatelliteManager.SATELLITE_RESULT_ENABLE_IN_PROGRESS, result);
                         return;
                     }
+                    if (!isDisableSatelliteWhileEnableInProgressSupported()) {
+                        plogd("requestSatelliteEnabled: disable satellite while enable in progress"
+                                + " is not supported");
+                        sendErrorAndReportSessionMetrics(
+                                SatelliteManager.SATELLITE_RESULT_ENABLE_IN_PROGRESS, result);
+                        return;
+                    }
                     mSatelliteDisabledRequest = request;
                 }
             }
@@ -2363,6 +2533,14 @@
         }
     }
 
+    private boolean isDisableSatelliteWhileEnableInProgressSupported() {
+        if (mOverriddenDisableSatelliteWhileEnableInProgressSupported != null) {
+            return mOverriddenDisableSatelliteWhileEnableInProgressSupported;
+        }
+        return mContext.getResources().getBoolean(
+            R.bool.config_support_disable_satellite_while_enable_in_progress);
+    }
+
     private void checkNetworkSelectionModeAuto(RequestSatelliteEnabledArgument argument) {
         plogd("checkNetworkSelectionModeAuto");
         if (argument.isEmergency) {
@@ -2531,11 +2709,7 @@
      *
      * @return {@code true} if the satellite modem is enabled and {@code false} otherwise.
      */
-    private boolean isSatelliteEnabled() {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("isSatelliteEnabled: oemEnabledSatelliteFlag is disabled");
-            return false;
-        }
+    public boolean isSatelliteEnabled() {
         synchronized (mIsSatelliteEnabledLock) {
             if (mIsSatelliteEnabled == null) return false;
             return mIsSatelliteEnabled;
@@ -2547,12 +2721,7 @@
      *
      * @return {@code true} if the satellite modem is being enabled and {@code false} otherwise.
      */
-    private boolean isSatelliteBeingEnabled() {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("isSatelliteBeingEnabled: oemEnabledSatelliteFlag is disabled");
-            return false;
-        }
-
+    public boolean isSatelliteBeingEnabled() {
         if (mSatelliteSessionController != null
                 && mSatelliteSessionController.isInEnablingState()) {
             return true;
@@ -2614,10 +2783,6 @@
      * @return {@code true} if the satellite demo mode is enabled and {@code false} otherwise.
      */
     public boolean isDemoModeEnabled() {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("isDemoModeEnabled: oemEnabledSatelliteFlag is disabled");
-            return false;
-        }
         return mIsDemoModeEnabled;
     }
 
@@ -2628,12 +2793,6 @@
      *               if the request is successful or an error code if the request failed.
      */
     public void requestIsEmergencyModeEnabled(@NonNull ResultReceiver result) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("requestIsEmergencyModeEnabled: oemEnabledSatelliteFlag is disabled");
-            result.send(SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED, null);
-            return;
-        }
-
         synchronized (mSatelliteEnabledRequestLock) {
             Bundle bundle = new Bundle();
             bundle.putBoolean(SatelliteManager.KEY_EMERGENCY_MODE_ENABLED,
@@ -2649,12 +2808,6 @@
      *               the device if the request is successful or an error code if the request failed.
      */
     public void requestIsSatelliteSupported(@NonNull ResultReceiver result) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("requestIsSatelliteSupported: oemEnabledSatelliteFlag is disabled");
-            result.send(SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED, null);
-            return;
-        }
-
         int subId = getSelectedSatelliteSubId();
         Boolean isSatelliteSupported = getIsSatelliteSupported();
         if (isSatelliteSupported != null) {
@@ -2891,11 +3044,6 @@
      */
     public void unregisterForSatelliteProvisionStateChanged(
             @NonNull ISatelliteProvisionStateCallback callback) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("unregisterForSatelliteProvisionStateChanged: "
-                    + "oemEnabledSatelliteFlag is disabled");
-            return;
-        }
         mSatelliteProvisionStateChangedListeners.remove(callback.asBinder());
     }
 
@@ -2936,10 +3084,6 @@
      */
     @SatelliteManager.SatelliteResult public int registerForSatelliteModemStateChanged(
             @NonNull ISatelliteModemStateCallback callback) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("registerForSatelliteModemStateChanged: oemEnabledSatelliteFlag is disabled");
-            return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
-        }
         if (mFeatureFlags.carrierRoamingNbIotNtn()) {
             plogd("registerForSatelliteModemStateChanged: add Listeners for ModemState");
             mSatelliteRegistrationFailureListeners.put(callback.asBinder(), callback);
@@ -2964,10 +3108,6 @@
      */
     public void unregisterForModemStateChanged(
             @NonNull ISatelliteModemStateCallback callback) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("unregisterForModemStateChanged: oemEnabledSatelliteFlag is disabled");
-            return;
-        }
         if (mSatelliteSessionController != null) {
             mSatelliteSessionController.unregisterForSatelliteModemStateChanged(callback);
         } else {
@@ -2990,10 +3130,6 @@
      */
     @SatelliteManager.SatelliteResult public int registerForIncomingDatagram(
             @NonNull ISatelliteDatagramCallback callback) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("registerForIncomingDatagram: oemEnabledSatelliteFlag is disabled");
-            return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
-        }
         if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
             return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
         }
@@ -3011,10 +3147,6 @@
      */
     public void unregisterForIncomingDatagram(
             @NonNull ISatelliteDatagramCallback callback) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("unregisterForIncomingDatagram: oemEnabledSatelliteFlag is disabled");
-            return;
-        }
         if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
             return;
         }
@@ -3109,11 +3241,6 @@
      * @param isAligned {@true} means device is aligned with the satellite, otherwise {@false}.
      */
     public void setDeviceAlignedWithSatellite(@NonNull boolean isAligned) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("setDeviceAlignedWithSatellite: oemEnabledSatelliteFlag is disabled");
-            return;
-        }
-
         DemoSimulator.getInstance().setDeviceAlignedWithSatellite(isAligned);
         mDatagramController.setDeviceAlignedWithSatellite(isAligned);
         if (mSatelliteSessionController != null) {
@@ -3137,14 +3264,8 @@
     public void addAttachRestrictionForCarrier(int subId,
             @SatelliteManager.SatelliteCommunicationRestrictionReason int reason,
             @NonNull IIntegerConsumer callback) {
-        if (DBG) logd("addAttachRestrictionForCarrier(" + subId + ", " + reason + ")");
+        logd("addAttachRestrictionForCarrier(" + subId + ", " + reason + ")");
         Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            result.accept(SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
-            logd("addAttachRestrictionForCarrier: carrierEnabledSatelliteFlag is "
-                    + "disabled");
-            return;
-        }
 
         synchronized (mIsSatelliteEnabledLock) {
             if (mSatelliteAttachRestrictionForCarrierArray.getOrDefault(
@@ -3176,14 +3297,8 @@
     public void removeAttachRestrictionForCarrier(int subId,
             @SatelliteManager.SatelliteCommunicationRestrictionReason int reason,
             @NonNull IIntegerConsumer callback) {
-        if (DBG) logd("removeAttachRestrictionForCarrier(" + subId + ", " + reason + ")");
+        logd("removeAttachRestrictionForCarrier(" + subId + ", " + reason + ")");
         Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            result.accept(SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
-            logd("removeAttachRestrictionForCarrier: carrierEnabledSatelliteFlag is "
-                    + "disabled");
-            return;
-        }
 
         synchronized (mIsSatelliteEnabledLock) {
             if (mSatelliteAttachRestrictionForCarrierArray.getOrDefault(
@@ -3210,11 +3325,6 @@
      * @return Set of reasons for disallowing satellite attach for carrier.
      */
     @NonNull public Set<Integer> getAttachRestrictionReasonsForCarrier(int subId) {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            logd("getAttachRestrictionReasonsForCarrier: carrierEnabledSatelliteFlag is "
-                    + "disabled");
-            return new HashSet<>();
-        }
         synchronized (mIsSatelliteEnabledLock) {
             Set<Integer> resultSet =
                     mSatelliteAttachRestrictionForCarrierArray.get(subId);
@@ -3344,12 +3454,7 @@
      * @return The {@link SatelliteManager.SatelliteResult} result of the operation.
      */
     @SatelliteManager.SatelliteResult public int registerForSatelliteSupportedStateChanged(
-            @NonNull ISatelliteSupportedStateCallback callback) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("registerForSatelliteSupportedStateChanged: oemEnabledSatelliteFlag is disabled");
-            return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
-        }
-
+            @NonNull IBooleanConsumer callback) {
         mSatelliteSupportedStateChangedListeners.put(callback.asBinder(), callback);
         return SATELLITE_RESULT_SUCCESS;
     }
@@ -3359,15 +3464,10 @@
      * If callback was not registered before, the request will be ignored.
      *
      * @param callback The callback that was passed to
-     * {@link #registerForSatelliteSupportedStateChanged(int, ISatelliteSupportedStateCallback)}.
+     *                 {@link #registerForSatelliteSupportedStateChanged(IBooleanConsumer)}
      */
     public void unregisterForSatelliteSupportedStateChanged(
-            @NonNull ISatelliteSupportedStateCallback callback) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("unregisterForSatelliteSupportedStateChanged: "
-                    + "oemEnabledSatelliteFlag is disabled");
-            return;
-        }
+            @NonNull IBooleanConsumer callback) {
         mSatelliteSupportedStateChangedListeners.remove(callback.asBinder());
     }
 
@@ -3445,12 +3545,6 @@
         synchronized (mIsSatelliteSupportedLock) {
             mIsSatelliteSupported = null;
         }
-        synchronized (mDeviceProvisionLock) {
-            mIsDeviceProvisioned = Optional.ofNullable(provisioned)
-                    .filter(s -> s.equalsIgnoreCase("true") || s.equalsIgnoreCase("false"))
-                    .map(s -> s.equalsIgnoreCase("true"))
-                    .orElse(null);
-        }
         synchronized (mIsSatelliteEnabledLock) {
             mIsSatelliteEnabled = null;
         }
@@ -3470,10 +3564,6 @@
      * @return {@code true} if the timeout duration is set successfully, {@code false} otherwise.
      */
     public boolean setSatelliteListeningTimeoutDuration(long timeoutMillis) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("setSatelliteListeningTimeoutDuration: oemEnabledSatelliteFlag is disabled");
-            return false;
-        }
         if (mSatelliteSessionController == null) {
             ploge("mSatelliteSessionController is not initialized yet");
             return false;
@@ -3482,6 +3572,25 @@
     }
 
     /**
+     * This API can be used by only CTS to override TN scanning support.
+     *
+     * @param concurrentTnScanningSupported Whether concurrent TN scanning is supported.
+     * @param tnScanningDuringSatelliteSessionAllowed Whether TN scanning is allowed during
+     * a satellite session.
+     * @return {@code true} if the TN scanning support is set successfully,
+     * {@code false} otherwise.
+     */
+    public boolean setTnScanningSupport(boolean reset, boolean concurrentTnScanningSupported,
+        boolean tnScanningDuringSatelliteSessionAllowed) {
+        if (mSatelliteSessionController == null) {
+            ploge("setTnScanningSupport: mSatelliteSessionController is not initialized yet");
+            return false;
+        }
+        return mSatelliteSessionController.setTnScanningSupport(reset,
+                concurrentTnScanningSupported, tnScanningDuringSatelliteSessionAllowed);
+    }
+
+    /**
      * This API can be used by only CTS to control ingoring cellular service state event.
      *
      * @param enabled Whether to enable boolean config.
@@ -3497,6 +3606,31 @@
     }
 
     /**
+     * This API can be used by only CTS to control the feature
+     * {@code config_support_disable_satellite_while_enable_in_progress}.
+     *
+     * @param reset Whether to reset the override.
+     * @param supported Whether to support the feature.
+     * @return {@code true} if the value is set successfully, {@code false} otherwise.
+     */
+    public boolean setSupportDisableSatelliteWhileEnableInProgress(
+        boolean reset, boolean supported) {
+        if (!isMockModemAllowed()) {
+            plogd("setSupportDisableSatelliteWhileEnableInProgress: mock modem not allowed");
+            return false;
+        }
+
+        plogd("setSupportDisableSatelliteWhileEnableInProgress - reset=" + reset
+                  + ", supported=" + supported);
+        if (reset) {
+            mOverriddenDisableSatelliteWhileEnableInProgressSupported = null;
+        } else {
+            mOverriddenDisableSatelliteWhileEnableInProgressSupported = supported;
+        }
+        return true;
+    }
+
+    /**
      * This API can be used by only CTS to override timeout durations used by DatagramController
      * module.
      *
@@ -3505,10 +3639,6 @@
      */
     public boolean setDatagramControllerTimeoutDuration(
             boolean reset, int timeoutType, long timeoutMillis) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("setDatagramControllerTimeoutDuration: oemEnabledSatelliteFlag is disabled");
-            return false;
-        }
         plogd("setDatagramControllerTimeoutDuration: reset=" + reset + ", timeoutType="
                 + timeoutType + ", timeoutMillis=" + timeoutMillis);
         return mDatagramController.setDatagramControllerTimeoutDuration(
@@ -3524,10 +3654,6 @@
      */
     public boolean setDatagramControllerBooleanConfig(
             boolean reset, int booleanType, boolean enable) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("setDatagramControllerBooleanConfig: oemEnabledSatelliteFlag is disabled");
-            return false;
-        }
         logd("setDatagramControllerBooleanConfig: reset=" + reset + ", booleanType="
                 + booleanType + ", enable=" + enable);
         return mDatagramController.setDatagramControllerBooleanConfig(
@@ -3543,10 +3669,6 @@
      */
     public boolean setSatelliteControllerTimeoutDuration(
             boolean reset, int timeoutType, long timeoutMillis) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("setSatelliteControllerTimeoutDuration: oemEnabledSatelliteFlag is disabled");
-            return false;
-        }
         if (!isMockModemAllowed()) {
             plogd("setSatelliteControllerTimeoutDuration: mock modem is not allowed");
             return false;
@@ -3598,10 +3720,6 @@
      * {@code false} otherwise.
      */
     public boolean setSatelliteGatewayServicePackageName(@Nullable String servicePackageName) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("setSatelliteGatewayServicePackageName: oemEnabledSatelliteFlag is disabled");
-            return false;
-        }
         if (mSatelliteSessionController == null) {
             ploge("mSatelliteSessionController is not initialized yet");
             return false;
@@ -3620,10 +3738,6 @@
      */
     public boolean setSatellitePointingUiClassName(
             @Nullable String packageName, @Nullable String className) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("setSatellitePointingUiClassName: oemEnabledSatelliteFlag is disabled");
-            return false;
-        }
         return mPointingAppController.setSatellitePointingUiClassName(packageName, className);
     }
 
@@ -3710,11 +3824,6 @@
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     public void onSatelliteServiceConnected() {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("onSatelliteServiceConnected: oemEnabledSatelliteFlag is disabled");
-            return;
-        }
-
         if (mSatelliteModemInterface.isSatelliteServiceSupported()) {
             plogd("onSatelliteServiceConnected");
             // Vendor service might have just come back from a crash
@@ -3747,10 +3856,6 @@
      */
     public void onSetCellularRadioPowerStateRequested(boolean powerOn) {
         logd("onSetCellularRadioPowerStateRequested: powerOn=" + powerOn);
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("onSetCellularRadioPowerStateRequested: oemEnabledSatelliteFlag is disabled");
-            return;
-        }
 
         synchronized (mIsRadioOnLock) {
             mRadioOffRequested = !powerOn;
@@ -3813,6 +3918,9 @@
         } else {
             logd("onSmsReceived: DatagramController is not initialized");
         }
+
+        mControllerMetricsStats.reportIncomingNtnSmsCount(
+                SatelliteManager.SATELLITE_RESULT_SUCCESS);
     }
 
     /**
@@ -3820,10 +3928,6 @@
      * {@code  false} otherwise.
      */
     public boolean isSatelliteSupportedViaOem() {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("isSatelliteSupported: oemEnabledSatelliteFlag is disabled");
-            return false;
-        }
         Boolean supported = isSatelliteSupportedViaOemInternal();
         return (supported != null ? supported : false);
     }
@@ -3834,72 +3938,142 @@
      */
     @NonNull
     public List<String> getSatellitePlmnsForCarrier(int subId) {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            logd("getSatellitePlmnsForCarrier: carrierEnabledSatelliteFlag is disabled");
-            return new ArrayList<>();
-        }
-
         if (!isSatelliteSupportedViaCarrier(subId)) {
             logd("Satellite for carrier is not supported.");
             return new ArrayList<>();
         }
 
-        synchronized (mSupportedSatelliteServicesLock) {
-            return mMergedPlmnListPerCarrier.get(subId, new ArrayList<>()).stream().toList();
+        return getCarrierPlmnList(subId);
+    }
+
+    /**
+     *  checks if data service is allowed, to add part of list of services supported by satellite
+     *  plmn, when data supported mode
+     *  {@link CarrierConfigManager#KEY_SATELLITE_DATA_SUPPORT_MODE_INT} is restricted mode and no
+     *  data service is included at allowed service info at the entitlement and when allowed service
+     *  info field is present at the entitlement.
+     *
+     * @param subId subscription id
+     * @param plmn  The satellite plmn
+     * @param allowedServiceValues allowed services info supported by entitlement
+     * @return {@code true} is supports data service else {@code false}
+     */
+    private boolean isDataServiceUpdateRequired(int subId, String plmn,
+            List<Integer> allowedServiceValues) {
+        if (!allowedServiceValues.contains(NetworkRegistrationInfo.SERVICE_TYPE_DATA)
+                && getCarrierSatelliteDataSupportedModeFromConfig(subId)
+                == CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED) {
+            return getSatelliteSupportedServicesFromConfig(subId, plmn)
+                    .contains(NetworkRegistrationInfo.SERVICE_TYPE_DATA);
         }
+        return false;
+    }
+
+    /**
+     *  checks if mms service is allowed, to add part of list of services supported by satellite
+     *  plmn, when no mms service is included at allowed services
+     *
+     * @param subId subscription id
+     * @param plmn  The satellite plmn
+     * @param allowedServiceValues allowed services info supported by entitlement
+     * @return {@code true} is supports data service else {@code false}
+     */
+    private boolean isMmsServiceUpdateRequired(int subId, String plmn,
+            List<Integer> allowedServiceValues) {
+        if (!allowedServiceValues.contains(NetworkRegistrationInfo.SERVICE_TYPE_MMS)) {
+            return getSatelliteSupportedServicesFromConfig(subId, plmn)
+                    .contains(NetworkRegistrationInfo.SERVICE_TYPE_MMS);
+        }
+        return false;
+    }
+
+    /**
+     * Gives the list of satellite services associated with
+     * {@link CarrierConfigManager#KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE}.
+     * Note: If this config not found, fallback to
+     * {@link CarrierConfigManager#KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY}.
+     *
+     * @param subId subsctiption id
+     * @param plmn The satellite plmn
+     * @return The list of services supported by the carrier associated with the
+     */
+    private List<Integer> getSatelliteSupportedServicesFromConfig(int subId, String plmn) {
+        if (plmn != null && !plmn.isEmpty()) {
+            synchronized (mSupportedSatelliteServicesLock) {
+                if (mSatelliteServicesSupportedByCarriersFromConfig.containsKey(subId)) {
+                    Map<String, Set<Integer>> supportedServices =
+                            mSatelliteServicesSupportedByCarriersFromConfig.get(subId);
+                    if (supportedServices != null && supportedServices.containsKey(plmn)) {
+                        return new ArrayList<>(supportedServices.get(plmn));
+                    } else {
+                        loge("getSupportedSatelliteServices: subId=" + subId
+                                + ", supportedServices "
+                                + "does not contain key plmn=" + plmn);
+                    }
+                } else {
+                    loge("getSupportedSatelliteServices: "
+                            + "mSatelliteServicesSupportedByCarriersFromConfig does not contain"
+                            + " key subId=" + subId);
+                }
+            }
+        }
+
+        /* Returns default capabilities when carrier config does not contain service capabilities
+         for the given plmn */
+        PersistableBundle config = getPersistableBundle(subId);
+        int [] defaultCapabilities = config.getIntArray(
+                KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY);
+        if (defaultCapabilities == null) {
+            logd("getSupportedSatelliteServices: defaultCapabilities is null");
+            return new ArrayList<>();
+        }
+        List<Integer> capabilitiesList = Arrays.stream(
+                defaultCapabilities).boxed().collect(Collectors.toList());
+        logd("getSupportedSatelliteServices: subId=" + subId
+                + ", supportedServices does not contain key plmn=" + plmn
+                + ", return default values " + capabilitiesList);
+        return capabilitiesList;
     }
 
     /**
      * @param subId Subscription ID.
      * @param plmn The satellite plmn.
      * @return The list of services supported by the carrier associated with the {@code subId} for
-     * the satellite network {@code plmn}.
+     * the satellite network {@code plmn}. Returns empty list at invalid sub id.
+     *
      */
     @NonNull
     public List<Integer> getSupportedSatelliteServicesForPlmn(int subId, String plmn) {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            logd("getSupportedSatelliteServices: carrierEnabledSatelliteFlag is disabled");
+
+        if (!isValidSubscriptionId(subId)) {
+            logd("getSupportedSatelliteServices: invalid sub id");
             return new ArrayList<>();
         }
         synchronized (mSupportedSatelliteServicesLock) {
-            Map<String, List<Integer>> allowedServicesList
-                    = mEntitlementServiceTypeMapPerCarrier.get(subId);
-            if (allowedServicesList != null && allowedServicesList.containsKey(plmn)) {
-                List<Integer> allowedServiceValues = allowedServicesList.get(plmn);
-                if (allowedServiceValues != null && !allowedServiceValues.isEmpty()) {
-                    return allowedServiceValues;
+            if (plmn != null && !plmn.isEmpty()) {
+                Map<String, List<Integer>> allowedServicesList =
+                        mEntitlementServiceTypeMapPerCarrier.get(subId);
+                if (allowedServicesList != null && allowedServicesList.containsKey(plmn)) {
+                    List<Integer> allowedServiceValues = new ArrayList<>(
+                            allowedServicesList.get(plmn));
+                    if (allowedServiceValues != null && !allowedServiceValues.isEmpty()) {
+                        if (isDataServiceUpdateRequired(subId, plmn, allowedServiceValues)) {
+                            logd("getSupportedSatelliteServices: data service added to satellite"
+                                    + " plmn");
+                            allowedServiceValues.add(NetworkRegistrationInfo.SERVICE_TYPE_DATA);
+                        }
+                        if (allowedServiceValues.contains(NetworkRegistrationInfo.SERVICE_TYPE_DATA)
+                                && isMmsServiceUpdateRequired(subId, plmn, allowedServiceValues)) {
+                            allowedServiceValues.add(NetworkRegistrationInfo.SERVICE_TYPE_MMS);
+                        }
+                        return allowedServiceValues;
+                    }
                 }
             }
-            if (mSatelliteServicesSupportedByCarriers.containsKey(subId)) {
-                Map<String, Set<Integer>> supportedServices =
-                        mSatelliteServicesSupportedByCarriers.get(subId);
-                if (supportedServices != null && supportedServices.containsKey(plmn)) {
-                    return new ArrayList<>(supportedServices.get(plmn));
-                } else {
-                    loge("getSupportedSatelliteServices: subId=" + subId + ", supportedServices "
-                            + "does not contain key plmn=" + plmn);
-                }
-            } else {
-                loge("getSupportedSatelliteServices: mSatelliteServicesSupportedByCarriers does "
-                        + "not contain key subId=" + subId);
-            }
 
-            /* Returns default capabilities when carrier config does not contain service
-               capabilities for the given plmn */
-            PersistableBundle config = getPersistableBundle(subId);
-            int [] defaultCapabilities = config.getIntArray(
-                    KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY);
-            if (defaultCapabilities == null) {
-                logd("getSupportedSatelliteServices: defaultCapabilities is null");
-                return new ArrayList<>();
-            }
-            List<Integer> capabilitiesList = Arrays.stream(
-                    defaultCapabilities).boxed().collect(Collectors.toList());
-            logd("getSupportedSatelliteServices: subId=" + subId
-                    + ", supportedServices does not contain key plmn=" + plmn
-                    + ", return default values " + capabilitiesList);
-            return capabilitiesList;
+            return getSatelliteSupportedServicesFromConfig(subId, plmn);
         }
+
     }
 
     /**
@@ -3909,11 +4083,6 @@
      * @return {@code true} if satellite attach is required, {@code false} otherwise.
      */
     public boolean isSatelliteAttachRequired() {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("isSatelliteAttachRequired: oemEnabledSatelliteFlag is disabled");
-            return false;
-        }
-
         SatelliteCapabilities satelliteCapabilities = getSatelliteCapabilities();
         if (satelliteCapabilities == null) {
             ploge("isSatelliteAttachRequired: mSatelliteCapabilities is null");
@@ -3931,10 +4100,6 @@
      * {@code false} otherwise.
      */
     public boolean isSatelliteSupportedViaCarrier() {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            logd("isSatelliteSupportedViaCarrier: carrierEnabledSatelliteFlag is disabled");
-            return false;
-        }
         for (Phone phone : PhoneFactory.getPhones()) {
             if (isSatelliteSupportedViaCarrier(phone.getSubId())) {
                 return true;
@@ -3948,11 +4113,6 @@
      * subscription on the device, {@code false} otherwise.
      */
     public boolean isSatelliteEmergencyMessagingSupportedViaCarrier() {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            logd("isSatelliteEmergencyMessagingSupportedViaCarrier: carrierEnabledSatelliteFlag is"
-                    + " disabled");
-            return false;
-        }
         for (Phone phone : PhoneFactory.getPhones()) {
             if (isSatelliteEmergencyMessagingSupportedViaCarrier(phone.getSubId())) {
                 return true;
@@ -3974,10 +4134,6 @@
      * satellite, {@code Pair<false, null>} otherwise.
      */
     Pair<Boolean, Integer> isUsingNonTerrestrialNetworkViaCarrier() {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            logd("isUsingNonTerrestrialNetwork: carrierEnabledSatelliteFlag is disabled");
-            return new Pair<>(false, null);
-        }
         for (Phone phone : PhoneFactory.getPhones()) {
             ServiceState serviceState = phone.getServiceState();
             if (serviceState != null && serviceState.isUsingNonTerrestrialNetwork()) {
@@ -3994,11 +4150,6 @@
      * duration, {@code false} and null otherwise.
      */
     public Pair<Boolean, Integer> isSatelliteConnectedViaCarrierWithinHysteresisTime() {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            logd("isSatelliteConnectedViaCarrierWithinHysteresisTime: carrierEnabledSatelliteFlag"
-                    + " is disabled");
-            return new Pair<>(false, null);
-        }
         Pair<Boolean, Integer> ntnConnectedState = isUsingNonTerrestrialNetworkViaCarrier();
         if (ntnConnectedState.first) {
             return ntnConnectedState;
@@ -4023,11 +4174,6 @@
      * duration, {@code false} otherwise.
      */
     public boolean isInSatelliteModeForCarrierRoaming(@Nullable Phone phone) {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            logd("isInSatelliteModeForCarrierRoaming: carrierEnabledSatelliteFlag is disabled");
-            return false;
-        }
-
         if (phone == null) {
             return false;
         }
@@ -4107,7 +4253,7 @@
      * @return {@code true} if phone is in carrier roaming nb iot ntn mode,
      * else {@return false}
      */
-    private boolean isInCarrierRoamingNbIotNtn(@Nullable Phone phone) {
+    public boolean isInCarrierRoamingNbIotNtn(@Nullable Phone phone) {
         if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
             plogd("isInCarrierRoamingNbIotNtn: carrier roaming nb iot ntn "
                     + "feature flag is disabled");
@@ -4157,12 +4303,6 @@
      */
     @NonNull
     public List<Integer> getCapabilitiesForCarrierRoamingSatelliteMode(Phone phone) {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            logd("getCapabilitiesForCarrierRoamingSatelliteMode: carrierEnabledSatelliteFlag"
-                    + " is disabled");
-            return new ArrayList<>();
-        }
-
         synchronized (mSatelliteConnectedLock) {
             int subId = phone.getSubId();
             if (mSatModeCapabilitiesForCarrierRoaming.containsKey(subId)) {
@@ -4181,9 +4321,6 @@
      *               if the request is successful or an error code if the request failed.
      */
     public void requestSatelliteSessionStats(int subId, @NonNull ResultReceiver result) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            return;
-        }
         mSessionMetricsStats.requestSatelliteSessionStats(subId, result);
     }
 
@@ -4248,19 +4385,29 @@
     }
 
     /**
-     * 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.
+     * To use the satellite service, update the EntitlementStatus, PlmnAllowedList, barred plmn list
+     * data plan, service type, data service policy and voice service policy after receiving the
+     * satellite configuration from the entitlement server. If satellite entitlement is enabled,
+     * enable satellite for the carrier. Otherwise, disable satellite.
      *
-     * @param subId              subId
-     * @param entitlementEnabled {@code true} Satellite service enabled
-     * @param allowedPlmnList    plmn allowed list to use the satellite service
-     * @param barredPlmnList    plmn barred list to pass the modem
-     * @param plmnDataPlanMap   data plan map for the plmn
-     * @param plmnServiceTypeMap available services map for the plmn
-     * @param plmnDataServicePolicyMap data service policy map for the plmn
-     * @param plmnVoiceServicePolicyMap voice service policy map for the plmn
-     * @param callback           callback for accept
+     * @param subId                     Subscription ID
+     * @param entitlementEnabled        {@code true} enables Satellite entitlement service.
+     * @param allowedPlmnList           Plmn [MCC+MNC] list of codes to determine if satellite
+     *                                  communication is allowed. Ex : "123123,12310".
+     * @param barredPlmnList            Plmn [MCC+MNC] list of codes to determine if satellite
+     *                                  communication is not allowed.  Ex : "123123,12310".
+     * @param plmnDataPlanMap           data plan per plmn of type {@link SatelliteDataPlan}.
+     *                                  Ex : {"302820":0, "31026":1}.
+     * @param plmnServiceTypeMap        list of supported services per plmn of type
+     *                                  {@link NetworkRegistrationInfo.ServiceType}).
+     *                                  Ex : {"302820":[1,3],"31026":[2,3]}.
+     * @param plmnDataServicePolicyMap  data support mode per plmn map of types
+     *                                  {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE}.
+     *                                  Ex : {"302820":2, "31026":1}.
+     * @param plmnVoiceServicePolicyMap voice support mode per plmn map of types
+     *                                  {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE}.
+     *                                  Ex : {"302820":2, "31026":1}.
+     * @param callback                  callback for accept.
      */
     public void onSatelliteEntitlementStatusUpdated(int subId, boolean entitlementEnabled,
             @Nullable List<String> allowedPlmnList, @Nullable List<String> barredPlmnList,
@@ -4269,11 +4416,6 @@
             @Nullable Map<String,Integer> plmnDataServicePolicyMap,
             @Nullable Map<String,Integer> plmnVoiceServicePolicyMap,
             @Nullable IIntegerConsumer callback) {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            logd("onSatelliteEntitlementStatusUpdated: carrierEnabledSatelliteFlag is not enabled");
-            return;
-        }
-
         if (callback == null) {
             callback = new IIntegerConsumer.Stub() {
                 @Override
@@ -4313,7 +4455,8 @@
             if (mSatelliteEntitlementStatusPerCarrier.get(subId, false) != entitlementEnabled) {
                 logd("update the carrier satellite enabled to " + entitlementEnabled);
                 mSatelliteEntitlementStatusPerCarrier.put(subId, entitlementEnabled);
-                mCarrierRoamingSatelliteControllerStats.reportIsDeviceEntitled(entitlementEnabled);
+                mCarrierRoamingSatelliteControllerStats.reportIsDeviceEntitled(subId,
+                        entitlementEnabled);
                 if (hasMessages(EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT)) {
                     removeMessages(EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT);
                     sendMessageDelayed(obtainMessage(
@@ -4333,12 +4476,19 @@
                 mEntitlementPlmnListPerCarrier.put(subId, allowedPlmnList);
                 mEntitlementBarredPlmnListPerCarrier.put(subId, barredPlmnList);
                 mEntitlementDataPlanMapPerCarrier.put(subId, plmnDataPlanMap);
-                mEntitlementServiceTypeMapPerCarrier.put(subId, plmnServiceTypeMap);
                 mEntitlementDataServicePolicyMapPerCarrier.put(subId, plmnDataServicePolicyMap);
                 mEntitlementVoiceServicePolicyMapPerCarrier.put(subId, plmnVoiceServicePolicyMap);
+                updateAndNotifyChangesInCarrierRoamingNtnAvailableServices(subId,
+                        plmnServiceTypeMap);
                 updatePlmnListPerCarrier(subId);
+
                 configureSatellitePlmnForCarrier(subId);
-                mSubscriptionManagerService.setSatelliteEntitlementPlmnList(subId, allowedPlmnList);
+                evaluateEnablingSatelliteForCarrier(subId,
+                        SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, null);
+                mSubscriptionManagerService.setSatelliteEntitlementInfo(subId, allowedPlmnList,
+                        barredPlmnList, plmnDataPlanMap, plmnServiceTypeMap,
+                        plmnDataServicePolicyMap, plmnVoiceServicePolicyMap);
+
             } else {
                 loge("onSatelliteEntitlementStatusUpdated: either invalid allowedPlmnList "
                         + "or invalid barredPlmnList");
@@ -4420,11 +4570,8 @@
         if (result == SATELLITE_RESULT_SUCCESS
                 || result == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
             persistOemEnabledSatelliteProvisionStatus(true);
-            synchronized (mDeviceProvisionLock) {
-                mIsDeviceProvisioned = true;
-            }
             callback.accept(SATELLITE_RESULT_SUCCESS);
-            handleEventSatelliteProvisionStateChanged(true);
+            updateCachedDeviceProvisionStatus();
         } else {
             callback.accept(result);
         }
@@ -4449,13 +4596,10 @@
         if (result == SATELLITE_RESULT_SUCCESS
                 || result == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
             persistOemEnabledSatelliteProvisionStatus(false);
-            synchronized (mDeviceProvisionLock) {
-                mIsDeviceProvisioned = false;
-            }
             if (arg.callback != null) {
                 arg.callback.accept(SATELLITE_RESULT_SUCCESS);
             }
-            handleEventSatelliteProvisionStateChanged(false);
+            updateCachedDeviceProvisionStatus();
         } else if (arg.callback != null) {
             arg.callback.accept(result);
         }
@@ -4563,9 +4707,9 @@
         startWaitForSatelliteEnablingResponseTimer(argument);
         // Logs satellite session timestamps for session metrics
         if (argument.enableSatellite) {
-            mSessionStartTimeStamp = System.currentTimeMillis();
+            mSessionStartTimeStamp = getElapsedRealtime();
         }
-        mSessionProcessingTimeStamp = System.currentTimeMillis();
+        mSessionProcessingTimeStamp = getElapsedRealtime();
     }
 
     /** Get the request attributes that modem needs to enable/disable satellite */
@@ -4700,11 +4844,6 @@
     }
 
     private void registerForNtnSignalStrengthChanged() {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("registerForNtnSignalStrengthChanged: oemEnabledSatelliteFlag is disabled");
-            return;
-        }
-
         if (mSatelliteModemInterface.isSatelliteServiceSupported()) {
             if (!mRegisteredForNtnSignalStrengthChanged.get()) {
                 mSatelliteModemInterface.registerForNtnSignalStrengthChanged(
@@ -4715,11 +4854,6 @@
     }
 
     private void registerForCapabilitiesChanged() {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("registerForCapabilitiesChanged: oemEnabledSatelliteFlag is disabled");
-            return;
-        }
-
         if (mSatelliteModemInterface.isSatelliteServiceSupported()) {
             if (!mRegisteredForSatelliteCapabilitiesChanged.get()) {
                 mSatelliteModemInterface.registerForSatelliteCapabilitiesChanged(
@@ -4759,23 +4893,13 @@
         }
     }
 
-    private void handleEventSatelliteProvisionStateChanged(boolean provisioned) {
-        plogd("handleSatelliteProvisionStateChangedEvent: provisioned=" + provisioned);
-
-        synchronized (mDeviceProvisionLock) {
-            persistOemEnabledSatelliteProvisionStatus(provisioned);
-            mIsDeviceProvisioned = provisioned;
-        }
-        notifyDeviceProvisionStateChanged(provisioned);
-    }
-
     private void notifyDeviceProvisionStateChanged(boolean provisioned) {
         List<ISatelliteProvisionStateCallback> deadCallersList = new ArrayList<>();
         mSatelliteProvisionStateChangedListeners.values().forEach(listener -> {
             try {
                 listener.onSatelliteProvisionStateChanged(provisioned);
             } catch (RemoteException e) {
-                plogd("handleSatelliteProvisionStateChangedEvent RemoteException: " + e);
+                plogd("notifyDeviceProvisionStateChanged RemoteException: " + e);
                 deadCallersList.add(listener);
             }
         });
@@ -4792,7 +4916,7 @@
         synchronized (mSatelliteTokenProvisionedLock) {
             for (SatelliteSubscriberInfo subscriberInfo : newList) {
 
-                int subId = subscriberInfo.getSubId();
+                int subId = subscriberInfo.getSubscriptionId();
                 Boolean currentProvisioned =
                         mProvisionedSubscriberId.get(subscriberInfo.getSubscriberId());
                 if (currentProvisioned == null) {
@@ -4835,7 +4959,7 @@
                 getPrioritizedSatelliteSubscriberProvisionStatusList();
         plogd("handleEventSatelliteSubscriptionProvisionStateChanged: " + informList);
         notifySatelliteSubscriptionProvisionStateChanged(informList);
-        updateDeviceProvisionStatus();
+        updateCachedDeviceProvisionStatus();
         // Report updated provisioned status to metrics.
         synchronized (mSatelliteTokenProvisionedLock) {
             boolean isProvisioned = !mProvisionedSubscriberId.isEmpty()
@@ -4846,9 +4970,9 @@
         evaluateCarrierRoamingNtnEligibilityChange();
     }
 
-    private void updateDeviceProvisionStatus() {
+    private void updateCachedDeviceProvisionStatus() {
         boolean isProvisioned = getPersistedDeviceProvisionStatus();
-        plogd("updateDeviceProvisionStatus: isProvisioned=" + isProvisioned);
+        plogd("updateCachedDeviceProvisionStatus: isProvisioned=" + isProvisioned);
         synchronized (mDeviceProvisionLock) {
             if (mIsDeviceProvisioned == null || mIsDeviceProvisioned != isProvisioned) {
                 mIsDeviceProvisioned = isProvisioned;
@@ -4924,11 +5048,6 @@
 
     private void handleEventNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) {
         logd("handleEventNtnSignalStrengthChanged: ntnSignalStrength=" + ntnSignalStrength);
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            logd("handleEventNtnSignalStrengthChanged: oemEnabledSatelliteFlag is disabled");
-            return;
-        }
-
         synchronized (mNtnSignalsStrengthLock) {
             mNtnSignalStrength = ntnSignalStrength;
         }
@@ -4950,10 +5069,6 @@
 
     private void handleEventSatelliteCapabilitiesChanged(SatelliteCapabilities capabilities) {
         plogd("handleEventSatelliteCapabilitiesChanged()");
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("handleEventSatelliteCapabilitiesChanged: oemEnabledSatelliteFlag is disabled");
-            return;
-        }
 
         synchronized (mSatelliteCapabilitiesLock) {
             mSatelliteCapabilities = capabilities;
@@ -5036,10 +5151,10 @@
     }
 
     private void notifySatelliteSupportedStateChanged(boolean supported) {
-        List<ISatelliteSupportedStateCallback> deadCallersList = new ArrayList<>();
+        List<IBooleanConsumer> deadCallersList = new ArrayList<>();
         mSatelliteSupportedStateChangedListeners.values().forEach(listener -> {
             try {
-                listener.onSatelliteSupportedStateChanged(supported);
+                listener.accept(supported);
             } catch (RemoteException e) {
                 plogd("handleSatelliteSupportedStateChangedEvent RemoteException: " + e);
                 deadCallersList.add(listener);
@@ -5214,6 +5329,10 @@
                             mSatelliteEnableAttributesUpdateRequest, null);
                 }
                 updateLastNotifiedNtnModeAndNotify(getSatellitePhone());
+
+                if (mFeatureFlags.satelliteExitP2pSessionOutsideGeofence()) {
+                    evaluateDisablingP2pSession();
+                }
             }
         }
     }
@@ -5292,20 +5411,106 @@
 
     private void configureSatellitePlmnForCarrier(int subId) {
         logd("configureSatellitePlmnForCarrier");
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            logd("configureSatellitePlmnForCarrier: carrierEnabledSatelliteFlag is disabled");
+        Phone phone = SatelliteServiceUtils.getPhone(subId);
+        if (phone == null) {
+            ploge("configureSatellitePlmnForCarrier: phone is null for subId=" + subId);
             return;
         }
+
+        List<String> allPlmnList = new ArrayList<>(getAllPlmnSet());
+        phone.setSatellitePlmn(phone.getPhoneId(), getCarrierPlmnList(subId), allPlmnList,
+                obtainMessage(EVENT_SET_SATELLITE_PLMN_INFO_DONE));
+    }
+
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    protected Set<String> getAllPlmnSet() {
+        Set<String> allPlmnSetFromSubInfo = new HashSet<>();
+        int[] activeSubIdArray = mSubscriptionManagerService.getActiveSubIdList(true);
+        for (int activeSubId : activeSubIdArray) {
+            allPlmnSetFromSubInfo.addAll(getCarrierPlmnList(activeSubId));
+            allPlmnSetFromSubInfo.addAll(getBarredPlmnList(activeSubId));
+        }
+        allPlmnSetFromSubInfo.addAll(mSatellitePlmnListFromOverlayConfig);
+
+        if (mIgnorePlmnListFromStorage.get()) {
+            // Do not use PLMN list from storage
+            plogd("getAllPlmnList: allPlmnSetFromSubInfo=" + allPlmnSetFromSubInfo);
+            return allPlmnSetFromSubInfo;
+        }
+
+        Set<String> allPlmnListFromStorage = getCarrierRoamingNtnAllSatellitePlmnSetFromStorage();
+        if (!allPlmnListFromStorage.containsAll(allPlmnSetFromSubInfo)) {
+            allPlmnListFromStorage.addAll(allPlmnSetFromSubInfo);
+            persistCarrierRoamingNtnAllSatellitePlmnSet(allPlmnListFromStorage);
+        }
+
+        plogd("getAllPlmnList: " + allPlmnListFromStorage);
+        return allPlmnListFromStorage;
+    }
+
+    private List<String> getCarrierPlmnList(int subId) {
         synchronized (mSupportedSatelliteServicesLock) {
-            List<String> carrierPlmnList = mMergedPlmnListPerCarrier.get(subId,
-                    new ArrayList<>()).stream().toList();
-            List<String> barredPlmnList = mEntitlementBarredPlmnListPerCarrier.get(subId,
-                    new ArrayList<>()).stream().toList();
-            int slotId = SubscriptionManager.getSlotIndex(subId);
-            mSatelliteModemInterface.setSatellitePlmn(slotId, carrierPlmnList,
-                    SatelliteServiceUtils.mergeStrLists(
-                            carrierPlmnList, mSatellitePlmnListFromOverlayConfig, barredPlmnList),
-                    obtainMessage(EVENT_SET_SATELLITE_PLMN_INFO_DONE));
+            return mMergedPlmnListPerCarrier.get(subId, new ArrayList<>()).stream().toList();
+        }
+    }
+
+    private List<String> getBarredPlmnList(int subId) {
+        synchronized (mSupportedSatelliteServicesLock) {
+            return mEntitlementBarredPlmnListPerCarrier.get(
+                    subId, new ArrayList<>()).stream().toList();
+        }
+    }
+
+    private void persistCarrierRoamingNtnAllSatellitePlmnSet(Set<String> allSatellitePlmnSet) {
+        plogd("persistCarrierRoamingNtnAllSatellitePlmnSet");
+        if (!loadSatelliteSharedPreferences()) return;
+
+        if (mSharedPreferences == null) {
+            ploge("persistCarrierRoamingNtnAllSatellitePlmnSet: mSharedPreferences is null");
+        } else {
+            try {
+                mSharedPreferences.edit().putStringSet(
+                        CARRIER_ROAMING_NTN_ALL_SATELLITE_PLMN_SET_KEY, allSatellitePlmnSet)
+                        .apply();
+            } catch (Exception ex) {
+                plogd("persistCarrierRoamingNtnAllSatellitePlmnSet: ex=" + ex);
+            }
+
+            synchronized (mCarrierRoamingNtnAllSatellitePlmnSetLock) {
+                mCarrierRoamingNtnAllSatellitePlmnSet = allSatellitePlmnSet;
+            }
+        }
+    }
+
+    private Set<String> getCarrierRoamingNtnAllSatellitePlmnSetFromStorage() {
+        synchronized (mCarrierRoamingNtnAllSatellitePlmnSetLock) {
+            if (mCarrierRoamingNtnAllSatellitePlmnSet != null) {
+                plogd("getCarrierRoamingNtnAllSatellitePlmnSetFromStorage: "
+                        + mCarrierRoamingNtnAllSatellitePlmnSet);
+                return mCarrierRoamingNtnAllSatellitePlmnSet;
+            }
+        }
+
+        if (!loadSatelliteSharedPreferences()) return new HashSet<>();
+
+        if (mSharedPreferences == null) {
+            ploge("getCarrierRoamingNtnAllSatellitePlmnSetFromStorage: mSharedPreferences is null");
+            return new HashSet<>();
+        } else {
+            Set<String> allSatellitePlmnSet = new HashSet<>();
+            try {
+                allSatellitePlmnSet = mSharedPreferences.getStringSet(
+                        CARRIER_ROAMING_NTN_ALL_SATELLITE_PLMN_SET_KEY, new HashSet<>());
+            } catch (Exception ex) {
+                plogd("getCarrierRoamingNtnAllSatellitePlmnSetFromStorage: ex=" + ex);
+            }
+
+            synchronized (mCarrierRoamingNtnAllSatellitePlmnSetLock) {
+                mCarrierRoamingNtnAllSatellitePlmnSet = allSatellitePlmnSet;
+                plogd("getCarrierRoamingNtnAllSatellitePlmnSetFromStorage: "
+                        + mCarrierRoamingNtnAllSatellitePlmnSet);
+                return mCarrierRoamingNtnAllSatellitePlmnSet;
+            }
         }
     }
 
@@ -5315,14 +5520,8 @@
     }
 
     private void updateSupportedSatelliteServicesForActiveSubscriptions() {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            logd("updateSupportedSatelliteServicesForActiveSubscriptions: "
-                    + "carrierEnabledSatelliteFlag is disabled");
-            return;
-        }
-
         synchronized (mSupportedSatelliteServicesLock) {
-            mSatelliteServicesSupportedByCarriers.clear();
+            mSatelliteServicesSupportedByCarriersFromConfig.clear();
             mMergedPlmnListPerCarrier.clear();
             int[] activeSubIds = mSubscriptionManagerService.getActiveSubIdList(true);
             if (activeSubIds != null) {
@@ -5355,7 +5554,7 @@
                 if (!entitlementPlmnList.isEmpty()) {
                     mMergedPlmnListPerCarrier.put(subId, entitlementPlmnList);
                     plogd("mMergedPlmnListPerCarrier is updated by Entitlement");
-                    mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(
+                    mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(subId,
                             SatelliteConstants.CONFIG_DATA_SOURCE_ENTITLEMENT);
                     return;
                 }
@@ -5370,19 +5569,20 @@
                     plogd("mMergedPlmnListPerCarrier is updated by ConfigUpdater : "
                             + String.join(",", plmnList));
                     mMergedPlmnListPerCarrier.put(subId, plmnList);
-                    mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(
+                    mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(subId,
                             SatelliteConstants.CONFIG_DATA_SOURCE_CONFIG_UPDATER);
                     return;
                 }
             }
 
-            if (mSatelliteServicesSupportedByCarriers.containsKey(subId)
-                    && mSatelliteServicesSupportedByCarriers.get(subId) != null) {
+            if (mSatelliteServicesSupportedByCarriersFromConfig.containsKey(subId)
+                    && mSatelliteServicesSupportedByCarriersFromConfig.get(subId) != null) {
                 carrierPlmnList =
-                        mSatelliteServicesSupportedByCarriers.get(subId).keySet().stream().toList();
+                        mSatelliteServicesSupportedByCarriersFromConfig.get(subId).keySet()
+                                .stream().toList();
                 plogd("mMergedPlmnListPerCarrier is updated by carrier config: "
                         + String.join(",", carrierPlmnList));
-                mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(
+                mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(subId,
                         SatelliteConstants.CONFIG_DATA_SOURCE_CARRIER_CONFIG);
             } else {
                 carrierPlmnList = new ArrayList<>();
@@ -5404,7 +5604,8 @@
                 Map<String, Set<Integer>> supportedServicesPerPlmn =
                         satelliteConfig.getSupportedSatelliteServices(carrierId);
                 if (!supportedServicesPerPlmn.isEmpty()) {
-                    mSatelliteServicesSupportedByCarriers.put(subId, supportedServicesPerPlmn);
+                    mSatelliteServicesSupportedByCarriersFromConfig.put(subId,
+                            supportedServicesPerPlmn);
                     plogd("updateSupportedSatelliteServices using ConfigUpdater, "
                             + "supportedServicesPerPlmn = " + supportedServicesPerPlmn.size());
                     updatePlmnListPerCarrier(subId);
@@ -5414,7 +5615,7 @@
                 }
             }
 
-            mSatelliteServicesSupportedByCarriers.put(
+            mSatelliteServicesSupportedByCarriersFromConfig.put(
                     subId, readSupportedSatelliteServicesFromCarrierConfig(subId));
             updatePlmnListPerCarrier(subId);
             plogd("updateSupportedSatelliteServices using carrier config");
@@ -5423,11 +5624,6 @@
 
     @NonNull
     private List<String> readSatellitePlmnsFromOverlayConfig() {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            logd("readSatellitePlmnsFromOverlayConfig: carrierEnabledSatelliteFlag is disabled");
-            return new ArrayList<>();
-        }
-
         String[] devicePlmns = readStringArrayFromOverlayConfig(
                 R.array.config_satellite_providers);
         return Arrays.stream(devicePlmns).toList();
@@ -5474,7 +5670,8 @@
                         KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE_BYTES_INT,
                         KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY,
                         KEY_REGIONAL_SATELLITE_EARFCN_BUNDLE,
-                        KEY_SATELLITE_DATA_SUPPORT_MODE_INT
+                        KEY_SATELLITE_DATA_SUPPORT_MODE_INT,
+                        KEY_SATELLITE_CONNECTED_NOTIFICATION_THROTTLE_MILLIS_INT
                 );
             } catch (Exception e) {
                 logw("getConfigForSubId: " + e);
@@ -5495,6 +5692,7 @@
             return;
         }
 
+        getSatelliteEnabledForCarrierAtModem(subId);
         updateCarrierConfig(subId);
         updateSatelliteESOSSupported(subId);
         updateSatelliteProvisionedStatePerSubscriberId();
@@ -5508,6 +5706,16 @@
         updateRegionalSatelliteEarfcns(subId);
     }
 
+    private void getSatelliteEnabledForCarrierAtModem(int subId) {
+        Phone phone = SatelliteServiceUtils.getPhone(subId);
+        synchronized (mIsSatelliteEnabledLock) {
+            if (!mIsSatelliteAttachEnabledForCarrierArrayPerSub.containsKey(subId)) {
+                // Get enabled status from modem for new subscription
+                sendRequestAsync(CMD_GET_SATELLITE_ENABLED_FOR_CARRIER, null, phone);
+            }
+        }
+    }
+
     // imsi, msisdn, default sms subId change
     private void handleSubscriptionsChanged() {
         sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
@@ -5515,9 +5723,10 @@
     }
 
     private void processNewCarrierConfigData(int subId) {
-        configureSatellitePlmnForCarrier(subId);
-        setSatelliteAttachEnabledForCarrierOnSimLoaded(subId);
         updateRestrictReasonForEntitlementPerCarrier(subId);
+        configureSatellitePlmnForCarrier(subId);
+        evaluateEnablingSatelliteForCarrier(subId,
+                SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, null);
     }
 
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@@ -5547,26 +5756,83 @@
                     plogd("updateEntitlementPlmnListPerCarrier: read empty list");
                     return;
                 }
-                plogd("updateEntitlementPlmnListPerCarrier: entitlementPlmnList="
-                        + String.join(",", entitlementPlmnList));
+                plogd("updateEntitlementPlmnListPerCarrier: entitlementPlmnList=" + String.join(",",
+                        entitlementPlmnList));
                 mEntitlementPlmnListPerCarrier.put(subId, entitlementPlmnList);
             }
-        }
-    }
 
-    /**
-     * When a SIM is loaded, we need to check if users has enabled satellite attach for the carrier
-     * associated with the SIM, and evaluate if satellite should be enabled for the carrier.
-     *
-     * @param subId Subscription ID.
-     */
-    private void setSatelliteAttachEnabledForCarrierOnSimLoaded(int subId) {
-        synchronized (mIsSatelliteEnabledLock) {
-            if (isSatelliteAttachEnabledForCarrierByUser(subId)
-                    && !mIsSatelliteAttachEnabledForCarrierArrayPerSub.getOrDefault(subId,
-                    false)) {
-                evaluateEnablingSatelliteForCarrier(subId,
-                        SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, null);
+            if (mEntitlementBarredPlmnListPerCarrier.indexOfKey(subId) < 0) {
+                plogd("updateEntitlementBarredPlmnList: no correspondent cache, load from "
+                        + "persist storage");
+                List<String> entitlementBarredPlmnList =
+                        mSubscriptionManagerService.getSatelliteEntitlementBarredPlmnList(subId);
+                if (entitlementBarredPlmnList.isEmpty()) {
+                    plogd("updateEntitlementBarredPlmnList: read empty list");
+                    return;
+                }
+                plogd("updateEntitlementBarredPlmnList: entitlementBarredPlmnList=" + String.join(
+                        ",", entitlementBarredPlmnList));
+                mEntitlementBarredPlmnListPerCarrier.put(subId, entitlementBarredPlmnList);
+            }
+
+            if (mEntitlementDataPlanMapPerCarrier.indexOfKey(subId) < 0) {
+                plogd("updateEntitlementDataPlanForPlmns: no correspondent cache, load from "
+                        + "persist storage");
+                Map<String, Integer> entitlementDataPlanForPlmns =
+                        mSubscriptionManagerService.getSatelliteEntitlementDataPlanForPlmns(subId);
+                if (entitlementDataPlanForPlmns.isEmpty()) {
+                    plogd("updateEntitlementBarredPlmnList: read empty list");
+                    return;
+                }
+                plogd("updateEntitlementDataPlanForPlmns: entitlementDataPlanForPlmns="
+                        + entitlementDataPlanForPlmns);
+                mEntitlementDataPlanMapPerCarrier.put(subId, entitlementDataPlanForPlmns);
+            }
+
+            if (mEntitlementServiceTypeMapPerCarrier.indexOfKey(subId) < 0) {
+                plogd("updateEntitlementTypeMapPerCarrier: no correspondent cache, load from "
+                        + "persist storage");
+                Map<String, List<Integer>> entitlementTypeMapPerCarrier =
+                        mSubscriptionManagerService.getSatelliteEntitlementPlmnServiceTypeMap(
+                                subId);
+                if (entitlementTypeMapPerCarrier.isEmpty()) {
+                    plogd("updateEntitlementTypeMapPerCarrier: read empty list");
+                    return;
+                }
+                plogd("updateEntitlementTypeMapPerCarrier: entitlementTypeMapPerCarrier="
+                        + entitlementTypeMapPerCarrier);
+                mEntitlementServiceTypeMapPerCarrier.put(subId, entitlementTypeMapPerCarrier);
+            }
+
+            if (mEntitlementDataServicePolicyMapPerCarrier.indexOfKey(subId) < 0) {
+                plogd("updateEntitlementDataServicePolicy: no correspondent cache, load from "
+                        + "persist storage");
+                Map<String, Integer> entitlementDataServicePolicy =
+                        mSubscriptionManagerService.getSatelliteEntitlementPlmnDataServicePolicy(
+                                subId);
+                if (entitlementDataServicePolicy.isEmpty()) {
+                    plogd("updateEntitlementDataServicePolicy: read empty list");
+                    return;
+                }
+                plogd("updateEntitlementDataServicePolicy: entitlementDataServicePolicy="
+                        + entitlementDataServicePolicy);
+                mEntitlementDataServicePolicyMapPerCarrier.put(subId, entitlementDataServicePolicy);
+            }
+
+            if (mEntitlementVoiceServicePolicyMapPerCarrier.indexOfKey(subId) < 0) {
+                plogd("updateEntitlementVoiceServicePolicy: no correspondent cache, load from "
+                        + "persist storage");
+                Map<String, Integer> entitlementVoiceServicePolicy =
+                        mSubscriptionManagerService.getSatelliteEntitlementPlmnVoiceServicePolicy(
+                                subId);
+                if (entitlementVoiceServicePolicy.isEmpty()) {
+                    plogd("updateEntitlementVoiceServicePolicy: read empty list");
+                    return;
+                }
+                plogd("updateEntitlementVoiceServicePolicy: entitlementVoiceServicePolicy="
+                        + entitlementVoiceServicePolicy);
+                mEntitlementVoiceServicePolicyMapPerCarrier.put(subId,
+                        entitlementVoiceServicePolicy);
             }
         }
     }
@@ -5611,14 +5877,15 @@
                             .isSatelliteProvisionedForNonIpDatagram(subId);
                     if (Provisioned) {
                         mProvisionedSubscriberId.put(subscriberId, true);
-                        logd("updateSatelliteProvisionStatePerSubscriberId: " + subscriberId
+                        logd("updateSatelliteProvisionStatePerSubscriberId: "
+                                + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, subscriberId)
                                 + " set true");
                     }
                 }
             }
         }
         // Need to update the provision status of the device
-        updateDeviceProvisionStatus();
+        updateCachedDeviceProvisionStatus();
     }
 
     @NonNull
@@ -5681,11 +5948,25 @@
     }
 
     @CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE
-    private int getCarrierSatelliteDataSupportedMode(int subId) {
+    private int getCarrierSatelliteDataSupportedModeFromConfig(int subId) {
         return getConfigForSubId(subId).getInt(KEY_SATELLITE_DATA_SUPPORT_MODE_INT);
     }
 
     /**
+     * Satellite notification display restriction timeout. Default value is 7 days in millis.
+     * @param subId : subscription Id.
+     * @return : Notification throttle timeout in millis.
+     */
+    private long getNotificationDisplayThrottleTimeout(int subId) {
+        if (Flags.starlinkDataBugfix()) {
+            return getConfigForSubId(subId).getLong(
+                    KEY_SATELLITE_CONNECTED_NOTIFICATION_THROTTLE_MILLIS_INT);
+        } else {
+            return TimeUnit.DAYS.toMillis(7);
+        }
+    }
+
+    /**
      * Check if satellite attach is enabled by user for the carrier associated with the
      * {@code subId}.
      *
@@ -5792,7 +6073,7 @@
                 }
                 boolean result = entitlementStatus.equals("1");
                 mSatelliteEntitlementStatusPerCarrier.put(subId, result);
-                mCarrierRoamingSatelliteControllerStats.reportIsDeviceEntitled(result);
+                mCarrierRoamingSatelliteControllerStats.reportIsDeviceEntitled(subId, result);
                 if (hasMessages(EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT)) {
                     removeMessages(EVENT_WAIT_FOR_REPORT_ENTITLED_TO_MERTICS_HYSTERESIS_TIMED_OUT);
                     sendMessageDelayed(obtainMessage(
@@ -5854,10 +6135,11 @@
     /**
      * Check whether satellite is enabled for carrier at modem.
      *
-     * @param subId Subscription ID to check for.
+     * @param subId subscription ID
      * @return {@code true} if satellite modem is enabled, {@code false} otherwise.
      */
-    private boolean isSatelliteEnabledForCarrierAtModem(int subId) {
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public boolean isSatelliteEnabledForCarrierAtModem(int subId) {
         synchronized (mIsSatelliteEnabledLock) {
             return mIsSatelliteAttachEnabledForCarrierArrayPerSub.getOrDefault(subId, false);
         }
@@ -5886,31 +6168,35 @@
                     + "SetSatelliteAttachEnableForCarrier error code =" + errorCode);
         }
 
-        if (!isSatelliteSupportedViaCarrier(subId)) {
-            plogd("Satellite for carrier is not supported. Only user setting is stored");
-            callback.accept(SATELLITE_RESULT_SUCCESS);
+        Phone phone = SatelliteServiceUtils.getPhone(subId);
+        if (phone == null) {
+            ploge("evaluateEnablingSatelliteForCarrier: phone is null for subId=" + subId);
+            callback.accept(SATELLITE_RESULT_INVALID_TELEPHONY_STATE);
             return;
         }
 
         /* Request to enable or disable the satellite in the cellular modem only when the desired
         state and the current state are different. */
-        boolean isSatelliteExpectedToBeEnabled = !isSatelliteRestrictedForCarrier(subId);
-        if (isSatelliteExpectedToBeEnabled != isSatelliteEnabledForCarrierAtModem(subId)) {
-            if (mSatelliteModemInterface.isSatelliteServiceSupported()) {
-                int simSlot = SubscriptionManager.getSlotIndex(subId);
-                RequestHandleSatelliteAttachRestrictionForCarrierArgument argument =
-                        new RequestHandleSatelliteAttachRestrictionForCarrierArgument(subId,
-                                reason, callback);
-                SatelliteControllerHandlerRequest request =
-                        new SatelliteControllerHandlerRequest(argument,
-                                SatelliteServiceUtils.getPhone(subId));
-                Message onCompleted = obtainMessage(
-                        EVENT_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE_DONE, request);
-                mSatelliteModemInterface.requestSetSatelliteEnabledForCarrier(simSlot,
-                        isSatelliteExpectedToBeEnabled, onCompleted);
-            } else {
-                callback.accept(SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE);
-            }
+        boolean isSatelliteExpectedToBeEnabled = !isSatelliteRestrictedForCarrier(subId)
+                && isSatelliteSupportedViaCarrier(subId);
+        boolean isSatelliteEnabledForCarrierAtModem = isSatelliteEnabledForCarrierAtModem(
+                phone.getSubId());
+        plogd("evaluateEnablingSatelliteForCarrier: subId=" + subId + " reason=" + reason
+                + " isSatelliteExpectedToBeEnabled=" + isSatelliteExpectedToBeEnabled
+                + " isSatelliteEnabledForCarrierAtModem=" + isSatelliteEnabledForCarrierAtModem);
+
+        if (isSatelliteExpectedToBeEnabled != isSatelliteEnabledForCarrierAtModem) {
+            int simSlot = SubscriptionManager.getSlotIndex(subId);
+            RequestHandleSatelliteAttachRestrictionForCarrierArgument argument =
+                    new RequestHandleSatelliteAttachRestrictionForCarrierArgument(subId,
+                            reason, callback);
+            SatelliteControllerHandlerRequest request =
+                    new SatelliteControllerHandlerRequest(argument,
+                            SatelliteServiceUtils.getPhone(subId));
+            Message onCompleted = obtainMessage(
+                    EVENT_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE_DONE, request);
+            phone.setSatelliteEnabledForCarrier(simSlot,
+                    isSatelliteExpectedToBeEnabled, onCompleted);
         } else {
             callback.accept(SATELLITE_RESULT_SUCCESS);
         }
@@ -5918,10 +6204,6 @@
 
     @SatelliteManager.SatelliteResult private int evaluateOemSatelliteRequestAllowed(
             boolean isProvisionRequired) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("oemEnabledSatelliteFlag is disabled");
-            return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
-        }
         if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
             plogd("evaluateOemSatelliteRequestAllowed: satellite service is not supported");
             return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
@@ -5999,9 +6281,6 @@
     }
 
     private void registerForServiceStateChanged() {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            return;
-        }
         for (Phone phone : PhoneFactory.getPhones()) {
             phone.registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED, null);
         }
@@ -6086,8 +6365,8 @@
     }
 
     private void updateLastNotifiedNtnModeAndNotify(@Nullable Phone phone) {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) return;
         if (phone == null) {
+            plogd("updateLastNotifiedNtnModeAndNotify: phone is null");
             return;
         }
 
@@ -6096,6 +6375,10 @@
             boolean initialized = mInitialized.get(subId);
             boolean lastNotifiedNtnMode = mLastNotifiedNtnMode.get(subId);
             boolean currNtnMode = isInSatelliteModeForCarrierRoaming(phone);
+            plogd("updateLastNotifiedNtnModeAndNotify: subId=" + subId
+                    + " initialized=" + initialized
+                    + " lastNotifiedNtnMode=" + lastNotifiedNtnMode
+                    + " currNtnMode=" + currNtnMode);
             if (!initialized || lastNotifiedNtnMode != currNtnMode) {
                 if (!initialized) mInitialized.put(subId, true);
                 mLastNotifiedNtnMode.put(subId, currNtnMode);
@@ -6109,6 +6392,36 @@
         }
     }
 
+    /**
+     * map data policy to support unknown case at metrics
+     * @param dataPolicy data support mode for the service type
+     * @return corresponding value from {@link SatelliteConstants.SatelliteEntitlementServicePolicy}
+     *
+     */
+    @SatelliteConstants.SatelliteEntitlementServicePolicy
+    public int mapDataPolicyForMetrics(int dataPolicy) {
+        switch (dataPolicy) {
+            case CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED -> {
+                return SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_RESTRICTED;
+            }
+            case CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED -> {
+                return SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_CONSTRAINED;
+            }
+            case CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL -> {
+                return SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNCONSTRAINED;
+            }
+        }
+        return SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN;
+    }
+
+    private int[] getSupportedSatelliteServicesOnSessionStart(List<Integer> supportedServices) {
+        if (supportedServices == null || supportedServices.isEmpty()) {
+            return new int[0];
+        }
+
+        return supportedServices.stream().mapToInt(Integer::intValue).toArray();
+    }
+
     private void logCarrierRoamingSatelliteSessionStats(@NonNull Phone phone,
             boolean lastNotifiedNtnMode, boolean currNtnMode) {
         synchronized (mSatelliteConnectedLock) {
@@ -6117,14 +6430,24 @@
                 // Log satellite session start
                 CarrierRoamingSatelliteSessionStats sessionStats =
                         CarrierRoamingSatelliteSessionStats.getInstance(subId);
-                sessionStats.onSessionStart(phone.getCarrierId(), phone);
+                int[] supported_satellite_services =
+                        getSupportedSatelliteServicesOnSessionStart(
+                                getSupportedSatelliteServicesForPlmn(subId,
+                        phone.getServiceState().getOperatorNumeric()));
+                int dataPolicy = mapDataPolicyForMetrics(getSatelliteDataServicePolicyForPlmn(subId,
+                        phone.getServiceState().getOperatorNumeric()));
+
+                sessionStats.onSessionStart(phone.getCarrierId(), phone,
+                        supported_satellite_services, dataPolicy);
                 mCarrierRoamingSatelliteSessionStatsMap.put(subId, sessionStats);
+                mCarrierRoamingSatelliteControllerStats.onSessionStart(subId);
             } else if (lastNotifiedNtnMode && !currNtnMode) {
                 // Log satellite session end
                 CarrierRoamingSatelliteSessionStats sessionStats =
                         mCarrierRoamingSatelliteSessionStatsMap.get(subId);
-                sessionStats.onSessionEnd();
+                sessionStats.onSessionEnd(subId);
                 mCarrierRoamingSatelliteSessionStatsMap.remove(subId);
+                mCarrierRoamingSatelliteControllerStats.onSessionEnd(subId);
             }
         }
     }
@@ -6136,7 +6459,7 @@
             return;
         }
 
-        registerForSatelliteCommunicationAllowedStateChanged();
+        registerForSatelliteCommunicationAccessStateChanged();
 
         if (isSatelliteEnabledOrBeingEnabled()) {
             plogd("evaluateCarrierRoamingNtnEligibilityChange: "
@@ -6213,8 +6536,6 @@
 
         if (mOverrideNtnEligibility != null) {
             satellitePhone.notifyCarrierRoamingNtnEligibleStateChanged(currentNtnEligibility);
-            mControllerMetricsStats.reportP2PSmsEligibilityNotificationsCount(
-                    currentNtnEligibility);
             return;
         }
 
@@ -6233,6 +6554,22 @@
         }
     }
 
+    /** Return last notified ntn eligibility. */
+    public boolean getLastNotifiedNtnEligibility(@NonNull Phone phone) {
+        int selectedSatelliteSubId = getSelectedSatelliteSubId();
+        int subId = phone.getSubId();
+        if (subId != selectedSatelliteSubId) {
+            plogd("getLastNotifiedNtnEligibility: subId=" + subId
+                    +  " does not match selectedSatelliteSubId=" + selectedSatelliteSubId);
+            return false;
+        }
+
+        synchronized (mSatellitePhoneLock) {
+            plogd("getLastNotifiedNtnEligibility: return " + mLastNotifiedNtnEligibility);
+            return mLastNotifiedNtnEligibility;
+        }
+    }
+
     private long getSatelliteConnectionHysteresisTimeMillis(int subId) {
         PersistableBundle config = getPersistableBundle(subId);
         return (config.getInt(
@@ -6294,6 +6631,12 @@
                     if (info.isSatelliteESOSSupported()) {
                         if (mSubscriptionManagerService.isSatelliteProvisionedForNonIpDatagram(
                                 info.getSubscriptionId())) {
+                            Pair<String, Integer> subscriberIdPair = getSubscriberIdAndType(
+                                    mSubscriptionManagerService.getSubscriptionInfo(subId));
+                            String subscriberId = subscriberIdPair.first;
+                            synchronized (mSatelliteTokenProvisionedLock) {
+                                mProvisionedSubscriberId.put(subscriberId, true);
+                            }
                             return true;
                         }
                     }
@@ -6407,6 +6750,45 @@
         }
     }
 
+    private void startWaitForUpdateSystemSelectionChannelsResponseTimer(
+            @NonNull UpdateSystemSelectionChannelsArgument argument) {
+        synchronized (mSatelliteEnabledRequestLock) {
+            if (hasMessages(
+                    EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT, argument)) {
+                plogd("WaitForUpdateSystemSelectionChannelsResponseTimer of request ID "
+                        + argument.requestId + " was already started");
+                return;
+            }
+            plogd("Start timer to wait for response of the system selection channels update request"
+                    + " ID=" + argument.requestId + ", mWaitTimeForSatelliteEnablingResponse="
+                    + mWaitTimeForSatelliteEnablingResponse);
+            sendMessageDelayed(
+                obtainMessage(EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT,
+                    argument), mWaitTimeForSatelliteEnablingResponse);
+        }
+    }
+
+    private void stopWaitForUpdateSystemSelectionChannelsResponseTimer(
+            @NonNull UpdateSystemSelectionChannelsArgument argument) {
+        synchronized (mSatelliteEnabledRequestLock) {
+            plogd("Stop timer to wait for response of the system selection channels"
+                      + " update request ID=" + argument.requestId);
+            removeMessages(
+                EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT, argument);
+        }
+    }
+
+    private boolean shouldProcessEventUpdateSystemSelectionChannelsDone(
+            @NonNull UpdateSystemSelectionChannelsArgument argument) {
+        synchronized (mSatelliteEnabledRequestLock) {
+            if (hasMessages(
+                    EVENT_WAIT_FOR_UPDATE_SYSTEM_SELECTION_CHANNELS_RESPONSE_TIMED_OUT, argument)) {
+                return true;
+            }
+            return false;
+        }
+    }
+
     private void startWaitForUpdateSatelliteEnableAttributesResponseTimer(
             @NonNull RequestSatelliteEnabledArgument argument) {
         synchronized (mSatelliteEnabledRequestLock) {
@@ -6482,7 +6864,7 @@
             mSessionMetricsStats.setInitializationResult(SATELLITE_RESULT_MODEM_TIMEOUT)
                     .setSatelliteTechnology(getSupportedNtnRadioTechnology())
                     .setInitializationProcessingTime(
-                            System.currentTimeMillis() - mSessionProcessingTimeStamp)
+                            getElapsedRealtime() - mSessionProcessingTimeStamp)
                     .setIsDemoMode(mIsDemoModeEnabled)
                     .setCarrierId(getSatelliteCarrierId())
                     .reportSessionMetrics();
@@ -6492,7 +6874,7 @@
             mSessionMetricsStats.setTerminationResult(SATELLITE_RESULT_MODEM_TIMEOUT)
                     .setSatelliteTechnology(getSupportedNtnRadioTechnology())
                     .setTerminationProcessingTime(
-                            System.currentTimeMillis() - mSessionProcessingTimeStamp)
+                            getElapsedRealtime() - mSessionProcessingTimeStamp)
                     .setSessionDurationSec(calculateSessionDurationTimeSec())
                     .reportSessionMetrics();
         }
@@ -6502,12 +6884,6 @@
     }
 
     private void handleCmdUpdateNtnSignalStrengthReporting(boolean shouldReport) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("handleCmdUpdateNtnSignalStrengthReporting: oemEnabledSatelliteFlag is "
-                    + "disabled");
-            return;
-        }
-
         if (!isSatelliteEnabledOrBeingEnabled()) {
             plogd("handleCmdUpdateNtnSignalStrengthReporting: ignore request, satellite is "
                     + "disabled");
@@ -6526,12 +6902,6 @@
     }
 
     private void updateNtnSignalStrengthReporting(boolean shouldReport) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("updateNtnSignalStrengthReporting: oemEnabledSatelliteFlag is "
-                    + "disabled");
-            return;
-        }
-
         SatelliteControllerHandlerRequest request = new SatelliteControllerHandlerRequest(
                 shouldReport, SatelliteServiceUtils.getPhone());
         Message onCompleted = obtainMessage(EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE,
@@ -6556,11 +6926,6 @@
      * @return {@code true} if the operation is successful, {@code false} otherwise.
      */
     public boolean setShouldSendDatagramToModemInDemoMode(boolean shouldSendToModemInDemoMode) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            plogd("setShouldSendDatagramToModemInDemoMode: oemEnabledSatelliteFlag is disabled");
-            return false;
-        }
-
         if (!isMockModemAllowed()) {
             plogd("setShouldSendDatagramToModemInDemoMode: mock modem not allowed.");
             return false;
@@ -6571,21 +6936,33 @@
     }
 
     private void determineAutoConnectSystemNotification() {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
-            logd("determineSystemNotification: carrierEnabledSatelliteFlag is disabled");
-            return;
-        }
-
         Pair<Boolean, Integer> isNtn = isUsingNonTerrestrialNetworkViaCarrier();
-        boolean notificationKeyStatus = mSharedPreferences.getBoolean(
+        boolean suppressSatelliteNotification = mSharedPreferences.getBoolean(
                 SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false);
+        if (suppressSatelliteNotification) {
+            // System already displayed the notification and user interacted with it.
+            // System will show notification again after 30 days.
+            long lastSetTimestamp = mSharedPreferences.getLong(
+                    SATELLITE_SYSTEM_NOTIFICATION_TIME, 0L);
+            logv("determineAutoConnectSystemNotification lastSetTimestamp = " + lastSetTimestamp);
+            long currentTime = System.currentTimeMillis();
+            int subId = getSelectedSatelliteSubId();
+            long throttleTime = getNotificationDisplayThrottleTimeout(subId);
+            if (lastSetTimestamp == 0L || currentTime - lastSetTimestamp >= throttleTime) {
+                // Reset the flag and update the timestamp
+                logd("determineAutoConnectSystemNotification: reset preference data");
+                suppressSatelliteNotification = false;
+                mSharedPreferences.edit().putBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY,
+                        false).remove(SATELLITE_SYSTEM_NOTIFICATION_TIME).apply();
+            }
+        }
         if (DEBUG) {
             logd("determineAutoConnectSystemNotification: isNtn.first = " + isNtn.first
-                    + " IsNotiToShow = " + !notificationKeyStatus + " mIsNotificationShowing = "
-                    + mIsNotificationShowing);
+                    + " IsNotiToShow = " + !suppressSatelliteNotification
+                    + " mIsNotificationShowing = " + mIsNotificationShowing);
         }
         if (isNtn.first) {
-            if (!notificationKeyStatus && getCarrierRoamingNtnConnectType(isNtn.second)
+            if (!suppressSatelliteNotification && getCarrierRoamingNtnConnectType(isNtn.second)
                     == CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC) {
                 updateSatelliteSystemNotification(isNtn.second,
                         CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC,
@@ -6617,7 +6994,21 @@
         if(isSatelliteSupported == null) {
             return false;
         }
-        return notifySatelliteAvailabilityEnabled && isSatelliteSupported;
+        int subId = getSelectedSatelliteSubId();
+        SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(subId);
+        logd("isSatelliteSystemNotificationsEnabled: SatelliteSubId = " + subId);
+        return notifySatelliteAvailabilityEnabled
+                && isSatelliteSupported
+                && isValidSubscriptionId(subId)
+                && ((isSatelliteSupportedViaCarrier(subId)
+                && (getCarrierRoamingNtnConnectType(subId)
+                == CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL))
+                || subInfo.isOnlyNonTerrestrialNetwork());
+    }
+
+    private boolean isDataServiceSupported(int subId) {
+        int[] services = getSupportedServicesOnCarrierRoamingNtn(subId);
+        return ArrayUtils.contains(services, NetworkRegistrationInfo.SERVICE_TYPE_DATA);
     }
 
     /**
@@ -6658,13 +7049,17 @@
         }
         notificationManager.createNotificationChannel(notificationChannel);
 
-        // if carrierRoamingNtnConnectType is CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC
         int title = R.string.satellite_notification_title;
         int summary = R.string.satellite_notification_summary;
         if (carrierRoamingNtnConnectType
                 == CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
             title = R.string.satellite_notification_manual_title;
             summary = R.string.satellite_notification_manual_summary;
+        } else if (carrierRoamingNtnConnectType
+                == CarrierConfigManager.CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC
+                && isDataServiceSupported(subId)) {
+            // In Auto Connected mode, if data services supported, show data supported summary
+            summary = R.string.satellite_notification_summary_with_data;
         }
 
         Notification.Builder notificationBuilder = new Notification.Builder(mContext,
@@ -6725,7 +7120,7 @@
                 Context.RECEIVER_EXPORTED);
 
         mIsNotificationShowing = true;
-        mCarrierRoamingSatelliteControllerStats.reportCountOfSatelliteNotificationDisplayed();
+        mCarrierRoamingSatelliteControllerStats.reportCountOfSatelliteNotificationDisplayed(subId);
         mCarrierRoamingSatelliteControllerStats.reportCarrierId(getSatelliteCarrierId());
         mSessionMetricsStats.addCountOfSatelliteNotificationDisplayed();
     }
@@ -6798,20 +7193,18 @@
         }
         // update the sharedpref only when user interacted with the notification.
         mSharedPreferences.edit().putBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, true).apply();
+        mSharedPreferences.edit().putLong(SATELLITE_SYSTEM_NOTIFICATION_TIME,
+                System.currentTimeMillis()).apply();
         mContext.unregisterReceiver(mNotificationInteractionBroadcastReceiver);
     }
 
     private void resetCarrierRoamingSatelliteModeParams() {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) return;
-
         for (Phone phone : PhoneFactory.getPhones()) {
             resetCarrierRoamingSatelliteModeParams(phone.getSubId());
         }
     }
 
     private void resetCarrierRoamingSatelliteModeParams(int subId) {
-        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) return;
-
         synchronized (mSatelliteConnectedLock) {
             mLastSatelliteDisconnectedTimesMillis.put(subId, null);
             mSatModeCapabilitiesForCarrierRoaming.remove(subId);
@@ -6841,7 +7234,7 @@
     // Should be invoked only when session termination done or session termination failed.
     private int calculateSessionDurationTimeSec() {
         return (int) (
-                (System.currentTimeMillis() - mSessionStartTimeStamp
+                (getElapsedRealtime() - mSessionStartTimeStamp
                 - mSessionMetricsStats.getSessionInitializationProcessingTimeMillis()
                 - mSessionMetricsStats.getSessionTerminationProcessingTimeMillis()) / 1000);
     }
@@ -6954,57 +7347,44 @@
     }
 
     private static void logv(@NonNull String log) {
-        Rlog.v(TAG, log);
+        Log.v(TAG, log);
     }
 
     private static void logd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
     }
 
     private static void logw(@NonNull String log) {
-        Rlog.w(TAG, log);
+        Log.w(TAG, log);
     }
 
     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;
-        }
+        Log.e(TAG, log);
     }
 
     private void plogd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.debug(TAG, log);
         }
     }
 
     private void plogw(@NonNull String log) {
-        Rlog.w(TAG, log);
+        Log.w(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.warn(TAG, log);
         }
     }
 
     private void ploge(@NonNull String log) {
-        Rlog.e(TAG, log);
+        Log.e(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.error(TAG, log);
         }
     }
 
     private void plogv(@NonNull String log) {
-        Rlog.v(TAG, log);
+        Log.v(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.debug(TAG, log);
         }
@@ -7194,7 +7574,7 @@
     private Pair<String, Integer> getSubscriberIdAndType(@Nullable SubscriptionInfo info) {
         String subscriberId = "";
         @SatelliteSubscriberInfo.SubscriberIdType int subscriberIdType =
-                SatelliteSubscriberInfo.ICCID;
+                SatelliteSubscriberInfo.SUBSCRIBER_ID_TYPE_ICCID;
         if (info == null) {
             logd("getSubscriberIdAndType: subscription info is null");
             return new Pair<>(subscriberId, subscriberIdType);
@@ -7203,29 +7583,59 @@
             subscriberId = info.getIccId();
         } else if (info.isSatelliteESOSSupported()) {
             subscriberId = getPhoneNumberBasedCarrier(info.getSubscriptionId());
-            subscriberIdType = SatelliteSubscriberInfo.IMSI_MSISDN;
+            subscriberIdType = SatelliteSubscriberInfo.SUBSCRIBER_ID_TYPE_IMSI_MSISDN;
         }
-        logd("getSubscriberIdAndType: subscriberId=" + subscriberId + ", subscriberIdType="
-                + subscriberIdType);
+        logd("getSubscriberIdAndType: subscriberId="
+                + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, subscriberId)
+                + ", subscriberIdType=" + subscriberIdType);
         return new Pair<>(subscriberId, subscriberIdType);
     }
 
-    private String getPhoneNumberBasedCarrier(int subId) {
+    /** Get subscriberId from phone number and carrier information. */
+    @VisibleForTesting(visibility =  VisibleForTesting.Visibility.PRIVATE)
+    public String getPhoneNumberBasedCarrier(int subId) {
+        String subscriberId = "";
         SubscriptionInfoInternal internal = mSubscriptionManagerService.getSubscriptionInfoInternal(
                 subId);
+        if (internal == null) {
+            plogd("getPhoneNumberBasedCarrier: subscriptionInfoInternal is null.");
+            return subscriberId;
+        }
+
         SubscriptionManager subscriptionManager = mContext.getSystemService(
                 SubscriptionManager.class);
         if (mInjectSubscriptionManager != null) {
-            logd("getPhoneNumberBasedCarrier: InjectSubscriptionManager");
+            plogd("getPhoneNumberBasedCarrier: InjectSubscriptionManager");
             subscriptionManager = mInjectSubscriptionManager;
         }
-        String phoneNumber = subscriptionManager.getPhoneNumber(subId);
-        if (phoneNumber == null) {
-            logd("getPhoneNumberBasedCarrier: phoneNumber null");
-            return "";
+
+        if (subscriptionManager == null) {
+            plogd("getPhoneNumberBasedCarrier: subscriptionManager is null");
+            return subscriberId;
         }
-        return internal.getImsi() == null ? "" : internal.getImsi().substring(0, 6)
+
+        String phoneNumber = subscriptionManager.getPhoneNumber(subId);
+        if (TextUtils.isEmpty(phoneNumber)) {
+            plogd("getPhoneNumberBasedCarrier: phoneNumber is empty.");
+            return subscriberId;
+        }
+
+        String imsi = internal.getImsi();
+        if (TextUtils.isEmpty(imsi)) {
+            plogd("getPhoneNumberBasedCarrier: imsi is empty");
+            return subscriberId;
+        }
+
+        if (imsi.length() < 6) {
+            plogd("getPhoneNumberBasedCarrier: imsi length is less than 6");
+            return subscriberId;
+        }
+
+        subscriberId = internal.getImsi().substring(0, 6)
                 + phoneNumber.replaceFirst("^\\+", "");
+        plogd("getPhoneNumberBasedCarrier: subscriberId="
+                + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, subscriberId));
+        return subscriberId;
     }
 
     private boolean isPriorityChanged(Map<Integer, List<SubscriptionInfo>> currentMap,
@@ -7332,6 +7742,7 @@
      */
     public void requestSatelliteSubscriberProvisionStatus(@NonNull ResultReceiver result) {
         if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+            logd("requestSatelliteSubscriberProvisionStatus: carrierRoamingNbIotNtn is disabled");
             result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
             return;
         }
@@ -7368,8 +7779,10 @@
                     int carrierId = info.getCarrierId();
                     String apn = getConfigForSubId(info.getSubscriptionId())
                             .getString(KEY_SATELLITE_NIDD_APN_NAME_STRING, "");
-                    logd("getPrioritySatelliteSubscriberProvisionStatusList: subscriberId:"
-                            + subscriberId + " , carrierId=" + carrierId + " , apn=" + apn);
+                    logd("getPrioritySatelliteSubscriberProvisionStatusList:"
+                            + " subscriberId:"
+                            + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, subscriberId)
+                            + " , carrierId=" + carrierId + " , apn=" + apn);
                     if (subscriberId.isEmpty()) {
                         logd("getPrioritySatelliteSubscriberProvisionStatusList: getSubscriberId "
                                 + "failed skip this subscriberId.");
@@ -7378,7 +7791,7 @@
                     SatelliteSubscriberInfo satelliteSubscriberInfo =
                             new SatelliteSubscriberInfo.Builder().setSubscriberId(subscriberId)
                                     .setCarrierId(carrierId).setNiddApn(apn)
-                                    .setSubId(info.getSubscriptionId())
+                                    .setSubscriptionId(info.getSubscriptionId())
                                     .setSubscriberIdType(subscriberIdPair.second)
                                     .build();
                     boolean provisioned = mProvisionedSubscriberId.getOrDefault(subscriberId,
@@ -7397,10 +7810,8 @@
     }
 
     public int getSelectedSatelliteSubId() {
-        synchronized (mSatelliteTokenProvisionedLock) {
-            plogd("getSelectedSatelliteSubId: subId=" + mSelectedSatelliteSubId);
-            return mSelectedSatelliteSubId;
-        }
+        plogd("getSelectedSatelliteSubId: subId=" + mSelectedSatelliteSubId);
+        return mSelectedSatelliteSubId;
     }
 
     /**
@@ -7463,6 +7874,9 @@
         setSelectedSatelliteSubId(selectedSubId);
         if (preSelectedSatelliteSubId != getSelectedSatelliteSubId()) {
             plogd("selectBindingSatelliteSubscription: SelectedSatelliteSubId changed");
+            mSatelliteSubIdChangedRegistrants.notifyRegistrants();
+            handleEventSelectedNbIotSatelliteSubscriptionChanged(selectedSubId);
+            handleCarrierRoamingNtnAvailableServicesChanged();
             evaluateCarrierRoamingNtnEligibilityChange();
         }
 
@@ -7477,8 +7891,6 @@
             mControllerMetricsStats.setIsNtnOnlyCarrier(isNtnOnlyCarrier());
         }
         plogd("selectBindingSatelliteSubscription: SelectedSatelliteSubId=" + selectedSubId);
-        handleEventSelectedNbIotSatelliteSubscriptionChanged(selectedSubId);
-        handleCarrierRoamingNtnAvailableServicesChanged();
     }
 
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@@ -7498,6 +7910,11 @@
             plogd("isSatelliteAvailableAtCurrentLocation: subscriptionInfo is null");
             return false;
         }
+        if (mCtsSatelliteAccessAllowedSubIds.contains(info.getSubscriptionId())) {
+            plogd("isSatelliteAvailableAtCurrentLocation: subscriptionId="
+                      + info.getSubscriptionId() + " is allowed for CTS testing");
+            return true;
+        }
         if (!isSatelliteAccessAllowedAtCurrentLocation()) {
             plogd("isSatelliteAvailableAtCurrentLocation: satellite access is not allowed at " +
                     "current location");
@@ -7518,14 +7935,37 @@
         }
 
         if(carrierTagIds == null) {
-            plogd("isSatelliteAvailableAtCurrentLocation: tagids for carrier satellite enabled " +
-                    "are not available");
-            return false;
+            String satelliteAccessConfigFile =
+                getSatelliteAccessConfigurationFileFromOverlayConfig();
+            if (TextUtils.isEmpty(satelliteAccessConfigFile)) {
+                plogd("isSatelliteAvailableAtCurrentLocation: device does not support"
+                          + " custom satellite access configuration per location");
+                return true;
+            } else {
+                plogd("isSatelliteAvailableAtCurrentLocation: tagids for carrier "
+                          + info.getCarrierName() + ", subId=" + info.getSubscriptionId()
+                          + " are not available");
+                return false;
+            }
         }
 
         return isCarrierSatelliteAvailableAtCurrentLocation(carrierTagIds);
     }
 
+    @Nullable
+    private String getSatelliteAccessConfigurationFileFromOverlayConfig() {
+        String satelliteAccessConfigFile = null;
+        try {
+            satelliteAccessConfigFile = mContext.getResources().getString(
+                    com.android.internal.R.string.satellite_access_config_file);
+        } catch (Resources.NotFoundException ex) {
+            loge("getSatelliteAccessConfigurationFileFromOverlayConfig: got ex=" + ex);
+        }
+
+        logd("satelliteAccessConfigFile =" + satelliteAccessConfigFile);
+        return satelliteAccessConfigFile;
+    }
+
     /**
      * Compares tagIds and determine if
      * carrier satellite is available at current location while selecting highest priority profile.
@@ -7762,15 +8202,13 @@
 
     /** Return the carrier ID of the binding satellite subscription. */
     public int getSatelliteCarrierId() {
-        synchronized (mSatelliteTokenProvisionedLock) {
-            SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(
-                    mSelectedSatelliteSubId);
-            if (subInfo == null) {
-                logd("getSatelliteCarrierId: returns UNKNOWN_CARRIER_ID");
-                return UNKNOWN_CARRIER_ID;
-            }
-            return subInfo.getCarrierId();
+        SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(
+            mSelectedSatelliteSubId);
+        if (subInfo == null) {
+            logd("getSatelliteCarrierId: returns UNKNOWN_CARRIER_ID");
+            return UNKNOWN_CARRIER_ID;
         }
+        return subInfo.getCarrierId();
     }
 
     /**
@@ -7805,6 +8243,13 @@
             return false;
         }
 
+        // Even if Location service is off, isSatelliteAccessAllowed can be true
+        // when the device is in emergency call and the allowed cache is valid.
+        if (!isLocationServiceEnabled()) {
+            plogd("isCarrierRoamingNtnEligible: Location service is off");
+            return false;
+        }
+
         if (phone == null) {
             plogd("isCarrierRoamingNtnEligible: phone is null");
             return false;
@@ -7905,52 +8350,97 @@
     }
 
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
-    protected void registerForSatelliteCommunicationAllowedStateChanged() {
-        if (mRegisteredForSatelliteCommunicationAllowedStateChanged.get()) {
+    protected void registerForSatelliteCommunicationAccessStateChanged() {
+        if (mRegisteredForSatelliteCommunicationAccessStateChanged.get()) {
             if (DEBUG) {
-                plogd("registerForSatelliteCommunicationAllowedStateChanged: already registered.");
+                plogd("registerForSatelliteCommunicationAccessStateChanged: already registered.");
             }
             return;
         }
 
         SatelliteManager satelliteManager = mContext.getSystemService(SatelliteManager.class);
         if (satelliteManager == null) {
-            ploge("registerForSatelliteCommunicationAllowedStateChanged: SatelliteManager is null");
+            ploge("registerForSatelliteCommunicationAccessStateChanged: SatelliteManager is null");
             return;
         }
 
-        SatelliteCommunicationAllowedStateCallback allowedStateCallback =
-            new SatelliteCommunicationAllowedStateCallback() {
+        SatelliteCommunicationAccessStateCallback accessStateCallback =
+            new SatelliteCommunicationAccessStateCallback() {
                 @Override
-                public void onSatelliteCommunicationAllowedStateChanged(boolean isAllowed) {
-                    plogd("onSatelliteCommunicationAllowedStateChanged: isAllowed="
-                        + isAllowed);
-                    synchronized (mSatelliteAccessConfigLock) {
-                        mSatelliteAccessAllowed = isAllowed;
+                public void onAccessAllowedStateChanged(boolean isAllowed) {
+                    plogd("onAccessStateChanged: isAllowed=" + isAllowed);
+                    if (mFeatureFlags.satelliteExitP2pSessionOutsideGeofence()) {
+                        handleSatelliteAccessAllowedStateChanged(isAllowed);
+                    } else{
+                        synchronized (mSatelliteAccessConfigLock) {
+                            mSatelliteAccessAllowed = isAllowed;
+                        }
+                        evaluateESOSProfilesPrioritization();
+                        evaluateCarrierRoamingNtnEligibilityChange();
+                        handleCarrierRoamingNtnAvailableServicesChanged();
                     }
-                    evaluateESOSProfilesPrioritization();
-                    evaluateCarrierRoamingNtnEligibilityChange();
-                    handleCarrierRoamingNtnAvailableServicesChanged();
                 }
 
                 @Override
-                public void onSatelliteAccessConfigurationChanged(
+                public void onAccessConfigurationChanged(
                     SatelliteAccessConfiguration satelliteAccessConfiguration) {
-                    plogd("onSatelliteAccessConfigurationChanged: satelliteAccessConfiguration="
+                    plogd("onAccessConfigurationChanged: satelliteAccessConfiguration="
                         + satelliteAccessConfiguration);
                     handleSatelliteAccessConfigUpdateResult(satelliteAccessConfiguration);
                 }
             };
         try {
-            satelliteManager.registerForCommunicationAllowedStateChanged(
-                    this::post, allowedStateCallback);
+            satelliteManager.registerForCommunicationAccessStateChanged(
+                    this::post, accessStateCallback);
         } catch(RuntimeException e) {
-            plogd("registerForSatelliteCommunicationAllowedStateChanged: " +
-                    "satelliteManager.registerForCommunicationAllowedStateChanged() failed, " +
-                    "e=" + e);
+            plogd("registerForSatelliteCommunicationAccessStateChanged: "
+                    + "satelliteManager.registerForCommunicationAccessStateChanged() failed, "
+                    + "e=" + e);
             return;
         }
-        mRegisteredForSatelliteCommunicationAllowedStateChanged.set(true);
+        mRegisteredForSatelliteCommunicationAccessStateChanged.set(true);
+    }
+
+    /** Handle access allowed state changes. */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public void handleSatelliteAccessAllowedStateChanged(boolean isAllowed) {
+        plogd("handleSatelliteAccessAllowedStateChanged: isAllowed=" + isAllowed);
+        synchronized (mSatelliteAccessConfigLock) {
+            mSatelliteAccessAllowed = isAllowed;
+        }
+
+        evaluateESOSProfilesPrioritization();
+        selectBindingSatelliteSubscription(false);
+        evaluateCarrierRoamingNtnEligibilityChange();
+        handleCarrierRoamingNtnAvailableServicesChanged();
+        evaluateDisablingP2pSession();
+    }
+
+    private void evaluateDisablingP2pSession() {
+        boolean isAllowed = isSatelliteAccessAllowedAtCurrentLocation();
+        boolean isSatelliteEnabled = isSatelliteEnabled();
+        boolean isEmergency = getRequestIsEmergency();
+
+        plogd("evaluateDisablingP2pSession: isAllowed=" + isAllowed
+                + " isEmergency=" + isEmergency
+                + " isSatelliteEnabled:" + isSatelliteEnabled);
+        if (!isAllowed && isSatelliteEnabled && !isEmergency) {
+            // Disable P2P session if satellite is not allowed in current location
+            disableSatelliteSession(isEmergency);
+        }
+    }
+
+    private void disableSatelliteSession(boolean isEmergency) {
+        plogd("disableSatelliteSession: isEmergency=" + isEmergency);
+        requestSatelliteEnabled(false /* enableSatellite */,
+                false /* enableDemoMode */, isEmergency,
+                new IIntegerConsumer.Stub() {
+                    @Override
+                    public void accept(int result) {
+                        plogd("disableSatelliteSession:"
+                                + " requestSatelliteEnabled result=" + result);
+                    }
+                });
     }
 
     private void handleSatelliteAccessConfigUpdateResult(
@@ -8074,6 +8564,42 @@
         return result;
     }
 
+    /**
+     * This API can be used by only CTS to override the satellite access allowed state for
+     * a list of subscription IDs.
+     *
+     * @param subIdListStr The string representation of the list of subscription IDs,
+     *                     which are numbers separated by comma.
+     * @return {@code true} if the satellite access allowed state is set successfully,
+     * {@code false} otherwise.
+     */
+    public boolean setSatelliteAccessAllowedForSubscriptions(@Nullable String subIdListStr) {
+        if (!isMockModemAllowed()) {
+            plogd("setSatelliteAccessAllowedForSubscriptions: mock modem not allowed");
+            return false;
+        }
+
+        plogd("setSatelliteAccessAllowedForSubscriptions: subIdListStr=" + subIdListStr);
+        if (subIdListStr == null) {
+            mCtsSatelliteAccessAllowedSubIds.clear();
+            return true;
+        }
+
+        List<Integer> subIdList = new ArrayList<>();
+        for (String subIdStr : subIdListStr.split(",")) {
+            try {
+                subIdList.add(Integer.parseInt(subIdStr));
+            } catch (NumberFormatException e) {
+                plogd("setSatelliteAccessAllowedForSubscriptions: invalid subIdStr=" + subIdStr);
+                return false;
+            }
+        }
+        mCtsSatelliteAccessAllowedSubIds.clear();
+        mCtsSatelliteAccessAllowedSubIds.addAll(subIdList);
+        selectBindingSatelliteSubscription(false);
+        return true;
+    }
+
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected String getConfigSatelliteGatewayServicePackage() {
         if (!mChangeIntentComponent) {
@@ -8225,19 +8751,45 @@
         int carrierId = subInfo.getCarrierId();
         String apn = getConfigForSubId(subInfo.getSubscriptionId())
                 .getString(KEY_SATELLITE_NIDD_APN_NAME_STRING, "");
-        logd("getSatelliteSubscriberInfo: subInfo: " + subInfo + ", subscriberId:"
-                + subscriberId + " , carrierId=" + carrierId + " , apn=" + apn);
+        logd("getSatelliteSubscriberInfo: subInfo: " + subInfo
+                + ", subscriberId:" + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, subscriberId)
+                + " , carrierId=" + carrierId + " , apn=" + apn);
         if (subscriberId.isEmpty()) {
             logw("getSatelliteSubscriberInfo: not a satellite subscription.");
             return null;
         }
         return new SatelliteSubscriberInfo.Builder().setSubscriberId(subscriberId)
                         .setCarrierId(carrierId).setNiddApn(apn)
-                        .setSubId(subInfo.getSubscriptionId())
+                        .setSubscriptionId(subInfo.getSubscriptionId())
                         .setSubscriberIdType(subscriberIdPair.second)
                         .build();
     }
 
+    /**
+     * The method will notify the change in the services update the
+     * mEntitlementServiceTypeMapPerCarrier.
+     *
+     * @param subId              : SubscriptionId
+     * @param plmnServiceTypeMap : entitlement service map.
+     */
+    private void updateAndNotifyChangesInCarrierRoamingNtnAvailableServices(int subId,
+            Map<String, List<Integer>> plmnServiceTypeMap) {
+        // If a service list is already cached, check it for changes
+        int[] existingServices = getSupportedServicesOnCarrierRoamingNtn(subId);
+        synchronized (mSupportedSatelliteServicesLock) {
+            mEntitlementServiceTypeMapPerCarrier.put(subId, plmnServiceTypeMap);
+        }
+        int[] updatedServices = getSupportedServicesOnCarrierRoamingNtn(subId);
+        if (existingServices.length > 0 && Arrays.equals(existingServices, updatedServices)) {
+            plogd("No change in Entitlement service support data");
+            return;
+        }
+        if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+            updateLastNotifiedNtnAvailableServicesAndNotify(subId);
+            evaluateCarrierRoamingNtnEligibilityChange();
+        }
+    }
+
     private void handleCarrierRoamingNtnAvailableServicesChanged() {
         int[] activeSubIds = mSubscriptionManagerService.getActiveSubIdList(true);
         if (activeSubIds == null) {
@@ -8279,11 +8831,47 @@
         phone.notifyCarrierRoamingNtnAvailableServicesChanged(services);
     }
 
-    /** Return services that are supported on carrier roaming non-terrestrial network. */
+    private int[] getAvailableServicesWithEntitlementForSubId(int subId) {
+        synchronized (mSupportedSatelliteServicesLock) {
+            Map<String, List<Integer>> allowedServicesList =
+                    mEntitlementServiceTypeMapPerCarrier.get(subId);
+            if (allowedServicesList != null && !allowedServicesList.isEmpty()) {
+                Set<Integer> serviceTypes = new HashSet<>();
+                for (List<Integer> values : allowedServicesList.values()) {
+                    serviceTypes.addAll(values);
+                }
+
+                int[] result = new int[serviceTypes.size()];
+                int i = 0;
+                for (int value : serviceTypes) {
+                    result[i++] = value;
+                }
+                return result;
+            } else {
+                return new int[0]; // Return an empty array if the map is null or empty
+            }
+        }
+    }
+
+    /**
+     * Given a subscription ID, this returns the carriers' supported services on
+     * non-terrestrial networks.
+     *
+     * @param subId Associated subscription ID.
+     * return supported services at entitlement for the available carriers. Note: If available
+     *        services/allowed service type field is empty at entitlement, information from
+     *        {@link
+     *        CarrierConfigManager#KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY}
+     *        will be returned.
+     */
     public int[] getSupportedServicesOnCarrierRoamingNtn(int subId) {
-        if (isSatelliteSupportedViaCarrier(subId)) {
-            // TODO: b/377367448 Cleanup get supported satellite services to align with starlink.
-            int[] services = getSupportedSatelliteServicesForCarrier(subId);
+        if (isValidSubscriptionId(subId) && isSatelliteSupportedViaCarrier(subId)) {
+            // check available services supported at entitlement for sub id
+            int[] services = getAvailableServicesWithEntitlementForSubId(subId);
+            logd("getAvailableServicesWithEntitlementForSubId: " + Arrays.toString(services));
+            if (services.length == 0) {
+                services = getSupportedSatelliteServicesForCarrier(subId);
+            }
             if (isP2PSmsDisallowedOnCarrierRoamingNtn(subId)) {
                 services = Arrays.stream(services).filter(
                         value -> value != NetworkRegistrationInfo.SERVICE_TYPE_SMS).toArray();
@@ -8300,7 +8888,6 @@
      * return {@code true} when the phone does not support P2P SMS over carrier roaming satellite
      *        {@code false} otherwise
      */
-    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     public boolean isP2PSmsDisallowedOnCarrierRoamingNtn(int subId) {
         int carrierRoamingNtnConnectType = getCarrierRoamingNtnConnectType(subId);
         if (carrierRoamingNtnConnectType == CARRIER_ROAMING_NTN_CONNECT_MANUAL) {
@@ -8372,6 +8959,12 @@
                 mContext.RECEIVER_EXPORTED);
     }
 
+    private void registerLocationServiceStateChanged() {
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION);
+        mContext.registerReceiver(mLocationServiceStateChangedReceiver, intentFilter);
+    }
+
 
     private void notifyEnabledStateChanged(boolean isEnabled) {
         TelephonyRegistryManager trm = mContext.getSystemService(TelephonyRegistryManager.class);
@@ -8600,9 +9193,35 @@
     }
 
     /**
+     * Check if the available satellite services support
+     * {@link NetworkRegistrationInfo#SERVICE_TYPE_DATA} service or not.
+     *
+     * @return {@code true} if data services is supported, otherwise {@code false}.
+     */
+    private boolean isSatelliteDataServicesAllowed(int subId, String plmn) {
+        // validate is available services support data, for satellite internet bringup
+        List<Integer> availableServices = getSupportedSatelliteServicesForPlmn(subId, plmn);
+        return availableServices.stream().anyMatch(num -> num
+                == NetworkRegistrationInfo.SERVICE_TYPE_DATA);
+    }
+
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    protected boolean isLocationServiceEnabled() {
+        LocationManager lm = mContext.createAttributionContext("telephony")
+                .getSystemService(LocationManager.class);
+        if (lm != null) {
+            return lm.isLocationEnabled();
+        }
+
+        return true;
+    }
+
+    /**
      * Method to return the current satellite data service policy supported mode for the registered
      * plmn based on entitlement provisioning information. Note: If no information at
-     * provisioning is supported this is overridden with operator carrier config information.
+     * provisioning is supported this is overridden with operator carrier config information
+     * if available satellite services support data else data service policy is marked as
+     * restricted.
      *
      * @param subId current subscription id
      * @param plmn current registered plmn information
@@ -8610,18 +9229,43 @@
      * @return Supported modes {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE}
      */
     public int getSatelliteDataServicePolicyForPlmn(int subId, String plmn) {
-        if (plmn != null) {
+        plogd("getSatelliteDataServicePolicyForPlmn: subId=" + subId + " plmn=" + plmn);
+        if (isValidSubscriptionId(subId)) {
+            Map<String, Integer> dataServicePolicy;
             synchronized (mSupportedSatelliteServicesLock) {
-                Map<String, Integer> dataServicePolicy =
-                        mEntitlementDataServicePolicyMapPerCarrier.get(
-                        subId);
-                logd("data policy available for sub id:" + dataServicePolicy);
-                if (dataServicePolicy != null && dataServicePolicy.containsKey(plmn)) {
+                dataServicePolicy = mEntitlementDataServicePolicyMapPerCarrier.get(subId);
+            }
+            plogd("getSatelliteDataServicePolicyForPlmn: dataServicePolicy=" + dataServicePolicy);
+
+            if (dataServicePolicy != null) {
+                if (!TextUtils.isEmpty(plmn) && dataServicePolicy.containsKey(plmn)) {
+                    plogd("getSatelliteDataServicePolicyForPlmn: "
+                            + "return policy using dataServicePolicy map");
                     return dataServicePolicy.get(plmn);
+                } else if (TextUtils.isEmpty(plmn)) {
+                    int preferredPolicy =
+                            CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED;
+                    for (String plmnKey : dataServicePolicy.keySet()) {
+                        int policy = dataServicePolicy.get(plmnKey);
+                        // higher value has higher preference
+                        if (policy > preferredPolicy) {
+                            preferredPolicy = policy;
+                        }
+                    }
+                    plogd("getSatelliteDataServicePolicyForPlmn: "
+                            + "return preferredPolicy=" + preferredPolicy);
+                    return preferredPolicy;
                 }
             }
+
+            if (isSatelliteDataServicesAllowed(subId, plmn)) {
+                plogd("getSatelliteDataServicePolicyForPlmn: return data support mode from config");
+                return getCarrierSatelliteDataSupportedModeFromConfig(subId);
+            }
         }
-        return getCarrierSatelliteDataSupportedMode(subId);
+
+        plogd("getSatelliteDataServicePolicyForPlmn: return data support only restricted");
+        return CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED;
     }
 
     /**
@@ -8641,7 +9285,8 @@
                         mEntitlementVoiceServicePolicyMapPerCarrier.get(
                                 subId);
                 logd("voice policy available for sub id:" + voiceServicePolicy);
-                if (voiceServicePolicy != null && voiceServicePolicy.containsKey(plmn)) {
+                if (voiceServicePolicy != null && voiceServicePolicy.containsKey(plmn)
+                        && !plmn.isEmpty()) {
                     return voiceServicePolicy.get(plmn);
                 }
             }
@@ -8650,4 +9295,52 @@
         // is added)
         return 0; // Restricted
     }
+
+    /**
+     * Get list of applications that are optimized for low bandwidth satellite data.
+     *
+     * @param userId is Identifier of user
+     *
+     * @return List of Application Name with data optimized network property.
+     * {@link #PROPERTY_SATELLITE_DATA_OPTIMIZED}
+     */
+    public List<String> getSatelliteDataOptimizedApps(int userId) {
+        if (mFeatureFlags.carrierRoamingNbIotNtn()) {
+            return mSatelliteOptimizedApplicationsTracker.getSatelliteOptimizedApplications(userId);
+        } else {
+            return new ArrayList<>();
+        }
+    }
+
+    /**
+     * Method to return the current satellite data service policy supported mode for the
+     * subscription id based on carrier config.
+     *
+     * @param subId current subscription id.
+     *
+     * @return Supported modes {@link SatelliteManager#SatelliteDataSupportMode}
+     *
+     * @hide
+     */
+    @SatelliteManager.SatelliteDataSupportMode
+    public int getSatelliteDataSupportMode(int subId) {
+        if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+            return SatelliteManager.SATELLITE_DATA_SUPPORT_RESTRICTED;
+        }
+
+        return getSatelliteDataServicePolicyForPlmn(subId, "");
+    }
+
+    /**
+     * This API can be used by only CTS to make the function {@link #getAllPlmnSet()} to exclude the
+     * PLMN list from storage from the returned result.
+     *
+     * @param enabled Whether to enable boolean config.
+     * @return {@code true} if the value is set successfully, {@code false} otherwise.
+     */
+    public boolean setSatelliteIgnorePlmnListFromStorage(boolean enabled) {
+        plogd("setSatelliteIgnorePlmnListFromStorage - " + enabled);
+        mIgnorePlmnListFromStorage.set(enabled);
+        return true;
+    }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
index 5b032e6..9e5d9de 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
@@ -30,11 +30,9 @@
 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;
 import android.telephony.satellite.SatelliteDatagram;
@@ -49,6 +47,7 @@
 import android.telephony.satellite.stub.SatelliteModemState;
 import android.telephony.satellite.stub.SatelliteService;
 import android.text.TextUtils;
+import android.util.Log;
 import android.util.Pair;
 
 import com.android.internal.R;
@@ -255,10 +254,7 @@
             SatelliteController satelliteController,
             @NonNull Looper looper,
             @NonNull FeatureFlags featureFlags) {
-        if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
-            mPersistentLogger = new PersistentLogger(
-                    DropBoxManagerLoggerBackend.getInstance(context));
-        }
+        mPersistentLogger = SatelliteServiceUtils.getPersistentLogger(context);
         mContext = context;
         mDemoSimulator = DemoSimulator.make(context, satelliteController);
         mVendorListener = new SatelliteListener(false);
@@ -1164,13 +1160,9 @@
                         }, new IBooleanConsumer.Stub() {
                             @Override
                             public void accept(boolean result) {
-                                // Convert for compatibility with SatelliteResponse
-                                // TODO: This should just report result instead.
-                                int[] enabled = new int[] {result ? 1 : 0};
-                                plogd("requestIsSatelliteEnabledForCarrier: "
-                                        + Arrays.toString(enabled));
+                                plogd("requestIsSatelliteEnabledForCarrier: " + result);
                                 Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
-                                        message, enabled,
+                                        message, result,
                                         SatelliteManager.SATELLITE_RESULT_SUCCESS));
                             }
                         });
@@ -1430,35 +1422,22 @@
     }
 
     private static void logd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
     }
 
     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;
-        }
+        Log.e(TAG, log);
     }
 
     private void plogd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.debug(TAG, log);
         }
     }
 
     private void ploge(@NonNull String log) {
-        Rlog.e(TAG, log);
+        Log.e(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.error(TAG, log);
         }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java b/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java
index f101f18..b84d7ae 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java
@@ -42,10 +42,7 @@
             Map<String,String> allowedServicesInfo) {
         mPlmn = plmn;
         mDataPlanType = dataPlanType;
-        if (allowedServicesInfo != null) {
-            mAllowedServicesInfo = new HashMap<>(allowedServicesInfo);
-        } else {
-            mAllowedServicesInfo = new HashMap<>();
-        }
+        mAllowedServicesInfo = allowedServicesInfo != null
+                ? new HashMap<>(allowedServicesInfo) : null;
     }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteOptimizedApplicationsTracker.java b/src/java/com/android/internal/telephony/satellite/SatelliteOptimizedApplicationsTracker.java
new file mode 100644
index 0000000..df656df
--- /dev/null
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteOptimizedApplicationsTracker.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.satellite;
+
+import android.annotation.NonNull;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+
+import com.android.internal.telephony.PackageChangeReceiver;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * SatelliteOptimizedApplicationsTracker will track the packages if they are Satellite optimized or
+ * not. According to this it is maintain a cache which store data about that packages.
+ */
+public class SatelliteOptimizedApplicationsTracker {
+
+    @NonNull private final Map<Integer, Set<String>> mSatelliteApplications = new HashMap<>();
+
+    /** Action used to initialize the state of the Tracker. */
+    private static final int ACTION_INITIALIZE_TRACKER = 0;
+
+    private static final int ACTION_USER_ADDED = 1;
+    private static final int ACTION_PACKAGE_ADDED = 2;
+    private static final int ACTION_PACKAGE_UPDATED = 3;
+    private static final int ACTION_PACKAGE_MODIFIED = 4;
+    private static final int ACTION_PACKAGE_REMOVED = 5;
+
+    private static final String APP_PROPERTY =
+            "android.telephony.PROPERTY_SATELLITE_DATA_OPTIMIZED";
+    private static final String TAG = "SatelliteAppTracker";
+
+    private final Context mContext;
+    private PackageManager mPackageManager;
+    private final UserManager mUserManager;
+    private volatile Handler mCurrentHandler;
+
+    public SatelliteOptimizedApplicationsTracker(@NonNull Looper looper, @NonNull Context context) {
+        mContext = context;
+        mPackageManager = context.getPackageManager();
+        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        mCurrentHandler =
+                new Handler(looper) {
+                    @Override
+                    public void handleMessage(@NonNull Message msg) {
+                        switch (msg.what) {
+                            case ACTION_INITIALIZE_TRACKER, ACTION_USER_ADDED -> {
+                                log("HandleInitializeTracker() STARTED");
+                                handleInitializeTracker();
+                            }
+                            case ACTION_PACKAGE_ADDED,
+                                    ACTION_PACKAGE_UPDATED,
+                                    ACTION_PACKAGE_MODIFIED -> {
+                                String packageName = (String) msg.obj;
+                                handlePackageMonitor(packageName);
+                            }
+                            case ACTION_PACKAGE_REMOVED -> {
+                                String packageName = (String) msg.obj;
+                                handlePackageRemoved(packageName);
+                            }
+                        }
+                    }
+                };
+        mCurrentHandler.sendMessage(mCurrentHandler.obtainMessage(ACTION_INITIALIZE_TRACKER));
+        Context mReceiverContext =
+                context.createContextAsUser(UserHandle.ALL, PackageManager.GET_META_DATA);
+        mReceiverContext.registerReceiver(
+                mBootCompleted, new IntentFilter(Intent.ACTION_USER_ADDED));
+        PackageChangeReceiver packageMonitor = new SatelliteApplicationPackageMonitor();
+        packageMonitor.register(context, mCurrentHandler.getLooper(), UserHandle.ALL);
+    }
+
+    private final BroadcastReceiver mBootCompleted =
+            new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    loge("new user added");
+                    // Recalculate all cached services to pick up ones that have just been enabled
+                    // since new user is added
+                    mCurrentHandler.obtainMessage(ACTION_USER_ADDED, null).sendToTarget();
+                }
+            };
+
+    private ApplicationInfo getApplicationInfo(String packageName) {
+        mPackageManager = mContext.getPackageManager();
+        try {
+            PackageInfo packageInfo =
+                    mPackageManager.getPackageInfo(packageName, PackageManager.GET_META_DATA);
+            if (packageInfo == null) {
+                loge("packageInfo is NULL");
+                return null;
+            }
+            return packageInfo.applicationInfo;
+        } catch (PackageManager.NameNotFoundException exp) {
+            loge(
+                    "Exception while reading packageInfo [ "
+                            + packageName
+                            + " ] exp = "
+                            + exp.getMessage());
+            return null;
+        }
+    }
+
+    private class SatelliteApplicationPackageMonitor extends PackageChangeReceiver {
+        @Override
+        public void onPackageAdded(String packageName) {
+            log("onPackageAdded : " + packageName);
+            mCurrentHandler.obtainMessage(ACTION_PACKAGE_ADDED, packageName).sendToTarget();
+        }
+
+        @Override
+        public void onPackageRemoved(String packageName) {
+            log("onPackageRemoved : " + packageName);
+            mCurrentHandler.obtainMessage(ACTION_PACKAGE_REMOVED, packageName).sendToTarget();
+        }
+
+        @Override
+        public void onPackageUpdateFinished(String packageName) {
+            log("onPackageUpdateFinished : " + packageName);
+            mCurrentHandler.obtainMessage(ACTION_PACKAGE_UPDATED, packageName).sendToTarget();
+        }
+
+        @Override
+        public void onPackageModified(String packageName) {
+            log("onPackageModified : " + packageName);
+            mCurrentHandler.obtainMessage(ACTION_PACKAGE_MODIFIED, packageName).sendToTarget();
+        }
+    }
+
+    private void handlePackageRemoved(String packageName) {
+        removeCacheOptimizedSatelliteApplication(packageName);
+    }
+
+    private void handlePackageMonitor(String packageName) {
+        ApplicationInfo applicationInfo = getApplicationInfo(packageName);
+        if (applicationInfo != null) {
+            if (isOptimizedSatelliteApplication(applicationInfo)) {
+                addCacheOptimizedSatelliteApplication(packageName);
+            } else {
+                removeCacheOptimizedSatelliteApplication(packageName);
+            }
+        }
+    }
+
+    private void handleInitializeTracker() {
+        List<UserInfo> users = mUserManager.getUsers();
+        for (UserInfo user : users) {
+            int userId = user.getUserHandle().getIdentifier();
+            mSatelliteApplications.putIfAbsent(userId, new HashSet<>());
+        }
+        // Get a list of installed packages
+        List<PackageInfo> packages =
+                mPackageManager.getInstalledPackages(PackageManager.GET_META_DATA);
+        // Iterate through the packages
+        for (PackageInfo packageInfo : packages) {
+            if (packageInfo.applicationInfo != null
+                    && isOptimizedSatelliteApplication(packageInfo.applicationInfo)) {
+                addCacheOptimizedSatelliteApplication(packageInfo.packageName);
+            }
+        }
+    }
+
+    private boolean isOptimizedSatelliteApplication(@NonNull ApplicationInfo applicationInfo) {
+        boolean flag = false;
+        if (applicationInfo.metaData != null) {
+            // Get the application's metadata
+            Bundle metadata = applicationInfo.metaData;
+            flag = metadata.containsKey(APP_PROPERTY);
+        }
+        return flag;
+    }
+
+    private void addCacheOptimizedSatelliteApplication(@NonNull String packageName) {
+        List<UserInfo> users = mUserManager.getUsers();
+        for (UserInfo user : users) {
+            int userId = user.getUserHandle().getIdentifier();
+            try {
+                mPackageManager.getPackageUidAsUser(
+                        packageName, PackageManager.GET_META_DATA, userId);
+                mSatelliteApplications.putIfAbsent(userId, new HashSet<>());
+                mSatelliteApplications.get(userId).add(packageName);
+            } catch (java.lang.Exception e) {
+                // package is not present for current user
+            }
+        }
+    }
+
+    private void removeCacheOptimizedSatelliteApplication(@NonNull String packageName) {
+        List<UserInfo> users = mUserManager.getUsers();
+        for (UserInfo user : users) {
+            int userId = user.getUserHandle().getIdentifier();
+            try {
+                mPackageManager.getPackageUidAsUser(
+                        packageName, PackageManager.GET_META_DATA, userId);
+            } catch (java.lang.Exception e) {
+                // package is not present for current user
+                if (mSatelliteApplications.containsKey(userId)
+                        && mSatelliteApplications.get(userId).contains(packageName)) {
+                    mSatelliteApplications.get(userId).remove(packageName);
+                }
+            }
+        }
+    }
+
+    /**
+     * Get list of applications that are optimized for low bandwidth satellite data.
+     *
+     * @param userId is Identifier of user
+     * @return List of applications package names with data optimized network property. {@link
+     *     #PROPERTY_SATELLITE_DATA_OPTIMIZED}
+     */
+    public @NonNull List<String> getSatelliteOptimizedApplications(int userId) {
+        return new ArrayList<>(mSatelliteApplications.get(userId));
+    }
+
+    private void log(String str) {
+        Log.i(TAG, str);
+    }
+
+    private void loge(String str) {
+        Log.e(TAG, str);
+    }
+}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index fc79c49..a7e35c9 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -28,7 +28,6 @@
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_NOT_SUPPORTED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_UNSUPPORTED_DEFAULT_MSG_APP;
 
-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;
@@ -48,9 +47,7 @@
 import android.os.SystemProperties;
 import android.provider.DeviceConfig;
 import android.telecom.Connection;
-import android.telephony.DropBoxManagerLoggerBackend;
 import android.telephony.PersistentLogger;
-import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -61,6 +58,7 @@
 import android.telephony.satellite.SatelliteManager;
 import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
 import android.text.TextUtils;
+import android.util.Log;
 import android.util.Pair;
 import android.util.SparseArray;
 
@@ -74,7 +72,6 @@
 import com.android.internal.telephony.SmsApplication;
 import com.android.internal.telephony.TelephonyCountryDetector;
 import com.android.internal.telephony.flags.FeatureFlags;
-import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.metrics.SatelliteStats;
 
 import java.util.Arrays;
@@ -160,10 +157,7 @@
             @NonNull SatelliteController satelliteController,
             ImsManager imsManager) {
         super(looper);
-        if (isSatellitePersistentLoggingEnabled(context)) {
-            mPersistentLogger = new PersistentLogger(
-                    DropBoxManagerLoggerBackend.getInstance(context));
-        }
+        mPersistentLogger = SatelliteServiceUtils.getPersistentLogger(context);
         mContext = context;
         mSatelliteController = satelliteController;
         mFeatureFlags = mSatelliteController.getFeatureFlags();
@@ -313,7 +307,7 @@
 
     private void handleSatelliteProvisionStateChangedEvent(boolean provisioned) {
         if (!provisioned
-                && !isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
+                && !isSatelliteEmergencyMessagingViaCarrierAvailable()) {
             cleanUpResources(false);
         }
     }
@@ -353,7 +347,7 @@
             if (!isCellularAvailable
                     && isSatelliteAllowed()
                     && ((isDeviceProvisioned() && isSatelliteAllowedByReasons())
-                    || isSatelliteConnectedViaCarrierWithinHysteresisTime())
+                    || isSatelliteEmergencyMessagingViaCarrierAvailable())
                     && shouldTrackCall(mEmergencyConnection.getState())) {
                 plogd("handleTimeoutEvent: Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer");
                 Bundle extras = createExtraBundleForEventDisplayEmergencyMessage(
@@ -373,7 +367,7 @@
 
     private boolean isSatelliteAllowed() {
         synchronized (mLock) {
-            if (isSatelliteConnectedViaCarrierWithinHysteresisTime()) return true;
+            if (isSatelliteEmergencyMessagingViaCarrierAvailable()) return true;
             return mIsSatelliteAllowedForCurrentLocation;
         }
     }
@@ -394,7 +388,12 @@
         return satelliteProvisioned != null ? satelliteProvisioned : false;
     }
 
-    private boolean isSatelliteConnectedViaCarrierWithinHysteresisTime() {
+    private boolean isSatelliteEmergencyMessagingViaCarrierAvailable() {
+        if (!mSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier()) {
+            plogd("isSatelliteEmergencyMessagingViaCarrierAvailable: false, "
+                    + "device does not support satellite emergency messaging via carrier");
+            return false;
+        }
         return mIsSatelliteConnectedViaCarrierWithinHysteresisTime.get();
     }
 
@@ -573,7 +572,7 @@
     }
 
     private void selectEmergencyCallWaitForConnectionTimeoutDuration() {
-        if (isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
+        if (isSatelliteEmergencyMessagingViaCarrierAvailable()) {
             int satelliteSubId = mSubIdOfSatelliteConnectedViaCarrierWithinHysteresisTime.get();
             mTimeoutMillis =
                     mSatelliteController.getCarrierEmergencyCallWaitForConnectionTimeoutMillis(
@@ -775,7 +774,7 @@
 
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     public int getEmergencyCallToSatelliteHandoverType() {
-        if (isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
+        if (isSatelliteEmergencyMessagingViaCarrierAvailable()) {
             int satelliteSubId = mSubIdOfSatelliteConnectedViaCarrierWithinHysteresisTime.get();
             return mSatelliteController.getCarrierRoamingNtnEmergencyCallToSatelliteHandoverType(
                     satelliteSubId);
@@ -847,6 +846,8 @@
     private void updateSatelliteConnectedViaCarrierWithinHysteresisTimeState() {
         Pair<Boolean, Integer> satelliteConnectedState =
                 mSatelliteController.isSatelliteConnectedViaCarrierWithinHysteresisTime();
+        plogd("updateSatelliteConnectedViaCarrierWithinHysteresisTimeState: subId="
+                  + satelliteConnectedState.second + ", connected="+ satelliteConnectedState.first);
         mIsSatelliteConnectedViaCarrierWithinHysteresisTime.set(satelliteConnectedState.first);
         if (satelliteConnectedState.first) {
             mSubIdOfSatelliteConnectedViaCarrierWithinHysteresisTime.set(
@@ -858,39 +859,26 @@
     }
 
     private static void logv(@NonNull String log) {
-        Rlog.v(TAG, log);
+        Log.v(TAG, log);
     }
 
     private static void logd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
     }
 
     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;
-        }
+        Log.e(TAG, log);
     }
 
     private void plogd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.debug(TAG, log);
         }
     }
 
     private void ploge(@NonNull String log) {
-        Rlog.e(TAG, log);
+        Log.e(TAG, log);
         if (mPersistentLogger != null) {
             mPersistentLogger.error(TAG, log);
         }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
index 2ee9759..fd47c16 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
@@ -30,8 +30,9 @@
 import android.telephony.AccessNetworkConstants;
 import android.telephony.CarrierConfigManager;
 import android.telephony.CellIdentity;
+import android.telephony.DropBoxManagerLoggerBackend;
 import android.telephony.NetworkRegistrationInfo;
-import android.telephony.Rlog;
+import android.telephony.PersistentLogger;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -50,12 +51,16 @@
 import android.telephony.satellite.stub.SatelliteModemState;
 import android.telephony.satellite.stub.SatelliteResult;
 import android.text.TextUtils;
+import android.util.Log;
 
+import com.android.internal.R;
+import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
 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;
@@ -290,8 +295,8 @@
         android.telephony.satellite.stub.SatelliteModemEnableRequestAttributes converted =
                 new android.telephony.satellite.stub.SatelliteModemEnableRequestAttributes();
         converted.isEnabled = attributes.isEnabled();
-        converted.isDemoMode = attributes.isDemoMode();
-        converted.isEmergencyMode = attributes.isEmergencyMode();
+        converted.isDemoMode = attributes.isForDemoMode();
+        converted.isEmergencyMode = attributes.isForEmergencyMode();
         converted.satelliteSubscriptionInfo = toSatelliteSubscriptionInfo(
                 attributes.getSatelliteSubscriptionInfo());
         return converted;
@@ -315,6 +320,10 @@
             if (ar.exception instanceof SatelliteManager.SatelliteException) {
                 errorCode = ((SatelliteManager.SatelliteException) ar.exception).getErrorCode();
                 loge(caller + " SatelliteException: " + ar.exception);
+            } else if (ar.exception instanceof CommandException) {
+                errorCode = convertCommandExceptionErrorToSatelliteError(
+                        ((CommandException) ar.exception).getCommandError());
+                loge(caller + " CommandException: "  + ar.exception);
             } else {
                 loge(caller + " unknown exception: " + ar.exception);
             }
@@ -323,6 +332,27 @@
         return errorCode;
     }
 
+    private static int convertCommandExceptionErrorToSatelliteError(
+            CommandException.Error commandExceptionError) {
+        logd("convertCommandExceptionErrorToSatelliteError: commandExceptionError="
+                + commandExceptionError.toString());
+
+        switch(commandExceptionError) {
+            case REQUEST_NOT_SUPPORTED:
+                return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
+            case RADIO_NOT_AVAILABLE:
+                return SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE;
+            case INTERNAL_ERR:
+            case INVALID_STATE:
+            case INVALID_MODEM_STATE:
+                return SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE;
+            case MODEM_ERR:
+                return SatelliteManager.SATELLITE_RESULT_MODEM_ERROR;
+            default:
+                return SatelliteManager.SATELLITE_RESULT_ERROR;
+        }
+    }
+
     /**
      * Get valid subscription id for satellite communication.
      *
@@ -504,8 +534,17 @@
             ServiceState serviceState = phone.getServiceState();
             if (serviceState != null) {
                 int state = serviceState.getState();
+                NetworkRegistrationInfo dataNri = serviceState.getNetworkRegistrationInfo(
+                        NetworkRegistrationInfo.DOMAIN_PS,
+                        AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+                boolean isCellularDataInService = dataNri != null && dataNri.isInService();
+                logd("isCellularAvailable: phoneId=" + phone.getPhoneId() + " state=" + state
+                        + " isEmergencyOnly=" + serviceState.isEmergencyOnly()
+                        + " isCellularDataInService=" + isCellularDataInService);
+
                 if ((state == STATE_IN_SERVICE || state == STATE_EMERGENCY_ONLY
-                        || serviceState.isEmergencyOnly())
+                        || serviceState.isEmergencyOnly()
+                        || isCellularDataInService)
                         && !isSatellitePlmn(phone.getSubId(), serviceState)) {
                     logd("isCellularAvailable true");
                     return true;
@@ -518,8 +557,8 @@
 
     /** Check whether device is connected to satellite PLMN */
     public static boolean isSatellitePlmn(int subId, @NonNull ServiceState serviceState) {
-        List<String> satellitePlmnList =
-                SatelliteController.getInstance().getSatellitePlmnsForCarrier(subId);
+        List<String> satellitePlmnList = new ArrayList<>(
+                SatelliteController.getInstance().getAllPlmnSet());
         if (satellitePlmnList.isEmpty()) {
             logd("isSatellitePlmn: satellitePlmnList is empty");
             return false;
@@ -529,12 +568,12 @@
                 serviceState.getNetworkRegistrationInfoListForTransportType(
                         AccessNetworkConstants.TRANSPORT_TYPE_WWAN)) {
             String registeredPlmn = nri.getRegisteredPlmn();
-            if (TextUtils.isEmpty(registeredPlmn)) {
-                logd("isSatellitePlmn: registeredPlmn is empty");
+            String mccmnc = getMccMnc(nri);
+            if (TextUtils.isEmpty(registeredPlmn) && TextUtils.isEmpty(mccmnc)) {
+                logd("isSatellitePlmn: registeredPlmn and cell plmn are empty");
                 continue;
             }
 
-            String mccmnc = getMccMnc(nri);
             for (String satellitePlmn : satellitePlmnList) {
                 if (TextUtils.equals(satellitePlmn, registeredPlmn)
                         || TextUtils.equals(satellitePlmn, mccmnc)) {
@@ -662,15 +701,52 @@
         return earfcnsMap;
     }
 
+    /**
+     * Returns a persistent logger to persist important log because logcat logs may not be
+     * retained long enough.
+     *
+     * @return a PersistentLogger, return {@code null} if it is not supported or encounters
+     * exception.
+     */
+    @Nullable
+    public static PersistentLogger getPersistentLogger(@NonNull Context context) {
+        try {
+            if (context.getResources().getBoolean(
+                    R.bool.config_dropboxmanager_persistent_logging_enabled)) {
+                return new PersistentLogger(DropBoxManagerLoggerBackend.getInstance(context));
+            }
+        } catch (RuntimeException ex) {
+            loge("getPersistentLogger: RuntimeException ex=" + ex);
+        }
+        return null;
+    }
+
+    /** Determines whether the subscription is in carrier roaming NB-IoT NTN or not. */
+    public static boolean isNbIotNtn(int subId) {
+        Phone phone = PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
+        if (phone == null) {
+            logd("isNbIotNtn(): phone is null");
+            return false;
+        }
+
+        SatelliteController satelliteController = SatelliteController.getInstance();
+        if (satelliteController == null) {
+            logd("isNbIotNtn(): satelliteController is null");
+            return false;
+        }
+
+        return satelliteController.isInCarrierRoamingNbIotNtn(phone);
+    }
+
     private static void logd(@NonNull String log) {
-        Rlog.d(TAG, log);
+        Log.d(TAG, log);
     }
 
     private static void loge(@NonNull String log) {
-        Rlog.e(TAG, log);
+        Log.e(TAG, log);
     }
 
     private static void logv(@NonNull String log) {
-        Rlog.v(TAG, log);
+        Log.v(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 ed3129a..5f23e09 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
@@ -30,8 +30,8 @@
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS;
-import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_ENABLING_SATELLITE;
@@ -59,7 +59,6 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.WorkSource;
-import android.telephony.DropBoxManagerLoggerBackend;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PersistentLogger;
 import android.telephony.ServiceState;
@@ -177,6 +176,8 @@
     private long mSatelliteStayAtListeningFromReceivingMillis;
     private long mSatelliteNbIotInactivityTimeoutMillis;
     private boolean mIgnoreCellularServiceState = false;
+    private Boolean mIsConcurrentTnScanningSupportedForCtsTest = null;
+    private Boolean mIsTnScanningDuringSatelliteSessionAllowedForCtsTest = null;
     private final ConcurrentHashMap<IBinder, ISatelliteModemStateCallback> mListeners;
     @SatelliteManager.SatelliteModemState private int mCurrentState;
     @SatelliteManager.SatelliteModemState private int mPreviousState;
@@ -274,11 +275,7 @@
             @NonNull SatelliteModemInterface satelliteModemInterface) {
         super(TAG, looper);
 
-        if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
-            mPersistentLogger = new PersistentLogger(
-                    DropBoxManagerLoggerBackend.getInstance(context));
-        }
-
+        mPersistentLogger = SatelliteServiceUtils.getPersistentLogger(context);
         mContext = context;
         mFeatureFlags = featureFlags;
         mSatelliteModemInterface = satelliteModemInterface;
@@ -547,6 +544,37 @@
     }
 
     /**
+     * This API can be used by only CTS to override TN scanning support.
+     *
+     * @param concurrentTnScanningSupported Whether concurrent TN scanning is supported.
+     * @param tnScanningDuringSatelliteSessionAllowed Whether TN scanning is allowed during
+     * a satellite session.
+     * @return {@code true} if the TN scanning support is set successfully,
+     * {@code false} otherwise.
+     */
+    boolean setTnScanningSupport(boolean reset, boolean concurrentTnScanningSupported,
+        boolean tnScanningDuringSatelliteSessionAllowed) {
+        if (!isMockModemAllowed()) {
+            ploge("setTnScanningSupport: modifying TN scanning support is not allowed");
+            return false;
+        }
+
+        plogd("setTnScanningSupport: reset=" + reset
+                  + ", concurrentTnScanningSupported=" + concurrentTnScanningSupported
+                  + ", tnScanningDuringSatelliteSessionAllowed="
+                  + tnScanningDuringSatelliteSessionAllowed);
+        if (reset) {
+            mIsConcurrentTnScanningSupportedForCtsTest = null;
+            mIsTnScanningDuringSatelliteSessionAllowedForCtsTest = null;
+        } else {
+            mIsConcurrentTnScanningSupportedForCtsTest = concurrentTnScanningSupported;
+            mIsTnScanningDuringSatelliteSessionAllowedForCtsTest =
+                    tnScanningDuringSatelliteSessionAllowed;
+        }
+        return true;
+    }
+
+    /**
      * Adjusts listening timeout duration when demo mode is on
      *
      * @param isDemoMode {@code true} : The listening timeout durations will be set to
@@ -2027,20 +2055,12 @@
         return true;
     }
 
-    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 boolean isConcurrentTnScanningSupported() {
+        if (mIsConcurrentTnScanningSupportedForCtsTest != null) {
+            plogd("isConcurrentTnScanningSupported: mIsConcurrentTnScanningSupportedForCtsTest="
+                    + mIsConcurrentTnScanningSupportedForCtsTest);
+            return mIsConcurrentTnScanningSupportedForCtsTest;
+        }
         try {
             return mContext.getResources().getBoolean(
                 R.bool.config_satellite_modem_support_concurrent_tn_scanning);
@@ -2051,6 +2071,12 @@
     }
 
     private boolean isTnScanningAllowedDuringSatelliteSession() {
+        if (mIsTnScanningDuringSatelliteSessionAllowedForCtsTest != null) {
+            plogd("isTnScanningAllowedDuringSatelliteSession: "
+                    + "mIsTnScanningDuringSatelliteSessionAllowedForCtsTest="
+                    + mIsTnScanningDuringSatelliteSessionAllowedForCtsTest);
+            return mIsTnScanningDuringSatelliteSessionAllowedForCtsTest;
+        }
         try {
             return mContext.getResources().getBoolean(
                     R.bool.config_satellite_allow_tn_scanning_during_satellite_session);
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java
index e97d234..0fbebf7 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java
@@ -17,20 +17,39 @@
 package com.android.internal.telephony.satellite.metrics;
 
 import android.annotation.NonNull;
+import android.os.SystemClock;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.metrics.SatelliteStats;
 import com.android.internal.telephony.satellite.SatelliteConstants;
+import com.android.internal.telephony.satellite.SatelliteServiceUtils;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 public class CarrierRoamingSatelliteControllerStats {
     private static final String TAG = CarrierRoamingSatelliteControllerStats.class.getSimpleName();
     private static CarrierRoamingSatelliteControllerStats sInstance = null;
     private static final int ADD_COUNT = 1;
-
     private SatelliteStats mSatelliteStats;
+    /** Map key subId, value: list of session start time in milliseconds */
+    private Map<Integer, List<Long>> mSessionStartTimeMap = new HashMap<>();
+    /** Map key subId, list of session end time in milliseconds */
+    private Map<Integer, List<Long>> mSessionEndTimeMap = new HashMap<>();
 
-    private CarrierRoamingSatelliteControllerStats() {
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public CarrierRoamingSatelliteControllerStats() {
         mSatelliteStats = SatelliteStats.getInstance();
+        resetSessionGapLists();
     }
 
     /**
@@ -49,18 +68,25 @@
     }
 
     /** Report config data source */
-    public void reportConfigDataSource(@SatelliteConstants.ConfigDataSource int configDataSource) {
+    public void reportConfigDataSource(int subId,
+            @SatelliteConstants.ConfigDataSource int configDataSource) {
         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
                 new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
                         .setConfigDataSource(configDataSource)
+                        .setCarrierId(getCarrierIdFromSubscription(subId))
+                        .setIsMultiSim(isMultiSim())
+                        .setIsNbIotNtn(SatelliteServiceUtils.isNbIotNtn(subId))
                         .build());
     }
 
     /** Report count of entitlement status query request */
-    public void reportCountOfEntitlementStatusQueryRequest() {
+    public void reportCountOfEntitlementStatusQueryRequest(int subId) {
         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
                 new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
                         .setCountOfEntitlementStatusQueryRequest(ADD_COUNT)
+                        .setCarrierId(getCarrierIdFromSubscription(subId))
+                        .setIsMultiSim(isMultiSim())
+                        .setIsNbIotNtn(SatelliteServiceUtils.isNbIotNtn(subId))
                         .build());
     }
 
@@ -69,14 +95,18 @@
         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
                 new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
                         .setCountOfSatelliteConfigUpdateRequest(ADD_COUNT)
+                        .setIsMultiSim(isMultiSim())
                         .build());
     }
 
     /** Report count of satellite notification displayed */
-    public void reportCountOfSatelliteNotificationDisplayed() {
+    public void reportCountOfSatelliteNotificationDisplayed(int subId) {
         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
                 new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
                         .setCountOfSatelliteNotificationDisplayed(ADD_COUNT)
+                        .setCarrierId(getCarrierIdFromSubscription(subId))
+                        .setIsMultiSim(isMultiSim())
+                        .setIsNbIotNtn(SatelliteServiceUtils.isNbIotNtn(subId))
                         .build());
     }
 
@@ -85,17 +115,124 @@
         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
                 new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
                         .setCarrierId(carrierId)
+                        .setIsMultiSim(isMultiSim())
                         .build());
     }
 
     /** Capture whether the device is satellite entitled or not */
-    public void reportIsDeviceEntitled(boolean isDeviceEntitled) {
+    public void reportIsDeviceEntitled(int subId, boolean isDeviceEntitled) {
         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
                 new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
                         .setIsDeviceEntitled(isDeviceEntitled)
+                        .setCarrierId(getCarrierIdFromSubscription(subId))
+                        .setIsMultiSim(isMultiSim())
+                        .setIsNbIotNtn(SatelliteServiceUtils.isNbIotNtn(subId))
                         .build());
     }
 
+    /** Log carrier roaming satellite session start */
+    public void onSessionStart(int subId) {
+        List<Long> sessionStartTimeListForSubscription = mSessionStartTimeMap.getOrDefault(subId,
+                new ArrayList<>());
+        sessionStartTimeListForSubscription.add(getElapsedRealtime());
+        mSessionStartTimeMap.put(subId, sessionStartTimeListForSubscription);
+
+        mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
+                new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+                        .setCarrierId(getCarrierIdFromSubscription(subId))
+                        .increaseCountOfSatelliteSessions()
+                        .build());
+    }
+
+    /** Log carrier roaming satellite session end */
+    public void onSessionEnd(int subId) {
+        List<Long> sessionEndTimeListForSubscription = mSessionEndTimeMap.getOrDefault(subId,
+                new ArrayList<>());
+        sessionEndTimeListForSubscription.add(getElapsedRealtime());
+        mSessionEndTimeMap.put(subId, sessionEndTimeListForSubscription);
+
+        int numberOfSatelliteSessions = getNumberOfSatelliteSessions(subId);
+        List<Integer> sessionGapList = getSatelliteSessionGapList(subId, numberOfSatelliteSessions);
+        int satelliteSessionGapMinSec = 0;
+        int satelliteSessionGapMaxSec = 0;
+        if (!sessionGapList.isEmpty()) {
+            satelliteSessionGapMinSec = Collections.min(sessionGapList);
+            satelliteSessionGapMaxSec = Collections.max(sessionGapList);
+        }
+
+        mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
+                new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+                        .setSatelliteSessionGapMinSec(satelliteSessionGapMinSec)
+                        .setSatelliteSessionGapAvgSec(getAvg(sessionGapList))
+                        .setSatelliteSessionGapMaxSec(satelliteSessionGapMaxSec)
+                        .setCarrierId(getCarrierIdFromSubscription(subId))
+                        .setIsMultiSim(isMultiSim())
+                        .setIsNbIotNtn(SatelliteServiceUtils.isNbIotNtn(subId))
+                        .build());
+    }
+
+    /** Atom is pulled once per day. Reset session gap lists after the atom is pulled. */
+    public void resetSessionGapLists() {
+        mSessionStartTimeMap = new HashMap<>();
+        mSessionEndTimeMap = new HashMap<>();
+    }
+
+    private int getNumberOfSatelliteSessions(int subId) {
+        return Math.min(mSessionStartTimeMap.getOrDefault(subId, new ArrayList<>()).size(),
+                mSessionEndTimeMap.getOrDefault(subId, new ArrayList<>()).size());
+    }
+
+    private List<Integer> getSatelliteSessionGapList(int subId, int numberOfSatelliteSessions) {
+        if (numberOfSatelliteSessions == 0) {
+            return new ArrayList<>();
+        }
+
+        List<Long> sessionStartTimeList = mSessionStartTimeMap.getOrDefault(subId,
+                new ArrayList<>());
+        List<Long> sessionEndTimeList = mSessionEndTimeMap.getOrDefault(subId, new ArrayList<>());
+        List<Integer> sessionGapList = new ArrayList<>();
+        for (int i = 1; i < numberOfSatelliteSessions; i++) {
+            long prevSessionEndTime = sessionEndTimeList.get(i - 1);
+            long currentSessionStartTime = sessionStartTimeList.get(i);
+            if (currentSessionStartTime > prevSessionEndTime && prevSessionEndTime > 0) {
+                sessionGapList.add((int) (
+                        (currentSessionStartTime - prevSessionEndTime) / 1000));
+            }
+        }
+        return sessionGapList;
+    }
+
+    private int getAvg(@NonNull List<Integer> list) {
+        if (list.isEmpty()) {
+            return 0;
+        }
+
+        int total = 0;
+        for (int num : list) {
+            total += num;
+        }
+
+        return total / list.size();
+    }
+
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    protected long getElapsedRealtime() {
+        return SystemClock.elapsedRealtime();
+    }
+
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public boolean isMultiSim() {
+        return SubscriptionManagerService.getInstance().getActiveSubIdList(true).length > 1;
+    }
+
+    /** Returns the carrier ID of the given subscription id. */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    protected int getCarrierIdFromSubscription(int subId) {
+        int phoneId = SubscriptionManager.getPhoneId(subId);
+        Phone phone = PhoneFactory.getPhone(phoneId);
+        return phone != null ? phone.getCarrierId() : TelephonyManager.UNKNOWN_CARRIER_ID;
+    }
+
     private static void logd(@NonNull String log) {
         Log.d(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 3138b16..7958769 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
@@ -17,6 +17,11 @@
 package com.android.internal.telephony.satellite.metrics;
 
 import android.annotation.NonNull;
+import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStatsManager;
+import android.content.Context;
+import android.net.NetworkTemplate;
+import android.os.SystemClock;
 import android.telephony.CellInfo;
 import android.telephony.CellSignalStrength;
 import android.telephony.CellSignalStrengthLte;
@@ -24,18 +29,24 @@
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
+import android.text.TextUtils;
 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.satellite.SatelliteConstants;
+import com.android.internal.telephony.satellite.SatelliteServiceUtils;
 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.OptionalDouble;
+import java.util.Set;
 
 public class CarrierRoamingSatelliteSessionStats {
     private static final String TAG = CarrierRoamingSatelliteSessionStats.class.getSimpleName();
@@ -49,12 +60,17 @@
     private int mCountOfIncomingMms;
     private int mCountOfOutgoingMms;
     private long mIncomingMessageId;
-
     private int mSessionStartTimeSec;
-    private List<Long> mConnectionStartTimeList;
-    private List<Long> mConnectionEndTimeList;
+    private SatelliteConnectionTimes mSatelliteConnectionTimes;
+    private List<SatelliteConnectionTimes> mSatelliteConnectionTimesList;
     private List<Integer> mRsrpList;
     private List<Integer> mRssnrList;
+    private int[] mSupportedSatelliteServices;
+    private int mServiceDataPolicy;
+    private Phone mPhone;
+    private Context mContext;
+    private long mSatelliteDataConsumedBytes = 0L;
+    private long mDataUsageOnSessionStartBytes = 0L;
 
     public CarrierRoamingSatelliteSessionStats(int subId) {
         logd("Create new CarrierRoamingSatelliteSessionStats. subId=" + subId);
@@ -74,29 +90,82 @@
     }
 
     /** Log carrier roaming satellite session start */
-    public void onSessionStart(int carrierId, Phone phone) {
+    public void onSessionStart(int carrierId, Phone phone, int[] supportedServices,
+            int serviceDataPolicy) {
+        mPhone = phone;
+        mContext = mPhone.getContext();
         mCarrierId = carrierId;
-        mSessionStartTimeSec = getCurrentTimeInSec();
+        mSupportedSatelliteServices = supportedServices;
+        mServiceDataPolicy = serviceDataPolicy;
+        mSessionStartTimeSec = getElapsedRealtimeInSec();
         mIsNtnRoamingInHomeCountry = false;
-        onConnectionStart(phone);
+        onConnectionStart(mPhone);
+        mDataUsageOnSessionStartBytes = getDataUsage();
+        logd("current data consumed: " + mDataUsageOnSessionStartBytes);
     }
 
     /** Log carrier roaming satellite connection start */
     public void onConnectionStart(Phone phone) {
-        mConnectionStartTimeList.add(getCurrentTime());
+        mSatelliteConnectionTimes = new SatelliteConnectionTimes(getElapsedRealtime());
         updateNtnRoamingInHomeCountry(phone);
     }
 
+    /** calculate total satellite data consumed at the session */
+    private long getDataUsage() {
+        if (mContext == null) {
+            return 0L;
+        }
+
+        NetworkStatsManager networkStatsManager =
+                mContext.getSystemService(NetworkStatsManager.class);
+
+        if (networkStatsManager != null) {
+            final NetworkTemplate.Builder builder =
+                    new NetworkTemplate.Builder(NetworkTemplate.MATCH_MOBILE);
+            final String subscriberId = mPhone.getSubscriberId();
+            logd("subscriber id for data consumed:" + subscriberId);
+
+            if (!TextUtils.isEmpty(subscriberId)) {
+                builder.setSubscriberIds(Set.of(subscriberId));
+                // Consider data usage calculation of only metered capabilities / data network
+                builder.setMeteredness(android.net.NetworkStats.METERED_YES);
+                NetworkTemplate template = builder.build();
+                final NetworkStats.Bucket ret = networkStatsManager
+                        .querySummaryForDevice(template, 0L, System.currentTimeMillis());
+                return ret.getRxBytes() + ret.getTxBytes();
+            }
+        }
+        return 0L;
+    }
+
     /** Log carrier roaming satellite session end */
-    public void onSessionEnd() {
+    public void onSessionEnd(int subId) {
         onConnectionEnd();
-        reportMetrics();
+        long dataUsageOnSessionEndBytes = getDataUsage();
+        logd("update data consumed: " + dataUsageOnSessionEndBytes);
+        if (dataUsageOnSessionEndBytes > 0L
+                && dataUsageOnSessionEndBytes > mDataUsageOnSessionStartBytes) {
+            mSatelliteDataConsumedBytes =
+                    dataUsageOnSessionEndBytes - mDataUsageOnSessionStartBytes;
+        }
+        logd("satellite data consumed at session: " + mSatelliteDataConsumedBytes);
+        reportMetrics(subId);
         mIsNtnRoamingInHomeCountry = false;
+        mSupportedSatelliteServices = new int[0];
+        mServiceDataPolicy = SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN;
+        mSatelliteDataConsumedBytes = 0L;
+        mDataUsageOnSessionStartBytes = 0L;
     }
 
     /** Log carrier roaming satellite connection end */
     public void onConnectionEnd() {
-        mConnectionEndTimeList.add(getCurrentTime());
+        if (mSatelliteConnectionTimes != null) {
+            mSatelliteConnectionTimes.setEndTime(getElapsedRealtime());
+            mSatelliteConnectionTimesList.add(mSatelliteConnectionTimes);
+            mSatelliteConnectionTimes = null;
+        } else {
+            loge("onConnectionEnd: mSatelliteConnectionTimes is null");
+        }
     }
 
     /** Log rsrp and rssnr when occurred the service state change with NTN is connected. */
@@ -155,12 +224,10 @@
         }
     }
 
-    private void reportMetrics() {
+    private void reportMetrics(int subId) {
         int totalSatelliteModeTimeSec = mSessionStartTimeSec > 0
-                ? getCurrentTimeInSec() - mSessionStartTimeSec : 0;
+                ? getElapsedRealtimeInSec() - mSessionStartTimeSec : 0;
         int numberOfSatelliteConnections = getNumberOfSatelliteConnections();
-        int avgDurationOfSatelliteConnectionSec = getAvgDurationOfSatelliteConnection(
-                numberOfSatelliteConnections);
 
         List<Integer> connectionGapList = getSatelliteConnectionGapList(
                 numberOfSatelliteConnections);
@@ -170,6 +237,7 @@
             satelliteConnectionGapMinSec = Collections.min(connectionGapList);
             satelliteConnectionGapMaxSec = Collections.max(connectionGapList);
         }
+        boolean isMultiSim = mSubscriptionManagerService.getActiveSubIdList(true).length > 1;
 
         SatelliteStats.CarrierRoamingSatelliteSessionParams params =
                 new SatelliteStats.CarrierRoamingSatelliteSessionParams.Builder()
@@ -177,7 +245,8 @@
                         .setIsNtnRoamingInHomeCountry(mIsNtnRoamingInHomeCountry)
                         .setTotalSatelliteModeTimeSec(totalSatelliteModeTimeSec)
                         .setNumberOfSatelliteConnections(numberOfSatelliteConnections)
-                        .setAvgDurationOfSatelliteConnectionSec(avgDurationOfSatelliteConnectionSec)
+                        .setAvgDurationOfSatelliteConnectionSec(
+                                getAvgDurationOfSatelliteConnection())
                         .setSatelliteConnectionGapMinSec(satelliteConnectionGapMinSec)
                         .setSatelliteConnectionGapAvgSec(getAvg(connectionGapList))
                         .setSatelliteConnectionGapMaxSec(satelliteConnectionGapMaxSec)
@@ -189,8 +258,14 @@
                         .setCountOfOutgoingSms(mCountOfOutgoingSms)
                         .setCountOfIncomingMms(mCountOfIncomingMms)
                         .setCountOfOutgoingMms(mCountOfOutgoingMms)
+                        .setSupportedSatelliteServices(mSupportedSatelliteServices)
+                        .setServiceDataPolicy(mServiceDataPolicy)
+                        .setSatelliteDataConsumedBytes(mSatelliteDataConsumedBytes)
+                        .setIsMultiSim(isMultiSim)
+                        .setIsNbIotNtn(SatelliteServiceUtils.isNbIotNtn(subId))
                         .build();
         SatelliteStats.getInstance().onCarrierRoamingSatelliteSessionMetrics(params);
+        logd("Supported satellite services: " + Arrays.toString(mSupportedSatelliteServices));
         logd("reportMetrics: " + params);
         initializeParams();
     }
@@ -205,8 +280,8 @@
         mIncomingMessageId = 0;
 
         mSessionStartTimeSec = 0;
-        mConnectionStartTimeList = new ArrayList<>();
-        mConnectionEndTimeList = new ArrayList<>();
+        mSatelliteConnectionTimes = null;
+        mSatelliteConnectionTimesList = new ArrayList<>();
         mRsrpList = new ArrayList<>();
         mRssnrList = new ArrayList<>();
         logd("initializeParams");
@@ -225,39 +300,39 @@
     }
 
     private int getNumberOfSatelliteConnections() {
-        return Math.min(mConnectionStartTimeList.size(), mConnectionEndTimeList.size());
+        return mSatelliteConnectionTimesList.size();
     }
 
-    private int getAvgDurationOfSatelliteConnection(int numberOfSatelliteConnections) {
-        if (numberOfSatelliteConnections == 0) {
+    private int getAvgDurationOfSatelliteConnection() {
+        if (mSatelliteConnectionTimesList.isEmpty()) {
             return 0;
         }
 
-        long totalConnectionsDuration = 0;
-        for (int i = 0; i < numberOfSatelliteConnections; i++) {
-            long endTime = mConnectionEndTimeList.get(i);
-            long startTime = mConnectionStartTimeList.get(i);
-            if (endTime >= startTime && startTime > 0) {
-                totalConnectionsDuration += endTime - startTime;
-            }
-        }
+        OptionalDouble averageDuration = mSatelliteConnectionTimesList.stream()
+                .filter(SatelliteConnectionTimes::isValid)
+                .mapToLong(SatelliteConnectionTimes::getDuration)
+                .average();
 
-        long avgConnectionDuration = totalConnectionsDuration / numberOfSatelliteConnections;
-        return (int) (avgConnectionDuration / 1000L);
+        return (int) (averageDuration.isPresent() ? averageDuration.getAsDouble() / 1000 : 0);
     }
 
     private List<Integer> getSatelliteConnectionGapList(int numberOfSatelliteConnections) {
-        if (numberOfSatelliteConnections == 0) {
+        if (mSatelliteConnectionTimesList.size() < 2) {
             return new ArrayList<>();
         }
 
         List<Integer> connectionGapList = new ArrayList<>();
-        for (int i = 1; i < numberOfSatelliteConnections; i++) {
-            long prevConnectionEndTime = mConnectionEndTimeList.get(i - 1);
-            long currentConnectionStartTime = mConnectionStartTimeList.get(i);
-            if (currentConnectionStartTime > prevConnectionEndTime && prevConnectionEndTime > 0) {
-                connectionGapList.add((int) (
-                        (currentConnectionStartTime - prevConnectionEndTime) / 1000));
+        for (int i = 1; i < mSatelliteConnectionTimesList.size(); i++) {
+            SatelliteConnectionTimes prevConnection =
+                    mSatelliteConnectionTimesList.get(i - 1);
+            SatelliteConnectionTimes currentConnection =
+                    mSatelliteConnectionTimesList.get(i);
+
+            if (prevConnection.getEndTime() > 0
+                    && currentConnection.getStartTime() > prevConnection.getEndTime()) {
+                int gap = (int) ((currentConnection.getStartTime() - prevConnection.getEndTime())
+                        / 1000);
+                connectionGapList.add(gap);
             }
         }
         return connectionGapList;
@@ -290,12 +365,12 @@
                 : list.get(size / 2);
     }
 
-    private int getCurrentTimeInSec() {
-        return (int) (System.currentTimeMillis() / 1000);
+    private int getElapsedRealtimeInSec() {
+        return (int) (getElapsedRealtime() / 1000);
     }
 
-    private long getCurrentTime() {
-        return System.currentTimeMillis();
+    private long getElapsedRealtime() {
+        return SystemClock.elapsedRealtime();
     }
 
     private boolean isNtnConnected() {
@@ -342,6 +417,39 @@
                 + mIsNtnRoamingInHomeCountry);
     }
 
+    private static class SatelliteConnectionTimes {
+        private final long mStartTime;
+        private long mEndTime;
+
+        SatelliteConnectionTimes(long startTime) {
+            this.mStartTime = startTime;
+            this.mEndTime = 0;
+        }
+
+        public void setEndTime(long endTime) {
+            this.mEndTime = endTime;
+        }
+
+        public long getStartTime() {
+            return mStartTime;
+        }
+
+        public long getEndTime() {
+            return mEndTime;
+        }
+
+        public long getDuration() {
+            if (isValid()) {
+                return mEndTime - mStartTime;
+            }
+            return 0;
+        }
+
+        public boolean isValid() {
+            return mEndTime > mStartTime && mStartTime > 0;
+        }
+    }
+
     private void logd(@NonNull String log) {
         Log.d(TAG, log);
     }
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java
index 608d91f..571c105 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java
@@ -22,6 +22,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.BatteryManager;
+import android.os.SystemClock;
 import android.telephony.satellite.SatelliteManager;
 import android.util.Log;
 
@@ -45,7 +46,7 @@
     private int mBatteryLevelWhenServiceOn;
     private boolean mIsSatelliteModemOn;
     private Boolean mIsBatteryCharged = null;
-    private int mBatteryChargedStartTimeSec;
+    private long mBatteryChargedStartTime;
     private int mTotalBatteryChargeTimeSec;
 
     /**
@@ -145,6 +146,8 @@
                 builder.setCountOfDatagramTypeLocationSharingSuccess(ADD_COUNT);
             } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
                 builder.setCountOfDatagramTypeKeepAliveSuccess(ADD_COUNT).build();
+            } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_SMS) {
+                builder.setCountOfOutgoingDatagramTypeSmsSuccess(ADD_COUNT);
             }
         }
 
@@ -169,6 +172,8 @@
                 builder.setCountOfDatagramTypeLocationSharingFail(ADD_COUNT);
             } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
                 builder.setCountOfDatagramTypeKeepAliveFail(ADD_COUNT);
+            } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_SMS) {
+                builder.setCountOfOutgoingDatagramTypeSmsFail(ADD_COUNT);
             }
         }
 
@@ -177,7 +182,7 @@
         mSatelliteStats.onSatelliteControllerMetrics(controllerParam);
     }
 
-    /** Report a counter when an attempt for incoming datagram is failed */
+    /** Increase counters for successful and failed incoming datagram attempts */
     public void reportIncomingDatagramCount(
             @NonNull @SatelliteManager.SatelliteResult int result, boolean isDemoMode) {
         SatelliteStats.SatelliteControllerParams.Builder builder =
@@ -190,9 +195,12 @@
             }
         } else {
             if (result == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
-                builder.setCountOfIncomingDatagramSuccess(ADD_COUNT);
+                builder.setCountOfIncomingDatagramSuccess(ADD_COUNT)
+                        .setCountOfIncomingDatagramTypeSosSmsSuccess(ADD_COUNT);
+
             } else {
-                builder.setCountOfIncomingDatagramFail(ADD_COUNT);
+                builder.setCountOfIncomingDatagramFail(ADD_COUNT)
+                        .setCountOfIncomingDatagramTypeSosSmsFail(ADD_COUNT);
             }
         }
         SatelliteStats.SatelliteControllerParams  controllerParam = builder.build();
@@ -200,6 +208,21 @@
         mSatelliteStats.onSatelliteControllerMetrics(controllerParam);
     }
 
+    /** Increase counters for successful and failed incoming ntn sms attempts */
+    public void reportIncomingNtnSmsCount(
+            @NonNull @SatelliteManager.SatelliteResult int result) {
+        SatelliteStats.SatelliteControllerParams.Builder builder =
+                new SatelliteStats.SatelliteControllerParams.Builder();
+        if (result == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
+            builder.setCountOfIncomingDatagramTypeSmsSuccess(ADD_COUNT);
+        } else {
+            builder.setCountOfIncomingDatagramTypeSmsFail(ADD_COUNT);
+        }
+        SatelliteStats.SatelliteControllerParams  controllerParam = builder.build();
+        logd("reportIncomingNtnSmsCount(): " + controllerParam);
+        mSatelliteStats.onSatelliteControllerMetrics(controllerParam);
+    }
+
     /** Report a counter when an attempt for de-provision is success or not */
     public void reportProvisionCount(@NonNull @SatelliteManager.SatelliteResult int result) {
         SatelliteStats.SatelliteControllerParams controllerParam;
@@ -265,7 +288,7 @@
     /** Return the total service up time for satellite service */
     @VisibleForTesting
     public int captureTotalServiceUpTimeSec() {
-        long totalTimeMillis = getCurrentTime() - mSatelliteOnTimeMillis;
+        long totalTimeMillis = getElapsedRealtime() - mSatelliteOnTimeMillis;
         mSatelliteOnTimeMillis = 0;
         return (int) (totalTimeMillis / 1000);
     }
@@ -286,7 +309,7 @@
             startCaptureBatteryLevel();
 
             // log the timestamp of the satellite modem power on
-            mSatelliteOnTimeMillis = getCurrentTime();
+            mSatelliteOnTimeMillis = getElapsedRealtime();
 
             // register broadcast receiver for monitoring battery status change
             IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
@@ -329,13 +352,12 @@
 
             // When charged, log the start time of battery charging
             if (isCharged) {
-                mBatteryChargedStartTimeSec = (int) (getCurrentTime() / 1000);
+                mBatteryChargedStartTime = getElapsedRealtime();
                 // When discharged, log the accumulated total battery charging time.
             } else {
                 mTotalBatteryChargeTimeSec +=
-                        (int) (getCurrentTime() / 1000)
-                                - mBatteryChargedStartTimeSec;
-                mBatteryChargedStartTimeSec = 0;
+                        (int) ((getElapsedRealtime() - mBatteryChargedStartTime) / 1000);
+                mBatteryChargedStartTime = 0;
             }
         }
     }
@@ -415,6 +437,17 @@
     }
 
     /**
+     * Report a current version of satellite access config.
+     */
+    public void reportCurrentVersionOfSatelliteAccessConfig(int version) {
+        logd("reportCurrentVersionOfSatelliteAccessConfig:" + version);
+        mSatelliteStats.onSatelliteControllerMetrics(
+                new SatelliteStats.SatelliteControllerParams.Builder()
+                        .setVersionOfSatelliteAccessControl(version)
+                        .build());
+    }
+
+    /**
      * Add count when the notification for P2P SMS over satellite avaibility is shown or removed.
      */
     public void reportP2PSmsEligibilityNotificationsCount(boolean isEligible) {
@@ -448,9 +481,9 @@
 
         @Override
         public void onReceive(Context context, Intent intent) {
-            long currentTime = getCurrentTime();
-            if (currentTime - mLastUpdatedTime > UPDATE_INTERVAL) {
-                mLastUpdatedTime = currentTime;
+            long elapsedTimeSinceBoot = getElapsedRealtime();
+            if (elapsedTimeSinceBoot - mLastUpdatedTime > UPDATE_INTERVAL) {
+                mLastUpdatedTime = elapsedTimeSinceBoot;
                 int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
                 boolean isCharged = (status == BatteryManager.BATTERY_STATUS_CHARGING);
                 logd("Battery is charged(" + isCharged + ")");
@@ -465,8 +498,8 @@
     }
 
     @VisibleForTesting
-    public long getCurrentTime() {
-        return System.currentTimeMillis();
+    public long getElapsedRealtime() {
+        return SystemClock.elapsedRealtime();
     }
 
     private static void logd(@NonNull String log) {
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/EntitlementMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/EntitlementMetricsStats.java
index 4862188..93185b2 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/EntitlementMetricsStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/EntitlementMetricsStats.java
@@ -35,6 +35,9 @@
     private int mResult;
     private int mEntitlementStatus;
     private boolean mIsRetry;
+    private boolean mIsAllowedServiceEntitlement;
+    private int[] mEntitlementServiceType;
+    private int mEntitlementDataPolicy;
 
     private EntitlementMetricsStats() {}
 
@@ -56,11 +59,14 @@
     /** Report metrics on entitlement query request success */
     public void reportSuccess(int subId,
             @SatelliteConstants.SatelliteEntitlementStatus int entitlementStatus,
-            boolean isRetry) {
+            boolean isRetry, boolean isAllowedServiceInfo, int[] serviceType, int dataPolicy) {
         mSubId = subId;
         mResult = RESULT_SUCCESS;
         mEntitlementStatus = entitlementStatus;
         mIsRetry = isRetry;
+        mIsAllowedServiceEntitlement = isAllowedServiceInfo;
+        mEntitlementServiceType = serviceType;
+        mEntitlementDataPolicy = dataPolicy;
         reportEntitlementMetrics();
     }
 
@@ -70,6 +76,9 @@
         mResult = result;
         mIsRetry = isRetry;
         mEntitlementStatus = SatelliteConstants.SATELLITE_ENTITLEMENT_STATUS_UNKNOWN;
+        mIsAllowedServiceEntitlement = false;
+        mEntitlementServiceType = new int[0];
+        mEntitlementDataPolicy = SatelliteConstants.SATELLITE_ENTITLEMENT_SERVICE_POLICY_UNKNOWN;
         reportEntitlementMetrics();
     }
 
@@ -82,12 +91,15 @@
                         .setEntitlementStatus(mEntitlementStatus)
                         .setIsRetry(mIsRetry)
                         .setCount(1)
+                        .setIsAllowedServiceEntitlement(mIsAllowedServiceEntitlement)
+                        .setEntitlementServiceType(mEntitlementServiceType)
+                        .setEntitlementDataPolicy(mEntitlementDataPolicy)
                         .build();
         SatelliteStats.getInstance().onSatelliteEntitlementMetrics(entitlementParams);
         logd("reportEntitlementMetrics: " + entitlementParams);
 
         CarrierRoamingSatelliteControllerStats.getOrCreateInstance()
-                .reportCountOfEntitlementStatusQueryRequest();
+                .reportCountOfEntitlementStatusQueryRequest(mSubId);
     }
 
     /** Returns the carrier ID of the given subscription id. */
diff --git a/src/java/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifier.java b/src/java/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifier.java
index 8591e86..ea38d4f 100644
--- a/src/java/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifier.java
+++ b/src/java/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifier.java
@@ -120,6 +120,12 @@
                 return;
             }
 
+            // Don't notify if the modem vendor indicates this is a benign disclosure.
+            if (disclosure.isBenign()) {
+                Rlog.i(TAG, "Ignoring identifier disclosure that is claimed to be benign.");
+                return;
+            }
+
             // Schedule incrementAndNotify from within the lock because we're sure at this point
             // that we're enabled. This allows incrementAndNotify to avoid re-checking mEnabled
             // because we know that any actions taken on disabled will be scheduled after this
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
index 9d62972..728f8ce 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
@@ -30,6 +30,7 @@
 import android.os.ParcelUuid;
 import android.provider.Telephony;
 import android.provider.Telephony.SimInfo;
+import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.SubscriptionManager.DataRoamingMode;
@@ -49,10 +50,15 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.satellite.SatelliteController;
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.util.function.TriConsumer;
 import com.android.telephony.Rlog;
 
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.AbstractMap;
@@ -299,7 +305,22 @@
                     SubscriptionInfoInternal::getSatelliteESOSSupported),
             new AbstractMap.SimpleImmutableEntry<>(
                     SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM,
-                    SubscriptionInfoInternal::getIsSatelliteProvisionedForNonIpDatagram)
+                    SubscriptionInfoInternal::getIsSatelliteProvisionedForNonIpDatagram),
+            new AbstractMap.SimpleImmutableEntry<>(
+                    SimInfo.COLUMN_SATELLITE_ENTITLEMENT_BARRED_PLMNS,
+                    SubscriptionInfoInternal::getSatelliteEntitlementBarredPlmnsList),
+            new AbstractMap.SimpleImmutableEntry<>(
+                    SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS,
+                    SubscriptionInfoInternal::getSatelliteEntitlementDataPlanForPlmns),
+            new AbstractMap.SimpleImmutableEntry<>(
+                    SimInfo.COLUMN_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP,
+                    SubscriptionInfoInternal::getSatelliteEntitlementPlmnsServiceTypes),
+            new AbstractMap.SimpleImmutableEntry<>(
+                    SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY,
+                    SubscriptionInfoInternal::getSatellitePlmnsDataServicePolicy),
+            new AbstractMap.SimpleImmutableEntry<>(
+                    SimInfo.COLUMN_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY,
+                    SubscriptionInfoInternal::getSatellitePlmnsVoiceServicePolicy)
     );
 
     /**
@@ -510,7 +531,22 @@
                     SubscriptionDatabaseManager::setNumberFromIms),
             new AbstractMap.SimpleImmutableEntry<>(
                     SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS,
-                    SubscriptionDatabaseManager::setSatelliteEntitlementPlmns)
+                    SubscriptionDatabaseManager::setSatelliteEntitlementPlmns),
+            new AbstractMap.SimpleImmutableEntry<>(
+                    SimInfo.COLUMN_SATELLITE_ENTITLEMENT_BARRED_PLMNS,
+                    SubscriptionDatabaseManager::setSatelliteEntitlementBarredPlmns),
+            new AbstractMap.SimpleImmutableEntry<>(
+                    SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS,
+                    SubscriptionDatabaseManager::setSatelliteEntitlementDataPlanForPlmns),
+            new AbstractMap.SimpleImmutableEntry<>(
+                    SimInfo.COLUMN_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP,
+                    SubscriptionDatabaseManager::setSatelliteEntitlementPlmnServiceTypeMap),
+            new AbstractMap.SimpleImmutableEntry<>(
+                    SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY,
+                    SubscriptionDatabaseManager::setSatelliteEntitlementPlmnDataServicePolicy),
+            new AbstractMap.SimpleImmutableEntry<>(
+                    SimInfo.COLUMN_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY,
+                    SubscriptionDatabaseManager::setSatelliteEntitlementPlmnVoiceServicePolicy)
     );
 
     /**
@@ -2072,9 +2108,6 @@
      * @throws IllegalArgumentException if the subscription does not exist.
      */
     public void setNtn(int subId, int isNtn) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            return;
-        }
         writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_IS_ONLY_NTN, isNtn,
                 SubscriptionInfoInternal.Builder::setOnlyNonTerrestrialNetwork);
     }
@@ -2157,17 +2190,56 @@
     }
 
     /**
-     * Set satellite entitlement plmn list by entitlement query result.
+     * Save the satellite entitlement Info in the subscription database.
      *
-     * @param subId Subscription id.
-     * @param satelliteEntitlementPlmnList Satellite entitlement plmn list
+     * @param subId                     subId.
+     * @param allowedPlmnList           Plmn [MCC+MNC] list of codes to determine if satellite
+     *                                  communication is allowed. Ex : "123123,12310".
+     * @param barredPlmnList            Plmn [MCC+MNC] list of codes to determine if satellite
+     *                                  communication is not allowed.  Ex : "123123,12310".
+     * @param plmnDataPlanMap           data plan per plmn of type
+     *                                  {@link SatelliteController#SATELLITE_DATA_PLAN_METERED} OR
+     *                                  {@link SatelliteController#SATELLITE_DATA_PLAN_UNMETERED}.
+     *                                  Ex : {"302820":0, "31026":1}
+     * @param plmnServiceTypeMap        list of supported services per plmn of type
+     *                                  {@link
+     *                                  android.telephony.NetworkRegistrationInfo.ServiceType}).
+     *                                  Ex : {"302820":[1,3],"31026":[2,3]}
+     * @param plmnDataServicePolicyMap  data support mode per plmn map of types
+     *                                  {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE}.
+     *                                  Ex : {"302820":2, "31026":1}
+     * @param plmnVoiceServicePolicyMap voice support mode per plmn map of types
+     *                                  {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE}
+     *                                  . Ex : {"302820":2, "31026":1}.
      * @throws IllegalArgumentException if the subscription does not exist.
      */
-    public void setSatelliteEntitlementPlmnList(int subId,
-            @NonNull List<String> satelliteEntitlementPlmnList) {
-        String satelliteEntitlementPlmns = satelliteEntitlementPlmnList.stream().collect(
+    public void setSatelliteEntitlementInfo(int subId,
+            @NonNull List<String> allowedPlmnList,
+            @Nullable List<String> barredPlmnList,
+            @Nullable Map<String, Integer> plmnDataPlanMap,
+            @Nullable Map<String, List<Integer>> plmnServiceTypeMap,
+            @Nullable Map<String, Integer> plmnDataServicePolicyMap,
+            @Nullable Map<String, Integer> plmnVoiceServicePolicyMap) {
+        String satelliteEntitlementPlmns = allowedPlmnList.stream().collect(
                 Collectors.joining(","));
         setSatelliteEntitlementPlmns(subId, satelliteEntitlementPlmns);
+
+        String satelliteEntitlementBarredPlmns = barredPlmnList.stream().collect(
+                Collectors.joining(","));
+        setSatelliteEntitlementBarredPlmns(subId, satelliteEntitlementBarredPlmns);
+
+
+        String plmnDataPlanJson = serializeMapToJsonString(plmnDataPlanMap);
+        setSatelliteEntitlementDataPlanForPlmns(subId, plmnDataPlanJson);
+
+        String plmnServiceTypeJson = serializeMapListToJsonString(plmnServiceTypeMap);
+        setSatelliteEntitlementPlmnServiceTypeMap(subId, plmnServiceTypeJson);
+
+        String plmnDataServicePolicyJson = serializeMapToJsonString(plmnDataServicePolicyMap);
+        setSatelliteEntitlementPlmnDataServicePolicy(subId, plmnDataServicePolicyJson);
+
+        String plmnVoiceServicePolicyJson = serializeMapToJsonString(plmnVoiceServicePolicyMap);
+        setSatelliteEntitlementPlmnVoiceServicePolicy(subId, plmnVoiceServicePolicyJson);
     }
 
     /**
@@ -2206,6 +2278,81 @@
     }
 
     /**
+     * Set satellite entitlement barred plmns list by entitlement query result.
+     *
+     * @param subId Subscription id.
+     * @param satelliteEntitlementBarredPlmns Satellite entitlement barred plmns
+     * @throws IllegalArgumentException if the subscription does not exist.
+     */
+    public void setSatelliteEntitlementBarredPlmns(int subId,
+            @NonNull String satelliteEntitlementBarredPlmns) {
+        writeDatabaseAndCacheHelper(subId,
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_BARRED_PLMNS,
+                satelliteEntitlementBarredPlmns,
+                SubscriptionInfoInternal.Builder::setSatelliteEntitlementBarredPlmnsList);
+    }
+
+    /**
+     * Set satellite entitlement data plan for the plmns by entitlement query result.
+     *
+     * @param subId Subscription id.
+     * @param plmnDataPlanJson Satellite entitlement data plan for plmns.
+     * @throws IllegalArgumentException if the subscription does not exist.
+     */
+    public void setSatelliteEntitlementDataPlanForPlmns(int subId,
+            @NonNull String plmnDataPlanJson) {
+        writeDatabaseAndCacheHelper(subId,
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS,
+                plmnDataPlanJson,
+                SubscriptionInfoInternal.Builder::setSatelliteEntitlementDataPlanForPlmns);
+    }
+
+    /**
+     * Set satellite entitlement services for the plmns by entitlement query result.
+     *
+     * @param subId                     Subscription id.
+     * @param plmnServiceTypeJson Satellite entitlement services for plmns.
+     * @throws IllegalArgumentException if the subscription does not exist.
+     */
+    public void setSatelliteEntitlementPlmnServiceTypeMap(int subId,
+            @NonNull String plmnServiceTypeJson) {
+        writeDatabaseAndCacheHelper(subId,
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP,
+                plmnServiceTypeJson,
+                SubscriptionInfoInternal.Builder::setSatelliteEntitlementPlmnServiceTypes);
+    }
+
+    /**
+     * Set satellite entitlement data service policy for plmns by entitlement query result.
+     *
+     * @param subId Subscription id.
+     * @param satellitePlmnsDataServicePolicy Satellite entitlement data service policy for plmns.
+     * @throws IllegalArgumentException if the subscription does not exist.
+     */
+    public void setSatelliteEntitlementPlmnDataServicePolicy(int subId,
+            @NonNull String satellitePlmnsDataServicePolicy) {
+        writeDatabaseAndCacheHelper(subId,
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY,
+                satellitePlmnsDataServicePolicy,
+                SubscriptionInfoInternal.Builder::setSatellitePlmnsDataServicePolicy);
+    }
+
+    /**
+     * Set satellite entitlement voice service policy for plmns by entitlement query result.
+     *
+     * @param subId Subscription id.
+     * @param satellitePlmnsVoiceServicePolicy Satellite entitlement voice service policy for plmns.
+     * @throws IllegalArgumentException if the subscription does not exist.
+     */
+    public void setSatelliteEntitlementPlmnVoiceServicePolicy(int subId,
+            @NonNull String satellitePlmnsVoiceServicePolicy) {
+        writeDatabaseAndCacheHelper(subId,
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY,
+                satellitePlmnsVoiceServicePolicy,
+                SubscriptionInfoInternal.Builder::setSatellitePlmnsVoiceServicePolicy);
+    }
+
+    /**
      * Reload the database from content provider to the cache. This must be a synchronous operation
      * to prevent cache/database out-of-sync. Callers should be cautious to call this method because
      * it might take longer time to complete.
@@ -2446,11 +2593,24 @@
                                 SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS)))
                 .setIsSatelliteProvisionedForNonIpDatagram(cursor.getInt(
                         cursor.getColumnIndexOrThrow(
-                                SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM)));
-        if (mFeatureFlags.oemEnabledSatelliteFlag()) {
-            builder.setOnlyNonTerrestrialNetwork(cursor.getInt(cursor.getColumnIndexOrThrow(
-                    SimInfo.COLUMN_IS_ONLY_NTN)));
-        }
+                                SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM)))
+                .setSatelliteEntitlementBarredPlmnsList(cursor.getString(
+                        cursor.getColumnIndexOrThrow(
+                                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_BARRED_PLMNS)))
+                .setSatelliteEntitlementDataPlanForPlmns(cursor.getString(
+                        cursor.getColumnIndexOrThrow(
+                                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS)))
+                .setSatelliteEntitlementPlmnServiceTypes(cursor.getString(
+                        cursor.getColumnIndexOrThrow(
+                                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP)))
+                .setSatellitePlmnsDataServicePolicy(cursor.getString(
+                        cursor.getColumnIndexOrThrow(
+                                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY)))
+                .setSatellitePlmnsVoiceServicePolicy(cursor.getString(
+                        cursor.getColumnIndexOrThrow(
+                                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY)));
+        builder.setOnlyNonTerrestrialNetwork(cursor.getInt(cursor.getColumnIndexOrThrow(
+                SimInfo.COLUMN_IS_ONLY_NTN)));
         if (mFeatureFlags.supportPsimToEsimConversion()) {
             builder.setTransferStatus(cursor.getInt(cursor.getColumnIndexOrThrow(
                     SimInfo.COLUMN_TRANSFER_STATUS)));
@@ -2552,6 +2712,52 @@
     }
 
     /**
+     * Serialize the given Map<String, Integer> to Json model string.
+     *
+     * @param mapInfo of type Map
+     * @return Json in string format.
+     */
+    public String serializeMapToJsonString(Map<String, Integer> mapInfo) {
+        JSONObject json = new JSONObject();
+        if (mapInfo == null || mapInfo.isEmpty()) {
+            return json.toString();
+        }
+        try {
+            for (Map.Entry<String, Integer> entry : mapInfo.entrySet()) {
+                json.put(entry.getKey(), entry.getValue());
+            }
+        } catch (JSONException e) {
+            loge("serializeMapToCV JSON error: " + e.getMessage());
+        }
+        return json.toString();
+    }
+
+    /**
+     * Serialize the given Map<String, List<Integer>> to Json model string.
+     *
+     * @param mapList of type Map
+     * @return Json in string format.
+     */
+    public String serializeMapListToJsonString(Map<String, List<Integer>> mapList) {
+        JSONObject json = new JSONObject();
+        if (mapList == null || mapList.isEmpty()) {
+            return json.toString();
+        }
+        try {
+            for (Map.Entry<String, List<Integer>> entry : mapList.entrySet()) {
+                JSONArray jsonArray = new JSONArray();
+                for (int value : entry.getValue()) {
+                    jsonArray.put(value);
+                }
+                json.put(entry.getKey(), jsonArray);
+            }
+        } catch (JSONException e) {
+            loge("serializeMapListToCV JSON error: " + e.getMessage());
+        }
+        return json.toString();
+    }
+
+    /**
      * Log debug messages.
      *
      * @param s debug messages
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
index 92e112d..48bb51d 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
@@ -505,6 +505,36 @@
     private final int mIsSatelliteProvisionedForNonIpDatagram;
 
     /**
+     * The satellite entitlement barred plmns based on the entitlement query results
+     * By default, its empty. It is intended to use string to fit the database format.
+     */
+    @NonNull private final String mSatelliteEntitlementBarredPlmnsList;
+
+    /**
+     * The satellite entitlement data plan for plmns based on the entitlement query results
+     * By default, its empty. It is intended to use string to fit the database format.
+     */
+    @NonNull private final String mSatelliteEntitlementDataPlanForPlmn;
+
+    /**
+     * The satellite entitlement plmns services based on the entitlement query results
+     * By default, its empty. It is intended to use string to fit the database format.
+     */
+    @NonNull private final String mSatelliteEntitlementServicesForPlmn;
+
+    /**
+     * The satellite entitlement plmns data service policy based on the entitlement query results
+     * By default, its empty. It is intended to use string to fit the database format.
+     */
+    @NonNull private final String mSatellitePlmnsDataServicePolicy;
+
+    /**
+     * The satellite entitlement plmns voice service policy based on the entitlement query results
+     * By default, its empty. It is intended to use string to fit the database format.
+     */
+    @NonNull private final String mSatellitePlmnsVoiceServicePolicy;
+
+    /**
      * Constructor from builder.
      *
      * @param builder Builder of {@link SubscriptionInfoInternal}.
@@ -586,6 +616,11 @@
         this.mIsSatelliteESOSSupported = builder.mIsSatelliteESOSSupported;
         this.mIsSatelliteProvisionedForNonIpDatagram =
                 builder.mIsSatelliteProvisionedForNonIpDatagram;
+        this.mSatelliteEntitlementBarredPlmnsList = builder.mSatelliteEntitlementBarredPlmnsList;
+        this.mSatelliteEntitlementDataPlanForPlmn = builder.mSatelliteEntitlementDataPlanForPlmn;
+        this.mSatelliteEntitlementServicesForPlmn = builder.mSatelliteEntitlementServicesForPlmn;
+        this.mSatellitePlmnsDataServicePolicy = builder.mSatellitePlmnsDataServicePolicy;
+        this.mSatellitePlmnsVoiceServicePolicy = builder.mSatellitePlmnsVoiceServicePolicy;
     }
 
     /**
@@ -1299,6 +1334,55 @@
         return mIsSatelliteProvisionedForNonIpDatagram;
     }
 
+    /**
+     * @return Satellite entitlement barred plmns is empty or not by entitlement query result.
+     *
+     */
+    @NonNull
+    public String getSatelliteEntitlementBarredPlmnsList() {
+        return mSatelliteEntitlementBarredPlmnsList;
+    }
+
+    /**
+     * @return Satellite entitlement data plan for plmns is empty or not by entitlement query
+     * result.
+     *
+     */
+    @NonNull
+    public String getSatelliteEntitlementDataPlanForPlmns() {
+        return mSatelliteEntitlementDataPlanForPlmn;
+    }
+
+    /**
+     * @return Satellite entitlement data plan for plmns is empty or not by entitlement query
+     * result.
+     *
+     */
+    @NonNull
+    public String getSatelliteEntitlementPlmnsServiceTypes() {
+        return mSatelliteEntitlementServicesForPlmn;
+    }
+
+    /**
+     * @return Satellite entitlement plmns data service policy is empty or not by entitlement query
+     * result.
+     *
+     */
+    @NonNull
+    public String getSatellitePlmnsDataServicePolicy() {
+        return mSatellitePlmnsDataServicePolicy;
+    }
+
+    /**
+     * @return Satellite entitlement plmns voice service policy is empty or not by entitlement query
+     * result.
+     *
+     */
+    @NonNull
+    public String getSatellitePlmnsVoiceServicePolicy() {
+        return mSatellitePlmnsVoiceServicePolicy;
+    }
+
     /** @return converted {@link SubscriptionInfo}. */
     @NonNull
     public SubscriptionInfo toSubscriptionInfo() {
@@ -1405,6 +1489,11 @@
                 + " isSatelliteESOSSupported=" + mIsSatelliteESOSSupported
                 + " isSatelliteProvisionedForNonIpDatagram="
                 + mIsSatelliteProvisionedForNonIpDatagram
+                + " mSatelliteEntitlementBarredPlmnsList=" + mSatelliteEntitlementBarredPlmnsList
+                + " mSatelliteEntitlementDataPlanForPlmn=" + mSatelliteEntitlementDataPlanForPlmn
+                + " mSatelliteEntitlementServicesForPlmn=" + mSatelliteEntitlementServicesForPlmn
+                + " mSatellitePlmnsDataServicePolicy=" + mSatellitePlmnsDataServicePolicy
+                + " mSatellitePlmnsVoiceServicePolicy=" + mSatellitePlmnsVoiceServicePolicy
                 + "]";
     }
 
@@ -1470,7 +1559,15 @@
                 && mSatelliteEntitlementPlmns.equals(that.mSatelliteEntitlementPlmns)
                 && mIsSatelliteESOSSupported == that.mIsSatelliteESOSSupported
                 && mIsSatelliteProvisionedForNonIpDatagram
-                == that.mIsSatelliteProvisionedForNonIpDatagram;
+                == that.mIsSatelliteProvisionedForNonIpDatagram
+                && mSatelliteEntitlementBarredPlmnsList.equals(
+                that.mSatelliteEntitlementBarredPlmnsList)
+                && mSatelliteEntitlementDataPlanForPlmn.equals(
+                that.mSatelliteEntitlementDataPlanForPlmn)
+                && mSatelliteEntitlementServicesForPlmn.equals(
+                that.mSatelliteEntitlementServicesForPlmn)
+                && mSatellitePlmnsDataServicePolicy.equals(that.mSatellitePlmnsDataServicePolicy)
+                && mSatellitePlmnsVoiceServicePolicy.equals(that.mSatellitePlmnsVoiceServicePolicy);
     }
 
     @Override
@@ -1504,7 +1601,9 @@
                 mIsSatelliteAttachEnabledForCarrier, mIsOnlyNonTerrestrialNetwork,
                 mServiceCapabilities, mTransferStatus, mIsSatelliteEntitlementStatus,
                 mSatelliteEntitlementPlmns, mIsSatelliteESOSSupported,
-                mIsSatelliteProvisionedForNonIpDatagram);
+                mIsSatelliteProvisionedForNonIpDatagram, mSatelliteEntitlementBarredPlmnsList,
+                mSatelliteEntitlementDataPlanForPlmn, mSatelliteEntitlementServicesForPlmn,
+                mSatellitePlmnsDataServicePolicy, mSatellitePlmnsVoiceServicePolicy);
         result = 31 * result + Arrays.hashCode(mNativeAccessRules);
         result = 31 * result + Arrays.hashCode(mCarrierConfigAccessRules);
         result = 31 * result + Arrays.hashCode(mRcsConfig);
@@ -1923,6 +2022,41 @@
         private int mIsSatelliteProvisionedForNonIpDatagram = 0;
 
         /**
+         * Whether satellite entitlement barred plmns is empty or not by entitlement query result.
+         */
+        @NonNull
+        private String mSatelliteEntitlementBarredPlmnsList = "";
+
+        /**
+         * Whether satellite entitlement data plan for plmns is empty or not by entitlement query
+         * result.
+         */
+        @NonNull
+        private String mSatelliteEntitlementDataPlanForPlmn = "";
+
+        /**
+         * Whether satellite entitlement servicves for plmns is empty or not by entitlement query
+         * result.
+         */
+        @NonNull
+        private String mSatelliteEntitlementServicesForPlmn = "";
+
+        /**
+         * Whether satellite entitlement plmns data service policy isempty or not by entitlement
+         * query result.
+         */
+        @NonNull
+        private String mSatellitePlmnsDataServicePolicy = "";
+
+        /**
+         * Whether satellite entitlement plmns voice service policy isempty or not by entitlement
+         * query result.
+         */
+        @NonNull
+        private String mSatellitePlmnsVoiceServicePolicy = "";
+
+
+        /**
          * Default constructor.
          */
         public Builder() {
@@ -2006,6 +2140,11 @@
             mSatelliteEntitlementPlmns = info.mSatelliteEntitlementPlmns;
             mIsSatelliteESOSSupported = info.mIsSatelliteESOSSupported;
             mIsSatelliteProvisionedForNonIpDatagram = info.mIsSatelliteProvisionedForNonIpDatagram;
+            mSatelliteEntitlementBarredPlmnsList = info.mSatelliteEntitlementBarredPlmnsList;
+            mSatelliteEntitlementDataPlanForPlmn = info.mSatelliteEntitlementDataPlanForPlmn;
+            mSatelliteEntitlementServicesForPlmn = info.mSatelliteEntitlementServicesForPlmn;
+            mSatellitePlmnsDataServicePolicy = info.mSatellitePlmnsDataServicePolicy;
+            mSatellitePlmnsVoiceServicePolicy = info.mSatellitePlmnsVoiceServicePolicy;
         }
 
         /**
@@ -3010,5 +3149,73 @@
         public SubscriptionInfoInternal build() {
             return new SubscriptionInfoInternal(this);
         }
+
+        /**
+         * Set whether satellite entitlement plmns is empty or not by entitlement query result.
+         *
+         * @param plmnsBarredList satellite entitlement plmns is empty or not by
+         * entitlement query result.
+         * @return The builder
+         */
+        @NonNull
+        public Builder setSatelliteEntitlementBarredPlmnsList(@NonNull String plmnsBarredList) {
+            mSatelliteEntitlementBarredPlmnsList = plmnsBarredList;
+            return this;
+        }
+
+        /**
+         * Set whether satellite entitlement Data plan for plmn is empty or not by entitlement
+         * query result.
+         *
+         * @param plmnDataPlanJson satellite entitlement data plan for plmns.
+         * @return The builder
+         */
+        @NonNull
+        public Builder setSatelliteEntitlementDataPlanForPlmns(@NonNull String plmnDataPlanJson) {
+            mSatelliteEntitlementDataPlanForPlmn = plmnDataPlanJson;
+            return this;
+        }
+
+        /**
+         * Set whether satellite entitlement services for the plmns is empty or not by entitlement
+         * query result.
+         *
+         * @param plmnServiceMapCv satellite entitlement services for plmns.
+         * @return The builder
+         */
+        @NonNull
+        public Builder setSatelliteEntitlementPlmnServiceTypes(
+                @NonNull String plmnServiceMapCv) {
+            mSatelliteEntitlementServicesForPlmn = plmnServiceMapCv;
+            return this;
+        }
+
+        /**
+         * Set whether satellite entitlement plmns data service policy is empty or not by
+         * entitlement query result.
+         *
+         * @param satellitePlmnsDataServicePolicy satellite entitlement plmns data service policy.
+         * @return The builder
+         */
+        @NonNull
+        public Builder setSatellitePlmnsDataServicePolicy(
+                @NonNull String satellitePlmnsDataServicePolicy) {
+            mSatellitePlmnsDataServicePolicy = satellitePlmnsDataServicePolicy;
+            return this;
+        }
+
+        /**
+         * Set whether satellite entitlement plmns voice service policy is empty or not by
+         * entitlement query result.
+         *
+         * @param satellitePlmnsVoiceServicePolicy satellite entitlement plmns voice service policy.
+         * @return The builder
+         */
+        @NonNull
+        public Builder setSatellitePlmnsVoiceServicePolicy(
+                @NonNull String satellitePlmnsVoiceServicePolicy) {
+            mSatellitePlmnsVoiceServicePolicy = satellitePlmnsVoiceServicePolicy;
+            return this;
+        }
     }
 }
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
index fc8d607..bedc20e 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -66,6 +66,7 @@
 import android.telecom.TelecomManager;
 import android.telephony.AnomalyReporter;
 import android.telephony.CarrierConfigManager;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.RadioAccessFamily;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -116,14 +117,21 @@
 import com.android.internal.telephony.uicc.UiccSlot;
 import com.android.internal.telephony.util.ArrayUtils;
 import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.internal.telephony.util.WorkerThread;
 import com.android.telephony.Rlog;
 
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -198,7 +206,12 @@
             SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS,
             SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS,
             SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED,
-            SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM
+            SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM,
+            SimInfo.COLUMN_SATELLITE_ENTITLEMENT_BARRED_PLMNS,
+            SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS,
+            SimInfo.COLUMN_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP,
+            SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY,
+            SimInfo.COLUMN_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY
     );
 
     /**
@@ -491,10 +504,14 @@
         mUiccController = UiccController.getInstance();
         mHandler = new Handler(looper);
 
-        HandlerThread backgroundThread = new HandlerThread(LOG_TAG);
-        backgroundThread.start();
+        if (mFeatureFlags.threadShred()) {
+            mBackgroundHandler = new Handler(WorkerThread.get().getLooper());
+        } else {
+            HandlerThread backgroundThread = new HandlerThread(LOG_TAG);
+            backgroundThread.start();
 
-        mBackgroundHandler = new Handler(backgroundThread.getLooper());
+            mBackgroundHandler = new Handler(backgroundThread.getLooper());
+        }
 
         mDefaultVoiceSubId = new WatchedInt(Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION,
@@ -549,12 +566,22 @@
         mSimState = new int[mTelephonyManager.getSupportedModemCount()];
         Arrays.fill(mSimState, TelephonyManager.SIM_STATE_UNKNOWN);
 
-        // Create a separate thread for subscription database manager. The database will be updated
-        // from a different thread.
-        HandlerThread handlerThread = new HandlerThread(LOG_TAG);
-        handlerThread.start();
-        mSubscriptionDatabaseManager = new SubscriptionDatabaseManager(context,
-                handlerThread.getLooper(), mFeatureFlags,
+        Looper dbLooper = null;
+
+        if (mFeatureFlags.threadShred()) {
+            dbLooper = WorkerThread.get().getLooper();
+        } else {
+            // Create a separate thread for subscription database manager.
+            // The database will be updated from a different thread.
+            HandlerThread handlerThread = new HandlerThread(LOG_TAG);
+            handlerThread.start();
+            dbLooper = handlerThread.getLooper();
+        }
+
+        mSubscriptionDatabaseManager = new SubscriptionDatabaseManager(
+                context,
+                dbLooper,
+                mFeatureFlags,
                 new SubscriptionDatabaseManagerCallback(mHandler::post) {
                     /**
                      * Called when database has been loaded into the cache.
@@ -909,10 +936,6 @@
      * {@code false} otherwise.
      */
     public void setNtn(int subId, boolean isNtn) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            return;
-        }
-
         // This can throw IllegalArgumentException if the subscription does not exist.
         try {
             mSubscriptionDatabaseManager.setNtn(subId, (isNtn ? 1 : 0));
@@ -1233,14 +1256,9 @@
                     }
 
                     boolean isSatelliteSpn = false;
-                    if (mFeatureFlags.oemEnabledSatelliteFlag() ) {
-                        if (isSatelliteSpn(embeddedProfile.getServiceProviderName())) {
-                            isSatelliteSpn = true;
-                            builder.setOnlyNonTerrestrialNetwork(1);
-                        }
-                    } else {
-                        log("updateEmupdateEmbeddedSubscriptions: oemEnabledSatelliteFlag is "
-                                + "disabled");
+                    if (isSatelliteSpn(embeddedProfile.getServiceProviderName())) {
+                        isSatelliteSpn = true;
+                        builder.setOnlyNonTerrestrialNetwork(1);
                     }
 
                     if (android.os.Build.isDebuggable() &&
@@ -1267,7 +1285,7 @@
                         String mnc = cid.getMnc();
                         builder.setMcc(mcc);
                         builder.setMnc(mnc);
-                        if (mFeatureFlags.oemEnabledSatelliteFlag() && !isSatelliteSpn) {
+                        if (!isSatelliteSpn) {
                             builder.setOnlyNonTerrestrialNetwork(
                                     isSatellitePlmn(mcc + mnc) ? 1 : 0);
                         }
@@ -1618,10 +1636,8 @@
                             SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_DATABASE_UPDATED)) {
                         logl("Sim specific settings changed the database.");
                         mSubscriptionDatabaseManager.reloadDatabaseSync();
-                        if (mFeatureFlags.backupAndRestoreForEnable2g()) {
-                            PhoneFactory.getPhone(phoneId)
-                                    .loadAllowedNetworksFromSubscriptionDatabase();
-                        }
+                        PhoneFactory.getPhone(phoneId)
+                                .loadAllowedNetworksFromSubscriptionDatabase();
                     }
                 }
 
@@ -2308,9 +2324,17 @@
 
         enforceTelephonyFeatureWithException(getCurrentPackageName(), "addSubInfo");
 
-        if (!SubscriptionManager.isValidSlotIndex(slotIndex)
-                && slotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
-            throw new IllegalArgumentException("Invalid slotIndex " + slotIndex);
+        if (subscriptionType == SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM) {
+            if (!SubscriptionManager.isValidSlotIndex(slotIndex)) {
+                throw new IllegalArgumentException("Invalid slot index " + slotIndex
+                        + " for local SIM");
+            }
+        } else if (subscriptionType == SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM) {
+            // We only support one remote SIM at this point, so use -1. This needs to be revisited
+            // if we plan to support multiple remote SIMs in the future.
+            slotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+        } else {
+            throw new IllegalArgumentException("Invalid subscription type " + subscriptionType);
         }
 
         // Now that all security checks passes, perform the operation as ourselves.
@@ -3835,47 +3859,17 @@
                 Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         enforceTelephonyFeatureWithException(callingPackage, "getPhoneNumber");
 
-        if (mFeatureFlags.saferGetPhoneNumber()) {
-            checkPhoneNumberSource(source);
-            subId = checkAndGetSubId(subId);
-            if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return "";
+        checkPhoneNumberSource(source);
+        subId = checkAndGetSubId(subId);
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return "";
 
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                return getPhoneNumberFromSourceInternal(subId, source);
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        } else {
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
-                        .getSubscriptionInfoInternal(subId);
-
-                if (subInfo == null) {
-                    loge("Invalid sub id " + subId + ", callingPackage=" + callingPackage);
-                    return "";
-                }
-
-                switch(source) {
-                    case SubscriptionManager.PHONE_NUMBER_SOURCE_UICC:
-                        Phone phone = PhoneFactory.getPhone(getSlotIndex(subId));
-                        if (phone != null) {
-                        return TextUtils.emptyIfNull(phone.getLine1Number());
-                        } else {
-                        return subInfo.getNumber();
-                        }
-                    case SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER:
-                        return subInfo.getNumberFromCarrier();
-                    case SubscriptionManager.PHONE_NUMBER_SOURCE_IMS:
-                        return subInfo.getNumberFromIms();
-                    default:
-                        throw new IllegalArgumentException("Invalid number source " + source);
-                }
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return getPhoneNumberFromSourceInternal(subId, source);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
+
     }
 
     /**
@@ -3924,20 +3918,10 @@
         switch(source) {
             case SubscriptionManager.PHONE_NUMBER_SOURCE_UICC:
                 final Phone phone = PhoneFactory.getPhone(getSlotIndex(subId));
-                if (mFeatureFlags.uiccPhoneNumberFix()) {
-                    if (phone != null) {
-                        String number = phone.getLine1Number();
-                        if (!TextUtils.isEmpty(number)) {
-                            return number;
-                        }
-                    }
-                    return subInfo.getNumber();
+                if (phone != null) {
+                    return TextUtils.emptyIfNull(phone.getLine1Number());
                 } else {
-                    if (phone != null) {
-                        return TextUtils.emptyIfNull(phone.getLine1Number());
-                    } else {
-                        return subInfo.getNumber();
-                    }
+                    return subInfo.getNumber();
                 }
             case SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER:
                 return subInfo.getNumberFromCarrier();
@@ -3981,50 +3965,28 @@
         enforceTelephonyFeatureWithException(callingPackage,
                 "getPhoneNumberFromFirstAvailableSource");
 
-        if (mFeatureFlags.saferGetPhoneNumber()) {
-            subId = checkAndGetSubId(subId);
-            if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return "";
+        subId = checkAndGetSubId(subId);
+        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return "";
 
-            final long identity = Binder.clearCallingIdentity();
-            try {
-                String number;
-                number = getPhoneNumberFromSourceInternal(
-                        subId,
-                        SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER);
-                if (!TextUtils.isEmpty(number)) return number;
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            String number;
+            number = getPhoneNumberFromSourceInternal(
+                    subId,
+                    SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER);
+            if (!TextUtils.isEmpty(number)) return number;
 
-                number = getPhoneNumberFromSourceInternal(
-                        subId,
-                        SubscriptionManager.PHONE_NUMBER_SOURCE_UICC);
-                if (!TextUtils.isEmpty(number)) return number;
+            number = getPhoneNumberFromSourceInternal(
+                    subId,
+                    SubscriptionManager.PHONE_NUMBER_SOURCE_UICC);
+            if (!TextUtils.isEmpty(number)) return number;
 
-                number = getPhoneNumberFromSourceInternal(
-                        subId,
-                        SubscriptionManager.PHONE_NUMBER_SOURCE_IMS);
-                return TextUtils.emptyIfNull(number);
-            } finally {
-                Binder.restoreCallingIdentity(identity);
-            }
-        } else {
-            String numberFromCarrier = getPhoneNumber(subId,
-                    SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER, callingPackage,
-                    callingFeatureId);
-            if (!TextUtils.isEmpty(numberFromCarrier)) {
-                return numberFromCarrier;
-            }
-            String numberFromUicc = getPhoneNumber(
-                    subId, SubscriptionManager.PHONE_NUMBER_SOURCE_UICC, callingPackage,
-                    callingFeatureId);
-            if (!TextUtils.isEmpty(numberFromUicc)) {
-                return numberFromUicc;
-            }
-            String numberFromIms = getPhoneNumber(
-                    subId, SubscriptionManager.PHONE_NUMBER_SOURCE_IMS, callingPackage,
-                    callingFeatureId);
-            if (!TextUtils.isEmpty(numberFromIms)) {
-                return numberFromIms;
-            }
-            return "";
+            number = getPhoneNumberFromSourceInternal(
+                    subId,
+                    SubscriptionManager.PHONE_NUMBER_SOURCE_IMS);
+            return TextUtils.emptyIfNull(number);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
         }
     }
 
@@ -4175,6 +4137,9 @@
      * Returns whether the given subscription is associated with the calling user.
      *
      * @param subscriptionId the subscription ID of the subscription
+     * @param callingPackage The package making the call
+     * @param callingFeatureId The feature in the package
+     *
      * @return {@code true} if the subscription is associated with the user that the calling process
      *         is running in; {@code false} otherwise.
      *
@@ -4182,13 +4147,16 @@
      * @throws SecurityException if the caller doesn't have permissions required.
      */
     @Override
-    public boolean isSubscriptionAssociatedWithCallingUser(int subscriptionId) {
-        enforcePermissions("isSubscriptionAssociatedWithCallingUser",
-                Manifest.permission.READ_PHONE_STATE);
+    public boolean isSubscriptionAssociatedWithCallingUser(int subscriptionId,
+            @NonNull String callingPackage, @Nullable String callingFeatureId) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subscriptionId,
+                callingPackage, callingFeatureId, "isSubscriptionAssociatedWithCallingUser")) {
+            throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or "
+                    + "carrier privilege");
+        }
 
         UserHandle myUserHandle = UserHandle.of(UserHandle.getCallingUserId());
-        return mFeatureFlags.subscriptionUserAssociationQuery()
-            && isSubscriptionAssociatedWithUserNoCheck(subscriptionId, myUserHandle);
+        return isSubscriptionAssociatedWithUserNoCheck(subscriptionId, myUserHandle);
     }
 
     /**
@@ -4376,10 +4344,8 @@
                     SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_DATABASE_UPDATED)) {
                 logl("Sim specific settings changed the database.");
                 mSubscriptionDatabaseManager.reloadDatabaseSync();
-                if (mFeatureFlags.backupAndRestoreForEnable2g()) {
-                    Arrays.stream(PhoneFactory.getPhones())
-                            .forEach(Phone::loadAllowedNetworksFromSubscriptionDatabase);
-                }
+                Arrays.stream(PhoneFactory.getPhones())
+                        .forEach(Phone::loadAllowedNetworksFromSubscriptionDatabase);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -4623,16 +4589,37 @@
     }
 
     /**
-     * Set the satellite entitlement plmn list value in the subscription database.
+     * Save the satellite entitlement Info in the subscription database.
      *
-     * @param subId subscription id.
-     * @param satelliteEntitlementPlmnList satellite entitlement plmn list
+     * @param subId                     Subscription ID.
+     * @param allowedPlmnList           Plmn [MCC+MNC] list of codes to determine if satellite
+     *                                  communication is allowed. Ex : "123123,12310".
+     * @param barredPlmnList            Plmn [MCC+MNC] list of codes to determine if satellite
+     *                                  communication is not allowed.  Ex : "123123,12310".
+     * @param plmnDataPlanMap           data plan per plmn of type
+     *                                  {@link SatelliteController.SatelliteDataPlan}.
+     *                                  Ex : {"302820":0, "31026":1}
+     * @param plmnServiceTypeMap        list of supported services per plmn of type
+     *                                  {@link NetworkRegistrationInfo.ServiceType}).
+     *                                  Ex : {"302820":[1,3],"31026":[2,3]}
+     * @param plmnDataServicePolicyMap  data support mode per plmn map of types
+     *                                  {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE}.
+     *                                  Ex : {"302820":2, "31026":1}
+     * @param plmnVoiceServicePolicyMap voice support mode per plmn map of types
+     *                                  {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE}.
+     *                                  Ex : {"302820":2, "31026":1}.
      */
-    public void setSatelliteEntitlementPlmnList(int subId,
-            @NonNull List<String> satelliteEntitlementPlmnList) {
+    public void setSatelliteEntitlementInfo(int subId,
+            @NonNull List<String> allowedPlmnList,
+            @Nullable List<String> barredPlmnList,
+            @Nullable Map<String, Integer> plmnDataPlanMap,
+            @Nullable Map<String, List<Integer>> plmnServiceTypeMap,
+            @Nullable Map<String, Integer> plmnDataServicePolicyMap,
+            @Nullable Map<String, Integer> plmnVoiceServicePolicyMap) {
         try {
-            mSubscriptionDatabaseManager.setSatelliteEntitlementPlmnList(
-                    subId, satelliteEntitlementPlmnList);
+            mSubscriptionDatabaseManager.setSatelliteEntitlementInfo(
+                    subId, allowedPlmnList, barredPlmnList, plmnDataPlanMap, plmnServiceTypeMap,
+                    plmnDataServicePolicyMap, plmnVoiceServicePolicyMap);
         } catch (IllegalArgumentException e) {
             loge("setSatelliteEntitlementPlmnList: invalid subId=" + subId);
         }
@@ -4712,6 +4699,94 @@
     }
 
     /**
+     * Get the satellite entitlement barred plmn list value from the subscription database.
+     *
+     * @param subId subscription id.
+     * @return satellite entitlement plmn list. Ex : "123123,12310".
+     */
+    @NonNull
+    public List<String> getSatelliteEntitlementBarredPlmnList(int subId) {
+        SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(
+                subId);
+
+        return Optional.ofNullable(subInfo).map(
+                SubscriptionInfoInternal::getSatelliteEntitlementBarredPlmnsList).filter(
+                s -> !s.isEmpty()).map(
+                s -> Arrays.stream(s.split(",")).collect(Collectors.toList())).orElse(
+                new ArrayList<>());
+    }
+
+    /**
+     * Get the satellite entitlement data plan for the plmns value from the subscription database.
+     *
+     * @param subId subscription id.
+     * @return satellite entitlement data plan map. Ex : {"302820":0, "31026":1}.
+     */
+    @NonNull
+    public Map<String, Integer> getSatelliteEntitlementDataPlanForPlmns(int subId) {
+        SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(
+                subId);
+        if (subInfo == null) {
+            return new HashMap<>();
+        }
+        String plmnDataPlanJson = subInfo.getSatelliteEntitlementDataPlanForPlmns();
+        return deSerializeCVToMap(plmnDataPlanJson);
+    }
+
+    /**
+     * Get the satellite entitlement services for the plmns value from the subscription database.
+     *
+     * @param subId subscription id.
+     * @return satellite entitlement services map. Ex : {"302820":[1,3],"31026":[2,3]}.
+     */
+    @NonNull
+    public Map<String, List<Integer>> getSatelliteEntitlementPlmnServiceTypeMap(int subId) {
+        SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(
+                subId);
+        if (subInfo == null) {
+            return new HashMap<>();
+        }
+        String plmnDataPlanJson = subInfo.getSatelliteEntitlementPlmnsServiceTypes();
+        return deSerializeCVToMapList(plmnDataPlanJson);
+    }
+
+    /**
+     * Get the satellite entitlement data service policy for plmns  value from the subscription
+     * database.
+     *
+     * @param subId subscription id.
+     * @return satellite entitlement data service policy map. Ex : {"302820":2, "31026":1}.
+     */
+    @NonNull
+    public Map<String, Integer> getSatelliteEntitlementPlmnDataServicePolicy(int subId) {
+        SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(
+                subId);
+        if (subInfo == null) {
+            return new HashMap<>();
+        }
+        String plmnDataPolicyJson = subInfo.getSatellitePlmnsDataServicePolicy();
+        return deSerializeCVToMap(plmnDataPolicyJson);
+    }
+
+    /**
+     * Get the satellite entitlement voice service policy for plmns  value from the subscription
+     * database.
+     *
+     * @param subId subscription id.
+     * @return satellite entitlement voice service policy map. Ex : {"302820":2, "31026":1}.
+     */
+    @NonNull
+    public Map<String, Integer> getSatelliteEntitlementPlmnVoiceServicePolicy(int subId) {
+        SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(
+                subId);
+        if (subInfo == null) {
+            return new HashMap<>();
+        }
+        String plmnVoicePolicyJson = subInfo.getSatellitePlmnsVoiceServicePolicy();
+        return deSerializeCVToMap(plmnVoicePolicyJson);
+    }
+
+    /**
      * Get whether the subscription is provisioned for OEM-enabled or carrier roaming NB-IOT
      * satellite service or not.
      *
@@ -4794,8 +4869,7 @@
             return;
         }
 
-        if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
-                || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+        if (!CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
                 Binder.getCallingUserHandle())
                 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
             // Skip to check associated telephony feature,
@@ -4826,11 +4900,6 @@
      * "config_satellite_sim_plmn_identifier", {@code false} otherwise.
      */
     private boolean isSatellitePlmn(@NonNull String mccMnc) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            log("isSatellitePlmn: oemEnabledSatelliteFlag is disabled");
-            return false;
-        }
-
         final int id = R.string.config_satellite_sim_plmn_identifier;
         String overlayMccMnc = null;
         try {
@@ -4855,11 +4924,6 @@
      * "config_satellite_sim_spn_identifier", {@code false} otherwise.
      */
     private boolean isSatelliteSpn(@NonNull String spn) {
-        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
-            log("isSatelliteSpn: oemEnabledSatelliteFlag is disabled");
-            return false;
-        }
-
         final int id = R.string.config_satellite_sim_spn_identifier;
         String overlaySpn = null;
         try {
@@ -4915,6 +4979,58 @@
     }
 
     /**
+     * DeSerialize the given Json model string to Map<String, Integer>.
+     *
+     * @param jsonString Json in string format.
+     * @return Map of type Map<String, Integer>.
+     */
+    public Map<String, Integer> deSerializeCVToMap(String jsonString) {
+        Map<String, Integer> map = new HashMap<>();
+        try {
+            if (TextUtils.isEmpty(jsonString)) {
+                return map;
+            }
+            JSONObject json = new JSONObject(jsonString);
+            Iterator<String> keys = json.keys();
+            while (keys.hasNext()) {
+                String key = keys.next();
+                map.put(key, json.getInt(key));
+            }
+        } catch (JSONException e) {
+            loge("deSerializeCVToMap JSON error: " + e.getMessage());
+        }
+        return map;
+    }
+
+    /**
+     * DeSerialize the given Json model string to Map<String, List<Integer>>.
+     *
+     * @param jsonString Json in string format.
+     * @return Map of type Map<String, List<Integer>>.
+     */
+    public Map<String, List<Integer>> deSerializeCVToMapList(String jsonString) {
+        Map<String, List<Integer>> map = new HashMap<>();
+        try {
+            if (TextUtils.isEmpty(jsonString)) {
+                return map;
+            }
+            JSONObject json = new JSONObject(jsonString);
+            Iterator<String> keys = json.keys();
+            while (keys.hasNext()) {
+                String key = keys.next();
+                JSONArray jsonArray = json.getJSONArray(key);
+                List<Integer> values = new ArrayList<>();
+                for (int i = 0; i < jsonArray.length(); i++) {
+                    values.add(jsonArray.getInt(i));
+                }
+                map.put(key, values);
+            }
+        } catch (JSONException e) {
+            loge("deSerializeCVToMapList JSON error: " + e.getMessage());
+        }
+        return map;
+    }
+     /**
      * Log debug messages.
      *
      * @param s debug messages
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index 9db25b6..c242a1b 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -56,6 +56,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.hidden_from_bootclasspath.com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.CarrierServiceBindHelper;
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
@@ -277,11 +278,6 @@
         if (DBG) {
             logWithLocalLog("config_num_physical_slots = " + numPhysicalSlots);
         }
-        // Minimum number of physical slot count should be equals to or greater than phone count,
-        // if it is less than phone count use phone count as physical slot count.
-        if (numPhysicalSlots < mCis.length) {
-            numPhysicalSlots = mCis.length;
-        }
 
         mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
 
@@ -1661,6 +1657,7 @@
      * @return true if CDMA is supported by the device
      */
     public static boolean isCdmaSupported(Context context) {
+        if (Flags.phoneTypeCleanup()) return false;
         PackageManager packageManager = context.getPackageManager();
         boolean isCdmaSupported =
                 packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA);
@@ -1668,7 +1665,7 @@
     }
 
     private boolean isValidPhoneIndex(int index) {
-        return (index >= 0 && index < TelephonyManager.getDefault().getPhoneCount());
+        return (index >= 0 && index < mTelephonyManager.getActiveModemCount());
     }
 
     private boolean isValidSlotIndex(int index) {
@@ -1676,7 +1673,7 @@
     }
 
     private boolean isShuttingDown() {
-        for (int i = 0; i < TelephonyManager.getDefault().getActiveModemCount(); i++) {
+        for (int i = 0; i < mTelephonyManager.getActiveModemCount(); i++) {
             if (PhoneFactory.getPhone(i) != null &&
                     PhoneFactory.getPhone(i).isShuttingDown()) {
                 return true;
diff --git a/src/java/com/android/internal/telephony/uicc/UiccSlot.java b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
index d986c93..eef42fa 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccSlot.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccSlot.java
@@ -38,6 +38,7 @@
 import android.view.WindowManager;
 
 import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.Phone;
@@ -495,7 +496,9 @@
      *  Use this API to get the iccId of the inactive port only.
      */
     public String getIccId(int portIdx) {
-        return mIccIds.get(portIdx);
+        synchronized (mLock) {
+            return mIccIds.get(portIdx);
+        }
     }
 
     public String getEid() {
@@ -660,10 +663,13 @@
     }
 
     private Map<Integer, String> getPrintableIccIds() {
-        Map<Integer, String> printableIccIds = mIccIds.entrySet().stream()
+        Map<Integer, String> copyOfIccIdMap;
+        synchronized (mLock) {
+            copyOfIccIdMap = new HashMap<>(mIccIds);
+        }
+        return copyOfIccIdMap.entrySet().stream()
                 .collect(Collectors.toMap(Map.Entry::getKey,
                         e -> SubscriptionInfo.getPrintableId(e.getValue())));
-        return printableIccIds;
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java b/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
index 309fe79..5a63179 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
@@ -54,8 +54,6 @@
  * @hide
  */
 public class ApduSender {
-    private static final String LOG_TAG = "ApduSender";
-
     // Parameter and response used by the command to get extra responses of an APDU command.
     private static final int INS_GET_MORE_RESPONSE = 0xC0;
     private static final int SW1_MORE_RESPONSE = 0x61;
@@ -70,18 +68,6 @@
     static final String ISD_R_AID = "A0000005591010FFFFFFFF8900000100";
     private static final String CHANNEL_RESPONSE_ID_PRE = "esim-res-id";
 
-    private static void logv(String msg) {
-        Rlog.v(LOG_TAG, msg);
-    }
-
-    private static void logd(String msg) {
-        Rlog.d(LOG_TAG, msg);
-    }
-
-    private static void loge(String msg) {
-        Rlog.e(LOG_TAG, msg);
-    }
-
     private final String mAid;
     private final boolean mSupportExtendedApdu;
     private final OpenLogicalChannelInvocation mOpenChannel;
@@ -92,6 +78,7 @@
     private final String mChannelResponseKey;
     // closeAnyOpenChannel() needs a handler for its async callbacks.
     private final Handler mHandler;
+    private final String mLogTag;
 
     // Lock for accessing mChannelInUse. We only allow to open a single logical
     // channel at any time for an AID and to invoke one command at any time.
@@ -110,6 +97,7 @@
         if (!aid.equals(ISD_R_AID) && !"user".equals(Build.TYPE)) {
             throw new IllegalArgumentException("Only ISD-R AID is supported.");
         }
+        mLogTag = "ApduSender-" + phoneId;
         mAid = aid;
         mContext = context;
         mSupportExtendedApdu = supportExtendedApdu;
@@ -146,7 +134,7 @@
             return;
         }
 
-        boolean euiccSession = EuiccSession.get().hasSession();
+        boolean euiccSession = EuiccSession.get(mContext).hasSession();
         // Case 1, channel was already opened AND EuiccSession is ongoing.
         // sendCommand directly. Do not immediately close channel after sendCommand.
         // Case 2, channel was already opened AND EuiccSession is not ongoing. This means
@@ -159,7 +147,7 @@
         // before sendCommand. Close channel immediately after sendCommand.
         if (mChannelOpened) {  // Case 1 or 2
             if (euiccSession) {
-                EuiccSession.get().noteChannelOpen(this);
+                EuiccSession.get(mContext).noteChannelOpen(this);
             }
             RequestBuilder builder = getRequestBuilderWithOpenedChannel(requestProvider,
                     !euiccSession /* closeChannelImmediately */, resultCallback, handler);
@@ -170,7 +158,7 @@
                     !euiccSession /* closeChannelImmediately */, resultCallback, handler);
         } else {  // Case 3 or 4
             if (euiccSession) {
-                EuiccSession.get().noteChannelOpen(this);
+                EuiccSession.get(mContext).noteChannelOpen(this);
             }
             openChannel(requestProvider,
                     !euiccSession /* closeChannelImmediately */, resultCallback, handler);
@@ -534,4 +522,16 @@
             return true;
         }
     }
+
+    private void logv(String msg) {
+        Rlog.v(mLogTag, msg);
+    }
+
+    private void logd(String msg) {
+        Rlog.d(mLogTag, msg);
+    }
+
+    private void loge(String msg) {
+        Rlog.e(mLogTag, msg);
+    }
 }
diff --git a/src/java/com/android/internal/telephony/util/LocaleUtils.java b/src/java/com/android/internal/telephony/util/LocaleUtils.java
index 064b10d..26cc6db 100644
--- a/src/java/com/android/internal/telephony/util/LocaleUtils.java
+++ b/src/java/com/android/internal/telephony/util/LocaleUtils.java
@@ -47,7 +47,7 @@
     public static Locale getLocaleFromMcc(Context context, int mcc, String simLanguage) {
         boolean hasSimLanguage = !TextUtils.isEmpty(simLanguage);
         String language = hasSimLanguage ? simLanguage : defaultLanguageForMcc(mcc);
-        String country = MccTable.countryCodeForMcc(mcc);
+        String country = MccTable.countryCodeForMcc(String.valueOf(mcc));
 
         Rlog.d(LOG_TAG, "getLocaleFromMcc(" + language + ", " + country + ", " + mcc);
         final Locale locale = getLocaleForLanguageCountry(context, language, country);
@@ -155,14 +155,13 @@
      * Returns null if unavailable.
      */
     public static String defaultLanguageForMcc(int mcc) {
-        MccTable.MccEntry entry = MccTable.entryForMcc(mcc);
-        if (entry == null) {
+        String country = MccTable.countryCodeForMcc(String.valueOf(mcc));
+
+        if (country.isEmpty()) {
             Rlog.d(LOG_TAG, "defaultLanguageForMcc(" + mcc + "): no country for mcc");
             return null;
         }
 
-        final String country = entry.mIso;
-
         // Choose English as the default language for India.
         if ("in".equals(country)) {
             return "en";
diff --git a/tests/telephonytests/Android.bp b/tests/telephonytests/Android.bp
index 8d63456..a06c15c 100644
--- a/tests/telephonytests/Android.bp
+++ b/tests/telephonytests/Android.bp
@@ -44,6 +44,7 @@
         "platform-compat-test-rules",
         "flag-junit",
         "telephony_flags_core_java_lib",
+        "telephony-config-update-proto-lite",
     ],
 
     jarjar_rules: ":jarjar-rules-telephony-tests",
diff --git a/tests/telephonytests/jarjar-rules-tests.txt b/tests/telephonytests/jarjar-rules-tests.txt
index dd69870..5a05b27 100644
--- a/tests/telephonytests/jarjar-rules-tests.txt
+++ b/tests/telephonytests/jarjar-rules-tests.txt
@@ -1,10 +1,3 @@
-# NetworkFactory is included in telephony-common and services.net
-# Rename the non-jarjared, services.net version to avoid conflicts.
-# This causes two NetworkFactory classes to appear in the test package (one used
-# by services-net and one by telephony-common), similarly to what happens on a
-# real device, except that in the test they have different package names.
-rule android.net.NetworkFactory* android.net.services.NetworkFactory@1
-
 # Telephony-common has already included net-utils-framework-common lib and jarjars
 # the package name. FrameworksTelephonyTests also includes net-utils-framework-common
 # via net-tests-utils and tries to jarjar it again. Rename the package names with
diff --git a/tests/telephonytests/src/android/telephony/ims/ImsFeatureTest.java b/tests/telephonytests/src/android/telephony/ims/ImsFeatureTest.java
index 2dc0b31..175b875 100644
--- a/tests/telephonytests/src/android/telephony/ims/ImsFeatureTest.java
+++ b/tests/telephonytests/src/android/telephony/ims/ImsFeatureTest.java
@@ -19,7 +19,7 @@
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertTrue;
 
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
 
diff --git a/tests/telephonytests/src/android/telephony/ims/ImsServiceTest.java b/tests/telephonytests/src/android/telephony/ims/ImsServiceTest.java
index d9d387c..725f84d 100644
--- a/tests/telephonytests/src/android/telephony/ims/ImsServiceTest.java
+++ b/tests/telephonytests/src/android/telephony/ims/ImsServiceTest.java
@@ -23,7 +23,7 @@
 import static junit.framework.Assert.fail;
 
 import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
diff --git a/tests/telephonytests/src/android/telephony/ims/SipTransportImplBaseTest.java b/tests/telephonytests/src/android/telephony/ims/SipTransportImplBaseTest.java
index 11b1d22..1fd9b6c 100644
--- a/tests/telephonytests/src/android/telephony/ims/SipTransportImplBaseTest.java
+++ b/tests/telephonytests/src/android/telephony/ims/SipTransportImplBaseTest.java
@@ -22,7 +22,7 @@
 
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyList;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CallManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/CallManagerTest.java
index 82bbc18..7918115 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CallManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CallManagerTest.java
@@ -18,11 +18,11 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Matchers.isNull;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyChar;
 import static org.mockito.Mockito.anyString;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierActionAgentTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierActionAgentTest.java
index ed45cd5..aa4f0ca 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierActionAgentTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierActionAgentTest.java
@@ -16,7 +16,7 @@
 package com.android.internal.telephony;
 
 import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java
index 1c58ef2..19e186f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierPrivilegesTrackerTest.java
@@ -30,9 +30,9 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.never;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java
index 753f85c..d4c2914 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java
@@ -18,7 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
index 331fcba..ae43b2f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceBindHelperTest.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doReturn;
@@ -25,18 +26,30 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.Bundle;
 import android.os.Message;
+import android.service.carrier.CarrierService;
+import android.service.carrier.ICarrierService;
 import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.telephony.flags.Flags;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
 
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
@@ -101,6 +114,16 @@
                         new Integer(0)));
     }
 
+    // Verify a CarrierPrivilegesCallback is registered and return the callback object. May return
+    // null if no callback is captured.
+    private CarrierPrivilegesCallback expectRegisterCarrierPrivilegesCallback(int phoneId) {
+        ArgumentCaptor<CarrierPrivilegesCallback> callbackCaptor =
+                ArgumentCaptor.forClass(CarrierPrivilegesCallback.class);
+        verify(mTelephonyManager)
+                .registerCarrierPrivilegesCallback(eq(phoneId), any(), callbackCaptor.capture());
+        return callbackCaptor.getAllValues().get(0);
+    }
+
     @Test
     public void testCarrierPrivilegesCallbackRegistration() {
         // Device starts with DSDS mode
@@ -110,18 +133,11 @@
 
         // Verify that CarrierPrivilegesCallbacks are registered on both phones.
         // Capture the callbacks for further verification
-        ArgumentCaptor<CarrierPrivilegesCallback> phone0CallbackCaptor = ArgumentCaptor.forClass(
-                CarrierPrivilegesCallback.class);
-        verify(mTelephonyManager).registerCarrierPrivilegesCallback(eq(PHONE_ID_0), any(),
-                phone0CallbackCaptor.capture());
-        CarrierPrivilegesCallback phone0Callback = phone0CallbackCaptor.getAllValues().get(0);
+        CarrierPrivilegesCallback phone0Callback =
+                expectRegisterCarrierPrivilegesCallback(PHONE_ID_0);
         assertNotNull(phone0Callback);
-
-        ArgumentCaptor<CarrierPrivilegesCallback> phone1CallbackCaptor = ArgumentCaptor.forClass(
-                CarrierPrivilegesCallback.class);
-        verify(mTelephonyManager).registerCarrierPrivilegesCallback(eq(PHONE_ID_1), any(),
-                phone1CallbackCaptor.capture());
-        CarrierPrivilegesCallback phone1Callback = phone1CallbackCaptor.getAllValues().get(0);
+        CarrierPrivilegesCallback phone1Callback =
+                expectRegisterCarrierPrivilegesCallback(PHONE_ID_1);
         assertNotNull(phone1Callback);
 
         // Switch back to single SIM.
@@ -133,5 +149,115 @@
         verify(mTelephonyManager).unregisterCarrierPrivilegesCallback(eq(phone1Callback));
         verify(mTelephonyManager, never()).unregisterCarrierPrivilegesCallback(eq(phone0Callback));
     }
+
+    @Test
+    public void testCarrierAppConnectionLost_resetsCarrierNetworkChange() {
+        if (!Flags.disableCarrierNetworkChangeOnCarrierAppLost()) {
+            return;
+        }
+        // Static test data
+        String carrierServicePackageName = "android.test.package.carrier";
+        ComponentName carrierServiceComponentName =
+                new ComponentName("android.test.package", "carrier");
+        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
+                ArgumentCaptor.forClass(ServiceConnection.class);
+        ResolveInfo resolveInfo = new ResolveInfo();
+        ServiceInfo serviceInfo = new ServiceInfo();
+        serviceInfo.packageName = carrierServicePackageName;
+        serviceInfo.name = "carrier";
+        serviceInfo.metaData = new Bundle();
+        serviceInfo.metaData.putBoolean("android.service.carrier.LONG_LIVED_BINDING", true);
+        resolveInfo.serviceInfo = serviceInfo;
+
+        // Set up expectations for construction/initialization.
+        doReturn(carrierServicePackageName)
+                .when(mTelephonyManager)
+                .getCarrierServicePackageNameForLogicalSlot(PHONE_ID_0);
+        doReturn(1).when(mTelephonyManager).getActiveModemCount();
+        doReturn(resolveInfo)
+                .when(mPackageManager)
+                .resolveService(any(), eq(PackageManager.GET_META_DATA));
+        ICarrierService carrierServiceInterface = Mockito.mock(ICarrierService.class);
+        mContextFixture.addService(
+                CarrierService.CARRIER_SERVICE_INTERFACE,
+                carrierServiceComponentName,
+                carrierServicePackageName,
+                carrierServiceInterface,
+                serviceInfo);
+
+        mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext);
+        processAllMessages();
+
+        CarrierPrivilegesCallback phoneCallback =
+                expectRegisterCarrierPrivilegesCallback(PHONE_ID_0);
+        assertNotNull(phoneCallback);
+        phoneCallback.onCarrierServiceChanged(null, 0);
+        processAllMessages();
+
+        // Grab the ServiceConnection for CarrierService
+        verify(mContext)
+                .bindService(any(Intent.class), anyInt(), any(), serviceConnectionCaptor.capture());
+        ServiceConnection serviceConnection = serviceConnectionCaptor.getAllValues().get(0);
+        assertNotNull(serviceConnection);
+
+        // Test CarrierService disconnection
+        serviceConnection.onServiceDisconnected(carrierServiceComponentName);
+        verify(mTelephonyRegistryManager).notifyCarrierNetworkChange(PHONE_ID_0, false);
+    }
+
+    @Test
+    public void testCarrierAppBindingLost_resetsCarrierNetworkChange() {
+        if (!Flags.disableCarrierNetworkChangeOnCarrierAppLost()) {
+            return;
+        }
+        // Static test data
+        String carrierServicePackageName = "android.test.package.carrier";
+        ComponentName carrierServiceComponentName =
+                new ComponentName("android.test.package", "carrier");
+        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
+                ArgumentCaptor.forClass(ServiceConnection.class);
+        ResolveInfo resolveInfo = new ResolveInfo();
+        ServiceInfo serviceInfo = new ServiceInfo();
+        serviceInfo.packageName = carrierServicePackageName;
+        serviceInfo.name = "carrier";
+        serviceInfo.metaData = new Bundle();
+        serviceInfo.metaData.putBoolean("android.service.carrier.LONG_LIVED_BINDING", true);
+        resolveInfo.serviceInfo = serviceInfo;
+
+        // Set up expectations for construction/initialization.
+        doReturn(carrierServicePackageName)
+                .when(mTelephonyManager)
+                .getCarrierServicePackageNameForLogicalSlot(PHONE_ID_0);
+        doReturn(1).when(mTelephonyManager).getActiveModemCount();
+        doReturn(resolveInfo)
+                .when(mPackageManager)
+                .resolveService(any(), eq(PackageManager.GET_META_DATA));
+        ICarrierService carrierServiceInterface = Mockito.mock(ICarrierService.class);
+        mContextFixture.addService(
+                CarrierService.CARRIER_SERVICE_INTERFACE,
+                carrierServiceComponentName,
+                carrierServicePackageName,
+                carrierServiceInterface,
+                serviceInfo);
+
+        mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext);
+        processAllMessages();
+
+        CarrierPrivilegesCallback phoneCallback =
+                expectRegisterCarrierPrivilegesCallback(PHONE_ID_0);
+        assertNotNull(phoneCallback);
+        phoneCallback.onCarrierServiceChanged(null, 0);
+        processAllMessages();
+
+        // Grab the ServiceConnection for CarrierService
+        verify(mContext)
+                .bindService(any(Intent.class), anyInt(), any(), serviceConnectionCaptor.capture());
+        ServiceConnection serviceConnection = serviceConnectionCaptor.getAllValues().get(0);
+        assertNotNull(serviceConnection);
+
+        // Test CarrierService disconnection
+        serviceConnection.onBindingDied(carrierServiceComponentName);
+        verify(mTelephonyRegistryManager).notifyCarrierNetworkChange(PHONE_ID_0, false);
+    }
     // TODO (b/232461097): Add UT cases to cover more scenarios (user unlock, SIM state change...)
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierServicesSmsFilterTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierServicesSmsFilterTest.java
index e68d065..7787be7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierServicesSmsFilterTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierServicesSmsFilterTest.java
@@ -18,10 +18,10 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.timeout;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierSignalAgentTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierSignalAgentTest.java
index 7710648..4cb637f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierSignalAgentTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierSignalAgentTest.java
@@ -26,9 +26,9 @@
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.argThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellBroadcastConfigTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellBroadcastConfigTrackerTest.java
index 6e6d4e4..0fdf90e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellBroadcastConfigTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellBroadcastConfigTrackerTest.java
@@ -43,6 +43,7 @@
 
 import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
 import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
 
 import org.junit.After;
@@ -132,6 +133,7 @@
         verify(mSpyCi, never()).setCdmaBroadcastConfig(any(), any());
         verify(mSpyCi, never()).setCdmaBroadcastActivation(anyBoolean(), any());
 
+        List<CellBroadcastIdRange> gsmRanges = new ArrayList<>(ranges);
         assertEquals(mPhone.getCellBroadcastIdRanges(), mergeRangesAsNeeded(ranges));
 
         //Verify to set cdma config and activate, but no more for gsm as no change
@@ -150,39 +152,62 @@
         processAllMessages();
 
         verify(mSpyCi, times(1)).setGsmBroadcastConfig(any(), any());
-        verify(mSpyCi, times(1)).setCdmaBroadcastConfig(cdmaCaptor.capture(), msgCaptor.capture());
-        List<CdmaSmsBroadcastConfigInfo> cdmaArgs = Arrays.asList(
-                (CdmaSmsBroadcastConfigInfo[]) cdmaCaptor.getValue());
-        assertEquals(cdmaConfigs, cdmaArgs);
+        List<CdmaSmsBroadcastConfigInfo> cdmaArgs;
+        if (!Flags.cleanupCdma()) {
+            verify(mSpyCi, times(1)).setCdmaBroadcastConfig(cdmaCaptor.capture(),
+                    msgCaptor.capture());
+            cdmaArgs = Arrays.asList(
+                    (CdmaSmsBroadcastConfigInfo[]) cdmaCaptor.getValue());
+            assertEquals(cdmaConfigs, cdmaArgs);
 
-        msg = msgCaptor.getValue();
-        assertNotNull(msg);
-        AsyncResult.forMessage(msg);
-        msg.sendToTarget();
-        processAllMessages();
+            msg = msgCaptor.getValue();
+            assertNotNull(msg);
+            AsyncResult.forMessage(msg);
+            msg.sendToTarget();
+            processAllMessages();
+        } else {
+            verify(mSpyCi, never()).setCdmaBroadcastConfig(any(), any());
+        }
 
         verify(mSpyCi, times(1)).setGsmBroadcastActivation(anyBoolean(), any());
-        verify(mSpyCi, times(1)).setCdmaBroadcastActivation(eq(true), msgCaptor.capture());
+        if (!Flags.cleanupCdma()) {
+            verify(mSpyCi, times(1)).setCdmaBroadcastActivation(eq(true), msgCaptor.capture());
 
-        msg = msgCaptor.getValue();
-        assertNotNull(msg);
-        AsyncResult.forMessage(msg);
-        msg.sendToTarget();
-        processAllMessages();
+            msg = msgCaptor.getValue();
+            assertNotNull(msg);
+            AsyncResult.forMessage(msg);
+            msg.sendToTarget();
+            processAllMessages();
+        } else {
+            verify(mSpyCi, never()).setCdmaBroadcastActivation(anyBoolean(), any());
+        }
 
-        assertEquals(mPhone.getCellBroadcastIdRanges(), mergeRangesAsNeeded(ranges));
+        if (!Flags.cleanupCdma()) {
+            assertEquals(mPhone.getCellBroadcastIdRanges(), mergeRangesAsNeeded(ranges));
+        } else {
+            assertEquals(mPhone.getCellBroadcastIdRanges(), mergeRangesAsNeeded(gsmRanges));
+        }
 
         // Verify not to set cdma or gsm config as the config is not changed
         mPhone.setCellBroadcastIdRanges(ranges, r -> assertTrue(
                 TelephonyManager.CELL_BROADCAST_RESULT_SUCCESS == r));
         processAllMessages();
 
-        verify(mSpyCi, times(1)).setCdmaBroadcastConfig(any(), any());
-        verify(mSpyCi, times(1)).setCdmaBroadcastActivation(anyBoolean(), any());
+        if (!Flags.cleanupCdma()) {
+            verify(mSpyCi, times(1)).setCdmaBroadcastConfig(any(), any());
+            verify(mSpyCi, times(1)).setCdmaBroadcastActivation(anyBoolean(), any());
+        } else {
+            verify(mSpyCi, never()).setCdmaBroadcastConfig(any(), any());
+            verify(mSpyCi, never()).setCdmaBroadcastActivation(anyBoolean(), any());
+        }
         verify(mSpyCi, times(1)).setGsmBroadcastConfig(any(), any());
         verify(mSpyCi, times(1)).setGsmBroadcastActivation(anyBoolean(), any());
 
-        assertEquals(mPhone.getCellBroadcastIdRanges(), mergeRangesAsNeeded(ranges));
+        if (!Flags.cleanupCdma()) {
+            assertEquals(mPhone.getCellBroadcastIdRanges(), mergeRangesAsNeeded(ranges));
+        } else {
+            assertEquals(mPhone.getCellBroadcastIdRanges(), mergeRangesAsNeeded(gsmRanges));
+        }
 
         // Verify to reset ranges with empty ranges list
         mPhone.setCellBroadcastIdRanges(new ArrayList<>(), r -> assertTrue(
@@ -208,23 +233,29 @@
         msg.sendToTarget();
         processAllMessages();
 
-        verify(mSpyCi, times(2)).setCdmaBroadcastConfig(cdmaCaptor.capture(), msgCaptor.capture());
-        assertEquals(0, ((CdmaSmsBroadcastConfigInfo[]) cdmaCaptor.getValue()).length);
+        if (!Flags.cleanupCdma()) {
+            verify(mSpyCi, times(2)).setCdmaBroadcastConfig(cdmaCaptor.capture(),
+                    msgCaptor.capture());
+            assertEquals(0, ((CdmaSmsBroadcastConfigInfo[]) cdmaCaptor.getValue()).length);
 
-        msg = msgCaptor.getValue();
-        assertNotNull(msg);
-        AsyncResult.forMessage(msg);
-        msg.sendToTarget();
-        processAllMessages();
+            msg = msgCaptor.getValue();
+            assertNotNull(msg);
+            AsyncResult.forMessage(msg);
+            msg.sendToTarget();
+            processAllMessages();
 
-        // Verify to deavtivate cdma broadcast on empty ranges
-        verify(mSpyCi, times(1)).setCdmaBroadcastActivation(eq(false), msgCaptor.capture());
+            // Verify to deavtivate cdma broadcast on empty ranges
+            verify(mSpyCi, times(1)).setCdmaBroadcastActivation(eq(false), msgCaptor.capture());
 
-        msg = msgCaptor.getValue();
-        assertNotNull(msg);
-        AsyncResult.forMessage(msg);
-        msg.sendToTarget();
-        processAllMessages();
+            msg = msgCaptor.getValue();
+            assertNotNull(msg);
+            AsyncResult.forMessage(msg);
+            msg.sendToTarget();
+            processAllMessages();
+        } else {
+            verify(mSpyCi, never()).setCdmaBroadcastConfig(any(), any());
+            verify(mSpyCi, never()).setCdmaBroadcastActivation(anyBoolean(), any());
+        }
 
         assertTrue(mPhone.getCellBroadcastIdRanges().isEmpty());
 
@@ -252,25 +283,35 @@
         msg.sendToTarget();
         processAllMessages();
 
-        verify(mSpyCi, times(3)).setCdmaBroadcastConfig(cdmaCaptor.capture(), msgCaptor.capture());
-        cdmaArgs = Arrays.asList((CdmaSmsBroadcastConfigInfo[]) cdmaCaptor.getValue());
-        assertEquals(cdmaConfigs, cdmaArgs);
+        if (!Flags.cleanupCdma()) {
+            verify(mSpyCi, times(3)).setCdmaBroadcastConfig(cdmaCaptor.capture(),
+                    msgCaptor.capture());
+            cdmaArgs = Arrays.asList((CdmaSmsBroadcastConfigInfo[]) cdmaCaptor.getValue());
+            assertEquals(cdmaConfigs, cdmaArgs);
 
-        msg = msgCaptor.getValue();
-        assertNotNull(msg);
-        AsyncResult.forMessage(msg);
-        msg.sendToTarget();
-        processAllMessages();
+            msg = msgCaptor.getValue();
+            assertNotNull(msg);
+            AsyncResult.forMessage(msg);
+            msg.sendToTarget();
+            processAllMessages();
 
-        verify(mSpyCi, times(2)).setCdmaBroadcastActivation(eq(true), msgCaptor.capture());
+            verify(mSpyCi, times(2)).setCdmaBroadcastActivation(eq(true), msgCaptor.capture());
 
-        msg = msgCaptor.getValue();
-        assertNotNull(msg);
-        AsyncResult.forMessage(msg);
-        msg.sendToTarget();
-        processAllMessages();
+            msg = msgCaptor.getValue();
+            assertNotNull(msg);
+            AsyncResult.forMessage(msg);
+            msg.sendToTarget();
+            processAllMessages();
+        } else {
+            verify(mSpyCi, never()).setCdmaBroadcastConfig(any(), any());
+            verify(mSpyCi, never()).setCdmaBroadcastActivation(anyBoolean(), any());
+        }
 
-        assertEquals(mPhone.getCellBroadcastIdRanges(), mergeRangesAsNeeded(ranges));
+        if (!Flags.cleanupCdma()) {
+            assertEquals(mPhone.getCellBroadcastIdRanges(), mergeRangesAsNeeded(ranges));
+        } else {
+            assertEquals(mPhone.getCellBroadcastIdRanges(), mergeRangesAsNeeded(gsmRanges));
+        }
     }
 
     @Test
@@ -335,8 +376,9 @@
         assertTrue(mPhone.getCellBroadcastIdRanges().isEmpty());
 
         // Verify the result on setCdmaBroadcastConfig failure
-        mPhone.setCellBroadcastIdRanges(ranges, r -> assertTrue(
-                TelephonyManager.CELL_BROADCAST_RESULT_FAIL_CONFIG == r));
+        mPhone.setCellBroadcastIdRanges(ranges, !Flags.cleanupCdma()
+                ? r -> assertTrue(TelephonyManager.CELL_BROADCAST_RESULT_FAIL_CONFIG == r)
+                : r -> assertTrue(TelephonyManager.CELL_BROADCAST_RESULT_SUCCESS == r));
         processAllMessages();
 
         verify(mSpyCi, times(3)).setGsmBroadcastConfig(any(), msgCaptor.capture());
@@ -355,14 +397,17 @@
         msg.sendToTarget();
         processAllMessages();
 
-        verify(mSpyCi, times(1)).setCdmaBroadcastConfig(any(), msgCaptor.capture());
+        if (!Flags.cleanupCdma()) {
+            verify(mSpyCi, times(1)).setCdmaBroadcastConfig(any(), msgCaptor.capture());
 
-        msg = msgCaptor.getValue();
-        assertNotNull(msg);
-        AsyncResult.forMessage(msg).exception = new RuntimeException();
-        msg.sendToTarget();
-        processAllMessages();
-
+            msg = msgCaptor.getValue();
+            assertNotNull(msg);
+            AsyncResult.forMessage(msg).exception = new RuntimeException();
+            msg.sendToTarget();
+            processAllMessages();
+        } else {
+            verify(mSpyCi, times(0)).setCdmaBroadcastConfig(any(), any());
+        }
         verify(mSpyCi, times(0)).setCdmaBroadcastActivation(anyBoolean(), any());
 
         List<CellBroadcastIdRange> ranges3gpp = new ArrayList<>();
@@ -371,28 +416,34 @@
         assertEquals(mPhone.getCellBroadcastIdRanges(), ranges3gpp);
 
         // Verify the result on setCdmaBroadcastActivation failure
-        mPhone.setCellBroadcastIdRanges(ranges, r -> assertTrue(
-                TelephonyManager.CELL_BROADCAST_RESULT_FAIL_ACTIVATION == r));
+        mPhone.setCellBroadcastIdRanges(ranges, !Flags.cleanupCdma()
+                ? r -> assertTrue(TelephonyManager.CELL_BROADCAST_RESULT_FAIL_ACTIVATION == r)
+                : r -> assertTrue(TelephonyManager.CELL_BROADCAST_RESULT_SUCCESS == r));
         processAllMessages();
 
         // Verify no more calls as there is no change of ranges for 3gpp
         verify(mSpyCi, times(3)).setGsmBroadcastConfig(any(), any());
         verify(mSpyCi, times(2)).setGsmBroadcastActivation(anyBoolean(), any());
-        verify(mSpyCi, times(2)).setCdmaBroadcastConfig(any(), msgCaptor.capture());
+        if (!Flags.cleanupCdma()) {
+            verify(mSpyCi, times(2)).setCdmaBroadcastConfig(any(), msgCaptor.capture());
 
-        msg = msgCaptor.getValue();
-        assertNotNull(msg);
-        AsyncResult.forMessage(msg);
-        msg.sendToTarget();
-        processAllMessages();
+            msg = msgCaptor.getValue();
+            assertNotNull(msg);
+            AsyncResult.forMessage(msg);
+            msg.sendToTarget();
+            processAllMessages();
 
-        verify(mSpyCi, times(1)).setCdmaBroadcastActivation(anyBoolean(), msgCaptor.capture());
+            verify(mSpyCi, times(1)).setCdmaBroadcastActivation(anyBoolean(), msgCaptor.capture());
 
-        msg = msgCaptor.getValue();
-        assertNotNull(msg);
-        AsyncResult.forMessage(msg).exception = new RuntimeException();
-        msg.sendToTarget();
-        processAllMessages();
+            msg = msgCaptor.getValue();
+            assertNotNull(msg);
+            AsyncResult.forMessage(msg).exception = new RuntimeException();
+            msg.sendToTarget();
+            processAllMessages();
+        } else {
+            verify(mSpyCi, times(0)).setCdmaBroadcastConfig(any(), any());
+            verify(mSpyCi, times(0)).setCdmaBroadcastActivation(anyBoolean(), any());
+        }
 
         assertEquals(mPhone.getCellBroadcastIdRanges(), ranges3gpp);
     }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityCdmaTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityCdmaTest.java
deleted file mode 100644
index c7668ca..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityCdmaTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony;
-
-import static org.junit.Assert.assertEquals;
-
-import android.os.Parcel;
-import android.telephony.CellIdentityCdma;
-import android.test.AndroidTestCase;
-
-import androidx.test.filters.SmallTest;
-
-/** Unit tests for {@link CellIdentityCdma}. */
-
-public class CellIdentityCdmaTest extends AndroidTestCase {
-    private static final String LOG_TAG = "CellIdentityCdmaTest";
-
-    // Network Id ranges from 0 to 65535.
-    private static final int NETWORK_ID  = 65535;
-    // CDMA System Id ranges from 0 to 32767
-    private static final int SYSTEM_ID = 32767;
-    // Base Station Id ranges from 0 to 65535
-    private static final int BASESTATION_ID = 65535;
-    // Longitude ranges from -2592000 to 2592000.
-    private static final int LONGITUDE = 2592000;
-    // Latitude ranges from -1296000 to 1296000.
-    private static final int LATITUDE = 1296000;
-    private static final String ALPHA_LONG = "long";
-    private static final String ALPHA_SHORT = "short";
-
-    @SmallTest
-    public void testConstructor() {
-        CellIdentityCdma  ci =
-                new CellIdentityCdma(NETWORK_ID, SYSTEM_ID, BASESTATION_ID, LONGITUDE, LATITUDE,
-                        ALPHA_LONG, ALPHA_SHORT);
-
-        assertEquals(NETWORK_ID, ci.getNetworkId());
-        assertEquals(LATITUDE, ci.getLatitude());
-        assertEquals(LONGITUDE, ci.getLongitude());
-        assertEquals(ALPHA_LONG, ci.getOperatorAlphaLong());
-        assertEquals(ALPHA_SHORT, ci.getOperatorAlphaShort());
-
-        String globalCi = Integer.toString(SYSTEM_ID, 16) + Integer.toString(NETWORK_ID, 16)
-                + Integer.toString(BASESTATION_ID, 16);
-        assertEquals(globalCi, ci.getGlobalCellId());
-    }
-
-    @SmallTest
-    public void testNullIsland() {
-        CellIdentityCdma  ci =
-                new CellIdentityCdma(NETWORK_ID, SYSTEM_ID, BASESTATION_ID, -1, 0,
-                        ALPHA_LONG, ALPHA_SHORT);
-
-        assertEquals(Integer.MAX_VALUE, ci.getLatitude());
-        assertEquals(Integer.MAX_VALUE, ci.getLongitude());
-    }
-
-    @SmallTest
-    public void testEquals() {
-        CellIdentityCdma  ciA =
-                new CellIdentityCdma(NETWORK_ID, SYSTEM_ID, BASESTATION_ID, LONGITUDE, LATITUDE,
-                        ALPHA_LONG, ALPHA_SHORT);
-        CellIdentityCdma  ciB =
-                new CellIdentityCdma(NETWORK_ID, SYSTEM_ID, BASESTATION_ID, LONGITUDE, LATITUDE,
-                        ALPHA_LONG, ALPHA_SHORT);
-
-        assertTrue(ciA.equals(ciB));
-
-        ciA = new CellIdentityCdma(NETWORK_ID, SYSTEM_ID, BASESTATION_ID, LONGITUDE, LATITUDE,
-                null, null);
-        ciB = new CellIdentityCdma(NETWORK_ID, SYSTEM_ID, BASESTATION_ID, LONGITUDE, LATITUDE,
-                null, null);
-
-        assertTrue(ciA.equals(ciB));
-
-        ciA = new CellIdentityCdma(NETWORK_ID, SYSTEM_ID, BASESTATION_ID, LONGITUDE, LATITUDE,
-                ALPHA_LONG, ALPHA_SHORT);
-        ciB = new CellIdentityCdma(NETWORK_ID, SYSTEM_ID, BASESTATION_ID, LONGITUDE, LATITUDE,
-                null, null);
-
-        assertFalse(ciA.equals(ciB));
-    }
-
-    @SmallTest
-    public void testParcel() {
-        CellIdentityCdma  ci =
-                new CellIdentityCdma(NETWORK_ID, SYSTEM_ID, BASESTATION_ID, LONGITUDE, LATITUDE,
-                        ALPHA_LONG, ALPHA_SHORT);
-
-        Parcel p = Parcel.obtain();
-        ci.writeToParcel(p, 0);
-        p.setDataPosition(0);
-
-        CellIdentityCdma newCi = CellIdentityCdma.CREATOR.createFromParcel(p);
-        assertEquals(ci, newCi);
-    }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthCdmaTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthCdmaTest.java
deleted file mode 100644
index 3a20497..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/CellSignalStrengthCdmaTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.os.Parcel;
-import android.telephony.CellSignalStrengthCdma;
-import android.test.AndroidTestCase;
-
-import androidx.test.filters.SmallTest;
-
-/** Unit tests for {@link CellSignalStrengthCdma}. */
-
-public class CellSignalStrengthCdmaTest extends AndroidTestCase {
-
-    private static final int CDMA_DBM = -74;
-    private static final int CDMA_ECIO = -124;
-    private static final int EVDO_DBM = -23;
-    private static final int EVDO_ECIO = -108;
-    private static final int EVDO_SNR = 7;
-
-    @SmallTest
-    public void testConstructor() {
-        CellSignalStrengthCdma css = new CellSignalStrengthCdma(
-                CDMA_DBM, CDMA_ECIO, EVDO_DBM, EVDO_ECIO, EVDO_SNR);
-        assertEquals(CDMA_DBM, css.getCdmaDbm());
-        assertEquals(CDMA_ECIO, css.getCdmaEcio());
-        assertEquals(EVDO_DBM, css.getEvdoDbm());
-        assertEquals(EVDO_ECIO, css.getEvdoEcio());
-        assertEquals(EVDO_SNR, css.getEvdoSnr());
-    }
-
-    @SmallTest
-    public void testInvalidConstructor() {
-        CellSignalStrengthCdma css = new CellSignalStrengthCdma(200, 2000, 20, 400, 200);
-        assertEquals(Integer.MAX_VALUE, css.getCdmaDbm());
-        assertEquals(Integer.MAX_VALUE, css.getCdmaEcio());
-        assertEquals(Integer.MAX_VALUE, css.getEvdoDbm());
-        assertEquals(Integer.MAX_VALUE, css.getEvdoEcio());
-        assertEquals(Integer.MAX_VALUE, css.getEvdoSnr());
-    }
-
-    @SmallTest
-    public void testDefaultConstructor() {
-        CellSignalStrengthCdma css = new CellSignalStrengthCdma();
-        assertEquals(Integer.MAX_VALUE, css.getCdmaDbm());
-        assertEquals(Integer.MAX_VALUE, css.getCdmaEcio());
-        assertEquals(Integer.MAX_VALUE, css.getEvdoDbm());
-        assertEquals(Integer.MAX_VALUE, css.getEvdoEcio());
-        assertEquals(Integer.MAX_VALUE, css.getEvdoSnr());
-    }
-
-    @SmallTest
-    public void testEquals() {
-        assertTrue(new CellSignalStrengthCdma(
-                CDMA_DBM, CDMA_ECIO, EVDO_DBM, EVDO_ECIO, EVDO_SNR).equals(
-                        new CellSignalStrengthCdma(
-                                CDMA_DBM, CDMA_ECIO, EVDO_DBM, EVDO_ECIO, EVDO_SNR)));
-        assertFalse(new CellSignalStrengthCdma(
-                CDMA_DBM, CDMA_ECIO, EVDO_DBM, EVDO_ECIO, EVDO_SNR).equals(
-                    new CellSignalStrengthCdma(CDMA_DBM, CDMA_ECIO, -24, EVDO_ECIO, EVDO_SNR)));
-    }
-
-    @SmallTest
-    public void testParcel() {
-        CellSignalStrengthCdma css = new CellSignalStrengthCdma(
-                CDMA_DBM, CDMA_ECIO, EVDO_DBM, EVDO_ECIO, EVDO_SNR);
-
-        Parcel p = Parcel.obtain();
-        css.writeToParcel(p, 0);
-        p.setDataPosition(0);
-
-        CellSignalStrengthCdma newCss = CellSignalStrengthCdma.CREATOR.createFromParcel(p);
-        assertEquals(css, newCss);
-    }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
index 9788320..fe6e1b9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
@@ -20,9 +20,9 @@
 import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.lenient;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
@@ -105,6 +105,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Executor;
 
 /**
  * Controls a test {@link Context} as would be provided by the Android framework to an
@@ -226,21 +227,37 @@
             if (mServiceByServiceConnection.containsKey(connection)) {
                 throw new RuntimeException("ServiceConnection already bound: " + connection);
             }
-            IInterface service = mServiceByComponentName.get(serviceIntent.getComponent());
+            IInterface service = null;
+            if (serviceIntent.getComponent() != null) {
+                service = mServiceByComponentName.get(serviceIntent.getComponent());
+            }
             if (service == null) {
                 service = mServiceByPackageName.get(serviceIntent.getPackage());
             }
             if (service == null) {
                 throw new RuntimeException(
-                        String.format("ServiceConnection not found for component: %s, package: %s",
+                        String.format(
+                                "ServiceConnection not found for component: %s, package: %s",
                                 serviceIntent.getComponent(), serviceIntent.getPackage()));
             }
             mServiceByServiceConnection.put(connection, service);
-            connection.onServiceConnected(serviceIntent.getComponent(), service.asBinder());
+            ComponentName componentName = null;
+            if (mComponentNameByService.containsKey(service)) {
+                componentName = mComponentNameByService.get(service);
+            } else {
+                componentName = serviceIntent.getComponent();
+            }
+            connection.onServiceConnected(componentName, service.asBinder());
             return true;
         }
 
         @Override
+        public boolean bindService(
+                Intent serviceIntent, int flags, Executor executor, ServiceConnection connection) {
+            return bindService(serviceIntent, connection, flags);
+        }
+
+        @Override
         public boolean bindServiceAsUser(
                 Intent serviceIntent,
                 ServiceConnection connection,
@@ -774,14 +791,14 @@
     public ContextFixture() {
         MockitoAnnotations.initMocks(this);
 
-        doAnswer(new Answer<List<ResolveInfo>>() {
+        lenient().doAnswer(new Answer<List<ResolveInfo>>() {
             @Override
             public List<ResolveInfo> answer(InvocationOnMock invocation) throws Throwable {
                 return doQueryIntentServices((Intent) invocation.getArguments()[0]);
             }
         }).when(mPackageManager).queryIntentServices((Intent) any(), anyInt());
 
-        doAnswer(new Answer<List<ResolveInfo>>() {
+        lenient().doAnswer(new Answer<List<ResolveInfo>>() {
             @Override
             public List<ResolveInfo> answer(InvocationOnMock invocation) throws Throwable {
                 return doQueryIntentServices((Intent) invocation.getArguments()[0]);
@@ -795,30 +812,34 @@
             Log.d(TAG, "NameNotFoundException: e=" + e);
         }
 
-        doAnswer((Answer<Boolean>)
+        lenient().doAnswer((Answer<Boolean>)
                 invocation -> mSystemFeatures.contains((String) invocation.getArgument(0)))
                 .when(mPackageManager).hasSystemFeature(any());
 
         try {
-            doReturn(mResources).when(mPackageManager).getResourcesForApplication(anyString());
+            lenient().doReturn(mResources).when(mPackageManager)
+                    .getResourcesForApplication(anyString());
         } catch (NameNotFoundException ex) {
             Log.d(TAG, "NameNotFoundException: ex=" + ex);
         }
 
-        doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
-        doReturn(mBundle).when(mCarrierConfigManager).getConfig();
-        doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
-        doAnswer(invocation -> mNetworkId++).when(mNetwork).getNetId();
-        doReturn(mNetwork).when(mConnectivityManager).registerNetworkAgent(
-                any(), any(), any(), any(), any(), any(), anyInt());
+        lenient().doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
+        lenient().doReturn(mBundle).when(mCarrierConfigManager).getConfig();
+        lenient().doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt(),
+                anyString());
+        lenient().doAnswer(invocation -> mNetworkId++).when(mNetwork).getNetId();
+        lenient().doReturn(
+                ConnectivityManager.MockHelpers.registerNetworkAgentResult(mNetwork, null))
+                        .when(mConnectivityManager).registerNetworkAgent(
+                                any(), any(), any(), any(), any(), any(), anyInt());
 
-        doReturn(true).when(mEuiccManager).isEnabled();
+        lenient().doReturn(true).when(mEuiccManager).isEnabled();
 
         mConfiguration.locale = Locale.US;
-        doReturn(mConfiguration).when(mResources).getConfiguration();
+        lenient().doReturn(mConfiguration).when(mResources).getConfiguration();
 
         mDisplayMetrics.density = 2.25f;
-        doReturn(mDisplayMetrics).when(mResources).getDisplayMetrics();
+        lenient().doReturn(mDisplayMetrics).when(mResources).getDisplayMetrics();
         mPermissionTable.add(PERMISSION_ENABLE_ALL);
     }
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
index 522cdac..7591161 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
@@ -23,7 +23,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/DeviceStateMonitorTest.java b/tests/telephonytests/src/com/android/internal/telephony/DeviceStateMonitorTest.java
index c9e4c12..057b745 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/DeviceStateMonitorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/DeviceStateMonitorTest.java
@@ -20,19 +20,17 @@
 import static android.hardware.radio.V1_0.DeviceStateType.POWER_SAVE_MODE;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.nullable;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 import static java.util.Arrays.asList;
 
@@ -476,7 +474,6 @@
     @Test
     public void testRegisterForSignalStrengthReportDecisionWithFeatureEnabled() {
         logd("testRegisterForSignalStrengthReportDecisionWithFeatureEnabled()");
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         mSatelliteControllerUT = new TestSatelliteController(Looper.myLooper(), mDSM);
 
         updateState(STATE_TYPE_RADIO_OFF_OR_NOT_AVAILABLE, 0);
@@ -515,45 +512,6 @@
         assertEquals(1, mSatelliteControllerUT.getStopEventCount());
     }
 
-    @Test
-    public void testRegisterForSignalStrengthReportDecisionWithFeatureDisabled() {
-        logd("testRegisterForSignalStrengthReportDecisionWithFeatureDisabled()");
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
-        mSatelliteControllerUT = new TestSatelliteController(Looper.myLooper(), mDSM);
-
-        updateState(STATE_TYPE_RADIO_OFF_OR_NOT_AVAILABLE, 0);
-        updateState(STATE_TYPE_SCREEN, STATE_OFF);
-        mSatelliteControllerUT.resetCount();
-        sEventDeviceStatusChanged.drainPermits();
-
-
-        /* Sending stop ntn signal strength as radio is off */
-        updateState(STATE_TYPE_SCREEN, STATE_ON);
-        assertFalse(waitForEventDeviceStatusChanged());
-        assertEquals(0, mSatelliteControllerUT.getStartEventCount());
-        assertEquals(0, mSatelliteControllerUT.getStopEventCount());
-
-        updateState(STATE_TYPE_SCREEN, STATE_OFF);
-        assertFalse(waitForEventDeviceStatusChanged());
-        assertEquals(0, mSatelliteControllerUT.getStartEventCount());
-        assertEquals(0, mSatelliteControllerUT.getStopEventCount());
-
-        updateState(STATE_TYPE_RADIO_ON, 0);
-        assertFalse(waitForEventDeviceStatusChanged());
-        assertEquals(0, mSatelliteControllerUT.getStartEventCount());
-        assertEquals(0, mSatelliteControllerUT.getStopEventCount());
-
-        updateState(STATE_TYPE_SCREEN, STATE_ON);
-        assertFalse(waitForEventDeviceStatusChanged());
-        assertEquals(0, mSatelliteControllerUT.getStartEventCount());
-        assertEquals(0, mSatelliteControllerUT.getStopEventCount());
-
-        updateState(STATE_TYPE_RADIO_OFF_OR_NOT_AVAILABLE, 0);
-        assertFalse(waitForEventDeviceStatusChanged());
-        assertEquals(0, mSatelliteControllerUT.getStartEventCount());
-        assertEquals(0, mSatelliteControllerUT.getStopEventCount());
-    }
-
     private static Semaphore sEventDeviceStatusChanged = new Semaphore(0);
     private boolean waitForEventDeviceStatusChanged() {
         try {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/DisplayInfoControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/DisplayInfoControllerTest.java
index 8eb2de6..adcd9a9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/DisplayInfoControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/DisplayInfoControllerTest.java
@@ -108,6 +108,7 @@
         mFeatureFlags = Mockito.mock(FeatureFlags.class);
         doReturn((Executor) Runnable::run).when(mContext).getMainExecutor();
         mBundle = mContextFixture.getCarrierConfigBundle();
+        mBundle.putBoolean(CarrierConfigManager.KEY_SHOW_ROAMING_INDICATOR_BOOL, true);
         mSstHandler = new ServiceStateTrackerTestHandler(getClass().getSimpleName());
         mSstHandler.start();
         waitUntilReady();
@@ -293,7 +294,6 @@
         mBundle.putStringArray(
                 CarrierConfigManager.KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, new String[] {NUMERIC});
         mBundle.putBoolean(CarrierConfigManager.KEY_SHOW_ROAMING_INDICATOR_BOOL, false);
-        doReturn(true).when(mFeatureFlags).hideRoamingIcon();
         sendCarrierConfigUpdate();
 
         changeRegState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java b/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
index 101c668..07049c3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
@@ -138,7 +138,12 @@
                     + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS + " TEXT,"
                     + Telephony.SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED + " INTEGER DEFAULT 0,"
                     + Telephony.SimInfo.COLUMN_IS_SATELLITE_PROVISIONED_FOR_NON_IP_DATAGRAM
-                    + " INTEGER DEFAULT 0"
+                    + " INTEGER DEFAULT 0,"
+                    + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_BARRED_PLMNS + " TEXT,"
+                    + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS + " TEXT,"
+                    + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP + " TEXT,"
+                    + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY + " TEXT,"
+                    + Telephony.SimInfo.COLUMN_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY + " TEXT"
                     + ");";
         }
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java
index 8898a0f..97c4962 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GbaManagerTest.java
@@ -22,9 +22,9 @@
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.fail;
 
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -42,6 +42,7 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.platform.test.annotations.EnableFlags;
 import android.telephony.IBootstrapAuthenticationCallback;
 import android.telephony.TelephonyManager;
 import android.telephony.gba.GbaAuthRequest;
@@ -52,6 +53,7 @@
 import android.testing.TestableLooper;
 import android.util.Log;
 
+import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.metrics.RcsStats;
 
 import org.junit.After;
@@ -97,30 +99,44 @@
         mMockGbaServiceBinder = mock(IGbaService.class);
         mMockCallback = mock(IBootstrapAuthenticationCallback.class);
         mMockRcsStats = mock(RcsStats.class);
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
         when(mMockContext.bindServiceAsUser(any(), any(), anyInt(), any(UserHandle.class)))
                 .thenReturn(true);
         when(mMockGbaServiceBinder.asBinder()).thenReturn(mMockBinder);
-        mTestGbaManager = new GbaManager(mMockContext, TEST_SUB_ID, null, 0, mMockRcsStats);
-        mHandler = mTestGbaManager.getHandler();
-        try {
-            mLooper = new TestableLooper(mHandler.getLooper());
-        } catch (Exception e) {
-            fail("Unable to create looper from handler.");
+
+        if (mFeatureFlags.threadShred()) {
+            mTestGbaManager = new GbaManager(
+                    mMockContext, TEST_SUB_ID, null, 0, mMockRcsStats,
+                    TestableLooper.get(this).getLooper(), mFeatureFlags);
+            monitorTestableLooper(TestableLooper.get(this));
+        } else {
+            if (Looper.myLooper() == null) {
+                Looper.prepare();
+            }
+            mTestGbaManager = new GbaManager(
+                    mMockContext, TEST_SUB_ID, null, 0, mMockRcsStats, null, mFeatureFlags);
+            mHandler = mTestGbaManager.getHandler();
+            try {
+                mLooper = new TestableLooper(mHandler.getLooper());
+            } catch (Exception e) {
+                fail("Unable to create looper from handler.");
+            }
+            monitorTestableLooper(mLooper);
         }
-        monitorTestableLooper(mLooper);
     }
 
     @After
     public void tearDown() throws Exception {
         log("tearDown");
-        mTestGbaManager.destroy();
+        if (mFeatureFlags.threadShred()) {
+            if (mTestGbaManager != null) mTestGbaManager.destroy();
+        } else {
+            mTestGbaManager.destroy();
+        }
         super.tearDown();
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_THREAD_SHRED)
     public void testFailOnRequest() throws Exception {
         GbaAuthRequest request = createDefaultRequest();
 
@@ -134,6 +150,7 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_THREAD_SHRED)
     public void testBindServiceOnRequest() throws Exception {
         mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
         GbaAuthRequest request = createDefaultRequest();
@@ -148,6 +165,7 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_THREAD_SHRED)
     public void testFailAndRetryOnRequest() throws RemoteException {
         when(mMockContext.bindServiceAsUser(any(), any(), anyInt(), any(UserHandle.class)))
                 .thenReturn(false);
@@ -168,6 +186,7 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_THREAD_SHRED)
     public void testBindServiceWhenPackageNameChanged() {
         mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
         mTestGbaManager.overrideReleaseTime(RELEASE_TIME_60S);
@@ -187,6 +206,7 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_THREAD_SHRED)
     public void testBindServiceWhenReleaseTimeChanged() {
         mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
         mTestGbaManager.overrideReleaseTime(RELEASE_NEVER);
@@ -199,6 +219,7 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_THREAD_SHRED)
     public void testDontBindServiceWhenPackageNameChanged() {
         mTestGbaManager.overrideServicePackage(TEST_SERVICE2_NAME.getPackageName(), 123);
 
@@ -210,6 +231,7 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_THREAD_SHRED)
     public void testDontBindServiceWhenReleaseTimeChanged() {
         mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
         mTestGbaManager.overrideReleaseTime(RELEASE_TIME_60S);
@@ -222,6 +244,7 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_THREAD_SHRED)
     public void testMetricsGbaEvent() throws Exception {
         mTestGbaManager.overrideServicePackage(TEST_DEFAULT_SERVICE_NAME.getPackageName(), 123);
         mTestGbaManager.overrideReleaseTime(RELEASE_NEVER);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
index e56ac90..1093bb9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
@@ -89,12 +89,6 @@
 
     @Test @SmallTest
     public void testOriginalDialString(){
-        doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mPhone).getPhoneType();
-        connection = new GsmCdmaConnection(mPhone, "+8610000", mCT, null,
-                new DialArgs.Builder().build());
-        assertEquals("+8610000", connection.getOrigDialString());
-
-        doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mPhone).getPhoneType();
         connection = new GsmCdmaConnection(mPhone, "+8610000", mCT, null,
                 new DialArgs.Builder().build());
         assertEquals("+8610000", connection.getOrigDialString());
@@ -118,24 +112,6 @@
     }
 
     @Test @SmallTest
-    public void testSanityCDMA() {
-        doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mPhone).getPhoneType();
-        connection = new GsmCdmaConnection(mPhone, String.format(
-                "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null,
-                new DialArgs.Builder().build());
-        logd("Testing initial state of GsmCdmaConnection");
-        assertEquals(GsmCdmaCall.State.IDLE, connection.getState());
-        assertEquals(Connection.PostDialState.NOT_STARTED, connection.getPostDialState());
-        assertEquals(DisconnectCause.NOT_DISCONNECTED, DisconnectCause.NOT_DISCONNECTED);
-        assertEquals(0, connection.getDisconnectTime());
-        assertEquals(0, connection.getHoldDurationMillis());
-        assertEquals(PhoneConstants.PRESENTATION_ALLOWED, connection.getNumberPresentation());
-        assertFalse(connection.isMultiparty());
-        assertNotNull(connection.getRemainingPostDialString());
-        assertEquals("+1 (700).555-41NN,1234", connection.getOrigDialString());
-    }
-
-    @Test @SmallTest
     public void testConnectionStateUpdate() {
         connection = new GsmCdmaConnection(mPhone, String.format(
                 "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null,
@@ -155,25 +131,6 @@
     }
 
     @Test @MediumTest
-    public void testCDMAPostDialPause() {
-        doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mPhone).getPhoneType();
-        connection = new GsmCdmaConnection(mPhone, String.format(
-                "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null,
-                new DialArgs.Builder().build());
-        logd("Mock connection state from alerting to active ");
-        mDC.state = DriverCall.State.ALERTING;
-        connection.update(mDC);
-        mDC.state = DriverCall.State.ACTIVE;
-        connection.update(mDC);
-        logd("process post dail sequence with pause");
-        assertEquals(Connection.PostDialState.PAUSE, connection.getPostDialState());
-        /* pause for 2000 ms */
-        moveTimeForward(GsmCdmaConnection.PAUSE_DELAY_MILLIS_CDMA);
-        processAllMessages();
-        assertEquals(Connection.PostDialState.COMPLETE, connection.getPostDialState());
-    }
-
-    @Test @MediumTest
     public void testGSMPostDialPause() {
         connection = new GsmCdmaConnection(mPhone, String.format(
                 "+1 (700).555-41NN%c1234", PhoneNumberUtils.PAUSE), mCT, null,
@@ -191,25 +148,6 @@
         assertEquals(Connection.PostDialState.COMPLETE, connection.getPostDialState());
     }
 
-
-    @Test @SmallTest
-    public void testPostDialWait() {
-        doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mPhone).getPhoneType();
-        connection = new GsmCdmaConnection(mPhone,
-                String.format("+1 (700).555-41NN%c1234", PhoneNumberUtils.WAIT),mCT,null,
-                new DialArgs.Builder().build());
-        logd("Mock connection state transition from alerting to active ");
-        mDC.state = DriverCall.State.ALERTING;
-        connection.update(mDC);
-        mDC.state = DriverCall.State.ACTIVE;
-        connection.update(mDC);
-        logd("Process the post dial sequence with wait ");
-        assertEquals(Connection.PostDialState.WAIT, connection.getPostDialState());
-        connection.proceedAfterWaitChar();
-        processAllMessages();
-        assertEquals(Connection.PostDialState.COMPLETE, connection.getPostDialState());
-    }
-
     @Test @SmallTest
     public void testHangUpConnection() {
         connection = new GsmCdmaConnection(mPhone, String.format(
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
index 7735c97..3f77744 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
@@ -37,8 +37,8 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.nullable;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.anyString;
@@ -47,7 +47,6 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -64,7 +63,6 @@
 import android.os.Message;
 import android.os.PersistableBundle;
 import android.os.Process;
-import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.WorkSource;
 import android.preference.PreferenceManager;
@@ -96,6 +94,7 @@
 import com.android.internal.telephony.emergency.EmergencyStateTracker;
 import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.imsphone.ImsPhone;
+import com.android.internal.telephony.imsphone.ImsPhoneCall;
 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.internal.telephony.test.SimulatedCommands;
@@ -106,7 +105,6 @@
 import com.android.internal.telephony.uicc.IccCardStatus;
 import com.android.internal.telephony.uicc.IccConstants;
 import com.android.internal.telephony.uicc.IccRecords;
-import com.android.internal.telephony.uicc.IccVmNotSupportedException;
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.telephony.uicc.UiccPort;
 import com.android.internal.telephony.uicc.UiccProfile;
@@ -118,7 +116,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
-import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 
@@ -150,22 +147,6 @@
     private static final int EVENT_EMERGENCY_CALL_TOGGLE = 2;
     private static final int EVENT_SET_ICC_LOCK_ENABLED = 3;
 
-    private void switchToGsm() {
-        mSimulatedCommands.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_GSM);
-        mPhoneUT.sendMessage(mPhoneUT.obtainMessage(GsmCdmaPhone.EVENT_VOICE_RADIO_TECH_CHANGED,
-                new AsyncResult(null, new int[]{ServiceState.RIL_RADIO_TECHNOLOGY_GSM}, null)));
-        processAllMessages();
-        assertEquals(PhoneConstants.PHONE_TYPE_GSM, mPhoneUT.getPhoneType());
-    }
-
-    private void switchToCdma() {
-        mSimulatedCommands.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_IS95A);
-        mPhoneUT.sendMessage(mPhoneUT.obtainMessage(GsmCdmaPhone.EVENT_VOICE_RADIO_TECH_CHANGED,
-                new AsyncResult(null, new int[]{ServiceState.RIL_RADIO_TECHNOLOGY_IS95A}, null)));
-        processAllMessages();
-        assertEquals(PhoneConstants.PHONE_TYPE_CDMA, mPhoneUT.getPhoneType());
-    }
-
     @Before
     public void setUp() throws Exception {
         super.setUp(getClass().getSimpleName());
@@ -210,14 +191,6 @@
 
     @Test
     @SmallTest
-    public void testPhoneTypeSwitch() {
-        assertTrue(mPhoneUT.isPhoneTypeGsm());
-        switchToCdma();
-        assertTrue(mPhoneUT.isPhoneTypeCdmaLte());
-    }
-
-    @Test
-    @SmallTest
     public void testGetServiceState() {
         ServiceState serviceState = new ServiceState();
         mSST.mSS = serviceState;
@@ -405,39 +378,6 @@
 
     @Test
     @SmallTest
-    public void testGetSubscriberIdForCdmaLtePhone() {
-        final String subscriberId = "abcdefghijk";
-        IccRecords iccRecords = Mockito.mock(IccRecords.class);
-        doReturn(subscriberId).when(iccRecords).getIMSI();
-        doReturn(iccRecords).when(mUiccController)
-                .getIccRecords(anyInt() /* phoneId */, eq(UiccController.APP_FAM_3GPP));
-
-        // Ensure the phone type is CdmaLte
-        GsmCdmaPhone spyPhone = spy(mPhoneUT);
-        doReturn(false).when(spyPhone).isPhoneTypeCdma();
-        doReturn(true).when(spyPhone).isPhoneTypeCdmaLte();
-        doReturn(false).when(spyPhone).isPhoneTypeGsm();
-
-        assertEquals(subscriberId, spyPhone.getSubscriberId());
-    }
-
-    @Test
-    @SmallTest
-    public void testGetSubscriberIdForCdmaPhone() {
-        final String subscriberId = "987654321";
-        doReturn(subscriberId).when(mSST).getImsi();
-
-        // Ensure the phone type is GSM
-        GsmCdmaPhone spyPhone = spy(mPhoneUT);
-        doReturn(true).when(spyPhone).isPhoneTypeCdma();
-        doReturn(false).when(spyPhone).isPhoneTypeCdmaLte();
-        doReturn(false).when(spyPhone).isPhoneTypeGsm();
-
-        assertEquals(subscriberId, spyPhone.getSubscriberId());
-    }
-
-    @Test
-    @SmallTest
     public void testGetCellLocation() {
         // GSM
         CellIdentity cellLocation = new CellIdentityGsm();
@@ -446,9 +386,6 @@
         doReturn(cellLocation).when(mSST).getCellIdentity();
         assertEquals(cellLocation, mPhoneUT.getCurrentCellIdentity());
 
-        // Switch to CDMA
-        switchToCdma();
-
         CellIdentityCdma cdmaCellLocation = new CellIdentityCdma();
         doReturn(cdmaCellLocation).when(mSST).getCellIdentity();
 
@@ -460,50 +397,6 @@
 
     @Test
     @SmallTest
-    public void testGetPhoneType() {
-        assertEquals(PhoneConstants.PHONE_TYPE_GSM, mPhoneUT.getPhoneType());
-
-        // Switch to CDMA
-        switchToCdma();
-
-        assertEquals(PhoneConstants.PHONE_TYPE_CDMA, mPhoneUT.getPhoneType());
-    }
-
-    @Test
-    @SmallTest
-    public void testHandleInCallMmiCommands() {
-        try {
-            // Switch to CDMA
-            switchToCdma();
-
-            assertFalse(mPhoneUT.handleInCallMmiCommands("0"));
-
-            // Switch to GSM
-            switchToGsm();
-
-            mCT.mForegroundCall = mGsmCdmaCall;
-            mCT.mBackgroundCall = mGsmCdmaCall;
-            mCT.mRingingCall = mGsmCdmaCall;
-            doReturn(GsmCdmaCall.State.IDLE).when(mGsmCdmaCall).getState();
-
-            // !isInCall
-            assertFalse(mPhoneUT.handleInCallMmiCommands("0"));
-
-            // isInCall
-            doReturn(GsmCdmaCall.State.ACTIVE).when(mGsmCdmaCall).getState();
-            assertTrue(mPhoneUT.handleInCallMmiCommands("0"));
-
-            // empty dialString
-            assertFalse(mPhoneUT.handleInCallMmiCommands(""));
-            assertFalse(mPhoneUT.handleInCallMmiCommands(null));
-
-        } catch (Exception e) {
-            fail(e.toString());
-        }
-    }
-
-    @Test
-    @SmallTest
     public void testDial() throws Exception {
         try {
             mSST.mSS = mServiceState;
@@ -526,6 +419,50 @@
 
     @Test
     @SmallTest
+    public void testDialWithShortEmergencyNumber() throws Exception {
+        ServiceState serviceState = Mockito.mock(ServiceState.class);
+        ImsPhoneCall imsPhoneCall = Mockito.mock(ImsPhoneCall.class);
+        GsmCdmaCall gsmCdmaCall2 = Mockito.mock(GsmCdmaCall.class);
+
+        mSST.mSS = mServiceState;
+        mCT.mForegroundCall = mGsmCdmaCall;
+        mCT.mBackgroundCall = gsmCdmaCall2;
+        mCT.mRingingCall = gsmCdmaCall2;
+
+        // Set the 2-digits as emergency number.
+        doReturn(true).when(mPackageManager).hasSystemFeature(
+                eq(PackageManager.FEATURE_TELEPHONY_CALLING));
+        doReturn(true).when(mTelephonyManager).isEmergencyNumber(eq("17"));
+
+        // Exist active call.
+        doReturn(GsmCdmaCall.State.ACTIVE).when(mGsmCdmaCall).getState();
+        doReturn(GsmCdmaCall.State.IDLE).when(gsmCdmaCall2).getState();
+        // ImsService is not ready.
+        doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(serviceState).getState();
+        doReturn(serviceState).when(mImsPhone).getServiceState();
+        doReturn(false).when(imsPhoneCall).isRinging();
+        doReturn(imsPhoneCall).when(mImsPhone).getRingingCall();
+
+        replaceInstance(Phone.class, "mImsPhone", mPhoneUT, mImsPhone);
+
+        Connection connection = mPhoneUT.dial("17",
+                new PhoneInternalInterface.DialArgs.Builder()
+                        .setIsEmergency(true)
+                        .build());
+        assertNull(connection);
+        verify(mCT, never()).dialGsm(eq("17"), any(PhoneInternalInterface.DialArgs.class));
+
+        // Enable feature flag.
+        doReturn(true).when(mFeatureFlags).skipMmiCodeCheckForEmergencyCall();
+        mPhoneUT.dial("17",
+                new PhoneInternalInterface.DialArgs.Builder()
+                        .setIsEmergency(true)
+                        .build());
+        verify(mCT).dialGsm(eq("17"), any(PhoneInternalInterface.DialArgs.class));
+    }
+
+    @Test
+    @SmallTest
     public void testWpsDialOverCs() throws Exception {
         try {
             setupForWpsCallTest();
@@ -703,17 +640,16 @@
         doReturn(true).when(mTelephonyManager).isEmergencyNumber(emergencyNumber);
 
         // Feature flag enabled
-        // Device does not have FEATURE_TELEPHONY_CALLING
-        doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
+        // Device does not have FEATURE_TELEPHONY_MESSAGING
         doReturn(false).when(mPackageManager).hasSystemFeature(
-                eq(PackageManager.FEATURE_TELEPHONY_CALLING));
+                eq(PackageManager.FEATURE_TELEPHONY_MESSAGING));
         mPhoneUT.notifySmsSent(emergencyNumber);
         processAllMessages();
         assertFalse(mPhoneUT.isInEmergencySmsMode());
 
-        // Device has FEATURE_TELEPHONY_CALLING
+        // Device has FEATURE_TELEPHONY_MESSAGING
         doReturn(true).when(mPackageManager).hasSystemFeature(
-                eq(PackageManager.FEATURE_TELEPHONY_CALLING));
+                eq(PackageManager.FEATURE_TELEPHONY_MESSAGING));
         mPhoneUT.notifySmsSent(emergencyNumber);
         processAllMessages();
         assertTrue(mPhoneUT.isInEmergencySmsMode());
@@ -721,37 +657,6 @@
 
     @Test
     @SmallTest
-    public void testSendBurstDtmf() {
-        //Should do nothing for GSM
-        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
-        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
-                anyInt(), nullable(Message.class));
-
-        switchToCdma();
-        //invalid character
-        mPhoneUT.sendBurstDtmf("12345a67890", 0, 0, null);
-        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
-                anyInt(), nullable(Message.class));
-
-        //state IDLE
-        mCT.mState = PhoneConstants.State.IDLE;
-        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
-        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
-                anyInt(), nullable(Message.class));
-
-        //state RINGING
-        mCT.mState = PhoneConstants.State.RINGING;
-        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
-        verify(mSimulatedCommandsVerifier, times(0)).sendBurstDtmf(nullable(String.class), anyInt(),
-                anyInt(), nullable(Message.class));
-
-        mCT.mState = PhoneConstants.State.OFFHOOK;
-        mPhoneUT.sendBurstDtmf("1234567890", 0, 0, null);
-        verify(mSimulatedCommandsVerifier).sendBurstDtmf("1234567890", 0, 0, null);
-    }
-
-    @Test
-    @SmallTest
     public void testVoiceMailNumberGsm() {
         String voiceMailNumber = "1234567890";
         // first test for GSM
@@ -811,90 +716,6 @@
         assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
     }
 
-    @Test
-    @SmallTest
-    public void testVoiceMailNumberCdma() {
-        switchToCdma();
-        String voiceMailNumber = "1234567890";
-
-        // config_telephony_use_own_number_for_voicemail
-        mContextFixture.getCarrierConfigBundle()
-                .putBoolean(CarrierConfigManager
-                                .KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL, true);
-        doReturn(voiceMailNumber).when(mSST).getMdnNumber();
-        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
-
-        // voicemail number from config
-        voiceMailNumber = "1234567891";
-        mContextFixture.getCarrierConfigBundle().
-                putString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_STRING, voiceMailNumber);
-        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
-
-        // voicemail number from config for roaming network
-        String voiceMailNumberForRoaming = "1234567892";
-        mContextFixture.getCarrierConfigBundle()
-                .putString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_ROAMING_STRING,
-                        voiceMailNumberForRoaming);
-
-        // voicemail number from config for roaming network and ims unregistered
-        String voiceMailNumberForImsRoamingAndUnregistered = "1234567893";
-        mContextFixture.getCarrierConfigBundle().putString(
-                CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_ROAMING_AND_IMS_UNREGISTERED_STRING,
-                        voiceMailNumberForImsRoamingAndUnregistered);
-
-        //Verify voicemail number for home
-        doReturn(false).when(mSST.mSS).getRoaming();
-        doReturn(true).when(mSST).isImsRegistered();
-        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
-        //Move to ims condition, verify voicemail number for ims unregistered
-        doReturn(false).when(mSST).isImsRegistered();
-        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
-        //Move to roaming condition, verify voicemail number for roaming
-        doReturn(true).when(mSST.mSS).getRoaming();
-        assertEquals(voiceMailNumberForImsRoamingAndUnregistered, mPhoneUT.getVoiceMailNumber());
-        //Move to ims condition, verify voicemail number for roaming
-        doReturn(true).when(mSST).isImsRegistered();
-        assertEquals(voiceMailNumberForRoaming, mPhoneUT.getVoiceMailNumber());
-        //Move to home condition, verify voicemail number for home
-        doReturn(false).when(mSST.mSS).getRoaming();
-        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
-
-        // voicemail number from sharedPreference
-        voiceMailNumber = "1234567893";
-        mPhoneUT.setVoiceMailNumber("alphaTag", voiceMailNumber, null);
-        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
-        InOrder inOrder = inOrder(mSimRecords);
-        inOrder.verify(mSimRecords).setVoiceMailNumber(eq("alphaTag"), eq(voiceMailNumber),
-                messageArgumentCaptor.capture());
-
-        // SIM does not support voicemail number (IccVmNotSupportedException) so should be saved in
-        // shared pref
-        Message msg = messageArgumentCaptor.getValue();
-        AsyncResult.forMessage(msg).exception =
-                new IccVmNotSupportedException("setVoiceMailNumber not implemented");
-        msg.sendToTarget();
-        processAllMessages();
-
-        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
-
-        // voicemail number from SIM
-        voiceMailNumber = "1234567894";
-        mPhoneUT.setVoiceMailNumber("alphaTag", voiceMailNumber, null);
-        messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
-        inOrder.verify(mSimRecords).setVoiceMailNumber(eq("alphaTag"), eq(voiceMailNumber),
-                messageArgumentCaptor.capture());
-
-        // successfully saved on SIM
-        msg = messageArgumentCaptor.getValue();
-        AsyncResult.forMessage(msg);
-        msg.sendToTarget();
-        processAllMessages();
-
-        doReturn(voiceMailNumber).when(mSimRecords).getVoiceMailNumber();
-
-        assertEquals(voiceMailNumber, mPhoneUT.getVoiceMailNumber());
-    }
-
     @FlakyTest
     @Test
     @Ignore
@@ -1000,60 +821,6 @@
         verify(mSimRecords).setVoiceCallForwardingFlag(anyInt(), anyBoolean(), eq(cfNumber));
     }
 
-    /**
-     * GsmCdmaPhone handles a lot of messages. This function verifies behavior for messages that are
-     * received when obj is created and that are received on phone type switch
-     */
-    @FlakyTest
-    @Ignore
-    @Test
-    @SmallTest
-    public void testHandleInitialMessages() {
-        // EVENT_RADIO_AVAILABLE
-        verify(mSimulatedCommandsVerifier).getBasebandVersion(nullable(Message.class));
-        verify(mSimulatedCommandsVerifier).getDeviceIdentity(nullable(Message.class));
-        verify(mSimulatedCommandsVerifier).getRadioCapability(nullable(Message.class));
-
-        // EVENT_RADIO_ON
-        verify(mSimulatedCommandsVerifier).getVoiceRadioTechnology(nullable(Message.class));
-        verify(mSimulatedCommandsVerifier).setPreferredNetworkType(
-                eq(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA), nullable(Message.class));
-
-        // verify responses for above requests:
-        // baseband version
-        verify(mTelephonyManager).setBasebandVersionForPhone(eq(mPhoneUT.getPhoneId()),
-                nullable(String.class));
-        // IMEI
-        assertEquals(FAKE_IMEI, mPhoneUT.getImei());
-        // IMEISV
-        assertEquals(SimulatedCommands.FAKE_IMEISV, mPhoneUT.getDeviceSvn());
-        // radio capability
-        verify(mSimulatedCommandsVerifier).getNetworkSelectionMode(nullable(Message.class));
-
-        switchToCdma(); // this leads to eventRadioAvailable handling on cdma
-
-        // EVENT_RADIO_AVAILABLE
-        verify(mSimulatedCommandsVerifier, times(2)).getBasebandVersion(nullable(Message.class));
-        verify(mSimulatedCommandsVerifier, times(2)).getDeviceIdentity(nullable(Message.class));
-
-        // EVENT_RADIO_ON
-        verify(mSimulatedCommandsVerifier, times(2)).getVoiceRadioTechnology(
-                nullable(Message.class));
-        // once on radio on, and once on get baseband version
-        verify(mSimulatedCommandsVerifier, times(3)).setPreferredNetworkType(
-                eq(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA), nullable(Message.class));
-
-        // verify responses for above requests:
-        // baseband version
-        verify(mTelephonyManager, times(2)).setBasebandVersionForPhone(eq(mPhoneUT.getPhoneId()),
-                nullable(String.class));
-        // device identity
-        assertEquals(FAKE_IMEI, mPhoneUT.getImei());
-        assertEquals(SimulatedCommands.FAKE_IMEISV, mPhoneUT.getDeviceSvn());
-        assertEquals(SimulatedCommands.FAKE_ESN, mPhoneUT.getEsn());
-        assertEquals(SimulatedCommands.FAKE_MEID, mPhoneUT.getMeid());
-    }
-
     @Test
     public void testZeroMeid() {
         doReturn(false).when(mSST).isDeviceShuttingDown();
@@ -1260,24 +1027,6 @@
     public void testGetLine1NumberForGsmPhone() {
         final String msisdn = "+1234567890";
         doReturn(msisdn).when(mSimRecords).getMsisdnNumber();
-
-        switchToGsm();
-        assertEquals(msisdn, mPhoneUT.getLine1Number());
-    }
-
-    @Test
-    @SmallTest
-    public void testGetLine1NumberForCdmaPhone() {
-        final String mdn = "1234567890";
-        final String msisdn = "+1234567890";
-        doReturn(mdn).when(mSST).getMdnNumber();
-        doReturn(msisdn).when(mSimRecords).getMsisdnNumber();
-
-        switchToCdma();
-        assertEquals(mdn, mPhoneUT.getLine1Number());
-
-        mContextFixture.getCarrierConfigBundle().putBoolean(
-                CarrierConfigManager.KEY_USE_USIM_BOOL, true);
         assertEquals(msisdn, mPhoneUT.getLine1Number());
     }
 
@@ -1519,8 +1268,6 @@
 
     @Test
     public void testNrCapabilityChanged_firstRequest_incompleteCarrierConfig_changeNeeded() {
-        when(mFeatureFlags.enableCarrierConfigN1ControlAttempt2()).thenReturn(true);
-
         mPhoneUT.mCi = mMockCi;
         PersistableBundle bundle = mContextFixture.getCarrierConfigBundle();
         bundle.putIntArray(CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY,
@@ -1550,8 +1297,6 @@
 
     @Test
     public void testNrCapabilityChanged_firstRequest_noChangeNeeded() {
-        when(mFeatureFlags.enableCarrierConfigN1ControlAttempt2()).thenReturn(true);
-
         mPhoneUT.mCi = mMockCi;
         PersistableBundle bundle = mContextFixture.getCarrierConfigBundle();
         bundle.putIntArray(CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY,
@@ -1574,8 +1319,6 @@
 
     @Test
     public void testNrCapabilityChanged_firstRequest_needsChange() {
-        when(mFeatureFlags.enableCarrierConfigN1ControlAttempt2()).thenReturn(true);
-
         mPhoneUT.mCi = mMockCi;
         PersistableBundle bundle = mContextFixture.getCarrierConfigBundle();
         bundle.putIntArray(CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY,
@@ -1598,8 +1341,6 @@
 
     @Test
     public void testNrCapabilityChanged_CarrierConfigChanges() {
-        when(mFeatureFlags.enableCarrierConfigN1ControlAttempt2()).thenReturn(true);
-
         // Initialize the inner cache and set the modem to N1 mode = enabled/true
         testNrCapabilityChanged_firstRequest_needsChange();
 
@@ -1620,8 +1361,6 @@
 
     @Test
     public void testNrCapabilityChanged_CarrierConfigChanges_ErrorResponse() {
-        when(mFeatureFlags.enableCarrierConfigN1ControlAttempt2()).thenReturn(true);
-
         mPhoneUT.mCi = mMockCi;
         for (int i = 0; i < 2; i++) {
             PersistableBundle bundle = mContextFixture.getCarrierConfigBundle();
@@ -1646,8 +1385,6 @@
 
     @Test
     public void testNrCapabilityChanged_firstRequest_ImsChanges() {
-        when(mFeatureFlags.enableCarrierConfigN1ControlAttempt2()).thenReturn(true);
-
         mPhoneUT.mCi = mMockCi;
         Message passthroughMessage = mTestHandler.obtainMessage(0xC0FFEE);
 
@@ -2510,21 +2247,6 @@
                 any(Message.class));
     }
 
-    @Test
-    public void testHandleNullCipherAndIntegrityEnabled_featureFlagOff() {
-        mPhoneUT.mCi = mMockCi;
-        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_CELLULAR_SECURITY,
-                TelephonyManager.PROPERTY_ENABLE_NULL_CIPHER_TOGGLE, Boolean.FALSE.toString(),
-                false);
-
-        mPhoneUT.sendMessage(mPhoneUT.obtainMessage(EVENT_RADIO_AVAILABLE,
-                new AsyncResult(null, new int[]{ServiceState.RIL_RADIO_TECHNOLOGY_GSM}, null)));
-        processAllMessages();
-
-        verify(mMockCi, times(0)).setNullCipherAndIntegrityEnabled(anyBoolean(),
-                any(Message.class));
-    }
-
     public void fdnCheckCleanup() {
         doReturn(false).when(mUiccCardApplication3gpp).getIccFdnAvailable();
         doReturn(false).when(mUiccCardApplication3gpp).getIccFdnEnabled();
@@ -2671,14 +2393,6 @@
     }
 
     @Test
-    public void getImei() {
-        assertTrue(mPhoneUT.isPhoneTypeGsm());
-        Message message = mPhoneUT.obtainMessage(Phone.EVENT_RADIO_AVAILABLE);
-        mPhoneUT.handleMessage(message);
-        verify(mSimulatedCommandsVerifier, times(2)).getImei(nullable(Message.class));
-    }
-
-    @Test
     public void testSetAllowedNetworkTypes_admin2gRestrictionHonored() throws Exception {
         // circumvent loading/saving to sim db. it's not behavior under test.
         TelephonyManager.setupISubForTest(Mockito.mock(SubscriptionManagerService.class));
@@ -2765,57 +2479,6 @@
     }
 
     @Test
-    @SmallTest
-    public void testEcbmOnModemResetForNonGsmPhone() throws Exception {
-        switchToCdma();
-        assertFalse(mPhoneUT.isInEcm());
-
-        mPhoneUT.handleMessage(mPhoneUT.obtainMessage(
-                GsmCdmaPhone.EVENT_EMERGENCY_CALLBACK_MODE_ENTER));
-
-        assertTrue(mPhoneUT.isInEcm());
-
-        Message m = mPhoneUT.obtainMessage(GsmCdmaPhone.EVENT_MODEM_RESET);
-        AsyncResult.forMessage(m);
-        mPhoneUT.handleMessage(m);
-
-        assertFalse(mPhoneUT.isInEcm());
-        verifyEcbmIntentWasSent(2 /*times*/, false /*inEcm*/);
-    }
-
-    @Test
-    @SmallTest
-    public void testEcbmOnModemResetWhenDomainSelectionEnabled() throws Exception {
-        DomainSelectionResolver dsResolver = Mockito.mock(DomainSelectionResolver.class);
-        doReturn(true).when(dsResolver).isDomainSelectionSupported();
-        DomainSelectionResolver.setDomainSelectionResolver(dsResolver);
-
-        EmergencyStateTracker est = Mockito.mock(EmergencyStateTracker.class);
-        doReturn(true).when(est).isInEcm();
-        replaceInstance(EmergencyStateTracker.class, "INSTANCE", null, est);
-
-        GsmCdmaPhone spyPhone = spy(mPhoneUT);
-        doReturn(true).when(spyPhone).isInEcm();
-        mPhoneUT.handleMessage(mPhoneUT.obtainMessage(GsmCdmaPhone.EVENT_MODEM_RESET));
-
-        verify(est).exitEmergencyCallbackMode();
-    }
-
-    @Test
-    public void testGetUserHandle() {
-        UserHandle userHandle = new UserHandle(123);
-        doReturn(userHandle).when(mSubscriptionManager).getSubscriptionUserHandle(anyInt());
-        assertEquals(userHandle, mPhoneUT.getUserHandle());
-
-        doReturn(null).when(mSubscriptionManager).getSubscriptionUserHandle(anyInt());
-        assertNull(mPhoneUT.getUserHandle());
-
-        doThrow(IllegalArgumentException.class).when(mSubscriptionManager)
-                .getSubscriptionUserHandle(anyInt());
-        assertNull(mPhoneUT.getUserHandle());
-    }
-
-    @Test
     public void testResetNetworkSelectionModeOnSimSwap() {
         // Set current network selection manual mode.
         mSimulatedCommands.setNetworkSelectionModeManual("123", 0, null);
@@ -2862,31 +2525,7 @@
     }
 
     @Test
-    public void testCellularIdentifierDisclosureFlagOff() {
-        when(mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()).thenReturn(false);
-
-        GsmCdmaPhone phoneUT =
-                new GsmCdmaPhone(
-                        mContext,
-                        mSimulatedCommands,
-                        mNotifier,
-                        true,
-                        0,
-                        PhoneConstants.PHONE_TYPE_GSM,
-                        mTelephonyComponentFactory,
-                        (c, p) -> mImsManager,
-                        mFeatureFlags);
-        phoneUT.mCi = mMockCi;
-
-        verify(mMockCi, never())
-                .registerForCellularIdentifierDisclosures(
-                        any(Handler.class), anyInt(), any(Object.class));
-    }
-
-    @Test
-    public void testCellularIdentifierDisclosureFlagOn() {
-        when(mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()).thenReturn(true);
-
+    public void testCellularIdentifierDisclosure() {
         Phone phoneUT =
                 new GsmCdmaPhone(
                         mContext,
@@ -2910,7 +2549,6 @@
     public void testCellularIdentifierDisclosure_disclosureEventAddedToNotifier() {
         int phoneId = 0;
         int subId = 10;
-        when(mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()).thenReturn(true);
         when(mSubscriptionManagerService.getSubId(phoneId)).thenReturn(subId);
 
         Phone phoneUT =
@@ -2945,7 +2583,6 @@
     public void testCellularIdentifierDisclosure_disclosureEventNull() {
         int phoneId = 4;
         int subId = 6;
-        when(mFeatureFlags.enableIdentifierDisclosureTransparencyUnsolEvents()).thenReturn(true);
         when(mSubscriptionManagerService.getSubId(phoneId)).thenReturn(subId);
         Phone phoneUT =
                 new GsmCdmaPhone(
@@ -2969,21 +2606,7 @@
     }
 
     @Test
-    public void testCellularIdentifierDisclosure_noModemCallOnRadioAvailable_FlagOff() {
-        when(mFeatureFlags.enableIdentifierDisclosureTransparency()).thenReturn(false);
-        GsmCdmaPhone phoneUT = makeNewPhoneUT();
-        assertFalse(phoneUT.isIdentifierDisclosureTransparencySupported());
-
-        sendRadioAvailableToPhone(phoneUT);
-
-        verify(mMockCi, never()).setCellularIdentifierTransparencyEnabled(anyBoolean(),
-                any(Message.class));
-        assertFalse(phoneUT.isIdentifierDisclosureTransparencySupported());
-    }
-
-    @Test
     public void testCellularIdentifierDisclosure_unsupportedByModemOnRadioAvailable() {
-        when(mFeatureFlags.enableIdentifierDisclosureTransparency()).thenReturn(true);
         GsmCdmaPhone phoneUT = makeNewPhoneUT();
         assertFalse(phoneUT.isIdentifierDisclosureTransparencySupported());
 
@@ -3000,7 +2623,6 @@
 
     @Test
     public void testCellularIdentifierDisclosure_supportedByModem() {
-        when(mFeatureFlags.enableIdentifierDisclosureTransparency()).thenReturn(true);
         GsmCdmaPhone phoneUT = makeNewPhoneUT();
         assertFalse(phoneUT.isIdentifierDisclosureTransparencySupported());
 
@@ -3016,18 +2638,7 @@
     }
 
     @Test
-    public void testSecurityAlgorithmUpdateFlagOff() {
-        when(mFeatureFlags.enableModemCipherTransparency()).thenReturn(false);
-
-        makeNewPhoneUT();
-
-        verify(mMockCi, never()).registerForSecurityAlgorithmUpdates(any(), anyInt(), any());
-    }
-
-    @Test
     public void testSecurityAlgorithmUpdateFlagOn() {
-        when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(true);
-
         Phone phoneUT = makeNewPhoneUT();
 
         verify(mMockCi, times(1))
@@ -3039,7 +2650,6 @@
 
     @Test
     public void testSecurityAlgorithm_updateAddedToNotifier() {
-        when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(true);
         Phone phoneUT = makeNewPhoneUT();
         SecurityAlgorithmUpdate update =
                 new SecurityAlgorithmUpdate(
@@ -3059,22 +2669,7 @@
     }
 
     @Test
-    public void testUpdateNullCipherNotifier_flagDisabled() {
-        when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(false);
-        Phone phoneUT = makeNewPhoneUT();
-        phoneUT.sendMessage(
-                mPhoneUT.obtainMessage(
-                        Phone.EVENT_SUBSCRIPTIONS_CHANGED,
-                        new AsyncResult(null, null, null)));
-        processAllMessages();
-
-        verify(mNullCipherNotifier, never()).setSubscriptionMapping(any(), anyInt(), anyInt());
-    }
-
-    @Test
     public void testUpdateNullCipherNotifier_activeSubscription() {
-        when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(true);
-
         int subId = 10;
         SubscriptionInfoInternal subInfo = new SubscriptionInfoInternal.Builder().setSimSlotIndex(
                 0).setId(subId).build();
@@ -3095,7 +2690,6 @@
 
     @Test
     public void testUpdateNullCipherNotifier_inactiveSubscription() {
-        when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(true);
         int subId = 1;
         SubscriptionInfoInternal subInfo = new SubscriptionInfoInternal.Builder().setSimSlotIndex(
                 -1).setId(subId).build();
@@ -3115,21 +2709,7 @@
     }
 
     @Test
-    public void testNullCipherNotification_noModemCallOnRadioAvailable_FlagOff() {
-        when(mFeatureFlags.enableModemCipherTransparency()).thenReturn(false);
-        GsmCdmaPhone phoneUT = makeNewPhoneUT();
-        assertFalse(phoneUT.isNullCipherNotificationSupported());
-
-        sendRadioAvailableToPhone(phoneUT);
-
-        verify(mMockCi, never()).setSecurityAlgorithmsUpdatedEnabled(anyBoolean(),
-                any(Message.class));
-        assertFalse(phoneUT.isNullCipherNotificationSupported());
-    }
-
-    @Test
     public void testNullCipherNotification_unsupportedByModemOnRadioAvailable() {
-        when(mFeatureFlags.enableModemCipherTransparency()).thenReturn(true);
         GsmCdmaPhone phoneUT = makeNewPhoneUT();
         assertFalse(phoneUT.isNullCipherNotificationSupported());
 
@@ -3143,7 +2723,6 @@
 
     @Test
     public void testNullCipherNotification_supportedByModem() {
-        when(mFeatureFlags.enableModemCipherTransparency()).thenReturn(true);
         GsmCdmaPhone phoneUT = makeNewPhoneUT();
         assertFalse(phoneUT.isNullCipherNotificationSupported());
 
@@ -3157,8 +2736,6 @@
 
     @Test
     public void testNullCipherNotification_preferenceEnabled() {
-        when(mFeatureFlags.enableModemCipherTransparency()).thenReturn(true);
-        when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(true);
         GsmCdmaPhone phoneUT = makeNewPhoneUT();
 
         setNullCipherNotificationPreferenceEnabled(true);
@@ -3171,8 +2748,7 @@
 
     @Test
     public void testNullCipherNotification_preferenceDisabled() {
-        when(mFeatureFlags.enableModemCipherTransparency()).thenReturn(true);
-        when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(true);
+        Mockito.reset(mNullCipherNotifier);
         GsmCdmaPhone phoneUT = makeNewPhoneUT();
 
         setNullCipherNotificationPreferenceEnabled(false);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java
index 6e50d88..7f9249b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/LocaleTrackerTest.java
@@ -19,13 +19,12 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 import android.content.Intent;
 import android.os.AsyncResult;
@@ -346,19 +345,8 @@
     }
 
     @Test
-    public void testNotifyCountryCodeChangedToTelephonyCountryDetector_featureFlagEnabled() {
-        testNotifyCountryCodeChangedToTelephonyCountryDetector(true);
-    }
-
-    @Test
-    public void testNotifyCountryCodeChangedToTelephonyCountryDetector_featureFlagDisabled() {
-        testNotifyCountryCodeChangedToTelephonyCountryDetector(false);
-    }
-
-    private void testNotifyCountryCodeChangedToTelephonyCountryDetector(
-            boolean oemEnabledSatelliteFlag) {
+    public void testNotifyCountryCodeChangedToTelephonyCountryDetector() {
         reset(mCountryDetector);
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(oemEnabledSatelliteFlag);
         doReturn(true).when(mPhone).isRadioOn();
         sendServiceState(ServiceState.STATE_IN_SERVICE);
         mLocaleTracker.updateOperatorNumeric(US_MCC + FAKE_MNC);
@@ -367,8 +355,6 @@
         verifyCountryCodeNotified(new String[]{COUNTRY_CODE_UNAVAILABLE, US_COUNTRY_CODE});
         assertFalse(mLocaleTracker.isTracking());
 
-        int notifiedCount = oemEnabledSatelliteFlag ? 1 : 0;
-        verify(mCountryDetector, times(notifiedCount))
-                .onNetworkCountryCodeChanged(mPhone, US_COUNTRY_CODE);
+        verify(mCountryDetector, times(1)).onNetworkCountryCodeChanged(mPhone, US_COUNTRY_CODE);
     }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java b/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
index 658935f..2af83fa 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/MccTableTest.java
@@ -17,40 +17,74 @@
 package com.android.internal.telephony;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import static org.junit.Assume.assumeTrue;
 
 import android.content.Context;
+import android.platform.test.annotations.UsesFlags;
+import android.platform.test.flag.junit.FlagsParameterization;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.timezone.MobileCountries;
+import android.timezone.TelephonyLookup;
+import android.timezone.TelephonyNetworkFinder;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.telephony.MccTable.MccMnc;
+import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.util.LocaleUtils;
 
+import org.junit.ClassRule;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
+import java.util.List;
 import java.util.Locale;
 
+@RunWith(Parameterized.class)
+@UsesFlags({
+        com.android.internal.telephony.flags.Flags.class,
+        com.android.icu.Flags.class
+})
 public class MccTableTest {
+    @ClassRule
+    public static final SetFlagsRule.ClassRule mSetFlagsClassRule = new SetFlagsRule.ClassRule();
+
+    @Parameterized.Parameters(name = "{0}")
+    public static List<FlagsParameterization> getParams() {
+        return FlagsParameterization.allCombinationsOf(
+                Flags.FLAG_USE_I18N_FOR_MCC_MAPPING,
+                com.android.icu.Flags.FLAG_TELEPHONY_LOOKUP_MCC_EXTENSION);
+    }
+
+    @Rule
+    public final SetFlagsRule mSetFlagsRule;
+
+    public MccTableTest(FlagsParameterization flags) {
+        mSetFlagsRule = mSetFlagsClassRule.createSetFlagsRule(flags);
+    }
 
     @SmallTest
     @Test
     public void testCountryCodeForMcc() throws Exception {
-        checkMccLookupWithNoMnc("lu", 270);
-        checkMccLookupWithNoMnc("gr", 202);
-        checkMccLookupWithNoMnc("fk", 750);
-        checkMccLookupWithNoMnc("mg", 646);
-        checkMccLookupWithNoMnc("us", 314);
-        checkMccLookupWithNoMnc("", 300);  // mcc not defined, hence default
-        checkMccLookupWithNoMnc("", 0);    // mcc not defined, hence default
-        checkMccLookupWithNoMnc("", 2000); // mcc not defined, hence default
+        checkMccLookupWithNoMnc("lu", "270");
+        checkMccLookupWithNoMnc("gr", "202");
+        checkMccLookupWithNoMnc("fk", "750");
+        checkMccLookupWithNoMnc("mg", "646");
+        checkMccLookupWithNoMnc("us", "314");
+        checkMccLookupWithNoMnc("", "300");  // mcc not defined, hence default
+        checkMccLookupWithNoMnc("", "0");    // mcc not defined, hence default
+        checkMccLookupWithNoMnc("", "2000"); // mcc not defined, hence default
     }
 
-    private void checkMccLookupWithNoMnc(String expectedCountryIsoCode, int mcc) {
+    private void checkMccLookupWithNoMnc(String expectedCountryIsoCode, String mcc) {
         assertEquals(expectedCountryIsoCode, MccTable.countryCodeForMcc(mcc));
-        assertEquals(expectedCountryIsoCode, MccTable.countryCodeForMcc(mcc));
-        assertEquals(expectedCountryIsoCode, MccTable.countryCodeForMcc("" + mcc));
         assertEquals(expectedCountryIsoCode,
-                MccTable.geoCountryCodeForMccMnc(new MccMnc("" + mcc, "999")));
+                MccTable.geoCountryCodeForMccMnc(new MccMnc(mcc, "999")));
     }
 
     @SmallTest
@@ -69,9 +103,9 @@
         assertEquals("nl", LocaleUtils.defaultLanguageForMcc(204));
         assertEquals("is", LocaleUtils.defaultLanguageForMcc(274));
         // mcc not defined, hence default
-        assertEquals(null, LocaleUtils.defaultLanguageForMcc(0));
+        assertNull(LocaleUtils.defaultLanguageForMcc(0));
         // mcc not defined, hence default
-        assertEquals(null, LocaleUtils.defaultLanguageForMcc(2000));
+        assertNull(LocaleUtils.defaultLanguageForMcc(2000));
     }
 
     @SmallTest
@@ -117,4 +151,27 @@
         // mcc not defined, hence default
         assertEquals(2, MccTable.smallestDigitsMccForMnc(2000));
     }
+
+    @Test
+    public void telephonyFinder_shouldBeIdenticalToTelephonyMccTable() {
+        assumeTrue(Flags.useI18nForMccMapping());
+        assumeTrue(com.android.icu.Flags.telephonyLookupMccExtension());
+
+        TelephonyNetworkFinder telephonyNetworkFinder =
+                TelephonyLookup.getInstance().getTelephonyNetworkFinder();
+
+        MccTable.getAllMccEntries().forEach(mccEntry -> {
+                MobileCountries telephonyCountry =
+                        telephonyNetworkFinder.findCountriesByMcc(
+                                String.valueOf(mccEntry.mMcc));
+
+                assertEquals(mccEntry.mIso, telephonyCountry.getDefaultCountryIsoCode());
+        });
+    }
+
+    @SmallTest
+    @Test
+    public void testNullMcc() throws Exception {
+        assertEquals("", MccTable.countryCodeForMcc(null));
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
index 855a5dc..50455ea 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
@@ -249,8 +249,6 @@
         bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
         doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
 
-        doReturn(true).when(mFeatureFlags).resetPrimarySimDefaultValues();
-
         replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
         // Capture listener to emulate the carrier config change notification used later
         ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
index a7923cf..4db6f56 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -112,6 +112,7 @@
         // Capture listener to emulate the carrier config change notification used later
         ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
                 ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
+        setPhysicalLinkStatus(true);
         mNetworkTypeController =
                 new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
         processAllMessages();
@@ -374,7 +375,6 @@
     @Test
     public void testTransitionToCurrentStateNrConnectedIdle() throws Exception {
         assertEquals("DefaultState", getCurrentState().getName());
-        doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         doReturn(new ArrayList<>()).when(mSST).getPhysicalChannelConfigList();
         sendCarrierConfigChanged();
@@ -640,7 +640,7 @@
         mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */,
                 new AsyncResult(null, new ArrayList<>(), null));
         processAllMessages();
-        assertEquals("connected_mmwave", getCurrentState().getName());
+        assertEquals("connected_rrc_idle", getCurrentState().getName());
 
         // bands and bandwidths should stay ratcheted as long as anchor NR cell is the same
         physicalChannelConfigs.remove(pcc2);
@@ -704,7 +704,7 @@
         mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */,
                 new AsyncResult(null, new ArrayList<>(), null));
         processAllMessages();
-        assertEquals("connected_mmwave", getCurrentState().getName());
+        assertEquals("connected_rrc_idle", getCurrentState().getName());
 
         // bands and bandwidths should change if PCC list changes
         physicalChannelConfigs.remove(pcc2);
@@ -809,7 +809,14 @@
                 new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
         sendCarrierConfigChanged();
         processAllMessages();
-        testTransitionToCurrentStateNrConnectedMmwave();
+
+        // service state of NrConnectedMmwave shouldn't affect the result
+        doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+        doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
+
+        mNetworkTypeController.sendMessage(3 /* EVENT_SERVICE_STATE_CHANGED */);
+        processAllMessages();
+
         doReturn(NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED).when(mServiceState).getNrState();
         mNetworkTypeController.sendMessage(4 /* EVENT_PHYSICAL_LINK_STATUS_CHANGED */,
                 DataCallResponse.LINK_STATUS_ACTIVE);
@@ -1252,7 +1259,6 @@
 
     @Test
     public void testPrimaryTimerPrimaryCellChangeNrIdle() throws Exception {
-        doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         ArrayList<PhysicalChannelConfig> physicalChannelConfigs = new ArrayList<>();
         physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
@@ -1367,6 +1373,60 @@
     }
 
     @Test
+    public void testSecondaryPciTimerExpire() throws Exception {
+        testTransitionToCurrentStateNrConnectedMmwave();
+        assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+                mNetworkTypeController.getOverrideNetworkType());
+
+        mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+                "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
+        mBundle.putInt(CarrierConfigManager.KEY_NR_ADVANCED_PCI_CHANGE_SECONDARY_TIMER_SECONDS_INT,
+                30);
+        sendCarrierConfigChanged();
+
+        // should trigger 10 second primary timer
+        doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
+        mNetworkTypeController.sendMessage(3 /* EVENT_SERVICE_STATE_CHANGED */);
+        processAllMessages();
+
+        assertEquals("legacy", getCurrentState().getName());
+        assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+                mNetworkTypeController.getOverrideNetworkType());
+        assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+        // Before primary timer expires, PCI changed, indicating 5G UW might soon recover
+        moveTimeForward(5 * 1000);
+        mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */,
+                new AsyncResult(null,
+                        List.of(new PhysicalChannelConfig.Builder()
+                                .setPhysicalCellId(2)
+                                .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+                                .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+                        .build()),
+                        null));
+        processAllMessages();
+
+        // primary timer expires
+        moveTimeForward(5 * 1000);
+        processAllMessages();
+
+        // should trigger 30 second secondary timer
+        assertEquals("legacy", getCurrentState().getName());
+        assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+                mNetworkTypeController.getOverrideNetworkType());
+        assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+        // secondary timer expires
+        moveTimeForward(30 * 1000);
+        processAllMessages();
+
+        assertEquals("legacy", getCurrentState().getName());
+        assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
+                mNetworkTypeController.getOverrideNetworkType());
+        assertFalse(mNetworkTypeController.areAnyTimersActive());
+    }
+
+    @Test
     public void testSecondaryTimerReset() throws Exception {
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
@@ -1509,7 +1569,6 @@
 
     @Test
     public void testTransitionToNrIdle() throws Exception {
-        doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(mServiceState).getNrFrequencyRange();
         ArrayList<PhysicalChannelConfig> physicalChannelConfigs = new ArrayList<>();
@@ -1555,7 +1614,6 @@
 
     @Test
     public void testSecondaryTimerAdvanceBand() throws Exception {
-        doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(mServiceState).getNrFrequencyRange();
         ArrayList<PhysicalChannelConfig> physicalChannelConfigs = new ArrayList<>();
@@ -1677,7 +1735,6 @@
 
     @Test
     public void testSecondaryTimerExpireNrIdle() throws Exception {
-        doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         ArrayList<PhysicalChannelConfig> physicalChannelConfigs = new ArrayList<>();
         physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
@@ -1748,7 +1805,6 @@
 
     @Test
     public void testSecondaryTimerResetNrIdle() throws Exception {
-        doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         ArrayList<PhysicalChannelConfig> physicalChannelConfigs = new ArrayList<>();
         physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
@@ -1830,7 +1886,6 @@
 
     @Test
     public void testSecondaryTimerPrimaryCellChangeNrIdle() throws Exception {
-        doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         ArrayList<PhysicalChannelConfig> physicalChannelConfigs = new ArrayList<>();
         physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
index 7a30984..b08830c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -21,8 +21,6 @@
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
 
-import com.android.internal.telephony.flags.Flags;
-
 import android.net.Uri;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.telephony.PhoneNumberUtils;
@@ -32,6 +30,8 @@
 import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.telephony.flags.Flags;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Ignore;
@@ -560,6 +560,8 @@
         assertEquals("+16502910000", PhoneNumberUtils.formatNumberToE164("650 2910000", "US"));
         assertNull(PhoneNumberUtils.formatNumberToE164("1234567", "US"));
         assertEquals("+18004664114", PhoneNumberUtils.formatNumberToE164("800-GOOG-114", "US"));
+
+        assertEquals("+447445032046", PhoneNumberUtils.formatNumberToE164("0 7445 032046", "GB"));
     }
 
     @SmallTest
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
index 28d0318..24267db 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
@@ -28,7 +28,7 @@
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Matchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
@@ -119,7 +119,6 @@
 
         // In order not to affect the existing implementation, define a telephony features
         // and disabled enforce_telephony_feature_mapping_for_public_apis feature flag
-        doReturn(false).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
         doReturn(true).when(mPm).hasSystemFeature(anyString());
         doReturn(new String[] {TAG}).when(mPm).getPackagesForUid(anyInt());
     }
@@ -218,27 +217,14 @@
 
     @Test
     @SmallTest
-    public void testGetNai() {
-        doReturn("aaa@example.com").when(mPhone).getNai();
-        assertEquals("aaa@example.com",
-                mPhoneSubInfoControllerUT.getNaiForSubscriber(0, TAG, FEATURE_ID));
-
-        doReturn("bbb@example.com").when(mSecondPhone).getNai();
-        assertEquals("bbb@example.com",
-                mPhoneSubInfoControllerUT.getNaiForSubscriber(1, TAG, FEATURE_ID));
-    }
-
-    @Test
-    @SmallTest
     @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
-    public void testGetNai_EnabledEnforceTelephonyFeatureMappingForPublicApis() throws Exception {
+    public void testGetNai() throws Exception {
         // Replace field to set SDK version of vendor partition to Android V
         int vendorApiLevel = Build.VERSION_CODES.VANILLA_ICE_CREAM;
         replaceInstance(PhoneSubInfoController.class, "mVendorApiLevel",
                 mPhoneSubInfoControllerUT, vendorApiLevel);
 
         // FeatureFlags enabled, System has required feature
-        doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
         doReturn(true).when(mPm).hasSystemFeature(
                 eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
         doReturn("bbb@example.com").when(mSecondPhone).getNai();
@@ -465,7 +451,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSubscriberId() {
         //IMSI
         doReturn("310260426283121").when(mPhone).getSubscriberId();
@@ -478,7 +464,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSubscriberIdWithInactiveSubId() {
         //IMSI
         assertNull(mPhoneSubInfoControllerUT.getSubscriberIdForSubscriber(2, TAG, FEATURE_ID));
@@ -557,7 +543,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetIccSerialNumber() {
         //IccId
         doReturn("8991101200003204510").when(mPhone).getIccSerialNumber();
@@ -641,7 +627,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetLine1Number() {
         mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
         doReturn("+18051234567").when(mPhone).getLine1Number();
@@ -654,7 +640,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetLine1NumberWithOutPermissionTargetPreR() {
         mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
         doReturn("+18051234567").when(mPhone).getLine1Number();
@@ -695,7 +681,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetLine1NumberWithOutPermissionTargetR() {
         mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.R;
         doReturn("+18051234567").when(mPhone).getLine1Number();
@@ -876,7 +862,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetVoiceMailNumber() {
         doReturn("+18051234567").when(mPhone).getVoiceMailNumber();
         assertEquals("+18051234567", mPhoneSubInfoControllerUT
@@ -888,7 +874,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetVoiceMailNumberWithOutPermission() {
         doReturn("+18051234567").when(mPhone).getVoiceMailNumber();
         doReturn("+18052345678").when(mSecondPhone).getVoiceMailNumber();
@@ -932,7 +918,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetVoiceMailAlphaTag() {
         doReturn("VM_SIM_0").when(mPhone).getVoiceMailAlphaTag();
         assertEquals("VM_SIM_0", mPhoneSubInfoControllerUT
@@ -944,7 +930,7 @@
     }
 
     @Test
-    @SmallTest
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetVoiceMailAlphaTagWithOutPermission() {
         doReturn("VM_SIM_0").when(mPhone).getVoiceMailAlphaTag();
         doReturn("VM_SIM_1").when(mSecondPhone).getVoiceMailAlphaTag();
@@ -1012,6 +998,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSmscIdentityForTelUri() {
         try {
             setUpInitials();
@@ -1029,6 +1016,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSmscIdentityForSipUri() {
         try {
             UiccPort uiccPort1 = Mockito.mock(UiccPort.class);
@@ -1067,6 +1055,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSmscIdentityWithOutPermissions() {
         setUpInitials();
 
@@ -1125,6 +1114,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSimServiceTable() throws RemoteException {
         String refSst = "1234567";
         doReturn(mUiccPort).when(mPhone).getUiccPort();
@@ -1139,6 +1129,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSimServiceTableEmpty() throws RemoteException {
         String refSst = null;
         doReturn(mUiccPort).when(mPhone).getUiccPort();
@@ -1153,6 +1144,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSstWhenNoUiccPort() throws RemoteException {
         String refSst = "1234567";
         doReturn(null).when(mPhone).getUiccPort();
@@ -1167,6 +1159,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSstWhenNoUiccProfile() throws RemoteException {
         String refSst = "1234567";
         doReturn(mUiccPort).when(mPhone).getUiccPort();
@@ -1181,6 +1174,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSstWhenNoUiccApplication() throws RemoteException {
         String refSst = "1234567";
         doReturn(mUiccPort).when(mPhone).getUiccPort();
@@ -1195,6 +1189,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSimServiceTableWithOutPermissions() throws RemoteException {
         String refSst = "1234567";
         doReturn(mUiccPort).when(mPhone).getUiccPort();
@@ -1262,6 +1257,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void getImsPublicUserIdentities() {
         String[] refImpuArray = new String[3];
         refImpuArray[0] = "012345678";
@@ -1280,6 +1276,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void getImsPublicUserIdentities_InvalidImpu() {
         String[] refImpuArray = new String[3];
         refImpuArray[0] = null;
@@ -1294,8 +1291,11 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void getImsPublicUserIdentities_IsimNotLoadedError() {
         doReturn(null).when(mPhone).getIsimRecords();
+        doReturn(true).when(mPackageManager).hasSystemFeature(
+                eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
 
         try {
             mPhoneSubInfoControllerUT.getImsPublicUserIdentities(0, TAG);
@@ -1333,6 +1333,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void getImsPcscfAddresses() {
         String[] preDefinedPcscfs = new String[3];
         preDefinedPcscfs[0] = "127.0.0.1";
@@ -1352,6 +1353,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void getImsPcscfAddresses_InvalidPcscf() {
         String[] preDefinedPcscfs = new String[3];
         preDefinedPcscfs[0] = null;
@@ -1369,6 +1371,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void getImsPcscfAddresses_IsimNotLoadedError() {
         doReturn(true).when(mFeatureFlags).supportIsimRecord();
         doReturn(null).when(mPhone).getIsimRecords();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
index 48c9f9c..8a7c1f0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
@@ -32,7 +32,6 @@
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_CONFERENCE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_DATA_REGISTRATION_STATE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_DELETE_SMS_ON_SIM;
-import static com.android.internal.telephony.RILConstants.RIL_REQUEST_DEVICE_IDENTITY;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_DEVICE_IMEI;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_DTMF;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ENABLE_UICC_APPLICATIONS;
@@ -57,7 +56,6 @@
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_HANGUP;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND;
-import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IMS_REGISTRATION_STATE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IMS_SEND_SMS;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_LAST_CALL_FAIL_CAUSE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_NV_READ_ITEM;
@@ -98,8 +96,8 @@
 
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
@@ -356,8 +354,6 @@
             replaceInstance(RIL.class, "mHalVersion", mRILUnderTest, mHalVersionV14);
         } catch (Exception e) {
         }
-
-        doReturn(true).when(mFeatureFlags).combineRilDeathHandle();
     }
 
     @After
@@ -1014,15 +1010,6 @@
 
     @FlakyTest
     @Test
-    public void testGetDeviceIdentity() throws Exception {
-        mRILUnderTest.getDeviceIdentity(obtainMessage());
-        verify(mRadioProxy).getDeviceIdentity(mSerialNumberCaptor.capture());
-        verifyRILResponse(
-                mRILUnderTest, mSerialNumberCaptor.getValue(), RIL_REQUEST_DEVICE_IDENTITY);
-    }
-
-    @FlakyTest
-    @Test
     public void testExitEmergencyCallbackMode() throws Exception {
         mRILUnderTest.exitEmergencyCallbackMode(obtainMessage());
         verify(mRadioProxy).exitEmergencyCallbackMode(mSerialNumberCaptor.capture());
@@ -1158,15 +1145,6 @@
 
     @FlakyTest
     @Test
-    public void testGetImsRegistrationState() throws Exception {
-        mRILUnderTest.getImsRegistrationState(obtainMessage());
-        verify(mRadioProxy).getImsRegistrationState(mSerialNumberCaptor.capture());
-        verifyRILResponse(
-                mRILUnderTest, mSerialNumberCaptor.getValue(), RIL_REQUEST_IMS_REGISTRATION_STATE);
-    }
-
-    @FlakyTest
-    @Test
     public void testSendRetryImsGsmSms() throws Exception {
         String smscPdu = "smscPdu";
         String pdu = "pdu";
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTest.java
index 05107df..4c42e2e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTest.java
@@ -173,7 +173,6 @@
         rats.add(new Pair<Integer, Boolean>(ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA, false));
         rats.add(new Pair<Integer, Boolean>(ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN, false));
         rats.add(new Pair<Integer, Boolean>(ServiceState.RIL_RADIO_TECHNOLOGY_NR, false));
-        rats.add(new Pair<Integer, Boolean>(ServiceState.RIL_RADIO_TECHNOLOGY_NB_IOT_NTN, false));
 
         for (Pair<Integer, Boolean> rat : rats) {
             boolean isCdma = rat.second;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index 60dd9b7..316ccd7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -27,9 +27,8 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.nullable;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.atLeast;
@@ -49,7 +48,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
@@ -99,7 +97,6 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.R;
-import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
 import com.android.internal.telephony.data.AccessNetworksManager;
 import com.android.internal.telephony.data.DataNetworkController;
 import com.android.internal.telephony.emergency.EmergencyStateTracker;
@@ -122,7 +119,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
 import java.util.concurrent.Executor;
 import java.util.stream.Collectors;
@@ -308,9 +304,6 @@
         int dds = SubscriptionManager.getDefaultDataSubscriptionId();
         doReturn(dds).when(mPhone).getSubId();
 
-        doReturn(true).when(mPackageManager)
-                .hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA);
-
         // Set cellular radio on after boot by default
         mContextFixture.putBooleanResource(
                 R.bool.config_enable_cellular_on_boot_default, true);
@@ -1014,52 +1007,6 @@
 
     @Test
     @MediumTest
-    public void testUpdatePhoneType() {
-        String brandOverride = "spn from brand override";
-        doReturn(brandOverride).when(mUiccProfile).getOperatorBrandOverride();
-        doReturn(false).when(mPhone).isPhoneTypeGsm();
-        doReturn(true).when(mPhone).isPhoneTypeCdmaLte();
-        doReturn(CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM).when(mCdmaSSM).
-                getCdmaSubscriptionSource();
-
-        // switch to CDMA
-        logd("Calling updatePhoneType");
-        sst.updatePhoneType();
-
-        ArgumentCaptor<Integer> integerArgumentCaptor = ArgumentCaptor.forClass(Integer.class);
-        verify(mRuimRecords).registerForRecordsLoaded(eq(sst), integerArgumentCaptor.capture(),
-                nullable(Object.class));
-
-        // response for mRuimRecords.registerForRecordsLoaded()
-        Message msg = Message.obtain();
-        msg.what = integerArgumentCaptor.getValue();
-        msg.obj = new AsyncResult(null, null, null);
-        sst.sendMessage(msg);
-        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
-
-        // on RUIM_RECORDS_LOADED, sst is expected to call following apis
-        verify(mRuimRecords, times(1)).isProvisioned();
-
-        // switch back to GSM
-        doReturn(true).when(mPhone).isPhoneTypeGsm();
-        doReturn(false).when(mPhone).isPhoneTypeCdmaLte();
-
-        // response for mRuimRecords.registerForRecordsLoaded() can be sent after switching to GSM
-        msg = Message.obtain();
-        msg.what = integerArgumentCaptor.getValue();
-        msg.obj = new AsyncResult(null, null, null);
-        sst.sendMessage(msg);
-
-        // There's no easy way to check if the msg was handled or discarded. Wait to make sure sst
-        // did not crash, and then verify that the functions called records loaded are not called
-        // again
-        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
-
-        verify(mRuimRecords, times(1)).isProvisioned();
-    }
-
-    @Test
-    @MediumTest
     public void testRegAndUnregForVoiceRoamingOn() throws Exception {
         sst.registerForVoiceRoamingOn(mTestHandler, EVENT_DATA_ROAMING_ON, null);
 
@@ -1804,59 +1751,6 @@
     }
 
     @Test
-    @MediumTest
-    public void testRegisterForSubscriptionInfoReady() {
-        sst.registerForSubscriptionInfoReady(mTestHandler, EVENT_SUBSCRIPTION_INFO_READY, null);
-
-        // Call functions which would trigger posting of message on test handler
-        doReturn(false).when(mPhone).isPhoneTypeGsm();
-        sst.updatePhoneType();
-        mSimulatedCommands.notifyOtaProvisionStatusChanged();
-
-        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
-
-        // verify posted message
-        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
-        verify(mTestHandler).sendMessageAtTime(messageArgumentCaptor.capture(), anyLong());
-        assertEquals(EVENT_SUBSCRIPTION_INFO_READY, messageArgumentCaptor.getValue().what);
-    }
-
-    @Test
-    @MediumTest
-    public void testRoamingPhoneTypeSwitch() {
-        // Enable roaming
-        doReturn(true).when(mPhone).isPhoneTypeGsm();
-
-        mSimulatedCommands.setVoiceRegState(NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
-        mSimulatedCommands.setDataRegState(NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
-        mSimulatedCommands.notifyNetworkStateChanged();
-
-        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
-
-        sst.registerForDataRoamingOff(mTestHandler, EVENT_DATA_ROAMING_OFF, null, true);
-        sst.registerForVoiceRoamingOff(mTestHandler, EVENT_VOICE_ROAMING_OFF, null);
-        sst.registerForDataConnectionDetached(AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
-                mTestHandler, EVENT_DATA_CONNECTION_DETACHED, null);
-
-        // Call functions which would trigger posting of message on test handler
-        doReturn(false).when(mPhone).isPhoneTypeGsm();
-        sst.updatePhoneType();
-
-        // verify if registered handler has message posted to it
-        ArgumentCaptor<Message> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class);
-        verify(mTestHandler, atLeast(3)).sendMessageAtTime(
-                messageArgumentCaptor.capture(), anyLong());
-        HashSet<Integer> messageSet = new HashSet<>();
-        for (Message m : messageArgumentCaptor.getAllValues()) {
-            messageSet.add(m.what);
-        }
-
-        assertTrue(messageSet.contains(EVENT_DATA_ROAMING_OFF));
-        assertTrue(messageSet.contains(EVENT_VOICE_ROAMING_OFF));
-        assertTrue(messageSet.contains(EVENT_DATA_CONNECTION_DETACHED));
-    }
-
-    @Test
     @SmallTest
     public void testGetDesiredPowerState() {
         sst.setRadioPower(true);
@@ -1871,34 +1765,6 @@
     }
 
     @Test
-    @SmallTest
-    public void testIsConcurrentVoiceAndDataAllowed() {
-        doReturn(false).when(mPhone).isPhoneTypeGsm();
-        sst.mSS.setCssIndicator(1);
-        assertEquals(true, sst.isConcurrentVoiceAndDataAllowed());
-        sst.mSS.setCssIndicator(0);
-        assertEquals(false, sst.isConcurrentVoiceAndDataAllowed());
-
-        doReturn(true).when(mPhone).isPhoneTypeGsm();
-        NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
-                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
-                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_HSPA)
-                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
-                .build();
-        sst.mSS.addNetworkRegistrationInfo(nri);
-        assertEquals(true, sst.isConcurrentVoiceAndDataAllowed());
-        nri = new NetworkRegistrationInfo.Builder()
-                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
-                .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_GPRS)
-                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
-                .build();
-        sst.mSS.addNetworkRegistrationInfo(nri);
-        assertEquals(false, sst.isConcurrentVoiceAndDataAllowed());
-        sst.mSS.setCssIndicator(1);
-        assertEquals(true, sst.isConcurrentVoiceAndDataAllowed());
-    }
-
-    @Test
     @MediumTest
     public void testIsImsRegistered() throws Exception {
         mSimulatedCommands.setImsRegistrationState(new int[]{1, PhoneConstants.PHONE_TYPE_GSM});
@@ -2767,59 +2633,6 @@
 
     @Test
     @SmallTest
-    public void testGetMdn() {
-        doReturn(false).when(mPhone).isPhoneTypeGsm();
-        doReturn(false).when(mPhone).isPhoneTypeCdma();
-        doReturn(true).when(mPhone).isPhoneTypeCdmaLte();
-        doReturn(CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM).when(mCdmaSSM)
-                .getCdmaSubscriptionSource();
-        doReturn(PHONE_ID).when(mPhone).getPhoneId();
-
-        logd("Calling updatePhoneType");
-        // switch to CDMA
-        sst.updatePhoneType();
-
-        // trigger RUIM_RECORDS_LOADED
-        ArgumentCaptor<Integer> integerArgumentCaptor = ArgumentCaptor.forClass(Integer.class);
-        verify(mRuimRecords).registerForRecordsLoaded(eq(sst), integerArgumentCaptor.capture(),
-                nullable(Object.class));
-
-        // response for mRuimRecords.registerForRecordsLoaded()
-        Message msg = Message.obtain();
-        msg.what = integerArgumentCaptor.getValue();
-        msg.obj = new AsyncResult(null, null, null);
-        sst.sendMessage(msg);
-
-        // wait for RUIM_RECORDS_LOADED to be handled
-        waitForHandlerAction(sst, 5000);
-
-        // mdn should be null as nothing populated it
-        assertEquals(null, sst.getMdnNumber());
-
-        // if ruim is provisioned, mdn should still be null
-        doReturn(true).when(mRuimRecords).isProvisioned();
-        assertEquals(null, sst.getMdnNumber());
-
-        // if ruim is not provisioned, and mdn is non null, sst should still return the correct
-        // value
-        doReturn(false).when(mRuimRecords).isProvisioned();
-        String mockMdn = "mockMdn";
-        doReturn(mockMdn).when(mRuimRecords).getMdn();
-
-        // trigger RUIM_RECORDS_LOADED
-        Message msg1 = Message.obtain();
-        msg1.what = integerArgumentCaptor.getValue();
-        msg1.obj = new AsyncResult(null, null, null);
-        sst.sendMessage(msg1);
-
-        // wait for RUIM_RECORDS_LOADED to be handled
-        waitForHandlerAction(sst, 5000);
-
-        assertEquals(mockMdn, sst.getMdnNumber());
-    }
-
-    @Test
-    @SmallTest
     public void testOnLteVopsInfoChanged() {
         ServiceState ss = new ServiceState();
         ss.setVoiceRegState(ServiceState.STATE_IN_SERVICE);
@@ -2942,15 +2755,6 @@
                 sSnetworkRegistrationInfo.getDataSpecificInfo().getVopsSupportInfo());
     }
 
-
-    @Test
-    @SmallTest
-    public void testEriLoading() {
-        sst.obtainMessage(GsmCdmaPhone.EVENT_CARRIER_CONFIG_CHANGED, null).sendToTarget();
-        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
-        verify(mEriManager, times(1)).loadEriFile();
-    }
-
     @Test
     public void testLastKnownCellIdentity() throws Exception {
         CellIdentityLte cellIdentity =
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthControllerTest.java
index 7e4cb08..b59c4de 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthControllerTest.java
@@ -64,6 +64,7 @@
 
 import androidx.test.filters.MediumTest;
 
+import com.android.internal.telephony.flags.Flags;
 import com.android.internal.util.ArrayUtils;
 
 import org.junit.After;
@@ -470,19 +471,21 @@
         assertEquals(mSsc.getSignalStrength(), ss);
         assertEquals(mSsc.getSignalStrength().isGsm(), true);
 
-        // Send in CDMA-only Signal Strength Info and expect isGsm == false
-        ss = new SignalStrength(
-                new CellSignalStrengthCdma(-90, -12,
-                        SignalStrength.INVALID, SignalStrength.INVALID, SignalStrength.INVALID),
-                new CellSignalStrengthGsm(),
-                new CellSignalStrengthWcdma(),
-                new CellSignalStrengthTdscdma(),
-                new CellSignalStrengthLte(),
-                new CellSignalStrengthNr());
+        if (!Flags.cleanupCdma()) {
+            // Send in CDMA-only Signal Strength Info and expect isGsm == false
+            ss = new SignalStrength(
+                    new CellSignalStrengthCdma(-90, -12,
+                            SignalStrength.INVALID, SignalStrength.INVALID, SignalStrength.INVALID),
+                    new CellSignalStrengthGsm(),
+                    new CellSignalStrengthWcdma(),
+                    new CellSignalStrengthTdscdma(),
+                    new CellSignalStrengthLte(),
+                    new CellSignalStrengthNr());
 
-        sendSignalStrength(ss);
-        assertEquals(mSsc.getSignalStrength(), ss);
-        assertEquals(mSsc.getSignalStrength().isGsm(), false);
+            sendSignalStrength(ss);
+            assertEquals(mSsc.getSignalStrength(), ss);
+            assertEquals(mSsc.getSignalStrength().isGsm(), false);
+        }
     }
 
     @Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthTest.java b/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthTest.java
index 8df4052..355704f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SignalStrengthTest.java
@@ -37,8 +37,6 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.internal.telephony.flags.Flags;
-
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -111,7 +109,6 @@
 
     @Before
     public void setUp() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
     }
 
     @Test
@@ -137,7 +134,7 @@
         ArrayList<Byte> NrCqiReport = new ArrayList<>(
                 Arrays.asList((byte) 3, (byte) 2 , (byte) 1));
         SignalStrength s = new SignalStrength(
-                new CellSignalStrengthCdma(-93, -132, -89, -125, 5),
+                new CellSignalStrengthCdma(),
                 new CellSignalStrengthGsm(-79, 2, 5),
                 new CellSignalStrengthWcdma(-94, 4, -102, -5),
                 new CellSignalStrengthTdscdma(-95, 2, -103),
@@ -175,7 +172,6 @@
     public void testGetCellSignalStrengths() throws Exception {
         CellSignalStrengthLte lte = new CellSignalStrengthLte(-85, -91, -6, -10, 1, 12, 1);
         CellSignalStrengthGsm gsm = new CellSignalStrengthGsm(-79, 2, 5);
-        CellSignalStrengthCdma cdma = new CellSignalStrengthCdma(-93, -132, -89, -125, 5);
         CellSignalStrengthWcdma wcdma = new CellSignalStrengthWcdma(-94, 4, -102, -5);
         CellSignalStrengthTdscdma tdscdma = new CellSignalStrengthTdscdma(-95, 2, -103);
 
@@ -194,16 +190,16 @@
 
         // Test that a multiple objects are properly stored and returned by getCellSignalStrengths()
         s = new SignalStrength(
-                cdma,
+                new CellSignalStrengthCdma(),
                 new CellSignalStrengthGsm(),
-                new CellSignalStrengthWcdma(),
+                wcdma,
                 new CellSignalStrengthTdscdma(),
                 lte,
                 new CellSignalStrengthNr());
 
         css = s.getCellSignalStrengths();
         assertEquals(2, css.size());
-        assertTrue(css.contains(cdma));
+        assertTrue(css.contains(wcdma));
         assertTrue(css.contains(lte));
     }
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimActivationTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SimActivationTrackerTest.java
index 23d992a..eb312f1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimActivationTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimActivationTrackerTest.java
@@ -22,7 +22,7 @@
 import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
 
 import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/Sms7BitEncodingTranslatorTest.java b/tests/telephonytests/src/com/android/internal/telephony/Sms7BitEncodingTranslatorTest.java
index 3295640..263e784 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/Sms7BitEncodingTranslatorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/Sms7BitEncodingTranslatorTest.java
@@ -18,7 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
-import static org.mockito.Matchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java
index 710f1ec..0f4f3d5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsControllerTest.java
@@ -219,6 +219,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void sendsendTextForSubscriberTest() {
         int subId = 1;
         doReturn(true).when(mSubscriptionManager)
@@ -232,6 +233,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void sendTextForSubscriberTest_InteractAcrossUsers() {
         int subId = 1;
         // Sending text to subscriber should not fail when the caller has the
@@ -313,7 +315,6 @@
         replaceInstance(SmsController.class, "mVendorApiLevel", mSmsControllerUT, vendorApiLevel);
 
         // Feature enabled, device does not have required telephony feature.
-        doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
         doReturn(false).when(mPackageManager).hasSystemFeature(
                 PackageManager.FEATURE_TELEPHONY_MESSAGING);
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
index 15e6ee2..37362d5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
@@ -16,8 +16,8 @@
 
 package com.android.internal.telephony;
 
-import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE;
 import static com.android.internal.telephony.SmsDispatchersController.PendingRequest;
+import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -26,13 +26,12 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.isNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -241,11 +240,6 @@
         switchImsSmsFormat(PhoneConstants.PHONE_TYPE_GSM);
         assertEquals(SmsConstants.FORMAT_3GPP, mSmsDispatchersController.getImsSmsFormat());
         assertTrue(mSmsDispatchersController.isIms());
-
-        //Mock ImsNetWorkStateChange with Cdma Phone type
-        switchImsSmsFormat(PhoneConstants.PHONE_TYPE_CDMA);
-        assertEquals(SmsConstants.FORMAT_3GPP2, mSmsDispatchersController.getImsSmsFormat());
-        assertTrue(mSmsDispatchersController.isIms());
     }
 
     @Test @SmallTest
@@ -291,30 +285,6 @@
                 anyInt(), anyInt(), any(Message.class));
     }
 
-    @Test @SmallTest @FlakyTest /* flakes 0.73% of the time on gce, 0.57% on marlin */
-    public void testSendImsCdmaTest() throws Exception {
-        switchImsSmsFormat(PhoneConstants.PHONE_TYPE_CDMA);
-        mSmsDispatchersController.sendText("111"/* desAddr*/, "222" /*scAddr*/, TAG,
-                null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
-        verify(mSimulatedCommandsVerifier).sendImsCdmaSms((byte[])any(), eq(0), eq(0),
-                any(Message.class));
-    }
-
-    @Test @SmallTest @FlakyTest /* flakes 0.71% of the time on marlin, 0.61% on gce */
-    public void testSendRetrySmsCdmaTest() throws Exception {
-        // newFormat will be based on voice technology
-        ArgumentCaptor<byte[]> captor = ArgumentCaptor.forClass(byte[].class);
-        switchImsSmsFormat(PhoneConstants.PHONE_TYPE_CDMA);
-        replaceInstance(SMSDispatcher.SmsTracker.class, "mFormat", mTracker,
-                SmsConstants.FORMAT_3GPP2);
-        doReturn(PhoneConstants.PHONE_TYPE_CDMA).when(mPhone).getPhoneType();
-        mSmsDispatchersController.sendRetrySms(mTracker);
-        verify(mSimulatedCommandsVerifier).sendImsCdmaSms(captor.capture(), eq(0), eq(0),
-                any(Message.class));
-        assertEquals(1, captor.getAllValues().size());
-        assertNull(captor.getAllValues().get(0));
-    }
-
     @Test @SmallTest @FlakyTest /* flakes 0.85% of the time on gce, 0.43% on marlin */
     public void testSendRetrySmsGsmTest() throws Exception {
         // newFormat will be based on voice technology will be GSM if phone type is not CDMA
@@ -387,13 +357,6 @@
 
     @Test
     @SmallTest
-    public void testSendDataWhenDomainCsAndCdma() throws Exception {
-        when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_CDMA);
-        sendDataWithDomainSelection(NetworkRegistrationInfo.DOMAIN_PS, true);
-    }
-
-    @Test
-    @SmallTest
     public void testSendDataWhenDomainCsAndGsm() throws Exception {
         when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);
         sendDataWithDomainSelection(NetworkRegistrationInfo.DOMAIN_PS, false);
@@ -407,13 +370,6 @@
 
     @Test
     @SmallTest
-    public void testSendTextWhenDomainCsAndCdma() throws Exception {
-        when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_CDMA);
-        sendTextWithDomainSelection(NetworkRegistrationInfo.DOMAIN_PS, true);
-    }
-
-    @Test
-    @SmallTest
     public void testSendTextWhenDomainCsAndGsm() throws Exception {
         when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);
         sendTextWithDomainSelection(NetworkRegistrationInfo.DOMAIN_PS, false);
@@ -427,13 +383,6 @@
 
     @Test
     @SmallTest
-    public void testSendMultipartTextWhenDomainCsAndCdma() throws Exception {
-        when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_CDMA);
-        sendMultipartTextWithDomainSelection(NetworkRegistrationInfo.DOMAIN_PS, true);
-    }
-
-    @Test
-    @SmallTest
     public void testSendMultipartTextWhenDomainCsAndGsm() throws Exception {
         when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);
         sendMultipartTextWithDomainSelection(NetworkRegistrationInfo.DOMAIN_PS, false);
@@ -448,13 +397,6 @@
 
     @Test
     @SmallTest
-    public void testSendRetrySmsWhenDomainCsAndCdma() throws Exception {
-        sendRetrySmsWithDomainSelection(NetworkRegistrationInfo.DOMAIN_CS,
-                PhoneConstants.PHONE_TYPE_CDMA, SmsConstants.FORMAT_3GPP2);
-    }
-
-    @Test
-    @SmallTest
     public void testSendRetrySmsWhenDomainCsAndGsm() throws Exception {
         sendRetrySmsWithDomainSelection(NetworkRegistrationInfo.DOMAIN_CS,
                 PhoneConstants.PHONE_TYPE_GSM, SmsConstants.FORMAT_3GPP);
@@ -462,12 +404,6 @@
 
     @Test
     @SmallTest
-    public void testSendRetrySmsWhenImsAlreadyUsedAndCdma() throws Exception {
-        sendRetrySmsWhenImsAlreadyUsed(PhoneConstants.PHONE_TYPE_CDMA, SmsConstants.FORMAT_3GPP2);
-    }
-
-    @Test
-    @SmallTest
     public void testSendRetrySmsWhenImsAlreadyUsedAndGsm() throws Exception {
         sendRetrySmsWhenImsAlreadyUsed(PhoneConstants.PHONE_TYPE_GSM, SmsConstants.FORMAT_3GPP);
     }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsNumberUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsNumberUtilsTest.java
index 90cc0fe..ae42f9c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsNumberUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsNumberUtilsTest.java
@@ -23,7 +23,6 @@
 import android.database.MatrixCursor;
 import android.net.Uri;
 import android.telephony.CarrierConfigManager;
-import android.telephony.TelephonyManager;
 import android.test.mock.MockContentProvider;
 import android.test.mock.MockContentResolver;
 
@@ -144,15 +143,6 @@
 
     @Test
     @SmallTest
-    public void testNaPcCountryCodeAreaLocalNumberConversion() {
-        // NP_NANP_NBPCD_CC_AREA_LOCAL tests
-        doReturn(TelephonyManager.PHONE_TYPE_CDMA).when(mTelephonyManager).getPhoneType();
-        assertEquals("18583420022", SmsNumberUtils.filterDestAddr(mContext, mPhone.getSubId(),
-                "+1-858-342-0022"));
-    }
-
-    @Test
-    @SmallTest
     public void testPcCountryCodeAreaLocalNumberConversion() {
         // NP_NBPCD_CC_AREA_LOCAL tests
         assertEquals("01188671234567", SmsNumberUtils.filterDestAddr(mContext, mPhone.getSubId(),
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
index 99ece85..916d51d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
@@ -48,7 +48,6 @@
 
     @Before
     public void setUp() throws Exception {
-        mSetFlagsRule.enableFlags(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG);
         mSubscriptionInfoUT = new SubscriptionInfo.Builder()
                 .setId(1)
                 .setIccId("890126042XXXXXXXXXXX")
@@ -88,9 +87,7 @@
         assertThat(mSubscriptionInfoUT.getSubscriptionId()).isEqualTo(1);
         assertThat(mSubscriptionInfoUT.getSimSlotIndex()).isEqualTo(0);
         assertThat(mSubscriptionInfoUT.getIccId()).isEqualTo("890126042XXXXXXXXXXX");
-        if (Flags.oemEnabledSatelliteFlag()) {
-            assertThat(mSubscriptionInfoUT.isOnlyNonTerrestrialNetwork()).isTrue();
-        }
+        assertThat(mSubscriptionInfoUT.isOnlyNonTerrestrialNetwork()).isTrue();
         assertThat(mSubscriptionInfoUT.getServiceCapabilities()).isEqualTo(
                 Set.of(SubscriptionManager.SERVICE_CAPABILITY_DATA));
         if (Flags.supportPsimToEsimConversion()) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java
index 5db1206..31c995b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyCountryDetectorTest.java
@@ -119,7 +119,6 @@
 
         when(mLocationManager.getProviders(true)).thenReturn(Arrays.asList("TEST_PROVIDER"));
 
-        when(mMockFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         mCountryDetectorUT = new TestTelephonyCountryDetector(
                 mLooper, mContext, mLocationManager, mConnectivityManager, mMockFeatureFlags);
         verify(mConnectivityManager).registerNetworkCallback(
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index e5aa541..4e00a71 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
@@ -224,7 +224,7 @@
             TelephonyCallback.DataActivityListener,
             TelephonyCallback.SimultaneousCellularCallingSupportListener,
             TelephonyCallback.EmergencyCallbackModeListener,
-            TelephonyCallback.CarrierRoamingNtnModeListener,
+            TelephonyCallback.CarrierRoamingNtnListener,
             TelephonyCallback.SecurityAlgorithmsListener,
             TelephonyCallback.CellularIdentifierDisclosedListener,
             TelephonyCallback.CallAttributesListener {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index 0db881c..26ab6da 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -21,13 +21,14 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.nullable;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.lenient;
 import static org.mockito.Mockito.spy;
 
 import android.app.ActivityManager;
@@ -143,6 +144,7 @@
 import com.android.internal.telephony.uicc.UiccPort;
 import com.android.internal.telephony.uicc.UiccProfile;
 import com.android.internal.telephony.uicc.UiccSlot;
+import com.android.internal.telephony.util.WorkerThread;
 import com.android.server.pm.permission.LegacyPermissionManagerService;
 
 import org.mockito.Mockito;
@@ -173,23 +175,6 @@
             new ArrayList<String>(), EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
             EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
 
-    private static final Field MESSAGE_QUEUE_FIELD;
-    private static final Field MESSAGE_WHEN_FIELD;
-    private static final Field MESSAGE_NEXT_FIELD;
-
-    static {
-        try {
-            MESSAGE_QUEUE_FIELD = MessageQueue.class.getDeclaredField("mMessages");
-            MESSAGE_QUEUE_FIELD.setAccessible(true);
-            MESSAGE_WHEN_FIELD = Message.class.getDeclaredField("when");
-            MESSAGE_WHEN_FIELD.setAccessible(true);
-            MESSAGE_NEXT_FIELD = Message.class.getDeclaredField("next");
-            MESSAGE_NEXT_FIELD.setAccessible(true);
-        } catch (NoSuchFieldException e) {
-            throw new RuntimeException("Failed to initialize TelephonyTest", e);
-        }
-    }
-
     // Mocked classes
     protected FeatureFlags mFeatureFlags;
     protected GsmCdmaPhone mPhone;
@@ -579,11 +564,13 @@
         mDomainSelectionResolver = Mockito.mock(DomainSelectionResolver.class);
         mNullCipherNotifier = Mockito.mock(NullCipherNotifier.class);
 
-        doReturn(true).when(mFeatureFlags).minimalTelephonyCdmCheck();
-        doReturn(true).when(mFeatureFlags).supportNetworkProvider();
-        doReturn(true).when(mFeatureFlags).hsumBroadcast();
-        doReturn(true).when(mFeatureFlags).hsumPackageManager();
+        lenient().doReturn(true).when(mFeatureFlags).hsumBroadcast();
+        lenient().doReturn(true).when(mFeatureFlags).hsumPackageManager();
+        lenient().doReturn(true).when(mFeatureFlags).dataServiceCheck();
+        lenient().doReturn(true).when(mFeatureFlags).phoneTypeCleanup();
+        lenient().doReturn(true).when(mFeatureFlags).cleanupCdma();
 
+        WorkerThread.reset();
         TelephonyManager.disableServiceHandleCaching();
         PropertyInvalidatedCache.disableForTestMode();
         // For testing do not allow Log.WTF as it can cause test process to crash
@@ -609,16 +596,16 @@
         Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
 
         mServiceManagerMockedServices.put("isub", mSubscriptionManagerService);
-        doReturn(mSubscriptionManagerService).when(mSubscriptionManagerService)
+        lenient().doReturn(mSubscriptionManagerService).when(mSubscriptionManagerService)
                 .queryLocalInterface(anyString());
 
         mPhone.mCi = mSimulatedCommands;
         mCT.mCi = mSimulatedCommands;
-        doReturn(mUiccCard).when(mPhone).getUiccCard();
-        doReturn(mUiccCard).when(mUiccSlot).getUiccCard();
-        doReturn(mUiccCard).when(mUiccController).getUiccCardForPhone(anyInt());
-        doReturn(mUiccPort).when(mPhone).getUiccPort();
-        doReturn(mUiccProfile).when(mUiccPort).getUiccProfile();
+        lenient().doReturn(mUiccCard).when(mPhone).getUiccCard();
+        lenient().doReturn(mUiccCard).when(mUiccSlot).getUiccCard();
+        lenient().doReturn(mUiccCard).when(mUiccController).getUiccCardForPhone(anyInt());
+        lenient().doReturn(mUiccPort).when(mPhone).getUiccPort();
+        lenient().doReturn(mUiccProfile).when(mUiccPort).getUiccProfile();
 
         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
         mTelecomManager = mContext.getSystemService(TelecomManager.class);
@@ -643,124 +630,130 @@
         mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
 
         //mTelephonyComponentFactory
-        doReturn(mTelephonyComponentFactory).when(mTelephonyComponentFactory).inject(anyString());
-        doReturn(mSST).when(mTelephonyComponentFactory)
+        lenient().doReturn(mTelephonyComponentFactory).when(mTelephonyComponentFactory)
+                .inject(anyString());
+        lenient().doReturn(mSST).when(mTelephonyComponentFactory)
                 .makeServiceStateTracker(nullable(GsmCdmaPhone.class),
                         nullable(CommandsInterface.class), nullable(FeatureFlags.class));
-        doReturn(mEmergencyNumberTracker).when(mTelephonyComponentFactory)
+        lenient().doReturn(mEmergencyNumberTracker).when(mTelephonyComponentFactory)
                 .makeEmergencyNumberTracker(nullable(Phone.class),
                         nullable(CommandsInterface.class), any(FeatureFlags.class));
-        doReturn(getTestEmergencyNumber()).when(mEmergencyNumberTracker)
+        lenient().doReturn(getTestEmergencyNumber()).when(mEmergencyNumberTracker)
                 .getEmergencyNumber(any());
-        doReturn(mUiccProfile).when(mTelephonyComponentFactory)
+        lenient().doReturn(mUiccProfile).when(mTelephonyComponentFactory)
                 .makeUiccProfile(nullable(Context.class), nullable(CommandsInterface.class),
                         nullable(IccCardStatus.class), anyInt(), nullable(UiccCard.class),
                         nullable(Object.class), any(FeatureFlags.class));
-        doReturn(mCT).when(mTelephonyComponentFactory)
+        lenient().doReturn(mCT).when(mTelephonyComponentFactory)
                 .makeGsmCdmaCallTracker(nullable(GsmCdmaPhone.class), any(FeatureFlags.class));
-        doReturn(mIccPhoneBookIntManager).when(mTelephonyComponentFactory)
+        lenient().doReturn(mIccPhoneBookIntManager).when(mTelephonyComponentFactory)
                 .makeIccPhoneBookInterfaceManager(nullable(Phone.class));
-        doReturn(mDisplayInfoController).when(mTelephonyComponentFactory)
+        lenient().doReturn(mDisplayInfoController).when(mTelephonyComponentFactory)
                 .makeDisplayInfoController(nullable(Phone.class), any(FeatureFlags.class));
-        doReturn(mWspTypeDecoder).when(mTelephonyComponentFactory)
+        lenient().doReturn(mWspTypeDecoder).when(mTelephonyComponentFactory)
                 .makeWspTypeDecoder(nullable(byte[].class));
-        doReturn(mImsCT).when(mTelephonyComponentFactory)
+        lenient().doReturn(mImsCT).when(mTelephonyComponentFactory)
                 .makeImsPhoneCallTracker(nullable(ImsPhone.class), any(FeatureFlags.class));
-        doReturn(mCdmaSSM).when(mTelephonyComponentFactory)
+        lenient().doReturn(mCdmaSSM).when(mTelephonyComponentFactory)
                 .getCdmaSubscriptionSourceManagerInstance(nullable(Context.class),
                         nullable(CommandsInterface.class), nullable(Handler.class),
                         anyInt(), nullable(Object.class));
-        doReturn(mImsExternalCallTracker).when(mTelephonyComponentFactory)
+        lenient().doReturn(mImsExternalCallTracker).when(mTelephonyComponentFactory)
                 .makeImsExternalCallTracker(nullable(ImsPhone.class));
-        doReturn(mImsNrSaModeHandler).when(mTelephonyComponentFactory)
+        lenient().doReturn(mImsNrSaModeHandler).when(mTelephonyComponentFactory)
                 .makeImsNrSaModeHandler(nullable(ImsPhone.class));
-        doReturn(mAppSmsManager).when(mTelephonyComponentFactory)
+        lenient().doReturn(mAppSmsManager).when(mTelephonyComponentFactory)
                 .makeAppSmsManager(nullable(Context.class));
-        doReturn(mCarrierSignalAgent).when(mTelephonyComponentFactory)
+        lenient().doReturn(mCarrierSignalAgent).when(mTelephonyComponentFactory)
                 .makeCarrierSignalAgent(nullable(Phone.class));
-        doReturn(mCarrierActionAgent).when(mTelephonyComponentFactory)
+        lenient().doReturn(mCarrierActionAgent).when(mTelephonyComponentFactory)
                 .makeCarrierActionAgent(nullable(Phone.class));
-        doReturn(mDeviceStateMonitor).when(mTelephonyComponentFactory)
+        lenient().doReturn(mDeviceStateMonitor).when(mTelephonyComponentFactory)
                 .makeDeviceStateMonitor(nullable(Phone.class), any(FeatureFlags.class));
-        doReturn(mAccessNetworksManager).when(mTelephonyComponentFactory)
+        lenient().doReturn(mAccessNetworksManager).when(mTelephonyComponentFactory)
                 .makeAccessNetworksManager(nullable(Phone.class), any(Looper.class));
-        doReturn(mNitzStateMachine).when(mTelephonyComponentFactory)
+        lenient().doReturn(mNitzStateMachine).when(mTelephonyComponentFactory)
                 .makeNitzStateMachine(nullable(GsmCdmaPhone.class));
-        doReturn(mLocaleTracker).when(mTelephonyComponentFactory)
+        lenient().doReturn(mLocaleTracker).when(mTelephonyComponentFactory)
                 .makeLocaleTracker(nullable(Phone.class), nullable(NitzStateMachine.class),
                         nullable(Looper.class), any(FeatureFlags.class));
-        doReturn(mEriManager).when(mTelephonyComponentFactory)
+        lenient().doReturn(mEriManager).when(mTelephonyComponentFactory)
                 .makeEriManager(nullable(Phone.class), anyInt());
-        doReturn(mLinkBandwidthEstimator).when(mTelephonyComponentFactory)
+        lenient().doReturn(mLinkBandwidthEstimator).when(mTelephonyComponentFactory)
                 .makeLinkBandwidthEstimator(nullable(Phone.class), any(Looper.class));
-        doReturn(mDataProfileManager).when(mTelephonyComponentFactory)
+        lenient().doReturn(mDataProfileManager).when(mTelephonyComponentFactory)
                 .makeDataProfileManager(any(Phone.class), any(DataNetworkController.class),
                         any(DataServiceManager.class), any(Looper.class),
                         any(FeatureFlags.class),
                         any(DataProfileManager.DataProfileManagerCallback.class));
-        doReturn(mSafetySource).when(mTelephonyComponentFactory)
+        lenient().doReturn(mSafetySource).when(mTelephonyComponentFactory)
                 .makeCellularNetworkSecuritySafetySource(any(Context.class));
-        doReturn(mIdentifierDisclosureNotifier)
+        lenient().doReturn(mIdentifierDisclosureNotifier)
                 .when(mTelephonyComponentFactory)
-                .makeIdentifierDisclosureNotifier(any(CellularNetworkSecuritySafetySource.class));
-        doReturn(mNullCipherNotifier)
+                .makeIdentifierDisclosureNotifier(
+                        nullable(CellularNetworkSecuritySafetySource.class));
+        lenient().doReturn(mNullCipherNotifier)
                 .when(mTelephonyComponentFactory)
-                .makeNullCipherNotifier(any(CellularNetworkSecuritySafetySource.class));
+                .makeNullCipherNotifier(nullable(CellularNetworkSecuritySafetySource.class));
 
         //mPhone
-        doReturn(mContext).when(mPhone).getContext();
-        doReturn(mContext).when(mImsPhone).getContext();
-        doReturn(true).when(mPhone).getUnitTestMode();
-        doReturn(mUiccProfile).when(mPhone).getIccCard();
-        doReturn(mServiceState).when(mPhone).getServiceState();
-        doReturn(mServiceState).when(mImsPhone).getServiceState();
-        doReturn(mPhone).when(mImsPhone).getDefaultPhone();
-        doReturn(true).when(mPhone).isPhoneTypeGsm();
-        doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mPhone).getPhoneType();
-        doReturn(mCT).when(mPhone).getCallTracker();
-        doReturn(mSST).when(mPhone).getServiceStateTracker();
-        doReturn(mDeviceStateMonitor).when(mPhone).getDeviceStateMonitor();
-        doReturn(mDisplayInfoController).when(mPhone).getDisplayInfoController();
-        doReturn(mSignalStrengthController).when(mPhone).getSignalStrengthController();
-        doReturn(mEmergencyNumberTracker).when(mPhone).getEmergencyNumberTracker();
-        doReturn(mCarrierSignalAgent).when(mPhone).getCarrierSignalAgent();
-        doReturn(mCarrierActionAgent).when(mPhone).getCarrierActionAgent();
-        doReturn(mAppSmsManager).when(mPhone).getAppSmsManager();
-        doReturn(mIccSmsInterfaceManager).when(mPhone).getIccSmsInterfaceManager();
-        doReturn(mAccessNetworksManager).when(mPhone).getAccessNetworksManager();
-        doReturn(mDataSettingsManager).when(mDataNetworkController).getDataSettingsManager();
-        doReturn(mDataNetworkController).when(mPhone).getDataNetworkController();
-        doReturn(mDataSettingsManager).when(mPhone).getDataSettingsManager();
-        doReturn(mCarrierPrivilegesTracker).when(mPhone).getCarrierPrivilegesTracker();
-        doReturn(mSignalStrength).when(mPhone).getSignalStrength();
-        doReturn(mVoiceCallSessionStats).when(mPhone).getVoiceCallSessionStats();
-        doReturn(mVoiceCallSessionStats).when(mImsPhone).getVoiceCallSessionStats();
-        doReturn(mSmsStats).when(mPhone).getSmsStats();
-        doReturn(mTelephonyAnalytics).when(mPhone).getTelephonyAnalytics();
-        doReturn(mImsStats).when(mImsPhone).getImsStats();
+        lenient().doReturn(mContext).when(mPhone).getContext();
+        lenient().doReturn(mContext).when(mPhone2).getContext();
+        lenient().doReturn(mContext).when(mImsPhone).getContext();
+        lenient().doReturn(true).when(mPhone).getUnitTestMode();
+        lenient().doReturn(mUiccProfile).when(mPhone).getIccCard();
+        lenient().doReturn(mServiceState).when(mPhone).getServiceState();
+        lenient().doReturn(mServiceState).when(mImsPhone).getServiceState();
+        lenient().doReturn(mPhone).when(mImsPhone).getDefaultPhone();
+        lenient().doReturn(true).when(mPhone).isPhoneTypeGsm();
+        lenient().doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mPhone).getPhoneType();
+        lenient().doReturn(mCT).when(mPhone).getCallTracker();
+        lenient().doReturn(mSST).when(mPhone).getServiceStateTracker();
+        lenient().doReturn(mDeviceStateMonitor).when(mPhone).getDeviceStateMonitor();
+        lenient().doReturn(mDisplayInfoController).when(mPhone).getDisplayInfoController();
+        lenient().doReturn(mSignalStrengthController).when(mPhone).getSignalStrengthController();
+        lenient().doReturn(mEmergencyNumberTracker).when(mPhone).getEmergencyNumberTracker();
+        lenient().doReturn(mCarrierSignalAgent).when(mPhone).getCarrierSignalAgent();
+        lenient().doReturn(mCarrierActionAgent).when(mPhone).getCarrierActionAgent();
+        lenient().doReturn(mAppSmsManager).when(mPhone).getAppSmsManager();
+        lenient().doReturn(mIccSmsInterfaceManager).when(mPhone).getIccSmsInterfaceManager();
+        lenient().doReturn(mAccessNetworksManager).when(mPhone).getAccessNetworksManager();
+        lenient().doReturn(mDataSettingsManager).when(mDataNetworkController)
+                .getDataSettingsManager();
+        lenient().doReturn(mDataNetworkController).when(mPhone).getDataNetworkController();
+        lenient().doReturn(mDataSettingsManager).when(mPhone).getDataSettingsManager();
+        lenient().doReturn(mCarrierPrivilegesTracker).when(mPhone).getCarrierPrivilegesTracker();
+        lenient().doReturn(mSignalStrength).when(mPhone).getSignalStrength();
+        lenient().doReturn(mVoiceCallSessionStats).when(mPhone).getVoiceCallSessionStats();
+        lenient().doReturn(mVoiceCallSessionStats).when(mImsPhone).getVoiceCallSessionStats();
+        lenient().doReturn(mSmsStats).when(mPhone).getSmsStats();
+        lenient().doReturn(mTelephonyAnalytics).when(mPhone).getTelephonyAnalytics();
+        lenient().doReturn(mImsStats).when(mImsPhone).getImsStats();
         mIccSmsInterfaceManager.mDispatchersController = mSmsDispatchersController;
-        doReturn(mLinkBandwidthEstimator).when(mPhone).getLinkBandwidthEstimator();
-        doReturn(mCellIdentity).when(mPhone).getCurrentCellIdentity();
-        doReturn(mCellLocation).when(mCellIdentity).asCellLocation();
-        doReturn(mDataConfigManager).when(mDataNetworkController).getDataConfigManager();
-        doReturn(mDataProfileManager).when(mDataNetworkController).getDataProfileManager();
-        doReturn(mDataRetryManager).when(mDataNetworkController).getDataRetryManager();
-        doReturn(mCarrierPrivilegesTracker).when(mPhone).getCarrierPrivilegesTracker();
-        doReturn(0).when(mPhone).getPhoneId();
-        doReturn(true).when(mPhone).hasCalling();
-        doReturn(true).when(mPhone2).hasCalling();
+        lenient().doReturn(mLinkBandwidthEstimator).when(mPhone).getLinkBandwidthEstimator();
+        lenient().doReturn(mCellIdentity).when(mPhone).getCurrentCellIdentity();
+        lenient().doReturn(mCellLocation).when(mCellIdentity).asCellLocation();
+        lenient().doReturn(mDataConfigManager).when(mDataNetworkController).getDataConfigManager();
+        lenient().doReturn(mDataProfileManager).when(mDataNetworkController)
+                .getDataProfileManager();
+        lenient().doReturn(mDataRetryManager).when(mDataNetworkController).getDataRetryManager();
+        lenient().doReturn(mCarrierPrivilegesTracker).when(mPhone).getCarrierPrivilegesTracker();
+        lenient().doReturn(0).when(mPhone).getPhoneId();
+        lenient().doReturn(1).when(mPhone2).getPhoneId();
+        lenient().doReturn(true).when(mPhone).hasCalling();
+        lenient().doReturn(true).when(mPhone2).hasCalling();
 
         //mUiccController
-        doReturn(mUiccCardApplication3gpp).when(mUiccController).getUiccCardApplication(anyInt(),
-                eq(UiccController.APP_FAM_3GPP));
-        doReturn(mUiccCardApplication3gpp2).when(mUiccController).getUiccCardApplication(anyInt(),
-                eq(UiccController.APP_FAM_3GPP2));
-        doReturn(mUiccCardApplicationIms).when(mUiccController).getUiccCardApplication(anyInt(),
-                eq(UiccController.APP_FAM_IMS));
-        doReturn(mUiccCard).when(mUiccController).getUiccCard(anyInt());
-        doReturn(mUiccPort).when(mUiccController).getUiccPort(anyInt());
+        lenient().doReturn(mUiccCardApplication3gpp).when(mUiccController).getUiccCardApplication(
+                anyInt(), eq(UiccController.APP_FAM_3GPP));
+        lenient().doReturn(mUiccCardApplication3gpp2).when(mUiccController).getUiccCardApplication(
+                anyInt(), eq(UiccController.APP_FAM_3GPP2));
+        lenient().doReturn(mUiccCardApplicationIms).when(mUiccController).getUiccCardApplication(
+                anyInt(), eq(UiccController.APP_FAM_IMS));
+        lenient().doReturn(mUiccCard).when(mUiccController).getUiccCard(anyInt());
+        lenient().doReturn(mUiccPort).when(mUiccController).getUiccPort(anyInt());
 
-        doAnswer(new Answer<IccRecords>() {
+        lenient().doAnswer(new Answer<IccRecords>() {
             public IccRecords answer(InvocationOnMock invocation) {
                 switch ((Integer) invocation.getArguments()[1]) {
                     case UiccController.APP_FAM_3GPP:
@@ -775,53 +768,54 @@
                 }
             }
         }).when(mUiccController).getIccRecords(anyInt(), anyInt());
-        doReturn(new UiccSlot[] {mUiccSlot}).when(mUiccController).getUiccSlots();
-        doReturn(mUiccSlot).when(mUiccController).getUiccSlotForPhone(anyInt());
-        doReturn(mPinStorage).when(mUiccController).getPinStorage();
+        lenient().doReturn(new UiccSlot[] {mUiccSlot}).when(mUiccController).getUiccSlots();
+        lenient().doReturn(mUiccSlot).when(mUiccController).getUiccSlotForPhone(anyInt());
+        lenient().doReturn(mPinStorage).when(mUiccController).getPinStorage();
 
         //UiccCardApplication
-        doReturn(mSimRecords).when(mUiccCardApplication3gpp).getIccRecords();
-        doReturn(mRuimRecords).when(mUiccCardApplication3gpp2).getIccRecords();
-        doReturn(mIsimUiccRecords).when(mUiccCardApplicationIms).getIccRecords();
+        lenient().doReturn(mSimRecords).when(mUiccCardApplication3gpp).getIccRecords();
+        lenient().doReturn(mRuimRecords).when(mUiccCardApplication3gpp2).getIccRecords();
+        lenient().doReturn(mIsimUiccRecords).when(mUiccCardApplicationIms).getIccRecords();
 
         //mUiccProfile
-        doReturn(mSimRecords).when(mUiccProfile).getIccRecords();
-        doAnswer(new Answer<IccRecords>() {
+        lenient().doReturn(mSimRecords).when(mUiccProfile).getIccRecords();
+        lenient().doAnswer(new Answer<IccRecords>() {
             public IccRecords answer(InvocationOnMock invocation) {
                 return mSimRecords;
             }
         }).when(mUiccProfile).getIccRecords();
 
         //mUiccProfile
-        doReturn(mUiccCardApplication3gpp).when(mUiccProfile).getApplication(
+        lenient().doReturn(mUiccCardApplication3gpp).when(mUiccProfile).getApplication(
                 eq(UiccController.APP_FAM_3GPP));
-        doReturn(mUiccCardApplication3gpp2).when(mUiccProfile).getApplication(
+        lenient().doReturn(mUiccCardApplication3gpp2).when(mUiccProfile).getApplication(
                 eq(UiccController.APP_FAM_3GPP2));
-        doReturn(mUiccCardApplicationIms).when(mUiccProfile).getApplication(
+        lenient().doReturn(mUiccCardApplicationIms).when(mUiccProfile).getApplication(
                 eq(UiccController.APP_FAM_IMS));
 
         //SMS
-        doReturn(true).when(mSmsStorageMonitor).isStorageAvailable();
-        doReturn(true).when(mSmsUsageMonitor).check(nullable(String.class), anyInt());
-        doReturn(true).when(mTelephonyManager).getSmsReceiveCapableForPhone(anyInt(), anyBoolean());
-        doReturn(true).when(mTelephonyManager).getSmsSendCapableForPhone(
+        lenient().doReturn(true).when(mSmsStorageMonitor).isStorageAvailable();
+        lenient().doReturn(true).when(mSmsUsageMonitor).check(nullable(String.class), anyInt());
+        lenient().doReturn(true).when(mTelephonyManager).getSmsReceiveCapableForPhone(anyInt(),
+                anyBoolean());
+        lenient().doReturn(true).when(mTelephonyManager).getSmsSendCapableForPhone(
                 anyInt(), anyBoolean());
 
         //Misc
-        doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_LTE).when(mServiceState)
+        lenient().doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_LTE).when(mServiceState)
                 .getRilDataRadioTechnology();
-        doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_LTE,
+        lenient().doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_LTE,
                 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false, false, false))
                 .when(mDisplayInfoController).getTelephonyDisplayInfo();
-        doReturn(mPhone).when(mCT).getPhone();
-        doReturn(mImsEcbm).when(mImsManager).getEcbmInterface();
-        doReturn(mPhone).when(mInboundSmsHandler).getPhone();
-        doReturn(mImsCallProfile).when(mImsCall).getCallProfile();
-        doReturn(mIBinder).when(mIIntentSender).asBinder();
+        lenient().doReturn(mPhone).when(mCT).getPhone();
+        lenient().doReturn(mImsEcbm).when(mImsManager).getEcbmInterface();
+        lenient().doReturn(mPhone).when(mInboundSmsHandler).getPhone();
+        lenient().doReturn(mImsCallProfile).when(mImsCall).getCallProfile();
+        lenient().doReturn(mIBinder).when(mIIntentSender).asBinder();
         doAnswer(invocation -> {
             Intent[] intents = invocation.getArgument(6);
             if (intents != null && intents.length > 0) {
-                doReturn(intents[0]).when(mIActivityManager)
+                lenient().doReturn(intents[0]).when(mIActivityManager)
                         .getIntentForIntentSender(mIIntentSender);
             }
             return mIIntentSender;
@@ -829,8 +823,9 @@
                 nullable(String.class), nullable(String.class), nullable(IBinder.class),
                 nullable(String.class), anyInt(), nullable(Intent[].class),
                 nullable(String[].class), anyInt(), nullable(Bundle.class), anyInt());
-        doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
-        doReturn(true).when(mTelephonyManager).isDataCapable();
+        lenient().doReturn(mTelephonyManager).when(mTelephonyManager)
+                .createForSubscriptionId(anyInt());
+        lenient().doReturn(true).when(mTelephonyManager).isDataCapable();
 
         mContextFixture.addSystemFeature(PackageManager.FEATURE_TELECOM);
         mContextFixture.addSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING);
@@ -838,45 +833,46 @@
         mContextFixture.addSystemFeature(PackageManager.FEATURE_TELEPHONY_EUICC);
         mContextFixture.addSystemFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING);
 
-        doReturn(TelephonyManager.PHONE_TYPE_GSM).when(mTelephonyManager).getPhoneType();
-        doReturn(mServiceState).when(mSST).getServiceState();
-        doReturn(mServiceStateStats).when(mSST).getServiceStateStats();
+        lenient().doReturn(TelephonyManager.PHONE_TYPE_GSM).when(mTelephonyManager).getPhoneType();
+        lenient().doReturn(mServiceState).when(mSST).getServiceState();
+        lenient().doReturn(mServiceStateStats).when(mSST).getServiceStateStats();
         mSST.mSS = mServiceState;
         mSST.mRestrictedState = mRestrictedState;
         mServiceManagerMockedServices.put("connectivity_metrics_logger", mConnMetLoggerBinder);
         mServiceManagerMockedServices.put("package", mMockPackageManager);
         mServiceManagerMockedServices.put("legacy_permission", mMockLegacyPermissionManager);
         logd("mMockLegacyPermissionManager replaced");
-        doReturn(new int[]{AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+        lenient().doReturn(new int[]{AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                 AccessNetworkConstants.TRANSPORT_TYPE_WLAN})
                 .when(mAccessNetworksManager).getAvailableTransports();
-        doReturn(true).when(mDataSettingsManager).isDataEnabled();
-        doReturn(mNetworkRegistrationInfo).when(mServiceState).getNetworkRegistrationInfo(
+        lenient().doReturn(true).when(mDataSettingsManager).isDataEnabled();
+        lenient().doReturn(mNetworkRegistrationInfo).when(mServiceState).getNetworkRegistrationInfo(
                 anyInt(), anyInt());
-        doReturn(RIL.RADIO_HAL_VERSION_2_0).when(mPhone).getHalVersion(anyInt());
-        doReturn(2).when(mSignalStrength).getLevel();
-        doReturn(mMockRadioConfigProxy).when(mMockRadioConfig).getRadioConfigProxy(any());
+        lenient().doReturn(RIL.RADIO_HAL_VERSION_2_0).when(mPhone).getHalVersion(anyInt());
+        lenient().doReturn(2).when(mSignalStrength).getLevel();
+        lenient().doReturn(mMockRadioConfigProxy).when(mMockRadioConfig).getRadioConfigProxy(any());
 
         // WiFi
-        doReturn(mWifiInfo).when(mWifiManager).getConnectionInfo();
-        doReturn(2).when(mWifiManager).calculateSignalLevel(anyInt());
-        doReturn(4).when(mWifiManager).getMaxSignalLevel();
+        lenient().doReturn(mWifiInfo).when(mWifiManager).getConnectionInfo();
+        lenient().doReturn(2).when(mWifiManager).calculateSignalLevel(anyInt());
+        lenient().doReturn(4).when(mWifiManager).getMaxSignalLevel();
 
-        doAnswer(invocation -> {
+        lenient().doAnswer(invocation -> {
             NetworkCapabilities nc = invocation.getArgument(0);
             return new VcnNetworkPolicyResult(
                     false /* isTearDownRequested */, nc);
         }).when(mVcnManager).applyVcnNetworkPolicy(any(), any());
 
         //SIM
-        doReturn(1).when(mTelephonyManager).getSimCount();
-        doReturn(1).when(mTelephonyManager).getPhoneCount();
-        doReturn(1).when(mTelephonyManager).getActiveModemCount();
+        lenient().doReturn(1).when(mTelephonyManager).getSimCount();
+        lenient().doReturn(1).when(mTelephonyManager).getPhoneCount();
+        lenient().doReturn(1).when(mTelephonyManager).getActiveModemCount();
         // Have getMaxPhoneCount always return the same value with getPhoneCount by default.
-        doAnswer((invocation)->Math.max(mTelephonyManager.getActiveModemCount(),
+        lenient().doAnswer((invocation)->Math.max(mTelephonyManager.getActiveModemCount(),
                 mTelephonyManager.getPhoneCount()))
                 .when(mTelephonyManager).getSupportedModemCount();
-        doReturn(mStatsManager).when(mContext).getSystemService(eq(Context.NETWORK_STATS_SERVICE));
+        lenient().doReturn(mStatsManager).when(mContext)
+                .getSystemService(eq(Context.NETWORK_STATS_SERVICE));
 
         //Data
         //Initial state is: userData enabled, provisioned.
@@ -887,56 +883,57 @@
                 Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED, 1);
         Settings.Global.putInt(resolver, Settings.Global.DATA_ROAMING, 0);
 
-        doReturn(90).when(mDataConfigManager).getNetworkCapabilityPriority(
+        lenient().doReturn(90).when(mDataConfigManager).getNetworkCapabilityPriority(
                 eq(NetworkCapabilities.NET_CAPABILITY_EIMS));
-        doReturn(80).when(mDataConfigManager).getNetworkCapabilityPriority(
+        lenient().doReturn(80).when(mDataConfigManager).getNetworkCapabilityPriority(
                 eq(NetworkCapabilities.NET_CAPABILITY_SUPL));
-        doReturn(70).when(mDataConfigManager).getNetworkCapabilityPriority(
+        lenient().doReturn(70).when(mDataConfigManager).getNetworkCapabilityPriority(
                 eq(NetworkCapabilities.NET_CAPABILITY_MMS));
-        doReturn(70).when(mDataConfigManager).getNetworkCapabilityPriority(
+        lenient().doReturn(70).when(mDataConfigManager).getNetworkCapabilityPriority(
                 eq(NetworkCapabilities.NET_CAPABILITY_XCAP));
-        doReturn(50).when(mDataConfigManager).getNetworkCapabilityPriority(
+        lenient().doReturn(50).when(mDataConfigManager).getNetworkCapabilityPriority(
                 eq(NetworkCapabilities.NET_CAPABILITY_CBS));
-        doReturn(50).when(mDataConfigManager).getNetworkCapabilityPriority(
+        lenient().doReturn(50).when(mDataConfigManager).getNetworkCapabilityPriority(
                 eq(NetworkCapabilities.NET_CAPABILITY_MCX));
-        doReturn(50).when(mDataConfigManager).getNetworkCapabilityPriority(
+        lenient().doReturn(50).when(mDataConfigManager).getNetworkCapabilityPriority(
                 eq(NetworkCapabilities.NET_CAPABILITY_FOTA));
-        doReturn(40).when(mDataConfigManager).getNetworkCapabilityPriority(
+        lenient().doReturn(40).when(mDataConfigManager).getNetworkCapabilityPriority(
                 eq(NetworkCapabilities.NET_CAPABILITY_IMS));
-        doReturn(30).when(mDataConfigManager).getNetworkCapabilityPriority(
+        lenient().doReturn(30).when(mDataConfigManager).getNetworkCapabilityPriority(
                 eq(NetworkCapabilities.NET_CAPABILITY_DUN));
-        doReturn(20).when(mDataConfigManager).getNetworkCapabilityPriority(
+        lenient().doReturn(20).when(mDataConfigManager).getNetworkCapabilityPriority(
                 eq(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE));
-        doReturn(20).when(mDataConfigManager).getNetworkCapabilityPriority(
+        lenient().doReturn(20).when(mDataConfigManager).getNetworkCapabilityPriority(
                 eq(NetworkCapabilities.NET_CAPABILITY_INTERNET));
-        doReturn(60000).when(mDataConfigManager).getAnomalyNetworkConnectingTimeoutMs();
-        doReturn(60000).when(mDataConfigManager)
+        lenient().doReturn(60000).when(mDataConfigManager).getAnomalyNetworkConnectingTimeoutMs();
+        lenient().doReturn(60000).when(mDataConfigManager)
                 .getAnomalyNetworkDisconnectingTimeoutMs();
-        doReturn(60000).when(mDataConfigManager).getNetworkHandoverTimeoutMs();
-        doReturn(new DataConfigManager.EventFrequency(300000, 12))
+        lenient().doReturn(60000).when(mDataConfigManager).getNetworkHandoverTimeoutMs();
+        lenient().doReturn(new DataConfigManager.EventFrequency(300000, 12))
                 .when(mDataConfigManager).getAnomalySetupDataCallThreshold();
-        doReturn(new DataConfigManager.EventFrequency(0, 2))
+        lenient().doReturn(new DataConfigManager.EventFrequency(0, 2))
                 .when(mDataConfigManager).getAnomalyImsReleaseRequestThreshold();
-        doReturn(new DataConfigManager.EventFrequency(300000, 12))
+        lenient().doReturn(new DataConfigManager.EventFrequency(300000, 12))
                 .when(mDataConfigManager).getAnomalyNetworkUnwantedThreshold();
 
         // CellularNetworkValidator
-        doReturn(SubscriptionManager.INVALID_PHONE_INDEX)
+        lenient().doReturn(SubscriptionManager.INVALID_PHONE_INDEX)
                 .when(mCellularNetworkValidator).getSubIdInValidation();
-        doReturn(true).when(mCellularNetworkValidator).isValidationFeatureSupported();
+        lenient().doReturn(true).when(mCellularNetworkValidator).isValidationFeatureSupported();
 
         // Metrics
-        doReturn(null).when(mContext).getFileStreamPath(anyString());
-        doReturn(mPersistAtomsStorage).when(mMetricsCollector).getAtomsStorage();
-        doReturn(mDefaultNetworkMonitor).when(mMetricsCollector).getDefaultNetworkMonitor();
-        doReturn(mWifiManager).when(mContext).getSystemService(eq(Context.WIFI_SERVICE));
-        doReturn(mDeviceStateHelper).when(mMetricsCollector).getDeviceStateHelper();
-        doReturn(CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_UNKNOWN)
+        lenient().doReturn(null).when(mContext).getFileStreamPath(anyString());
+        lenient().doReturn(mPersistAtomsStorage).when(mMetricsCollector).getAtomsStorage();
+        lenient().doReturn(mDefaultNetworkMonitor).when(mMetricsCollector)
+                .getDefaultNetworkMonitor();
+        lenient().doReturn(mWifiManager).when(mContext).getSystemService(eq(Context.WIFI_SERVICE));
+        lenient().doReturn(mDeviceStateHelper).when(mMetricsCollector).getDeviceStateHelper();
+        lenient().doReturn(CELLULAR_SERVICE_STATE__FOLD_STATE__STATE_UNKNOWN)
                 .when(mDeviceStateHelper)
                 .getFoldState();
-        doReturn(null).when(mContext).getSystemService(eq(Context.DEVICE_STATE_SERVICE));
+        lenient().doReturn(null).when(mContext).getSystemService(eq(Context.DEVICE_STATE_SERVICE));
 
-        doReturn(false).when(mDomainSelectionResolver).isDomainSelectionSupported();
+        lenient().doReturn(false).when(mDomainSelectionResolver).isDomainSelectionSupported();
         DomainSelectionResolver.setDomainSelectionResolver(mDomainSelectionResolver);
 
         //Use reflection to mock singletons
@@ -1048,6 +1045,28 @@
         Log.d(TAG, s);
     }
 
+    protected void unmockActivityManager() throws Exception {
+        // Normally, these two should suffice. But we're having some flakiness due to restored
+        // instances being mocks...
+        restoreInstance(Singleton.class, "mInstance", mIActivityManagerSingleton);
+        restoreInstance(ActivityManager.class, "IActivityManagerSingleton", null);
+
+        // Copy-paste from android.app.ActivityManager.IActivityManagerSingleton
+        Singleton<IActivityManager> amSingleton = new Singleton<IActivityManager>() {
+                @Override
+                protected IActivityManager create() {
+                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
+                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
+                    return am;
+                }
+            };
+
+        // ...so we're setting correct values explicitly, to be sure and not let the flake propagate
+        // to other tests.
+        replaceInstance(Singleton.class, "mInstance", mIActivityManagerSingleton, null);
+        replaceInstance(ActivityManager.class, "IActivityManagerSingleton", null, amSingleton);
+    }
+
     public static class FakeBlockedNumberContentProvider extends MockContentProvider {
         public Set<String> mBlockedNumbers = new HashSet<>();
         public int mNumEmergencyContactNotifications = 0;
@@ -1313,36 +1332,12 @@
     }
 
     /**
-     * @return The longest delay from all the message queues.
-     */
-    private long getLongestDelay() {
-        long delay = 0;
-        for (TestableLooper looper : mTestableLoopers) {
-            MessageQueue queue = looper.getLooper().getQueue();
-            try {
-                Message msg = (Message) MESSAGE_QUEUE_FIELD.get(queue);
-                while (msg != null) {
-                    delay = Math.max(msg.getWhen(), delay);
-                    msg = (Message) MESSAGE_NEXT_FIELD.get(msg);
-                }
-            } catch (IllegalAccessException e) {
-                throw new RuntimeException("Access failed in TelephonyTest", e);
-            }
-        }
-        return delay;
-    }
-
-    /**
      * @return {@code true} if there are any messages in the queue.
      */
     private boolean messagesExist() {
         for (TestableLooper looper : mTestableLoopers) {
-            MessageQueue queue = looper.getLooper().getQueue();
-            try {
-                Message msg = (Message) MESSAGE_QUEUE_FIELD.get(queue);
-                if (msg != null) return true;
-            } catch (IllegalAccessException e) {
-                throw new RuntimeException("Access failed in TelephonyTest", e);
+            if (looper.peekWhen() > 0) {
+                return true;
             }
         }
         return false;
@@ -1352,8 +1347,14 @@
      * Handle all messages including the delayed messages.
      */
     public void processAllFutureMessages() {
+        final long now = SystemClock.uptimeMillis();
         while (messagesExist()) {
-            moveTimeForward(getLongestDelay());
+            for (TestableLooper looper : mTestableLoopers) {
+                long nextDelay = looper.peekWhen() - now;
+                if (nextDelay > 0) {
+                    looper.moveTimeForward(nextDelay);
+                }
+            }
             processAllMessages();
         }
     }
@@ -1378,20 +1379,7 @@
      */
     public void moveTimeForward(long milliSeconds) {
         for (TestableLooper looper : mTestableLoopers) {
-            MessageQueue queue = looper.getLooper().getQueue();
-            try {
-                Message msg = (Message) MESSAGE_QUEUE_FIELD.get(queue);
-                while (msg != null) {
-                    long updatedWhen = msg.getWhen() - milliSeconds;
-                    if (updatedWhen < 0) {
-                        updatedWhen = 0;
-                    }
-                    MESSAGE_WHEN_FIELD.set(msg, updatedWhen);
-                    msg = (Message) MESSAGE_NEXT_FIELD.get(msg);
-                }
-            } catch (IllegalAccessException e) {
-                throw new RuntimeException("Access failed in TelephonyTest", e);
-            }
+            looper.moveTimeForward(milliSeconds);
         }
     }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/VisualVoicemailSmsFilterTest.java b/tests/telephonytests/src/com/android/internal/telephony/VisualVoicemailSmsFilterTest.java
index 9f76337..df094ce 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/VisualVoicemailSmsFilterTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/VisualVoicemailSmsFilterTest.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.telephony;
 
-import static org.mockito.Matchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.when;
 
 import android.content.ComponentName;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java b/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
index 58e5617..db44cd3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/WapPushOverSmsTest.java
@@ -17,8 +17,8 @@
 package com.android.internal.telephony;
 
 import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.nullable;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.doReturn;
@@ -107,7 +107,7 @@
                 eq(android.Manifest.permission.RECEIVE_WAP_PUSH),
                 eq(AppOpsManager.OPSTR_RECEIVE_WAP_PUSH),
                 nullable(Bundle.class),
-                isNull(InboundSmsHandler.SmsBroadcastReceiver.class),
+                isNull(),
                 eq(MOCKED_MAIN_USER),
                 anyInt());
         Intent intent = intentArgumentCaptor.getValue();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cat/CATServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/cat/CATServiceTest.java
index a07ddbe..7ee4832 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/cat/CATServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/cat/CATServiceTest.java
@@ -211,7 +211,7 @@
         mCatService.sendStkSms("test", "12345", 1, cmdPrms, mProxyController);
         verify(mSmsController, Mockito.times(1)).sendTextForSubscriber(anyInt(),
                 anyString(), nullable(String.class), anyString(), nullable(String.class),
-                anyString(), Mockito.anyObject(), any(), eq(false), anyLong(), eq(true), eq(true));
+                anyString(), Mockito.any(), any(), eq(false), anyLong(), eq(true), eq(true));
     }
 
     @Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java
deleted file mode 100644
index cab76f7..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaInboundSmsHandlerTest.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.cdma;
-
-import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.os.AsyncResult;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Telephony;
-import android.test.mock.MockContentResolver;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import androidx.test.filters.FlakyTest;
-import androidx.test.filters.MediumTest;
-
-import com.android.internal.telephony.FakeSmsContentProvider;
-import com.android.internal.telephony.InboundSmsHandler;
-import com.android.internal.telephony.InboundSmsTracker;
-import com.android.internal.telephony.SmsStorageMonitor;
-import com.android.internal.telephony.TelephonyTest;
-import com.android.internal.telephony.cdma.sms.SmsEnvelope;
-import com.android.internal.util.IState;
-import com.android.internal.util.StateMachine;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class CdmaInboundSmsHandlerTest extends TelephonyTest {
-    // Mocked classes
-    private SmsStorageMonitor mSmsStorageMonitor;
-    private android.telephony.SmsMessage mSmsMessage;
-    private SmsMessage mCdmaSmsMessage;
-
-    private CdmaInboundSmsHandler mCdmaInboundSmsHandler;
-    private SmsEnvelope mSmsEnvelope = new SmsEnvelope();
-    private FakeSmsContentProvider mContentProvider;
-    private InboundSmsTracker mInboundSmsTracker;
-    private final byte[] mSmsPdu = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
-    private final int mSubId0 = 0;
-    private static final UserHandle MOCKED_MAIN_USER = UserHandle.of(10);
-
-    private IState getCurrentState() {
-        try {
-            Method method = StateMachine.class.getDeclaredMethod("getCurrentState");
-            method.setAccessible(true);
-            return (IState) method.invoke(mCdmaInboundSmsHandler);
-        } catch (Exception e) {
-            fail(e.toString());
-            return null;
-        }
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        super.setUp(getClass().getSimpleName());
-        mSmsStorageMonitor = mock(SmsStorageMonitor.class);
-        mSmsMessage = mock(android.telephony.SmsMessage.class);
-        mCdmaSmsMessage = mock(SmsMessage.class);
-
-        Field field = SmsMessage.class.getDeclaredField("mEnvelope");
-        field.setAccessible(true);
-        field.set(mCdmaSmsMessage, mSmsEnvelope);
-
-        UserManager userManager = (UserManager) mContextFixture.getTestDouble().
-                getSystemService(Context.USER_SERVICE);
-        doReturn(MOCKED_MAIN_USER).when(userManager).getMainUser();
-        doReturn(true).when(userManager).isUserUnlocked();
-        doReturn(true).when(mFeatureFlags).smsMmsDeliverBroadcastsRedirectToMainUser();
-
-        try {
-            doReturn(new int[]{0, MOCKED_MAIN_USER.getIdentifier()})
-                .when(mIActivityManager).getRunningUserIds();
-        } catch (RemoteException re) {
-            StringWriter reString = new StringWriter();
-            re.printStackTrace(new PrintWriter(reString));
-            fail("Unexpected RemoteException: " + reString);
-        }
-
-        mSmsMessage.mWrappedSmsMessage = mCdmaSmsMessage;
-        doReturn(mSmsPdu).when(mCdmaSmsMessage).getPdu();
-
-        doReturn(true).when(mTelephonyManager).getSmsReceiveCapableForPhone(anyInt(), anyBoolean());
-        doReturn(true).when(mSmsStorageMonitor).isStorageAvailable();
-
-        mInboundSmsTracker = new InboundSmsTracker(
-                mContext,
-                mSmsPdu, /* pdu */
-                System.currentTimeMillis(), /* timestamp */
-                -1, /* destPort */
-                true, /* is3gpp2 */
-                false, /* is3gpp2WapPdu */
-                "1234567890", /* address */
-                "1234567890", /* displayAddress */
-                "This is the message body of a single-part message" /* messageBody */,
-                false, /* isClass0 */
-                mSubId0,
-                InboundSmsHandler.SOURCE_NOT_INJECTED);
-
-        doReturn(mInboundSmsTracker).when(mTelephonyComponentFactory)
-                .makeInboundSmsTracker(any(Context.class), nullable(byte[].class), anyLong(),
-                anyInt(), anyBoolean(),
-                anyBoolean(), nullable(String.class), nullable(String.class),
-                nullable(String.class), anyBoolean(), anyInt(), anyInt());
-        doReturn(mInboundSmsTracker).when(mTelephonyComponentFactory)
-                .makeInboundSmsTracker(any(Context.class), nullable(byte[].class), anyLong(),
-                anyInt(), anyBoolean(),
-                nullable(String.class), nullable(String.class), anyInt(), anyInt(),
-                anyInt(), anyBoolean(), nullable(String.class), anyBoolean(), anyInt(),
-                anyInt());
-        doReturn(mInboundSmsTracker).when(mTelephonyComponentFactory)
-                .makeInboundSmsTracker(any(Context.class), nullable(Cursor.class), anyBoolean());
-
-        mContentProvider = new FakeSmsContentProvider();
-        ((MockContentResolver)mContext.getContentResolver()).addProvider(
-                Telephony.Sms.CONTENT_URI.getAuthority(), mContentProvider);
-
-        mCdmaInboundSmsHandler = CdmaInboundSmsHandler.makeInboundSmsHandler(mContext,
-            mSmsStorageMonitor, mPhone, null, mTestableLooper.getLooper(),
-                mFeatureFlags);
-        monitorTestableLooper(new TestableLooper(mCdmaInboundSmsHandler.getHandler().getLooper()));
-        processAllMessages();
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        // wait for wakelock to be released; timeout at 10s
-        int i = 0;
-        while (mCdmaInboundSmsHandler.getWakeLock().isHeld() && i < 100) {
-            processAllMessages();
-            waitForMs(100);
-            i++;
-        }
-        assertFalse(mCdmaInboundSmsHandler.getWakeLock().isHeld());
-        mCdmaInboundSmsHandler.quit();
-        mCdmaInboundSmsHandler = null;
-        mContentProvider.shutdown();
-        mContentProvider = null;
-        mSmsEnvelope = null;
-        mInboundSmsTracker = null;
-        super.tearDown();
-    }
-
-    private void transitionFromStartupToIdle() {
-        // verify initially in StartupState
-        assertEquals("StartupState", getCurrentState().getName());
-
-        // trigger transition to IdleState
-        mCdmaInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_START_ACCEPTING_SMS);
-        processAllMessages();
-
-        assertEquals("IdleState", getCurrentState().getName());
-    }
-
-    @FlakyTest
-    @Test
-    @MediumTest
-    @Ignore
-    public void testNewSms() {
-        transitionFromStartupToIdle();
-
-        // send new SMS to state machine and verify that triggers SMS_DELIVER_ACTION
-        doReturn(SmsEnvelope.TELESERVICE_WMT).when(mCdmaSmsMessage).getTeleService();
-        mCdmaInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS,
-                new AsyncResult(null, mSmsMessage, null));
-        processAllMessages();
-
-        ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
-        verify(mContext).sendBroadcast(intentArgumentCaptor.capture());
-        assertEquals(Telephony.Sms.Intents.SMS_DELIVER_ACTION,
-                intentArgumentCaptor.getValue().getAction());
-
-        // verify a message id was created on receive.
-        assertNotEquals(0L,
-                intentArgumentCaptor.getValue().getLongExtra("messageId", 0L));
-        assertEquals("WaitingState", getCurrentState().getName());
-
-        mContextFixture.sendBroadcastToOrderedBroadcastReceivers();
-
-        intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
-        verify(mContext, times(2)).sendBroadcast(intentArgumentCaptor.capture());
-        assertEquals(Telephony.Sms.Intents.SMS_RECEIVED_ACTION,
-                intentArgumentCaptor.getAllValues().get(1).getAction());
-        assertEquals("WaitingState", getCurrentState().getName());
-
-        mContextFixture.sendBroadcastToOrderedBroadcastReceivers();
-        processAllMessages();
-
-        assertEquals("IdleState", getCurrentState().getName());
-    }
-
-    @FlakyTest /* flakes 0.43% of the time */
-    @Test
-    @MediumTest
-    public void testNewSmsFromBlockedNumber_noBroadcastsSent() {
-        String blockedNumber = "123456789";
-        mInboundSmsTracker = new InboundSmsTracker(
-                mContext,
-                mSmsPdu, /* pdu */
-                System.currentTimeMillis(), /* timestamp */
-                -1, /* destPort */
-                true, /* is3gpp2 */
-                false, /* is3gpp2WapPdu */
-                "1234567890", /* address */
-                blockedNumber, /* displayAddress */
-                "This is the message body of a single-part message" /* messageBody */,
-                false, /* isClass0 */
-                mSubId0,
-                InboundSmsHandler.SOURCE_NOT_INJECTED);
-        doReturn(mInboundSmsTracker).when(mTelephonyComponentFactory)
-                .makeInboundSmsTracker(any(Context.class), nullable(byte[].class), anyLong(),
-                anyInt(), anyBoolean(),
-                anyBoolean(), nullable(String.class), nullable(String.class),
-                nullable(String.class), anyBoolean(), anyInt(), anyInt());
-        mFakeBlockedNumberContentProvider.mBlockedNumbers.add(blockedNumber);
-
-        transitionFromStartupToIdle();
-
-        doReturn(SmsEnvelope.TELESERVICE_WMT).when(mCdmaSmsMessage).getTeleService();
-        mCdmaInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_NEW_SMS,
-                new AsyncResult(null, mSmsMessage, null));
-        processAllMessages();
-
-        verify(mContext, never()).sendBroadcast(any(Intent.class));
-        assertEquals("IdleState", getCurrentState().getName());
-    }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
deleted file mode 100644
index 100c391..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsCbTest.java
+++ /dev/null
@@ -1,766 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.cdma;
-
-import android.hardware.radio.V1_0.CdmaSmsMessage;
-import android.telephony.SmsCbCmasInfo;
-import android.telephony.SmsCbMessage;
-import android.telephony.cdma.CdmaSmsCbProgramData;
-import android.test.AndroidTestCase;
-
-import androidx.test.filters.FlakyTest;
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.telephony.GsmAlphabet;
-import com.android.internal.telephony.RILUtils;
-import com.android.internal.telephony.cdma.sms.BearerData;
-import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
-import com.android.internal.telephony.cdma.sms.SmsEnvelope;
-import com.android.internal.telephony.cdma.sms.UserData;
-import com.android.internal.util.BitwiseOutputStream;
-import com.android.telephony.Rlog;
-
-import org.junit.Ignore;
-import org.junit.Test;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Random;
-
-/**
- * Test cases for basic SmsCbMessage operation for CDMA.
- */
-public class CdmaSmsCbTest extends AndroidTestCase {
-
-    /* Copy of private subparameter identifier constants from BearerData class. */
-    private static final byte SUBPARAM_MESSAGE_IDENTIFIER   = (byte) 0x00;
-    private static final byte SUBPARAM_USER_DATA            = (byte) 0x01;
-    private static final byte SUBPARAM_PRIORITY_INDICATOR   = (byte) 0x08;
-    private static final byte SUBPARAM_LANGUAGE_INDICATOR   = (byte) 0x0D;
-    private static final byte SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA    = 0x12;
-
-    /**
-     * Initialize a Parcel for an incoming CDMA cell broadcast. The caller will write the
-     * bearer data and then convert it to an SmsMessage.
-     * @param serviceCategory the CDMA service category
-     * @return the initialized Parcel
-     */
-    private static CdmaSmsMessage createBroadcastParcel(int serviceCategory) {
-        CdmaSmsMessage msg = new CdmaSmsMessage();
-
-        msg.teleserviceId = SmsEnvelope.TELESERVICE_NOT_SET;
-        msg.isServicePresent = true;
-        msg.serviceCategory = serviceCategory;
-
-        // placeholder address (RIL may generate a different placeholder address for broadcasts)
-        msg.address.digitMode = CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF;
-        msg.address.numberMode = CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK;
-        msg.address.numberType = CdmaSmsAddress.TON_UNKNOWN;
-        msg.address.numberPlan = CdmaSmsAddress.NUMBERING_PLAN_ISDN_TELEPHONY;
-        msg.subAddress.subaddressType = 0;
-        msg.subAddress.odd = false;
-        return msg;
-    }
-
-    /**
-     * Initialize a BitwiseOutputStream with the CDMA bearer data subparameters except for
-     * user data. The caller will append the user data and add it to the parcel.
-     * @param messageId the 16-bit message identifier
-     * @param priority message priority
-     * @param language message language code
-     * @return the initialized BitwiseOutputStream
-     */
-    private static BitwiseOutputStream createBearerDataStream(int messageId, int priority,
-            int language) throws BitwiseOutputStream.AccessException {
-        BitwiseOutputStream bos = new BitwiseOutputStream(10);
-        bos.write(8, SUBPARAM_MESSAGE_IDENTIFIER);
-        bos.write(8, 3);    // length: 3 bytes
-        bos.write(4, BearerData.MESSAGE_TYPE_DELIVER);
-        bos.write(8, ((messageId >>> 8) & 0xff));
-        bos.write(8, (messageId & 0xff));
-        bos.write(1, 0);    // no User Data Header
-        bos.write(3, 0);    // reserved
-
-        if (priority != -1) {
-            bos.write(8, SUBPARAM_PRIORITY_INDICATOR);
-            bos.write(8, 1);    // length: 1 byte
-            bos.write(2, (priority & 0x03));
-            bos.write(6, 0);    // reserved
-        }
-
-        if (language != -1) {
-            bos.write(8, SUBPARAM_LANGUAGE_INDICATOR);
-            bos.write(8, 1);    // length: 1 byte
-            bos.write(8, (language & 0xff));
-        }
-
-        return bos;
-    }
-
-    /**
-     * Write the bearer data array to the parcel, then return a new SmsMessage from the parcel.
-     * @param msg CdmaSmsMessage containing the CDMA SMS headers
-     * @param bearerData the bearer data byte array to append to the parcel
-     * @return the new SmsMessage created from the parcel
-     */
-    private static SmsMessage createMessageFromParcel(CdmaSmsMessage msg, byte[] bearerData) {
-        for (byte b : bearerData) {
-            msg.bearerData.add(b);
-        }
-        SmsMessage message = RILUtils.convertHalCdmaSmsMessage(msg);
-        return message;
-    }
-
-    /**
-     * Create a parcel for an incoming CMAS broadcast, then return a new SmsMessage created
-     * from the parcel.
-     * @param serviceCategory the CDMA service category
-     * @param messageId the 16-bit message identifier
-     * @param priority message priority
-     * @param language message language code
-     * @param body message body
-     * @param cmasCategory CMAS category (or -1 to skip adding CMAS type 1 elements record)
-     * @param responseType CMAS response type
-     * @param severity CMAS severity
-     * @param urgency CMAS urgency
-     * @param certainty CMAS certainty
-     * @return the newly created SmsMessage object
-     */
-    private static SmsMessage createCmasSmsMessage(int serviceCategory, int messageId, int priority,
-            int language, int encoding, String body, int cmasCategory, int responseType,
-            int severity, int urgency, int certainty) throws Exception {
-        BitwiseOutputStream cmasBos = new BitwiseOutputStream(10);
-        cmasBos.write(8, 0);    // CMAE protocol version 0
-
-        if (body != null) {
-            cmasBos.write(8, 0);        // Type 0 elements (alert text)
-            encodeBody(encoding, body, true, cmasBos);
-        }
-
-        if (cmasCategory != SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN) {
-            cmasBos.write(8, 1);    // Type 1 elements
-            cmasBos.write(8, 4);    // length: 4 bytes
-            cmasBos.write(8, (cmasCategory & 0xff));
-            cmasBos.write(8, (responseType & 0xff));
-            cmasBos.write(4, (severity & 0x0f));
-            cmasBos.write(4, (urgency & 0x0f));
-            cmasBos.write(4, (certainty & 0x0f));
-            cmasBos.write(4, 0);    // pad to octet boundary
-        }
-
-        byte[] cmasUserData = cmasBos.toByteArray();
-
-        CdmaSmsMessage msg = createBroadcastParcel(serviceCategory);
-        BitwiseOutputStream bos = createBearerDataStream(messageId, priority, language);
-
-        bos.write(8, SUBPARAM_USER_DATA);
-        bos.write(8, cmasUserData.length + 2);  // add 2 bytes for msg_encoding and num_fields
-        bos.write(5, UserData.ENCODING_OCTET);
-        bos.write(8, cmasUserData.length);
-        bos.writeByteArray(cmasUserData.length * 8, cmasUserData);
-        bos.write(3, 0);    // pad to byte boundary
-
-        return createMessageFromParcel(msg, bos.toByteArray());
-    }
-
-    /**
-     * Create a parcel for an incoming CDMA cell broadcast, then return a new SmsMessage created
-     * from the parcel.
-     * @param serviceCategory the CDMA service category
-     * @param messageId the 16-bit message identifier
-     * @param priority message priority
-     * @param language message language code
-     * @param encoding user data encoding method
-     * @param body the message body
-     * @return the newly created SmsMessage object
-     */
-    private static SmsMessage createBroadcastSmsMessage(int serviceCategory, int messageId,
-            int priority, int language, int encoding, String body) throws Exception {
-        CdmaSmsMessage msg = createBroadcastParcel(serviceCategory);
-        BitwiseOutputStream bos = createBearerDataStream(messageId, priority, language);
-
-        bos.write(8, SUBPARAM_USER_DATA);
-        encodeBody(encoding, body, false, bos);
-
-        return createMessageFromParcel(msg, bos.toByteArray());
-    }
-
-    /**
-     * Append the message length, encoding, and body to the BearerData output stream.
-     * This is used for writing the User Data subparameter for non-CMAS broadcasts and for
-     * writing the alert text for CMAS broadcasts.
-     * @param encoding one of the CDMA UserData encoding values
-     * @param body the message body
-     * @param isCmasRecord true if this is a CMAS type 0 elements record; false for user data
-     * @param bos the BitwiseOutputStream to write to
-     * @throws Exception on any encoding error
-     */
-    private static void encodeBody(int encoding, String body, boolean isCmasRecord,
-            BitwiseOutputStream bos) throws Exception {
-        if (encoding == UserData.ENCODING_7BIT_ASCII || encoding == UserData.ENCODING_IA5) {
-            int charCount = body.length();
-            int recordBits = (charCount * 7) + 5;       // add 5 bits for char set field
-            int recordOctets = (recordBits + 7) / 8;    // round up to octet boundary
-            int padBits = (recordOctets * 8) - recordBits;
-
-            if (!isCmasRecord) {
-                recordOctets++;                         // add 8 bits for num_fields
-            }
-
-            bos.write(8, recordOctets);
-            bos.write(5, (encoding & 0x1f));
-
-            if (!isCmasRecord) {
-                bos.write(8, charCount);
-            }
-
-            for (int i = 0; i < charCount; i++) {
-                bos.write(7, body.charAt(i));
-            }
-
-            bos.write(padBits, 0);      // pad to octet boundary
-        } else if (encoding == UserData.ENCODING_GSM_7BIT_ALPHABET
-                || encoding == UserData.ENCODING_GSM_DCS) {
-            // convert to 7-bit packed encoding with septet count in index 0 of byte array
-            byte[] encodedBody = GsmAlphabet.stringToGsm7BitPacked(body);
-
-            int charCount = encodedBody[0];             // septet count
-            int recordBits = (charCount * 7) + 5;       // add 5 bits for char set field
-            int recordOctets = (recordBits + 7) / 8;    // round up to octet boundary
-            int padBits = (recordOctets * 8) - recordBits;
-
-            if (!isCmasRecord) {
-                recordOctets++;                         // add 8 bits for num_fields
-                if (encoding == UserData.ENCODING_GSM_DCS) {
-                    recordOctets++;                     // add 8 bits for DCS (message type)
-                }
-            }
-
-            bos.write(8, recordOctets);
-            bos.write(5, (encoding & 0x1f));
-
-            if (!isCmasRecord && encoding == UserData.ENCODING_GSM_DCS) {
-                bos.write(8, 0);        // GSM DCS: 7 bit default alphabet, no msg class
-            }
-
-            if (!isCmasRecord) {
-                bos.write(8, charCount);
-            }
-            byte[] bodySeptets = Arrays.copyOfRange(encodedBody, 1, encodedBody.length);
-            bos.writeByteArray(charCount * 7, bodySeptets);
-            bos.write(padBits, 0);      // pad to octet boundary
-        } else if (encoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) {
-            // 6 bit packed encoding with 0x20 offset (ASCII 0x20 - 0x60)
-            int charCount = body.length();
-            int recordBits = (charCount * 6) + 21;      // add 21 bits for header fields
-            int recordOctets = (recordBits + 7) / 8;    // round up to octet boundary
-            int padBits = (recordOctets * 8) - recordBits;
-
-            bos.write(8, recordOctets);
-
-            bos.write(5, (encoding & 0x1f));
-            bos.write(8, UserData.IS91_MSG_TYPE_SHORT_MESSAGE);
-            bos.write(8, charCount);
-
-            for (int i = 0; i < charCount; i++) {
-                bos.write(6, ((int) body.charAt(i) - 0x20));
-            }
-
-            bos.write(padBits, 0);      // pad to octet boundary
-        } else {
-            byte[] encodedBody;
-            switch (encoding) {
-                case UserData.ENCODING_UNICODE_16:
-                    encodedBody = body.getBytes("UTF-16BE");
-                    break;
-
-                case UserData.ENCODING_SHIFT_JIS:
-                    encodedBody = body.getBytes("Shift_JIS");
-                    break;
-
-                case UserData.ENCODING_KOREAN:
-                    encodedBody = body.getBytes("KSC5601");
-                    break;
-
-                case UserData.ENCODING_LATIN_HEBREW:
-                    encodedBody = body.getBytes("ISO-8859-8");
-                    break;
-
-                case UserData.ENCODING_LATIN:
-                default:
-                    encodedBody = body.getBytes("ISO-8859-1");
-                    break;
-            }
-            int charCount = body.length();              // use actual char count for num fields
-            int recordOctets = encodedBody.length + 1;  // add 1 byte for encoding and pad bits
-            if (!isCmasRecord) {
-                recordOctets++;                         // add 8 bits for num_fields
-            }
-            bos.write(8, recordOctets);
-            bos.write(5, (encoding & 0x1f));
-            if (!isCmasRecord) {
-                bos.write(8, charCount);
-            }
-            bos.writeByteArray(encodedBody.length * 8, encodedBody);
-            bos.write(3, 0);            // pad to octet boundary
-        }
-    }
-
-    private static final String TEST_TEXT = "This is a test CDMA cell broadcast message..."
-            + "678901234567890123456789012345678901234567890";
-
-    private static final String PRES_ALERT =
-            "THE PRESIDENT HAS ISSUED AN EMERGENCY ALERT. CHECK LOCAL MEDIA FOR MORE DETAILS";
-
-    private static final String EXTREME_ALERT = "FLASH FLOOD WARNING FOR SOUTH COCONINO COUNTY"
-            + " - NORTH CENTRAL ARIZONA UNTIL 415 PM MST";
-
-    private static final String SEVERE_ALERT = "SEVERE WEATHER WARNING FOR SOMERSET COUNTY"
-            + " - NEW JERSEY UNTIL 415 PM MST";
-
-    private static final String AMBER_ALERT =
-            "AMBER ALERT:Mountain View,CA VEH'07 Blue Honda Civic CA LIC 5ABC123";
-
-    private static final String MONTHLY_TEST_ALERT = "This is a test of the emergency alert system."
-            + " This is only a test. 89012345678901234567890";
-
-    private static final String IS91_TEXT = "IS91 SHORT MSG";   // max length 14 chars
-
-    /**
-     * Verify that the SmsCbMessage has the correct values for CDMA.
-     * @param cbMessage the message to test
-     */
-    private static void verifyCbValues(SmsCbMessage cbMessage) {
-        assertEquals(SmsCbMessage.MESSAGE_FORMAT_3GPP2, cbMessage.getMessageFormat());
-        assertEquals(SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE, cbMessage.getGeographicalScope());
-        assertEquals(false, cbMessage.isEtwsMessage()); // ETWS on CDMA not currently supported
-    }
-
-    private static void doTestNonEmergencyBroadcast(int encoding) throws Exception {
-        SmsMessage msg = createBroadcastSmsMessage(123, 456, BearerData.PRIORITY_NORMAL,
-                BearerData.LANGUAGE_ENGLISH, encoding, TEST_TEXT);
-
-        SmsCbMessage cbMessage = msg.parseBroadcastSms("", 0, 1);
-        verifyCbValues(cbMessage);
-        assertEquals(123, cbMessage.getServiceCategory());
-        assertEquals(456, cbMessage.getSerialNumber());
-        assertEquals(SmsCbMessage.MESSAGE_PRIORITY_NORMAL, cbMessage.getMessagePriority());
-        assertEquals("en", cbMessage.getLanguageCode());
-        assertEquals(TEST_TEXT, cbMessage.getMessageBody());
-        assertEquals(false, cbMessage.isEmergencyMessage());
-        assertEquals(false, cbMessage.isCmasMessage());
-    }
-
-    @Test @SmallTest
-    public void testNonEmergencyBroadcast7bitAscii() throws Exception {
-        doTestNonEmergencyBroadcast(UserData.ENCODING_7BIT_ASCII);
-    }
-
-    @Test @SmallTest
-    public void testNonEmergencyBroadcast7bitGsm() throws Exception {
-        doTestNonEmergencyBroadcast(UserData.ENCODING_GSM_7BIT_ALPHABET);
-    }
-
-    @Test @SmallTest
-    public void testNonEmergencyBroadcast16bitUnicode() throws Exception {
-        doTestNonEmergencyBroadcast(UserData.ENCODING_UNICODE_16);
-    }
-
-    @Test @SmallTest
-    public void testNonEmergencyBroadcastIs91Extended() throws Exception {
-        // IS-91 doesn't support language or priority subparameters, max 14 chars text
-        SmsMessage msg = createBroadcastSmsMessage(987, 654, -1, -1,
-                UserData.ENCODING_IS91_EXTENDED_PROTOCOL, IS91_TEXT);
-
-        SmsCbMessage cbMessage = msg.parseBroadcastSms("", 0, 1);
-        verifyCbValues(cbMessage);
-        assertEquals(987, cbMessage.getServiceCategory());
-        assertEquals(654, cbMessage.getSerialNumber());
-        assertEquals(SmsCbMessage.MESSAGE_PRIORITY_NORMAL, cbMessage.getMessagePriority());
-        assertEquals(null, cbMessage.getLanguageCode());
-        assertEquals(IS91_TEXT, cbMessage.getMessageBody());
-        assertEquals(false, cbMessage.isEmergencyMessage());
-        assertEquals(false, cbMessage.isCmasMessage());
-    }
-
-    private static void doTestCmasBroadcast(int serviceCategory, int messageClass, String body)
-            throws Exception {
-        SmsMessage msg = createCmasSmsMessage(
-                serviceCategory, 1234, BearerData.PRIORITY_EMERGENCY, BearerData.LANGUAGE_ENGLISH,
-                UserData.ENCODING_7BIT_ASCII, body, -1, -1, -1, -1, -1);
-
-        SmsCbMessage cbMessage = msg.parseBroadcastSms("", 0, 1);
-        verifyCbValues(cbMessage);
-        assertEquals(serviceCategory, cbMessage.getServiceCategory());
-        assertEquals(1234, cbMessage.getSerialNumber());
-        assertEquals(SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, cbMessage.getMessagePriority());
-        assertEquals("en", cbMessage.getLanguageCode());
-        assertEquals(body, cbMessage.getMessageBody());
-        assertEquals(true, cbMessage.isEmergencyMessage());
-        assertEquals(true, cbMessage.isCmasMessage());
-        SmsCbCmasInfo cmasInfo = cbMessage.getCmasWarningInfo();
-        assertEquals(messageClass, cmasInfo.getMessageClass());
-        assertEquals(SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN, cmasInfo.getCategory());
-        assertEquals(SmsCbCmasInfo.CMAS_RESPONSE_TYPE_UNKNOWN, cmasInfo.getResponseType());
-        assertEquals(SmsCbCmasInfo.CMAS_SEVERITY_UNKNOWN, cmasInfo.getSeverity());
-        assertEquals(SmsCbCmasInfo.CMAS_URGENCY_UNKNOWN, cmasInfo.getUrgency());
-        assertEquals(SmsCbCmasInfo.CMAS_CERTAINTY_UNKNOWN, cmasInfo.getCertainty());
-    }
-
-    @Test @SmallTest
-    public void testCmasPresidentialAlert() throws Exception {
-        doTestCmasBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT,
-                SmsCbCmasInfo.CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT, PRES_ALERT);
-    }
-
-    @Test @SmallTest
-    public void testCmasExtremeAlert() throws Exception {
-        doTestCmasBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
-                SmsCbCmasInfo.CMAS_CLASS_EXTREME_THREAT, EXTREME_ALERT);
-    }
-
-    @Test @SmallTest
-    public void testCmasSevereAlert() throws Exception {
-        doTestCmasBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT,
-                SmsCbCmasInfo.CMAS_CLASS_SEVERE_THREAT, SEVERE_ALERT);
-    }
-
-    @Test @SmallTest
-    public void testCmasAmberAlert() throws Exception {
-        doTestCmasBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY,
-                SmsCbCmasInfo.CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY, AMBER_ALERT);
-    }
-
-    @Test @SmallTest
-    public void testCmasTestMessage() throws Exception {
-        doTestCmasBroadcast(SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE,
-                SmsCbCmasInfo.CMAS_CLASS_REQUIRED_MONTHLY_TEST, MONTHLY_TEST_ALERT);
-    }
-
-    @Test @SmallTest
-    public void testCmasExtremeAlertType1Elements() throws Exception {
-        SmsMessage msg = createCmasSmsMessage(SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
-                5678, BearerData.PRIORITY_EMERGENCY, BearerData.LANGUAGE_ENGLISH,
-                UserData.ENCODING_7BIT_ASCII, EXTREME_ALERT, SmsCbCmasInfo.CMAS_CATEGORY_ENV,
-                SmsCbCmasInfo.CMAS_RESPONSE_TYPE_MONITOR, SmsCbCmasInfo.CMAS_SEVERITY_SEVERE,
-                SmsCbCmasInfo.CMAS_URGENCY_EXPECTED, SmsCbCmasInfo.CMAS_CERTAINTY_LIKELY);
-
-        SmsCbMessage cbMessage = msg.parseBroadcastSms("", 0, 1);
-        verifyCbValues(cbMessage);
-        assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
-                cbMessage.getServiceCategory());
-        assertEquals(5678, cbMessage.getSerialNumber());
-        assertEquals(SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, cbMessage.getMessagePriority());
-        assertEquals("en", cbMessage.getLanguageCode());
-        assertEquals(EXTREME_ALERT, cbMessage.getMessageBody());
-        assertEquals(true, cbMessage.isEmergencyMessage());
-        assertEquals(true, cbMessage.isCmasMessage());
-        SmsCbCmasInfo cmasInfo = cbMessage.getCmasWarningInfo();
-        assertEquals(SmsCbCmasInfo.CMAS_CLASS_EXTREME_THREAT, cmasInfo.getMessageClass());
-        assertEquals(SmsCbCmasInfo.CMAS_CATEGORY_ENV, cmasInfo.getCategory());
-        assertEquals(SmsCbCmasInfo.CMAS_RESPONSE_TYPE_MONITOR, cmasInfo.getResponseType());
-        assertEquals(SmsCbCmasInfo.CMAS_SEVERITY_SEVERE, cmasInfo.getSeverity());
-        assertEquals(SmsCbCmasInfo.CMAS_URGENCY_EXPECTED, cmasInfo.getUrgency());
-        assertEquals(SmsCbCmasInfo.CMAS_CERTAINTY_LIKELY, cmasInfo.getCertainty());
-    }
-
-    // VZW requirement is to discard message with unsupported charset. Verify that we return null
-    // for this unsupported character set.
-    @FlakyTest
-    @Ignore
-    @Test
-    @SmallTest
-    public void testCmasUnsupportedCharSet() throws Exception {
-        SmsMessage msg = createCmasSmsMessage(SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
-                12345, BearerData.PRIORITY_EMERGENCY, BearerData.LANGUAGE_ENGLISH,
-                0x1F, EXTREME_ALERT, -1, -1, -1, -1, -1);
-
-        SmsCbMessage cbMessage = msg.parseBroadcastSms("", 0, 1);
-        assertNull("expected null for unsupported charset", cbMessage);
-    }
-
-    // VZW requirement is to discard message with unsupported charset. Verify that we return null
-    // for this unsupported character set.
-    @Test @SmallTest
-    public void testCmasUnsupportedCharSet2() throws Exception {
-        SmsMessage msg = createCmasSmsMessage(SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT,
-                67890, BearerData.PRIORITY_EMERGENCY, BearerData.LANGUAGE_ENGLISH,
-                UserData.ENCODING_KOREAN, EXTREME_ALERT, -1, -1, -1, -1, -1);
-
-        SmsCbMessage cbMessage = msg.parseBroadcastSms("", 0, 1);
-        assertNull("expected null for unsupported charset", cbMessage);
-    }
-
-    // VZW requirement is to discard message without record type 0. The framework will decode it
-    // and the app will discard it.
-    @Test @SmallTest
-    public void testCmasNoRecordType0() throws Exception {
-        SmsMessage msg = createCmasSmsMessage(
-                SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT, 1234,
-                BearerData.PRIORITY_EMERGENCY, BearerData.LANGUAGE_ENGLISH,
-                UserData.ENCODING_7BIT_ASCII, null, -1, -1, -1, -1, -1);
-
-        SmsCbMessage cbMessage = msg.parseBroadcastSms("", 0, 1);
-        verifyCbValues(cbMessage);
-        assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT,
-                cbMessage.getServiceCategory());
-        assertEquals(1234, cbMessage.getSerialNumber());
-        assertEquals(SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, cbMessage.getMessagePriority());
-        assertEquals("en", cbMessage.getLanguageCode());
-        assertEquals(null, cbMessage.getMessageBody());
-        assertEquals(true, cbMessage.isEmergencyMessage());
-        assertEquals(true, cbMessage.isCmasMessage());
-        SmsCbCmasInfo cmasInfo = cbMessage.getCmasWarningInfo();
-        assertEquals(SmsCbCmasInfo.CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT, cmasInfo.getMessageClass());
-        assertEquals(SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN, cmasInfo.getCategory());
-        assertEquals(SmsCbCmasInfo.CMAS_RESPONSE_TYPE_UNKNOWN, cmasInfo.getResponseType());
-        assertEquals(SmsCbCmasInfo.CMAS_SEVERITY_UNKNOWN, cmasInfo.getSeverity());
-        assertEquals(SmsCbCmasInfo.CMAS_URGENCY_UNKNOWN, cmasInfo.getUrgency());
-        assertEquals(SmsCbCmasInfo.CMAS_CERTAINTY_UNKNOWN, cmasInfo.getCertainty());
-    }
-
-    // Make sure we don't throw an exception if we feed completely random data to BearerStream.
-    @Test @SmallTest
-    public void testRandomBearerStreamData() {
-        Random r = new Random(54321);
-        for (int run = 0; run < 1000; run++) {
-            int len = r.nextInt(140);
-            byte[] data = new byte[len];
-            for (int i = 0; i < len; i++) {
-                data[i] = (byte) r.nextInt(256);
-            }
-            // Rlog.d("CdmaSmsCbTest", "trying random bearer data run " + run + " length " + len);
-            try {
-                int category = 0x0ff0 + r.nextInt(32);  // half CMAS, half non-CMAS
-                CdmaSmsMessage cdmaSmsMessage = createBroadcastParcel(category);
-                SmsMessage msg = createMessageFromParcel(cdmaSmsMessage, data);
-                SmsCbMessage cbMessage = msg.parseBroadcastSms("", 0, 1);
-                // with random input, cbMessage will almost always be null (log when it isn't)
-                if (cbMessage != null) {
-                    Rlog.d("CdmaSmsCbTest", "success: " + cbMessage);
-                }
-            } catch (Exception e) {
-                Rlog.d("CdmaSmsCbTest", "exception thrown", e);
-                fail("Exception in decoder at run " + run + " length " + len + ": " + e);
-            }
-        }
-    }
-
-    // Make sure we don't throw an exception if we put random data in the UserData subparam.
-    @Test @SmallTest
-    public void testRandomUserData() {
-        Random r = new Random(94040);
-        for (int run = 0; run < 1000; run++) {
-            int category = 0x0ff0 + r.nextInt(32);  // half CMAS, half non-CMAS
-            CdmaSmsMessage cdmaSmsMessage = createBroadcastParcel(category);
-            int len = r.nextInt(140);
-            // Rlog.d("CdmaSmsCbTest", "trying random user data run " + run + " length " + len);
-
-            try {
-                BitwiseOutputStream bos = createBearerDataStream(r.nextInt(65536), r.nextInt(4),
-                        r.nextInt(256));
-
-                bos.write(8, SUBPARAM_USER_DATA);
-                bos.write(8, len);
-
-                for (int i = 0; i < len; i++) {
-                    bos.write(8, r.nextInt(256));
-                }
-
-                SmsMessage msg = createMessageFromParcel(cdmaSmsMessage, bos.toByteArray());
-                SmsCbMessage cbMessage = msg.parseBroadcastSms("", 0, 1);
-            } catch (Exception e) {
-                Rlog.d("CdmaSmsCbTest", "exception thrown", e);
-                fail("Exception in decoder at run " + run + " length " + len + ": " + e);
-            }
-        }
-    }
-
-    /**
-     * Initialize a Parcel for incoming Service Category Program Data teleservice. The caller will
-     * write the bearer data and then convert it to an SmsMessage.
-     * @return the initialized Parcel
-     */
-    private static CdmaSmsMessage createServiceCategoryProgramDataParcel() {
-        CdmaSmsMessage msg = new CdmaSmsMessage();
-
-        msg.teleserviceId = SmsEnvelope.TELESERVICE_SCPT;
-        msg.isServicePresent = false;
-        msg.serviceCategory = 0;
-
-        // placeholder address (RIL may generate a different placeholder address for broadcasts)
-        msg.address.digitMode = CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF;
-        msg.address.numberMode = CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK;
-        msg.address.numberType = CdmaSmsAddress.TON_UNKNOWN;
-        msg.address.numberPlan = CdmaSmsAddress.NUMBERING_PLAN_ISDN_TELEPHONY;
-        msg.subAddress.subaddressType = 0;
-        msg.subAddress.odd = false;
-        return msg;
-    }
-
-    private static final String CAT_EXTREME_THREAT = "Extreme Threat to Life and Property";
-    private static final String CAT_SEVERE_THREAT = "Severe Threat to Life and Property";
-    private static final String CAT_AMBER_ALERTS = "AMBER Alerts";
-
-    @Test @SmallTest
-    public void testServiceCategoryProgramDataAddCategory() throws Exception {
-        CdmaSmsMessage cdmaSmsMessage = createServiceCategoryProgramDataParcel();
-        BitwiseOutputStream bos = createBearerDataStream(123, -1, -1);
-
-        int categoryNameLength = CAT_EXTREME_THREAT.length();
-        int subparamLengthBits = (53 + (categoryNameLength * 7));
-        int subparamLengthBytes = (subparamLengthBits + 7) / 8;
-        int subparamPadBits = (subparamLengthBytes * 8) - subparamLengthBits;
-
-        bos.write(8, SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA);
-        bos.write(8, subparamLengthBytes);
-        bos.write(5, UserData.ENCODING_7BIT_ASCII);
-
-        bos.write(4, CdmaSmsCbProgramData.OPERATION_ADD_CATEGORY);
-        bos.write(8, (SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT >>> 8));
-        bos.write(8, (SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT & 0xff));
-        bos.write(8, BearerData.LANGUAGE_ENGLISH);
-        bos.write(8, 100);  // max messages
-        bos.write(4, CdmaSmsCbProgramData.ALERT_OPTION_DEFAULT_ALERT);
-
-        bos.write(8, categoryNameLength);
-        for (int i = 0; i < categoryNameLength; i++) {
-            bos.write(7, CAT_EXTREME_THREAT.charAt(i));
-        }
-        bos.write(subparamPadBits, 0);
-
-        SmsMessage msg = createMessageFromParcel(cdmaSmsMessage, bos.toByteArray());
-        assertNotNull(msg);
-        msg.parseSms();
-        List<CdmaSmsCbProgramData> programDataList = msg.getSmsCbProgramData();
-        assertNotNull(programDataList);
-        assertEquals(1, programDataList.size());
-        CdmaSmsCbProgramData programData = programDataList.get(0);
-        assertEquals(CdmaSmsCbProgramData.OPERATION_ADD_CATEGORY, programData.getOperation());
-        assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_EXTREME_THREAT, programData.getCategory());
-        assertEquals(CAT_EXTREME_THREAT, programData.getCategoryName());
-        assertEquals(BearerData.LANGUAGE_ENGLISH, programData.getLanguage());
-        assertEquals(100, programData.getMaxMessages());
-        assertEquals(CdmaSmsCbProgramData.ALERT_OPTION_DEFAULT_ALERT, programData.getAlertOption());
-    }
-
-    @Test @SmallTest
-    public void testServiceCategoryProgramDataDeleteTwoCategories() throws Exception {
-        CdmaSmsMessage cdmaSmsMessage = createServiceCategoryProgramDataParcel();
-        BitwiseOutputStream bos = createBearerDataStream(456, -1, -1);
-
-        int category1NameLength = CAT_SEVERE_THREAT.length();
-        int category2NameLength = CAT_AMBER_ALERTS.length();
-
-        int subparamLengthBits = (101 + (category1NameLength * 7) + (category2NameLength * 7));
-        int subparamLengthBytes = (subparamLengthBits + 7) / 8;
-        int subparamPadBits = (subparamLengthBytes * 8) - subparamLengthBits;
-
-        bos.write(8, SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA);
-        bos.write(8, subparamLengthBytes);
-        bos.write(5, UserData.ENCODING_7BIT_ASCII);
-
-        bos.write(4, CdmaSmsCbProgramData.OPERATION_DELETE_CATEGORY);
-        bos.write(8, (SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT >>> 8));
-        bos.write(8, (SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT & 0xff));
-        bos.write(8, BearerData.LANGUAGE_ENGLISH);
-        bos.write(8, 0);  // max messages
-        bos.write(4, CdmaSmsCbProgramData.ALERT_OPTION_NO_ALERT);
-
-        bos.write(8, category1NameLength);
-        for (int i = 0; i < category1NameLength; i++) {
-            bos.write(7, CAT_SEVERE_THREAT.charAt(i));
-        }
-
-        bos.write(4, CdmaSmsCbProgramData.OPERATION_DELETE_CATEGORY);
-        bos.write(8, (SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY >>> 8));
-        bos.write(8, (SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY & 0xff));
-        bos.write(8, BearerData.LANGUAGE_ENGLISH);
-        bos.write(8, 0);  // max messages
-        bos.write(4, CdmaSmsCbProgramData.ALERT_OPTION_NO_ALERT);
-
-        bos.write(8, category2NameLength);
-        for (int i = 0; i < category2NameLength; i++) {
-            bos.write(7, CAT_AMBER_ALERTS.charAt(i));
-        }
-
-        bos.write(subparamPadBits, 0);
-
-        SmsMessage msg = createMessageFromParcel(cdmaSmsMessage, bos.toByteArray());
-        assertNotNull(msg);
-        msg.parseSms();
-        List<CdmaSmsCbProgramData> programDataList = msg.getSmsCbProgramData();
-        assertNotNull(programDataList);
-        assertEquals(2, programDataList.size());
-
-        CdmaSmsCbProgramData programData = programDataList.get(0);
-        assertEquals(CdmaSmsCbProgramData.OPERATION_DELETE_CATEGORY, programData.getOperation());
-        assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_SEVERE_THREAT, programData.getCategory());
-        assertEquals(CAT_SEVERE_THREAT, programData.getCategoryName());
-        assertEquals(BearerData.LANGUAGE_ENGLISH, programData.getLanguage());
-        assertEquals(0, programData.getMaxMessages());
-        assertEquals(CdmaSmsCbProgramData.ALERT_OPTION_NO_ALERT, programData.getAlertOption());
-
-        programData = programDataList.get(1);
-        assertEquals(CdmaSmsCbProgramData.OPERATION_DELETE_CATEGORY, programData.getOperation());
-        assertEquals(SmsEnvelope.SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY,
-                programData.getCategory());
-        assertEquals(CAT_AMBER_ALERTS, programData.getCategoryName());
-        assertEquals(BearerData.LANGUAGE_ENGLISH, programData.getLanguage());
-        assertEquals(0, programData.getMaxMessages());
-        assertEquals(CdmaSmsCbProgramData.ALERT_OPTION_NO_ALERT, programData.getAlertOption());
-    }
-
-    private static final byte[] CMAS_TEST_BEARER_DATA = {
-        0x00, 0x03, 0x1C, 0x78, 0x00, 0x01, 0x59, 0x02, (byte) 0xB8, 0x00, 0x02, 0x10, (byte) 0xAA,
-        0x68, (byte) 0xD3, (byte) 0xCD, 0x06, (byte) 0x9E, 0x68, 0x30, (byte) 0xA0, (byte) 0xE9,
-        (byte) 0x97, (byte) 0x9F, 0x44, 0x1B, (byte) 0xF3, 0x20, (byte) 0xE9, (byte) 0xA3,
-        0x2A, 0x08, 0x7B, (byte) 0xF6, (byte) 0xED, (byte) 0xCB, (byte) 0xCB, 0x1E, (byte) 0x9C,
-        0x3B, 0x10, 0x4D, (byte) 0xDF, (byte) 0x8B, 0x4E,
-        (byte) 0xCC, (byte) 0xA8, 0x20, (byte) 0xEC, (byte) 0xCB, (byte) 0xCB, (byte) 0xA2, 0x0A,
-        0x7E, 0x79, (byte) 0xF4, (byte) 0xCB, (byte) 0xB5, 0x72, 0x0A, (byte) 0x9A, 0x34,
-        (byte) 0xF3, 0x41, (byte) 0xA7, (byte) 0x9A, 0x0D, (byte) 0xFB, (byte) 0xB6, 0x79, 0x41,
-        (byte) 0x85, 0x07, 0x4C, (byte) 0xBC, (byte) 0xFA, 0x2E, 0x00, 0x08, 0x20, 0x58, 0x38,
-        (byte) 0x88, (byte) 0x80, 0x10, 0x54, 0x06, 0x38, 0x20, 0x60,
-        0x30, (byte) 0xA8, (byte) 0x81, (byte) 0x90, 0x20, 0x08
-    };
-
-    // Test case for CMAS test message received on the Sprint network.
-    @Test @SmallTest
-    public void testDecodeRawBearerData() throws Exception {
-        CdmaSmsMessage cdmaSmsMessage = createBroadcastParcel(SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE);
-        SmsMessage msg = createMessageFromParcel(cdmaSmsMessage, CMAS_TEST_BEARER_DATA);
-
-        SmsCbMessage cbMessage = msg.parseBroadcastSms("", 0, 1);
-        assertNotNull("expected non-null for bearer data", cbMessage);
-        assertEquals("geoScope", cbMessage.getGeographicalScope(), 1);
-        assertEquals("serialNumber", cbMessage.getSerialNumber(), 51072);
-        assertEquals("serviceCategory", cbMessage.getServiceCategory(),
-                SmsEnvelope.SERVICE_CATEGORY_CMAS_TEST_MESSAGE);
-        assertEquals("payload", cbMessage.getMessageBody(),
-                "This is a test of the Commercial Mobile Alert System. This is only a test.");
-
-        SmsCbCmasInfo cmasInfo = cbMessage.getCmasWarningInfo();
-        assertNotNull("expected non-null for CMAS info", cmasInfo);
-        assertEquals("category", cmasInfo.getCategory(), SmsCbCmasInfo.CMAS_CATEGORY_OTHER);
-        assertEquals("responseType", cmasInfo.getResponseType(),
-                SmsCbCmasInfo.CMAS_RESPONSE_TYPE_NONE);
-        assertEquals("severity", cmasInfo.getSeverity(), SmsCbCmasInfo.CMAS_SEVERITY_SEVERE);
-        assertEquals("urgency", cmasInfo.getUrgency(), SmsCbCmasInfo.CMAS_URGENCY_EXPECTED);
-        assertEquals("certainty", cmasInfo.getCertainty(), SmsCbCmasInfo.CMAS_CERTAINTY_LIKELY);
-    }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java
deleted file mode 100644
index 118adbc..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/CdmaSmsDispatcherTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.cdma;
-
-import static org.mockito.Mockito.*;
-
-import android.os.Binder;
-import android.os.HandlerThread;
-import android.os.Message;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.telephony.SMSDispatcher;
-import com.android.internal.telephony.SmsDispatchersController;
-import com.android.internal.telephony.TelephonyTest;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class CdmaSmsDispatcherTest extends TelephonyTest {
-    // Mocked classes
-    private SmsDispatchersController mSmsDispatchersController;
-    private SMSDispatcher.SmsTracker mSmsTracker;
-
-    private CdmaSMSDispatcher mCdmaSmsDispatcher;
-    private CdmaSmsDispatcherTestHandler mCdmaSmsDispatcherTestHandler;
-    private int mCallingUserId;
-
-    private class CdmaSmsDispatcherTestHandler extends HandlerThread {
-
-        private CdmaSmsDispatcherTestHandler(String name) {
-            super(name);
-        }
-
-        @Override
-        public void onLooperPrepared() {
-            mCdmaSmsDispatcher = new CdmaSMSDispatcher(mPhone, mSmsDispatchersController);
-            setReady(true);
-        }
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        super.setUp(getClass().getSimpleName());
-        mSmsDispatchersController = mock(SmsDispatchersController.class);
-        mSmsTracker = mock(SMSDispatcher.SmsTracker.class);
-
-        setupMockPackagePermissionChecks();
-        doReturn(mSmsUsageMonitor).when(mSmsDispatchersController).getUsageMonitor();
-        mCdmaSmsDispatcherTestHandler = new CdmaSmsDispatcherTestHandler(TAG);
-        mCdmaSmsDispatcherTestHandler.start();
-        waitUntilReady();
-        mCallingUserId = Binder.getCallingUserHandle().getIdentifier();
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        mCdmaSmsDispatcherTestHandler.quit();
-        mCdmaSmsDispatcherTestHandler.join();
-        mCdmaSmsDispatcherTestHandler = null;
-        mCdmaSmsDispatcher = null;
-        super.tearDown();
-    }
-
-    @Test @SmallTest
-    public void testSendSms() {
-        doReturn(mServiceState).when(mPhone).getServiceState();
-        mCdmaSmsDispatcher.sendSms(mSmsTracker);
-        verify(mSimulatedCommandsVerifier).sendCdmaSms(nullable(byte[].class), any(Message.class));
-    }
-
-    @Test @SmallTest
-    public void testSendText() {
-        mCdmaSmsDispatcher.sendText("111"/* desAddr*/, "222" /*scAddr*/, TAG,
-                null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
-        verify(mSimulatedCommandsVerifier).sendCdmaSms(any(byte[].class), any(Message.class));
-    }
-
-    @Test @SmallTest
-    public void testSendTextWithOutDesAddr() {
-        mCdmaSmsDispatcher.sendText(null, "222" /*scAddr*/, TAG,
-                null, null, null, null, mCallingUserId, false, -1, false, -1, false, 0L);
-        verify(mSimulatedCommandsVerifier, times(0)).sendImsGsmSms(anyString(), anyString(),
-                anyInt(), anyInt(), any(Message.class));
-    }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsAddressTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsAddressTest.java
deleted file mode 100644
index 0c706f4..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsAddressTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.cdma.sms;
-
-import static org.junit.Assert.assertArrayEquals;
-
-import android.test.AndroidTestCase;
-
-import org.junit.Test;
-
-/**
- * Tests for {@link CdmaSmsAddress}.
- */
-public class CdmaSmsAddressTest extends AndroidTestCase {
-    @Test
-    public void testNumberAddress() {
-        String address = "3141592653";
-        CdmaSmsAddress cdmaAddress = CdmaSmsAddress.parse(address);
-        assertEquals(address, cdmaAddress.address);
-        assertEquals(CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF, cdmaAddress.digitMode);
-        assertEquals(CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK, cdmaAddress.numberMode);
-        assertArrayEquals(CdmaSmsAddress.parseToDtmf(address), cdmaAddress.origBytes);
-    }
-
-    @Test
-    public void testNumberWithSugar() {
-        String address = "(314)1592653";
-        CdmaSmsAddress cdmaAddress = CdmaSmsAddress.parse(address);
-        assertEquals(address, cdmaAddress.address);
-        assertEquals(CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF, cdmaAddress.digitMode);
-        assertEquals(CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK, cdmaAddress.numberMode);
-        assertArrayEquals(CdmaSmsAddress.parseToDtmf("3141592653"), cdmaAddress.origBytes);
-    }
-
-    @Test
-    public void testInternationalAddress() {
-        String address = "+10068";
-        CdmaSmsAddress cdmaAddress = CdmaSmsAddress.parse(address);
-        assertEquals(address, cdmaAddress.address);
-        assertEquals(CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR, cdmaAddress.digitMode);
-        assertEquals(CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK, cdmaAddress.numberMode);
-        assertEquals(CdmaSmsAddress.NUMBERING_PLAN_ISDN_TELEPHONY, cdmaAddress.numberPlan);
-        assertEquals(CdmaSmsAddress.TON_INTERNATIONAL_OR_IP, cdmaAddress.ton);
-        assertArrayEquals(UserData.stringToAscii("10068"), cdmaAddress.origBytes);
-    }
-
-    @Test
-    public void testEmailAddress() {
-        String address = "fb769394+10086@tvb.com";
-        CdmaSmsAddress cdmaAddress = CdmaSmsAddress.parse(address);
-        assertEquals(address, cdmaAddress.address);
-        assertEquals(CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR, cdmaAddress.digitMode);
-        assertEquals(CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK, cdmaAddress.numberMode);
-        assertEquals(CdmaSmsAddress.TON_NATIONAL_OR_EMAIL, cdmaAddress.ton);
-        assertArrayEquals(UserData.stringToAscii(address), cdmaAddress.origBytes);
-    }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java b/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java
deleted file mode 100644
index d2a6922..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/cdma/sms/CdmaSmsTest.java
+++ /dev/null
@@ -1,1069 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.cdma.sms;
-
-import android.telephony.TelephonyManager;
-import android.test.AndroidTestCase;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
-import com.android.internal.telephony.SmsHeader;
-import com.android.internal.telephony.SmsMessageBase;
-import com.android.internal.telephony.cdma.SmsMessage;
-import com.android.internal.util.HexDump;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-public class CdmaSmsTest extends AndroidTestCase {
-
-    // CJK ideographs, Hiragana, Katakana, full width letters, Cyrillic, etc.
-    private static final String sUnicodeChars = "\u4e00\u4e01\u4e02\u4e03" +
-            "\u4e04\u4e05\u4e06\u4e07\u4e08\u4e09\u4e0a\u4e0b\u4e0c\u4e0d" +
-            "\u4e0e\u4e0f\u3041\u3042\u3043\u3044\u3045\u3046\u3047\u3048" +
-            "\u30a1\u30a2\u30a3\u30a4\u30a5\u30a6\u30a7\u30a8" +
-            "\uff10\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18" +
-            "\uff70\uff71\uff72\uff73\uff74\uff75\uff76\uff77\uff78" +
-            "\u0400\u0401\u0402\u0403\u0404\u0405\u0406\u0407\u0408" +
-            "\u00a2\u00a9\u00ae\u2122";
-
-    // "Hello, world" in Japanese.
-    private static final String sHelloWorldJa = "\u3053\u3093\u306b\u3061\u306f\u4e16\u754c";
-
-    @SmallTest
-    public void testCdmaSmsAddrParsing() throws Exception {
-        CdmaSmsAddress addr = CdmaSmsAddress.parse("6502531000");
-        assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
-        assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
-        assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
-        assertEquals(addr.numberOfDigits, 10);
-        assertEquals(addr.origBytes.length, 10);
-        byte[] data = {6, 5, 10, 2, 5, 3, 1, 10, 10, 10};
-        for (int i = 0; i < data.length; i++) {
-            assertEquals(addr.origBytes[i], data[i]);
-        }
-        addr = CdmaSmsAddress.parse("(650) 253-1000");
-        assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
-        assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
-        assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
-        assertEquals(addr.numberOfDigits, 10);
-        assertEquals(addr.origBytes.length, 10);
-        byte[] data2 = {6, 5, 10, 2, 5, 3, 1, 10, 10, 10};
-        for (int i = 0; i < data2.length; i++) {
-            assertEquals(addr.origBytes[i], data2[i]);
-        }
-        addr = CdmaSmsAddress.parse("650.253.1000");
-        assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
-        assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
-        assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
-        assertEquals(addr.numberOfDigits, 10);
-        assertEquals(addr.origBytes.length, 10);
-        byte[] data5 = {6, 5, 10, 2, 5, 3, 1, 10, 10, 10};
-        for (int i = 0; i < data2.length; i++) {
-            assertEquals(addr.origBytes[i], data5[i]);
-        }
-        addr = CdmaSmsAddress.parse("(+886) 917 222 555");
-        assertEquals(addr.ton, CdmaSmsAddress.TON_INTERNATIONAL_OR_IP);
-        assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR);
-        assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
-        assertEquals(addr.numberOfDigits, 12);
-        assertEquals(addr.origBytes.length, 12);
-        String expectedAddr = "886917222555";
-        for (int i = 0; i < addr.numberOfDigits; i++) {
-            assertEquals((int) expectedAddr.charAt(i), addr.origBytes[i]);
-        }
-        addr = CdmaSmsAddress.parse("(650) *253-1000 #600");
-        byte[] data4 = {6, 5, 10, 11, 2, 5, 3, 1, 10, 10, 10, 12, 6, 10, 10};
-        for (int i = 0; i < data4.length; i++) {
-            assertEquals(addr.origBytes[i], data4[i]);
-        }
-        String input = "x@y.com,a@b.com";
-        addr = CdmaSmsAddress.parse(input);
-        assertEquals(addr.ton, CdmaSmsAddress.TON_NATIONAL_OR_EMAIL);
-        assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR);
-        assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK);
-        assertEquals(addr.numberOfDigits, 15);
-        assertEquals(addr.origBytes.length, 15);
-        assertEquals(new String(addr.origBytes), input);
-        addr = CdmaSmsAddress.parse("foo bar");
-        assertEquals(addr.ton, CdmaSmsAddress.TON_UNKNOWN);
-        assertEquals(addr.digitMode, CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR);
-        assertEquals(addr.numberMode, CdmaSmsAddress.NUMBER_MODE_DATA_NETWORK);
-        assertEquals(addr.numberOfDigits, 6);
-        assertEquals(addr.origBytes.length, 6);
-        assertEquals(new String(addr.origBytes), "foobar");
-        addr = CdmaSmsAddress.parse("f\noo\tb   a\rr");
-        assertEquals(new String(addr.origBytes), "foobar");
-        assertEquals(CdmaSmsAddress.parse("f\u0000oo bar"), null);
-        assertEquals(CdmaSmsAddress.parse("f\u0007oo bar"), null);
-        assertEquals(CdmaSmsAddress.parse("f\u0080oo bar"), null);
-        assertEquals(CdmaSmsAddress.parse("f\u1ECFboo\u001fbar"), null);
-        assertEquals(CdmaSmsAddress.parse("f\u0080oo bar"), null);
-    }
-
-    @SmallTest
-    public void testRecipientAddress() throws Exception {
-        String pdu = "011a0000001002080d0003100160010610262d5ab500040401448888";
-        SmsMessage sms = SmsMessage.createFromEfRecord(0,
-                HexDump.hexStringToByteArray(pdu));
-        assertEquals("12222", sms.getRecipientAddress());
-    }
-
-    @SmallTest
-    public void testUserData7bitGsm() throws Exception {
-        String pdu = "00031040900112488ea794e074d69e1b7392c270326cde9e98";
-        BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
-        assertEquals("Test standard SMS", bearerData.userData.payloadStr);
-    }
-
-    @SmallTest
-    public void testUserData7bitAscii() throws Exception {
-        String pdu = "0003100160010610262d5ab500";
-        BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
-        assertEquals("bjjj", bearerData.userData.payloadStr);
-    }
-
-    @SmallTest
-    public void testUserData7bitAsciiTwo() throws Exception {
-        String pdu = "00031001d00109104539b4d052ebb3d0";
-        BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
-        assertEquals("SMS Rulz", bearerData.userData.payloadStr);
-    }
-
-    @SmallTest
-    public void testUserDataIa5() throws Exception {
-        String pdu = "00031002100109184539b4d052ebb3d0";
-        BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
-        assertEquals("SMS Rulz", bearerData.userData.payloadStr);
-    }
-
-    @SmallTest
-    public void testUserData7bitAsciiFeedback() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 0;
-        bearerData.hasUserDataHeader = false;
-        UserData userData = new UserData();
-        userData.payloadStr = "Test standard SMS";
-        userData.msgEncoding = UserData.ENCODING_7BIT_ASCII;
-        userData.msgEncodingSet = true;
-        bearerData.userData = userData;
-        byte []encodedSms = BearerData.encode(bearerData);
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        assertEquals(BearerData.MESSAGE_TYPE_DELIVER, revBearerData.messageType);
-        assertEquals(0, revBearerData.messageId);
-        assertEquals(false, revBearerData.hasUserDataHeader);
-        assertEquals(userData.msgEncoding, revBearerData.userData.msgEncoding);
-        assertEquals(userData.payloadStr.length(), revBearerData.userData.numFields);
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        userData.payloadStr = "Test \u007f standard \u0000 SMS";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals("Test   standard   SMS", revBearerData.userData.payloadStr);
-        userData.payloadStr = "Test \n standard \r SMS";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        userData.payloadStr = "";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-    }
-
-    @SmallTest
-    public void testUserData7bitGsmFeedback() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 0;
-        bearerData.hasUserDataHeader = false;
-        UserData userData = new UserData();
-        userData.payloadStr = "Test standard SMS";
-        userData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
-        userData.msgEncodingSet = true;
-        bearerData.userData = userData;
-        byte []encodedSms = BearerData.encode(bearerData);
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        assertEquals(BearerData.MESSAGE_TYPE_DELIVER, revBearerData.messageType);
-        assertEquals(0, revBearerData.messageId);
-        assertEquals(false, revBearerData.hasUserDataHeader);
-        assertEquals(userData.msgEncoding, revBearerData.userData.msgEncoding);
-        assertEquals(userData.payloadStr.length(), revBearerData.userData.numFields);
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        userData.payloadStr = "1234567";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        userData.payloadStr = "";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        userData.payloadStr = "12345678901234567890123456789012345678901234567890" +
-                "12345678901234567890123456789012345678901234567890" +
-                "12345678901234567890123456789012345678901234567890" +
-                "1234567890";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        userData.payloadStr = "Test \u007f illegal \u0000 SMS chars";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals("Test   illegal   SMS chars", revBearerData.userData.payloadStr);
-        userData.payloadStr = "More @ testing\nis great^|^~woohoo";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
-        concatRef.refNumber = 0xEE;
-        concatRef.msgCount = 2;
-        concatRef.seqNumber = 2;
-        concatRef.isEightBits = true;
-        SmsHeader smsHeader = new SmsHeader();
-        smsHeader.concatRef = concatRef;
-        byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
-        userData.userDataHeader = smsHeader;
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        SmsHeader decodedHeader = revBearerData.userData.userDataHeader;
-        assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
-        assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
-        assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
-    }
-
-    @SmallTest
-    public void testUserDataUtf16Feedback() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 0;
-        bearerData.hasUserDataHeader = false;
-        UserData userData = new UserData();
-        userData.payloadStr = "\u0160u\u1E5B\u0301r\u1ECFg\uD835\uDC1At\u00E9\u4E002\u3042";
-        userData.msgEncoding = UserData.ENCODING_UNICODE_16;
-        userData.msgEncodingSet = true;
-        bearerData.userData = userData;
-        byte []encodedSms = BearerData.encode(bearerData);
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        assertEquals(BearerData.MESSAGE_TYPE_DELIVER, revBearerData.messageType);
-        assertEquals(0, revBearerData.messageId);
-        assertEquals(false, revBearerData.hasUserDataHeader);
-        assertEquals(userData.msgEncoding, revBearerData.userData.msgEncoding);
-        assertEquals(userData.payloadStr.length(), revBearerData.userData.numFields);
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        userData.msgEncoding = UserData.ENCODING_OCTET;
-        userData.msgEncodingSet = false;
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals(BearerData.MESSAGE_TYPE_DELIVER, revBearerData.messageType);
-        assertEquals(0, revBearerData.messageId);
-        assertEquals(false, revBearerData.hasUserDataHeader);
-        assertEquals(userData.msgEncoding, revBearerData.userData.msgEncoding);
-        assertEquals(userData.payloadStr.length(), revBearerData.userData.numFields);
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        userData.payloadStr = "1234567";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        userData.payloadStr = "";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-    }
-
-    @SmallTest
-    public void testUserData7BitAsciiFeedback() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 0;
-        bearerData.hasUserDataHeader = false;
-        UserData userData = new UserData();
-        userData.payloadStr = "Test standard SMS";
-        userData.msgEncoding = UserData.ENCODING_7BIT_ASCII;
-        userData.msgEncodingSet = true;
-        bearerData.userData = userData;
-        byte[] encodedSms = BearerData.encode(bearerData);
-
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        assertEquals(userData.msgEncoding, revBearerData.userData.msgEncoding);
-        assertEquals(userData.payloadStr.length(), revBearerData.userData.numFields);
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-
-        userData.payloadStr = "1234567";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        userData.payloadStr = "";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        userData.payloadStr = "12345678901234567890123456789012345678901234567890" +
-                "12345678901234567890123456789012345678901234567890" +
-                "12345678901234567890123456789012345678901234567890" +
-                "1234567890";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        userData.payloadStr = "Test \u007f illegal \u0000 SMS chars";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals("Test   illegal   SMS chars", revBearerData.userData.payloadStr);
-        userData.payloadStr = "More @ testing\nis great^|^~woohoo";
-        revBearerData = BearerData.decode(BearerData.encode(bearerData));
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-    }
-
-    @SmallTest
-    public void testMonolithicOne() throws Exception {
-        String pdu = "0003200010010410168d2002010503060812011101590501c706069706180000000701c108" +
-                "01c00901800a01e00b01030c01c00d01070e05039acc13880f018011020566";
-        BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
-        assertEquals(bearerData.messageType, BearerData.MESSAGE_TYPE_SUBMIT);
-        assertEquals(bearerData.messageId, 1);
-        assertEquals(bearerData.priority, BearerData.PRIORITY_EMERGENCY);
-        assertEquals(bearerData.privacy, BearerData.PRIVACY_CONFIDENTIAL);
-        assertEquals(bearerData.userAckReq, true);
-        assertEquals(bearerData.readAckReq, true);
-        assertEquals(bearerData.deliveryAckReq, true);
-        assertEquals(bearerData.reportReq, false);
-        assertEquals(bearerData.numberOfMessages, 3);
-        assertEquals(bearerData.alert, BearerData.ALERT_HIGH_PRIO);
-        assertEquals(bearerData.language, BearerData.LANGUAGE_HEBREW);
-        assertEquals(bearerData.callbackNumber.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
-        assertEquals(bearerData.callbackNumber.numberMode,
-                     CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
-        assertEquals(bearerData.callbackNumber.ton, CdmaSmsAddress.TON_UNKNOWN);
-        assertEquals(bearerData.callbackNumber.numberPlan, CdmaSmsAddress.NUMBERING_PLAN_UNKNOWN);
-        assertEquals(bearerData.callbackNumber.numberOfDigits, 7);
-        assertEquals(bearerData.callbackNumber.address, "3598271");
-        assertEquals(bearerData.displayMode, BearerData.DISPLAY_MODE_USER);
-        assertEquals(bearerData.depositIndex, 1382);
-        assertEquals(bearerData.userResponseCode, 5);
-        assertEquals(bearerData.msgCenterTimeStamp.year, 2008);
-        assertEquals(bearerData.msgCenterTimeStamp.monthOrdinal, 12);
-        assertEquals(bearerData.msgCenterTimeStamp.monthDay, 1);
-        assertEquals(bearerData.msgCenterTimeStamp.hour, 11);
-        assertEquals(bearerData.msgCenterTimeStamp.minute, 1);
-        assertEquals(bearerData.msgCenterTimeStamp.second, 59);
-        assertEquals(bearerData.validityPeriodAbsolute, null);
-        assertEquals(bearerData.validityPeriodRelative, 193);
-        assertEquals(bearerData.deferredDeliveryTimeAbsolute.year, 1997);
-        assertEquals(bearerData.deferredDeliveryTimeAbsolute.monthOrdinal, 6);
-        assertEquals(bearerData.deferredDeliveryTimeAbsolute.monthDay, 18);
-        assertEquals(bearerData.deferredDeliveryTimeAbsolute.hour, 0);
-        assertEquals(bearerData.deferredDeliveryTimeAbsolute.minute, 0);
-        assertEquals(bearerData.deferredDeliveryTimeAbsolute.second, 0);
-        assertEquals(bearerData.deferredDeliveryTimeRelative, 199);
-        assertEquals(bearerData.hasUserDataHeader, false);
-        assertEquals(bearerData.userData.msgEncoding, UserData.ENCODING_7BIT_ASCII);
-        assertEquals(bearerData.userData.numFields, 2);
-        assertEquals(bearerData.userData.payloadStr, "hi");
-    }
-
-    @SmallTest
-    public void testMonolithicTwo() throws Exception {
-        String pdu = "0003200010010410168d200201050306081201110159050192060697061800000007013d0" +
-                "801c00901800a01e00b01030c01c00d01070e05039acc13880f018011020566";
-        BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
-        assertEquals(bearerData.messageType, BearerData.MESSAGE_TYPE_SUBMIT);
-        assertEquals(bearerData.messageId, 1);
-        assertEquals(bearerData.priority, BearerData.PRIORITY_EMERGENCY);
-        assertEquals(bearerData.privacy, BearerData.PRIVACY_CONFIDENTIAL);
-        assertEquals(bearerData.userAckReq, true);
-        assertEquals(bearerData.readAckReq, true);
-        assertEquals(bearerData.deliveryAckReq, true);
-        assertEquals(bearerData.reportReq, false);
-        assertEquals(bearerData.numberOfMessages, 3);
-        assertEquals(bearerData.alert, BearerData.ALERT_HIGH_PRIO);
-        assertEquals(bearerData.language, BearerData.LANGUAGE_HEBREW);
-        assertEquals(bearerData.callbackNumber.digitMode, CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF);
-        assertEquals(bearerData.callbackNumber.numberMode,
-                     CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK);
-        assertEquals(bearerData.callbackNumber.ton, CdmaSmsAddress.TON_UNKNOWN);
-        assertEquals(bearerData.callbackNumber.numberPlan, CdmaSmsAddress.NUMBERING_PLAN_UNKNOWN);
-        assertEquals(bearerData.callbackNumber.numberOfDigits, 7);
-        assertEquals(bearerData.callbackNumber.address, "3598271");
-        assertEquals(bearerData.displayMode, BearerData.DISPLAY_MODE_USER);
-        assertEquals(bearerData.depositIndex, 1382);
-        assertEquals(bearerData.userResponseCode, 5);
-        assertEquals(bearerData.msgCenterTimeStamp.year, 2008);
-        assertEquals(bearerData.msgCenterTimeStamp.monthOrdinal, 12);
-        assertEquals(bearerData.msgCenterTimeStamp.monthDay, 1);
-        assertEquals(bearerData.msgCenterTimeStamp.hour, 11);
-        assertEquals(bearerData.msgCenterTimeStamp.minute, 1);
-        assertEquals(bearerData.msgCenterTimeStamp.second, 59);
-        assertEquals(bearerData.validityPeriodAbsolute, null);
-        assertEquals(bearerData.validityPeriodRelative, 61);
-        assertEquals(bearerData.deferredDeliveryTimeAbsolute.year, 1997);
-        assertEquals(bearerData.deferredDeliveryTimeAbsolute.monthOrdinal, 6);
-        assertEquals(bearerData.deferredDeliveryTimeAbsolute.monthDay, 18);
-        assertEquals(bearerData.deferredDeliveryTimeAbsolute.hour, 0);
-        assertEquals(bearerData.deferredDeliveryTimeAbsolute.minute, 0);
-        assertEquals(bearerData.deferredDeliveryTimeAbsolute.second, 0);
-        assertEquals(bearerData.deferredDeliveryTimeRelative, 146);
-        assertEquals(bearerData.hasUserDataHeader, false);
-        assertEquals(bearerData.userData.msgEncoding, UserData.ENCODING_7BIT_ASCII);
-        assertEquals(bearerData.userData.numFields, 2);
-        assertEquals(bearerData.userData.payloadStr, "hi");
-    }
-
-    @SmallTest
-    public void testUserDataHeaderConcatRefFeedback() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 55;
-        SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
-        concatRef.refNumber = 0xEE;
-        concatRef.msgCount = 2;
-        concatRef.seqNumber = 2;
-        concatRef.isEightBits = true;
-        SmsHeader smsHeader = new SmsHeader();
-        smsHeader.concatRef = concatRef;
-        byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
-        SmsHeader decodedHeader = SmsHeader.fromByteArray(encodedHeader);
-        assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
-        assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
-        assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
-        assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
-        assertEquals(decodedHeader.portAddrs, null);
-        UserData userData = new UserData();
-        userData.payloadStr = "User Data Header (UDH) feedback test";
-        userData.userDataHeader = smsHeader;
-        bearerData.userData = userData;
-        byte[] encodedSms = BearerData.encode(bearerData);
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        decodedHeader = revBearerData.userData.userDataHeader;
-        assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
-        assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
-        assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
-        assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
-        assertEquals(decodedHeader.portAddrs, null);
-    }
-
-    @SmallTest
-    public void testUserDataHeaderIllegalConcatRef() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 55;
-        SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
-        concatRef.refNumber = 0x10;
-        concatRef.msgCount = 0;
-        concatRef.seqNumber = 2;
-        concatRef.isEightBits = true;
-        SmsHeader smsHeader = new SmsHeader();
-        smsHeader.concatRef = concatRef;
-        byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
-        SmsHeader decodedHeader = SmsHeader.fromByteArray(encodedHeader);
-        assertEquals(decodedHeader.concatRef, null);
-        concatRef.isEightBits = false;
-        encodedHeader = SmsHeader.toByteArray(smsHeader);
-        decodedHeader = SmsHeader.fromByteArray(encodedHeader);
-        assertEquals(decodedHeader.concatRef, null);
-        concatRef.msgCount = 1;
-        concatRef.seqNumber = 2;
-        encodedHeader = SmsHeader.toByteArray(smsHeader);
-        decodedHeader = SmsHeader.fromByteArray(encodedHeader);
-        assertEquals(decodedHeader.concatRef, null);
-        concatRef.msgCount = 1;
-        concatRef.seqNumber = 0;
-        encodedHeader = SmsHeader.toByteArray(smsHeader);
-        decodedHeader = SmsHeader.fromByteArray(encodedHeader);
-        assertEquals(decodedHeader.concatRef, null);
-        concatRef.msgCount = 2;
-        concatRef.seqNumber = 1;
-        encodedHeader = SmsHeader.toByteArray(smsHeader);
-        decodedHeader = SmsHeader.fromByteArray(encodedHeader);
-        assertEquals(decodedHeader.concatRef.msgCount, 2);
-        assertEquals(decodedHeader.concatRef.seqNumber, 1);
-    }
-
-    @SmallTest
-    public void testUserDataHeaderMixedFeedback() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 42;
-        SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
-        concatRef.refNumber = 0x34;
-        concatRef.msgCount = 5;
-        concatRef.seqNumber = 2;
-        concatRef.isEightBits = false;
-        SmsHeader.PortAddrs portAddrs = new SmsHeader.PortAddrs();
-        portAddrs.destPort = 88;
-        portAddrs.origPort = 66;
-        portAddrs.areEightBits = false;
-        SmsHeader smsHeader = new SmsHeader();
-        smsHeader.concatRef = concatRef;
-        smsHeader.portAddrs = portAddrs;
-        byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
-        SmsHeader decodedHeader = SmsHeader.fromByteArray(encodedHeader);
-        assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
-        assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
-        assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
-        assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
-        assertEquals(decodedHeader.portAddrs.destPort, portAddrs.destPort);
-        assertEquals(decodedHeader.portAddrs.origPort, portAddrs.origPort);
-        assertEquals(decodedHeader.portAddrs.areEightBits, portAddrs.areEightBits);
-        UserData userData = new UserData();
-        userData.payloadStr = "User Data Header (UDH) feedback test";
-        userData.userDataHeader = smsHeader;
-        bearerData.userData = userData;
-        byte[] encodedSms = BearerData.encode(bearerData);
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        decodedHeader = revBearerData.userData.userDataHeader;
-        assertEquals(decodedHeader.concatRef.refNumber, concatRef.refNumber);
-        assertEquals(decodedHeader.concatRef.msgCount, concatRef.msgCount);
-        assertEquals(decodedHeader.concatRef.seqNumber, concatRef.seqNumber);
-        assertEquals(decodedHeader.concatRef.isEightBits, concatRef.isEightBits);
-        assertEquals(decodedHeader.portAddrs.destPort, portAddrs.destPort);
-        assertEquals(decodedHeader.portAddrs.origPort, portAddrs.origPort);
-        assertEquals(decodedHeader.portAddrs.areEightBits, portAddrs.areEightBits);
-    }
-
-    @SmallTest
-    public void testReplyOption() throws Exception {
-        String pdu1 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87450080a0180";
-        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
-        assertEquals("Test Acknowledgement 1", bd1.userData.payloadStr);
-        assertEquals(true, bd1.userAckReq);
-        assertEquals(false, bd1.deliveryAckReq);
-        assertEquals(false, bd1.readAckReq);
-        assertEquals(false, bd1.reportReq);
-        String pdu2 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87490080a0140";
-        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
-        assertEquals("Test Acknowledgement 2", bd2.userData.payloadStr);
-        assertEquals(false, bd2.userAckReq);
-        assertEquals(true, bd2.deliveryAckReq);
-        assertEquals(false, bd2.readAckReq);
-        assertEquals(false, bd2.reportReq);
-        String pdu3 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d874d0080a0120";
-        BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
-        assertEquals("Test Acknowledgement 3", bd3.userData.payloadStr);
-        assertEquals(false, bd3.userAckReq);
-        assertEquals(false, bd3.deliveryAckReq);
-        assertEquals(true, bd3.readAckReq);
-        assertEquals(false, bd3.reportReq);
-        String pdu4 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87510080a0110";
-        BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
-        assertEquals("Test Acknowledgement 4", bd4.userData.payloadStr);
-        assertEquals(false, bd4.userAckReq);
-        assertEquals(false, bd4.deliveryAckReq);
-        assertEquals(false, bd4.readAckReq);
-        assertEquals(true, bd4.reportReq);
-    }
-
-    @SmallTest
-    public void testReplyOptionFeedback() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 0;
-        bearerData.hasUserDataHeader = false;
-        UserData userData = new UserData();
-        userData.payloadStr = "test reply option";
-        bearerData.userData = userData;
-        bearerData.userAckReq = true;
-        byte []encodedSms = BearerData.encode(bearerData);
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        assertEquals(true, revBearerData.userAckReq);
-        assertEquals(false, revBearerData.deliveryAckReq);
-        assertEquals(false, revBearerData.readAckReq);
-        assertEquals(false, revBearerData.reportReq);
-        bearerData.userAckReq = false;
-        bearerData.deliveryAckReq = true;
-        encodedSms = BearerData.encode(bearerData);
-        revBearerData = BearerData.decode(encodedSms);
-        assertEquals(false, revBearerData.userAckReq);
-        assertEquals(true, revBearerData.deliveryAckReq);
-        assertEquals(false, revBearerData.readAckReq);
-        assertEquals(false, revBearerData.reportReq);
-        bearerData.deliveryAckReq = false;
-        bearerData.readAckReq = true;
-        encodedSms = BearerData.encode(bearerData);
-        revBearerData = BearerData.decode(encodedSms);
-        assertEquals(false, revBearerData.userAckReq);
-        assertEquals(false, revBearerData.deliveryAckReq);
-        assertEquals(true, revBearerData.readAckReq);
-        assertEquals(false, revBearerData.reportReq);
-        bearerData.readAckReq = false;
-        bearerData.reportReq = true;
-        encodedSms = BearerData.encode(bearerData);
-        revBearerData = BearerData.decode(encodedSms);
-        assertEquals(false, revBearerData.userAckReq);
-        assertEquals(false, revBearerData.deliveryAckReq);
-        assertEquals(false, revBearerData.readAckReq);
-        assertEquals(true, revBearerData.reportReq);
-    }
-
-    @SmallTest
-    public void testNumberOfMessages() throws Exception {
-        // Note that the message text below does not properly reflect
-        // the message count.  The author of these messages was
-        // apparently unaware that the values are bcd encoded, and the
-        // values being tested against (not the ones in the message
-        // text) are actually correct.
-        String pdu1 = "000310409001124896a794e07595f69f199540ea759a0dc8e00b0163";
-        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
-        assertEquals("Test Voice mail 99", bd1.userData.payloadStr);
-        assertEquals(63, bd1.numberOfMessages);
-        String pdu2 = "00031040900113489ea794e07595f69f199540ea759a0988c0600b0164";
-        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
-        assertEquals("Test Voice mail 100", bd2.userData.payloadStr);
-        assertEquals(64, bd2.numberOfMessages);
-    }
-
-    @SmallTest
-    public void testCallbackNum() throws Exception {
-        String pdu1 = "00031040900112488ea794e070d436cb638bc5e035ce2f97900e06910431323334";
-        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
-        assertEquals("Test Callback nbr", bd1.userData.payloadStr);
-        assertEquals(CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR, bd1.callbackNumber.digitMode);
-        assertEquals(CdmaSmsAddress.TON_INTERNATIONAL_OR_IP, bd1.callbackNumber.ton);
-        assertEquals(CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK, bd1.callbackNumber.numberMode);
-        assertEquals(CdmaSmsAddress.NUMBERING_PLAN_ISDN_TELEPHONY, bd1.callbackNumber.numberPlan);
-        assertEquals("1234", bd1.callbackNumber.address);
-    }
-
-    @SmallTest
-    public void testCallbackNumDtmf() throws Exception {
-        String pdu1 = "00031002300109104539b4d052ebb3d00e07052d4c90a55080";
-        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
-        assertEquals("SMS Rulz", bd1.userData.payloadStr);
-        assertEquals(CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF, bd1.callbackNumber.digitMode);
-        assertEquals(CdmaSmsAddress.TON_UNKNOWN, bd1.callbackNumber.ton);
-        assertEquals(CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK, bd1.callbackNumber.numberMode);
-        assertEquals(CdmaSmsAddress.NUMBERING_PLAN_UNKNOWN, bd1.callbackNumber.numberPlan);
-        assertEquals("5099214001", bd1.callbackNumber.address);
-    }
-
-    @SmallTest
-    public void testCallbackNumFeedback() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 0;
-        bearerData.hasUserDataHeader = false;
-        UserData userData = new UserData();
-        userData.payloadStr = "test callback number";
-        bearerData.userData = userData;
-        CdmaSmsAddress addr = new CdmaSmsAddress();
-        addr.digitMode = CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR;
-        addr.ton = CdmaSmsAddress.TON_NATIONAL_OR_EMAIL;
-        addr.numberMode = CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK;
-        addr.numberPlan = CdmaSmsAddress.NUMBERING_PLAN_UNKNOWN;
-        addr.address = "8005551212";
-        addr.numberOfDigits = (byte)addr.address.length();
-        bearerData.callbackNumber = addr;
-        byte []encodedSms = BearerData.encode(bearerData);
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        CdmaSmsAddress revAddr = revBearerData.callbackNumber;
-        assertEquals(addr.digitMode, revAddr.digitMode);
-        assertEquals(addr.ton, revAddr.ton);
-        assertEquals(addr.numberMode, revAddr.numberMode);
-        assertEquals(addr.numberPlan, revAddr.numberPlan);
-        assertEquals(addr.numberOfDigits, revAddr.numberOfDigits);
-        assertEquals(addr.address, revAddr.address);
-        addr.address = "8*55#1012";
-        addr.numberOfDigits = (byte)addr.address.length();
-        addr.digitMode = CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF;
-        encodedSms = BearerData.encode(bearerData);
-        revBearerData = BearerData.decode(encodedSms);
-        revAddr = revBearerData.callbackNumber;
-        assertEquals(addr.digitMode, revAddr.digitMode);
-        assertEquals(addr.numberOfDigits, revAddr.numberOfDigits);
-        assertEquals(addr.address, revAddr.address);
-    }
-
-    @SmallTest
-    public void testPrivacyIndicator() throws Exception {
-        String pdu1 = "0003104090010c485f4194dfea34becf61b840090140";
-        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
-        assertEquals(bd1.privacy, BearerData.PRIVACY_RESTRICTED);
-        String pdu2 = "0003104090010c485f4194dfea34becf61b840090180";
-        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
-        assertEquals(bd2.privacy, BearerData.PRIVACY_CONFIDENTIAL);
-        String pdu3 = "0003104090010c485f4194dfea34becf61b8400901c0";
-        BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
-        assertEquals(bd3.privacy, BearerData.PRIVACY_SECRET);
-    }
-
-    @SmallTest
-    public void testPrivacyIndicatorFeedback() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 0;
-        bearerData.hasUserDataHeader = false;
-        UserData userData = new UserData();
-        userData.payloadStr = "test privacy indicator";
-        bearerData.userData = userData;
-        bearerData.privacy = BearerData.PRIVACY_SECRET;
-        bearerData.privacyIndicatorSet = true;
-        byte []encodedSms = BearerData.encode(bearerData);
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
-        assertEquals(revBearerData.privacyIndicatorSet, true);
-        assertEquals(revBearerData.privacy, BearerData.PRIVACY_SECRET);
-        bearerData.privacy = BearerData.PRIVACY_RESTRICTED;
-        encodedSms = BearerData.encode(bearerData);
-        revBearerData = BearerData.decode(encodedSms);
-        assertEquals(revBearerData.privacy, BearerData.PRIVACY_RESTRICTED);
-    }
-
-    @SmallTest
-    public void testMsgDeliveryAlert() throws Exception {
-        String pdu1 = "0003104090010d4866a794e07055965b91d040300c0100";
-        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
-        assertEquals(bd1.alert, 0);
-        assertEquals(bd1.userData.payloadStr, "Test Alert 0");
-        String pdu2 = "0003104090010d4866a794e07055965b91d140300c0140";
-        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
-        assertEquals(bd2.alert, 1);
-        assertEquals(bd2.userData.payloadStr, "Test Alert 1");
-        String pdu3 = "0003104090010d4866a794e07055965b91d240300c0180";
-        BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
-        assertEquals(bd3.alert, 2);
-        assertEquals(bd3.userData.payloadStr, "Test Alert 2");
-        String pdu4 = "0003104090010d4866a794e07055965b91d340300c01c0";
-        BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
-        assertEquals(bd4.alert, 3);
-        assertEquals(bd4.userData.payloadStr, "Test Alert 3");
-        String pdu5 = "00031000000126114F4CBCFA20DB979F3C39F2A0C9976" +
-            "69ED979794187665E5D1028EFA7A6840E1062D3D39A900C028000";
-        BearerData bd5 = BearerData.decode(HexDump.hexStringToByteArray(pdu5));
-        assertEquals(bd5.alert, BearerData.ALERT_MEDIUM_PRIO);
-        assertEquals(bd5.userData.payloadStr, "test message delivery alert (with 8 bits)");
-        String pdu6 = "00031000000126114F4CBCFA20DB979F3C39F2A0C9976" +
-            "69ED979794187665E5D1028EFA7A6840C1062D3D39A900C00";
-        BearerData bd6 = BearerData.decode(HexDump.hexStringToByteArray(pdu6));
-        assertEquals(bd6.userData.payloadStr, "test message delivery alert (with 0 bits)");
-        assertEquals(bd6.alertIndicatorSet, false);
-    }
-
-    @SmallTest
-    public void testMiscParams() throws Exception {
-        String pdu1 = "00031002400109104539b4d052ebb3d00c0180";
-        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
-        assertEquals(bd1.alert, BearerData.ALERT_MEDIUM_PRIO);
-        assertEquals(bd1.userData.payloadStr, "SMS Rulz");
-        String pdu2 = "00031002500109104539b4d052ebb3d00801800901c0";
-        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
-        assertEquals(bd2.priority, BearerData.PRIORITY_URGENT);
-        assertEquals(bd2.privacy, BearerData.PRIVACY_SECRET);
-        assertEquals(bd2.userData.payloadStr, "SMS Rulz");
-        String pdu3 = "00031002600109104539b4d052ebb3d00901400c01c0";
-        BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
-        assertEquals(bd3.privacy, BearerData.PRIVACY_RESTRICTED);
-        assertEquals(bd3.alert, BearerData.ALERT_HIGH_PRIO);
-        assertEquals(bd3.userData.payloadStr, "SMS Rulz");
-        String pdu4 = "00031002700109104539b4d052ebb3d00f0105";
-        BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
-        assertEquals(bd4.displayMode, BearerData.DISPLAY_MODE_IMMEDIATE);
-        assertEquals(bd4.userData.payloadStr, "SMS Rulz");
-    }
-   @SmallTest
-    public void testMsgDeliveryAlertFeedback() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 0;
-        bearerData.hasUserDataHeader = false;
-        UserData userData = new UserData();
-        userData.payloadStr = "test message delivery alert";
-        bearerData.userData = userData;
-        bearerData.alert = BearerData.ALERT_MEDIUM_PRIO;
-        bearerData.alertIndicatorSet = true;
-        byte []encodedSms = BearerData.encode(bearerData);
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
-        assertEquals(revBearerData.alertIndicatorSet, true);
-        assertEquals(revBearerData.alert, bearerData.alert);
-        bearerData.alert = BearerData.ALERT_HIGH_PRIO;
-        encodedSms = BearerData.encode(bearerData);
-        revBearerData = BearerData.decode(encodedSms);
-        assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
-        assertEquals(revBearerData.alertIndicatorSet, true);
-        assertEquals(revBearerData.alert, bearerData.alert);
-    }
-
-    @SmallTest
-    public void testLanguageIndicator() throws Exception {
-        String pdu1 = "0003104090011748bea794e0731436ef3bd7c2e0352eef27a1c263fe58080d0101";
-        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
-        assertEquals(bd1.userData.payloadStr, "Test Language indicator");
-        assertEquals(bd1.language, BearerData.LANGUAGE_ENGLISH);
-        String pdu2 = "0003104090011748bea794e0731436ef3bd7c2e0352eef27a1c263fe58080d0106";
-        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
-        assertEquals(bd2.userData.payloadStr, "Test Language indicator");
-        assertEquals(bd2.language, BearerData.LANGUAGE_CHINESE);
-    }
-
-    @SmallTest
-    public void testLanguageIndicatorFeedback() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 0;
-        bearerData.hasUserDataHeader = false;
-        UserData userData = new UserData();
-        userData.payloadStr = "test language indicator";
-        bearerData.userData = userData;
-        bearerData.language = BearerData.LANGUAGE_ENGLISH;
-        bearerData.languageIndicatorSet = true;
-        byte []encodedSms = BearerData.encode(bearerData);
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
-        assertEquals(revBearerData.languageIndicatorSet, true);
-        assertEquals(revBearerData.language, bearerData.language);
-        bearerData.language = BearerData.LANGUAGE_KOREAN;
-        encodedSms = BearerData.encode(bearerData);
-        revBearerData = BearerData.decode(encodedSms);
-        assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
-        assertEquals(revBearerData.languageIndicatorSet, true);
-        assertEquals(revBearerData.language, bearerData.language);
-    }
-
-    @SmallTest
-    public void testDisplayMode() throws Exception {
-        String pdu1 = "0003104090010c485f4194dfea34becf61b8400f0100";
-        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
-        assertEquals(bd1.displayMode, BearerData.DISPLAY_MODE_IMMEDIATE);
-        String pdu2 = "0003104090010c485f4194dfea34becf61b8400f0140";
-        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
-        assertEquals(bd2.displayMode, BearerData.DISPLAY_MODE_DEFAULT);
-        String pdu3 = "0003104090010c485f4194dfea34becf61b8400f0180";
-        BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
-        assertEquals(bd3.displayMode, BearerData.DISPLAY_MODE_USER);
-    }
-
-    @SmallTest
-    public void testDisplayModeFeedback() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 0;
-        bearerData.hasUserDataHeader = false;
-        UserData userData = new UserData();
-        userData.payloadStr = "test display mode";
-        bearerData.userData = userData;
-        bearerData.displayMode = BearerData.DISPLAY_MODE_IMMEDIATE;
-        bearerData.displayModeSet = true;
-        byte []encodedSms = BearerData.encode(bearerData);
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
-        assertEquals(revBearerData.displayModeSet, true);
-        assertEquals(revBearerData.displayMode, bearerData.displayMode);
-        bearerData.displayMode = BearerData.DISPLAY_MODE_USER;
-        encodedSms = BearerData.encode(bearerData);
-        revBearerData = BearerData.decode(encodedSms);
-        assertEquals(revBearerData.userData.payloadStr, userData.payloadStr);
-        assertEquals(revBearerData.displayModeSet, true);
-        assertEquals(revBearerData.displayMode, bearerData.displayMode);
-    }
-
-    @SmallTest
-    public void testIs91() throws Exception {
-        String pdu1 = "000320001001070c2039acc13880";
-        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
-        assertEquals(bd1.callbackNumber.address, "3598271");
-        String pdu4 = "000320001001080c283c314724b34e";
-        BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
-        assertEquals(bd4.userData.payloadStr, "ABCDEFG");
-    }
-
-    @SmallTest
-    public void testUserDataHeaderWithEightCharMsg() throws Exception {
-        SmsHeader smsHeader = getConcatUserDataHeader(2, 2);
-        encodeDecodeAssertEquals("01234567", smsHeader, -1);
-        SmsHeader smsHeader2 = getOddLengthUserDataHeader();
-        encodeDecodeAssertEquals("01234567", smsHeader2, -1);
-    }
-
-    @SmallTest
-    public void testShiftJis() throws Exception {
-        encodeDecodeAssertEquals(sHelloWorldJa, null, UserData.ENCODING_UNICODE_16);
-        encodeDecodeAssertEquals(sHelloWorldJa, null, UserData.ENCODING_SHIFT_JIS);
-    }
-
-    @SmallTest
-    public void testIgnoreReservedSubparam() throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 1234;
-        UserData userData = new UserData();
-        userData.payloadStr = sHelloWorldJa;
-        bearerData.userData = userData;
-        byte[] encodedSms = BearerData.encode(bearerData);
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-
-        byte[] smsWithValidSubparam = Arrays.copyOf(encodedSms, encodedSms.length + 5);
-        smsWithValidSubparam[encodedSms.length] = 0x18; // BearerData.SUBPARAM_ID_LAST_DEFINED + 1
-        smsWithValidSubparam[encodedSms.length + 1] = 3;
-        smsWithValidSubparam[encodedSms.length + 2] = 0x12;
-        smsWithValidSubparam[encodedSms.length + 3] = 0x34;
-        smsWithValidSubparam[encodedSms.length + 4] = 0x56;
-        revBearerData = BearerData.decode(smsWithValidSubparam);
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-
-        smsWithValidSubparam = Arrays.copyOf(encodedSms, encodedSms.length + 2);
-        smsWithValidSubparam[encodedSms.length] = 0x18;
-        smsWithValidSubparam[encodedSms.length + 1] = 0;
-        revBearerData = BearerData.decode(smsWithValidSubparam);
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-
-        byte[] smsWithInvalidSubparam = Arrays.copyOf(encodedSms, encodedSms.length + 2);
-        smsWithInvalidSubparam[encodedSms.length] = 0x18;
-        smsWithInvalidSubparam[encodedSms.length + 1] = (byte) 1;
-        revBearerData = BearerData.decode(smsWithInvalidSubparam);
-        assertNull(revBearerData);
-    }
-
-    // Return a user data header for a concatenated message
-    private static SmsHeader getConcatUserDataHeader(int index, int total) {
-        SmsHeader smsHeader = new SmsHeader();
-        SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
-        concatRef.refNumber = 0xEE;
-        concatRef.msgCount = total;
-        concatRef.seqNumber = index;
-        concatRef.isEightBits = true;
-        smsHeader.concatRef = concatRef;
-        return smsHeader;
-    }
-
-    // Return a user data header of odd length to verify correct UTF-16 header padding
-    private static SmsHeader getOddLengthUserDataHeader() {
-        SmsHeader smsHeader = new SmsHeader();
-        SmsHeader.MiscElt miscElt = new SmsHeader.MiscElt();
-        miscElt.id = 0x27;  // reserved for future use; ignored on decode
-        miscElt.data = new byte[]{0x12, 0x34};
-        smsHeader.miscEltList.add(miscElt);
-        return smsHeader;
-    }
-
-    private static void encodeDecodeAssertEquals(String payload, SmsHeader smsHeader,
-            int msgEncoding) throws Exception {
-        BearerData bearerData = new BearerData();
-        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
-        bearerData.messageId = 55;
-        UserData userData = new UserData();
-        userData.payloadStr = payload;
-        userData.userDataHeader = smsHeader;    // may be null
-        if (msgEncoding != -1) {
-            userData.msgEncoding = msgEncoding;
-            userData.msgEncodingSet = true;
-        }
-        bearerData.userData = userData;
-        byte[] encodedSms = BearerData.encode(bearerData);
-        BearerData revBearerData = BearerData.decode(encodedSms);
-        assertEquals(userData.payloadStr, revBearerData.userData.payloadStr);
-        if (smsHeader != null) {
-            assertTrue(revBearerData.hasUserDataHeader);
-            byte[] encodeHeader = SmsHeader.toByteArray(smsHeader);
-            byte[] decodeHeader = SmsHeader.toByteArray(revBearerData.userData.userDataHeader);
-            assertTrue(Arrays.equals(encodeHeader, decodeHeader));
-        } else {
-            assertFalse(revBearerData.hasUserDataHeader);
-        }
-    }
-
-    @SmallTest
-    public void testFragmentText() throws Exception {
-        boolean isCdmaPhone = (TelephonyManager.getDefault().getPhoneType() ==
-                TelephonyManager.PHONE_TYPE_CDMA);
-        // Valid 160 character ASCII text.
-        String text1 = "123456789012345678901234567890123456789012345678901234567890" +
-                "1234567890123456789012345678901234567890123456789012345678901234567890" +
-                "12345678901234567890123456789[";
-        TextEncodingDetails ted = SmsMessage.calculateLength(text1, false, true);
-        assertEquals(ted.msgCount, 1);
-        assertEquals(ted.codeUnitCount, 160);
-        assertEquals(ted.codeUnitSize, 1);
-        if (isCdmaPhone) {
-            ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text1);
-            assertEquals(fragments.size(), 1);
-        }
-
-        /*
-           This is not a valid test: we will never encode a single-segment
-           EMS message.  Leaving this here, since we may try to support
-           this in the future.
-
-        // Valid 160 character GSM text -- the last character is
-        // non-ASCII, and so this will currently generate a singleton
-        // EMS message, which is not necessarily supported by Verizon.
-        String text2 = "123456789012345678901234567890123456789012345678901234567890" +
-                "1234567890123456789012345678901234567890123456789012345678901234567890" +
-                "12345678901234567890123456789\u00a3";  // Trailing pound-currency sign.
-        ted = SmsMessage.calculateLength(text2, false);
-        assertEquals(ted.msgCount, 1);
-        assertEquals(ted.codeUnitCount, 160);
-        assertEquals(ted.codeUnitSize, 1);
-        if (isCdmaPhone) {
-            ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text2);
-            assertEquals(fragments.size(), 1);
-        }
-        */
-
-        // *IF* we supported single-segment EMS, this text would result in a
-        // single fragment with 7-bit encoding. But we don't, so this text
-        // results in three fragments of 16-bit encoding.
-        String text2 = "123456789012345678901234567890123456789012345678901234567890" +
-                "1234567890123456789012345678901234567890123456789012345678901234567890" +
-                "12345678901234567890123456789\u00a3";  // Trailing pound-currency sign.
-        ted = SmsMessage.calculateLength(text2, false, true);
-        assertEquals(3, ted.msgCount);
-        assertEquals(160, ted.codeUnitCount);
-        assertEquals(3, ted.codeUnitSize);
-        if (isCdmaPhone) {
-            ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text2);
-            assertEquals(3, fragments.size());
-
-            for (int i = 0; i < 3; i++) {
-                SmsHeader header = getConcatUserDataHeader(i + 1, 3);
-                SmsHeader header2 = getOddLengthUserDataHeader();
-                encodeDecodeAssertEquals(fragments.get(i), header, -1);
-                encodeDecodeAssertEquals(fragments.get(i), header2, -1);
-            }
-        }
-
-        // Test case for multi-part UTF-16 message.
-        String text3 = sUnicodeChars + sUnicodeChars + sUnicodeChars;
-        ted = SmsMessage.calculateLength(text3, false, true);
-        assertEquals(3, ted.msgCount);
-        assertEquals(189, ted.codeUnitCount);
-        assertEquals(3, ted.codeUnitSize);
-        if (isCdmaPhone) {
-            ArrayList<String> fragments = android.telephony.SmsMessage.fragmentText(text3);
-            assertEquals(3, fragments.size());
-
-            for (int i = 0; i < 3; i++) {
-                SmsHeader header = getConcatUserDataHeader(i + 1, 3);
-                SmsHeader header2 = getOddLengthUserDataHeader();
-                encodeDecodeAssertEquals(fragments.get(i), header, -1);
-                encodeDecodeAssertEquals(fragments.get(i), header2, -1);
-            }
-        }
-    }
-
-    @SmallTest
-    public void testPreprocessFdeaWdpUserData() throws Exception {
-        // Refer to https://patents.google.com/patent/CN103906005A/en
-        String wdpUserData =
-                "0003156D60018103F80008011F805C26B031230B8383634B1B0BA34B7B717BB3732173BB0B81736B" +
-                "6B996B6B2B9B9B0B3B2805A43D7C246414C212522A3A522BD31AD3931210046C841B43A3A381D179" +
-                "798981719199A1718999B97189897A12522A3A522BD31AD393121004402C081815175C486C018999" +
-                "9989B181C9B99991C80454047011AF78";
-
-        SmsMessage cdmaSmsMessage = new SmsMessage();
-
-        Field field = SmsMessageBase.class.getDeclaredField("mUserData");
-        field.setAccessible(true);
-        field.set(cdmaSmsMessage, HexDump.hexStringToByteArray(wdpUserData));
-
-        BearerData bearerData = new BearerData();
-        bearerData.userData = new UserData();
-
-        field = SmsMessage.class.getDeclaredField("mBearerData");
-        field.setAccessible(true);
-        field.set(cdmaSmsMessage, bearerData);
-        bearerData = (BearerData) field.get(cdmaSmsMessage);
-
-        assertTrue(cdmaSmsMessage.preprocessCdmaFdeaWap());
-        assertEquals(BearerData.MESSAGE_TYPE_DELIVER, bearerData.messageType);
-        assertEquals(0x56D6, bearerData.messageId);
-        assertEquals(0x7F, bearerData.userData.numFields);
-        assertNotNull(bearerData.userData.payload);
-    }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java b/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java
index 0563481..64dd24e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java
@@ -29,12 +29,14 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.content.Intent;
 import android.util.ArraySet;
@@ -64,6 +66,7 @@
 public class TelephonyConfigUpdateInstallReceiverTest extends TelephonyTest {
 
     public static final String DOMAIN_SATELLITE = "satellite";
+    private static final int[] ACTIVE_SUB_LIST = {1};
     @Mock
     private Executor mExecutor;
     @Mock
@@ -73,6 +76,8 @@
     public void setUp() throws Exception {
         super.setUp(getClass().getSimpleName());
         MockitoAnnotations.initMocks(this);
+        when(mSubscriptionManagerService.getActiveSubIdList(anyBoolean())).thenReturn(
+                ACTIVE_SUB_LIST);
         logd(TAG + " Setup!");
     }
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/AccessNetworksManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/AccessNetworksManagerTest.java
index e45023c..1203510 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/AccessNetworksManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/AccessNetworksManagerTest.java
@@ -42,7 +42,6 @@
 import android.telephony.AccessNetworkConstants.AccessNetworkType;
 import android.telephony.NetworkService;
 import android.telephony.data.ApnSetting;
-import android.telephony.data.DataServiceCallback;
 import android.telephony.data.IQualifiedNetworksService;
 import android.telephony.data.IQualifiedNetworksServiceCallback;
 import android.testing.AndroidTestingRunner;
@@ -323,9 +322,7 @@
     }
 
     @Test
-    public void testRequestNetworkValidation_WithFlagEnabled()  throws Exception {
-        when(mFeatureFlags.networkValidation()).thenReturn(true);
-
+    public void testRequestNetworkValidation()  throws Exception {
         mQnsCallback.onNetworkValidationRequested(NetworkCapabilities.NET_CAPABILITY_IMS,
                 mIIntegerConsumer);
         processAllMessages();
@@ -333,27 +330,7 @@
     }
 
     @Test
-    public void testRequestNetworkValidation_WithFlagDisabled() throws Exception {
-        mIIntegerConsumerResults.clear();
-        when(mFeatureFlags.networkValidation()).thenReturn(false);
-
-        mQnsCallback.onNetworkValidationRequested(NetworkCapabilities.NET_CAPABILITY_IMS,
-                mIIntegerConsumer);
-        processAllMessages();
-
-        assertThat(waitForIIntegerConsumerResult(1 /*numOfEvents*/)).isTrue();
-        assertThat((long) mIIntegerConsumerResults.get(0))
-                .isEqualTo(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
-        verify(mDataNetworkController, never()).requestNetworkValidation(
-                NetworkCapabilities.NET_CAPABILITY_IMS,
-                mIntegerConsumer);
-    }
-
-    @Test
-    public void testCallbackForReconnectQualifiedNetworkTypeWithFlagEnabled()  throws Exception {
-        when(mFeatureFlags.reconnectQualifiedNetwork()).thenReturn(true);
-
-
+    public void testCallbackForReconnectQualifiedNetworkType()  throws Exception {
         mAccessNetworksManager.registerCallback(mMockedCallback);
 
         mQnsCallback.onReconnectQualifiedNetworkType(ApnSetting.TYPE_IMS | ApnSetting.TYPE_MMS,
@@ -377,29 +354,4 @@
                 NetworkCapabilities.NET_CAPABILITY_XCAP)).isEqualTo(
                 AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
     }
-
-    @Test
-    public void testCallbackForReconnectQualifiedNetworkTypeWithFlagDisabled() throws Exception {
-        when(mFeatureFlags.reconnectQualifiedNetwork()).thenReturn(false);
-        mQnsCallback.onReconnectQualifiedNetworkType(ApnSetting.TYPE_IMS | ApnSetting.TYPE_MMS,
-                AccessNetworkType.IWLAN);
-        processAllMessages();
-
-        verify(mMockedCallback, never()).onPreferredTransportChanged(
-                eq(NetworkCapabilities.NET_CAPABILITY_MMS), eq(true));
-        verify(mMockedCallback, never()).onPreferredTransportChanged(
-                eq(NetworkCapabilities.NET_CAPABILITY_IMS), eq(true));
-        verify(mMockedCallback, never()).onPreferredTransportChanged(
-                eq(NetworkCapabilities.NET_CAPABILITY_XCAP), eq(true));
-        Mockito.clearInvocations(mMockedCallback);
-        assertThat(mAccessNetworksManager.getPreferredTransportByNetworkCapability(
-                NetworkCapabilities.NET_CAPABILITY_MMS)).isEqualTo(
-                AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
-        assertThat(mAccessNetworksManager.getPreferredTransportByNetworkCapability(
-                NetworkCapabilities.NET_CAPABILITY_IMS)).isEqualTo(
-                AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
-        assertThat(mAccessNetworksManager.getPreferredTransportByNetworkCapability(
-                NetworkCapabilities.NET_CAPABILITY_XCAP)).isEqualTo(
-                AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
-    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
index 0d6a668..1dcf2fa 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
@@ -164,7 +164,6 @@
 
         // Change data config
         doReturn(true).when(mDataConfigManager).isPingTestBeforeAutoDataSwitchRequired();
-        doReturn(true).when(mDataConfigManager).doesAutoDataSwitchAllowRoaming();
         doReturn(10000L).when(mDataConfigManager)
                 .getAutoDataSwitchAvailabilityStabilityTimeThreshold();
         doReturn(120000L).when(mDataConfigManager)
@@ -197,9 +196,7 @@
         mScheduledEventsToExtras = getPrivateField(mAutoDataSwitchControllerUT,
                 "mScheduledEventsToExtras", Map.class);
 
-        doReturn(true).when(mFeatureFlags).autoDataSwitchAllowRoaming();
-        doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag();
-        doReturn(true).when(mFeatureFlags).autoDataSwitchUsesDataEnabled();
+        doReturn(true).when(mFeatureFlags).autoDataSwitchEnhanced();
     }
 
     @After
@@ -296,7 +293,7 @@
     }
 
     @Test
-    public void testRoaming_prefer_roam_over_nonTerrestrial() {
+    public void testRoaming_prefer_roam_over_satellite() {
         // DDS -> nDDS: Prefer Roaming over non-terrestrial
         prepareIdealUsesNonDdsCondition();
         mIsNonTerrestrialNetwork = true;
@@ -321,6 +318,23 @@
     }
 
     @Test
+    public void testRoaming_satellite_bypass_settings() {
+        prepareIdealUsesNonDdsCondition();
+
+        doReturn(true).when(mDataConfigManager).isIgnoringDataRoamingSettingForSatellite();
+        doReturn(false).when(mPhone).getDataRoamingEnabled();
+
+        mIsNonTerrestrialNetwork = true;
+        serviceStateChanged(PHONE_1, NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+        mIsNonTerrestrialNetwork = false;
+        serviceStateChanged(PHONE_2, NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+        processAllFutureMessages();
+
+        verify(mMockedPhoneSwitcherCallback).onRequireValidation(PHONE_2, true/*needValidation*/);
+    }
+
+
+    @Test
     public void testRoaming_roaming_but_roam_disabled() {
         // Disable RAT + signalStrength base switching.
         doReturn(-1).when(mDataConfigManager).getAutoDataSwitchScoreTolerance();
@@ -369,21 +383,19 @@
     @Test
     public void testRoaming_same_roaming_condition_uses_rat_signalStrength() {
         // On primary phone
-        // 1. Both roaming, user allow roaming on both phone, uses RAT score to decide switch.
+        // 1. Both roaming, user allow roaming on both phone, do NOT use RAT score to decide switch.
         prepareIdealUsesNonDdsCondition();
         serviceStateChanged(PHONE_1, NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
         serviceStateChanged(PHONE_2, NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
         processAllFutureMessages();
 
-        verify(mMockedPhoneSwitcherCallback).onRequireValidation(PHONE_2, true/*needValidation*/);
+        verify(mMockedPhoneSwitcherCallback, never()).onRequireValidation(PHONE_2,
+                true/*needValidation*/);
 
         // On backup phone
         doReturn(PHONE_2).when(mPhoneSwitcher).getPreferredDataPhoneId();
-        // 2. Both roaming, user allow roaming on both phone, uses RAT score to decide switch.
-        signalStrengthChanged(PHONE_1, SignalStrength.SIGNAL_STRENGTH_GREAT);
-        signalStrengthChanged(PHONE_2, SignalStrength.SIGNAL_STRENGTH_POOR);
-        displayInfoChanged(PHONE_1, mGoodTelephonyDisplayInfo);
-        displayInfoChanged(PHONE_2, mBadTelephonyDisplayInfo);
+        // 2. Both roaming, do NOT uses RAT score to decide switch, so switch back to primary.
+        mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED);
         processAllFutureMessages();
 
         verify(mMockedPhoneSwitcherCallback).onRequireValidation(DEFAULT_PHONE_INDEX,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/CellularNetworkValidatorTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/CellularNetworkValidatorTest.java
index bbfd7a9..cef59d6 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/CellularNetworkValidatorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/CellularNetworkValidatorTest.java
@@ -16,15 +16,13 @@
 
 package com.android.internal.telephony.data;
 
-import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -64,6 +62,7 @@
             new PhoneCapability(1, 1, null, true, new int[0]);
     private static final PhoneCapability CAPABILITY_WITHOUT_VALIDATION_SUPPORTED =
             new PhoneCapability(1, 1, null, false, new int[0]);
+    private static final int CLEANUP_VALIDATION_TIMEOUT = 5010;
     private final CellIdentityLte mCellIdentityLte1 = new CellIdentityLte(123, 456, 0, 0, 111);
     private final CellIdentityLte mCellIdentityLte2 = new CellIdentityLte(321, 654, 0, 0, 222);
 
@@ -77,7 +76,7 @@
 
         doReturn(CAPABILITY_WITH_VALIDATION_SUPPORTED).when(mPhoneConfigurationManager)
                 .getCurrentPhoneCapability();
-        mValidatorUT = new CellularNetworkValidator(mContext);
+        mValidatorUT = new CellularNetworkValidator(mContext, mFeatureFlags);
         doReturn(new SubscriptionInfoInternal.Builder().setSimSlotIndex(0).setId(1).build())
                 .when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
         processAllMessages();
@@ -226,7 +225,7 @@
 
         // Mark mValidationCacheTtl to only 1 second.
         setCacheTtlInCarrierConfig(1000);
-        waitForMs(1100);
+        moveTimeForward(1100);
 
         resetStates();
         mValidatorUT.validate(subId, timeout, true, mCallback);
@@ -309,6 +308,8 @@
         mValidatorUT.validate(1, timeout, true, mCallback);
         mValidatorUT.mNetworkCallback.onCapabilitiesChanged(null, new NetworkCapabilities()
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED));
+        moveTimeForward(CLEANUP_VALIDATION_TIMEOUT);
+        processAllMessages();
         assertNetworkRecentlyValidated(1, true);
 
         // Change reg state to a different network.
@@ -340,6 +341,9 @@
             mValidatorUT.validate(subId, timeout, true, mCallback);
             mValidatorUT.mNetworkCallback.onCapabilitiesChanged(null, new NetworkCapabilities()
                     .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED));
+            // release the request
+            moveTimeForward(CLEANUP_VALIDATION_TIMEOUT);
+            processAllMessages();
             assertNetworkRecentlyValidated(subId, true);
         }
 
@@ -457,6 +461,9 @@
     }
 
     private void assertValidationResult(int subId, boolean shouldPass) {
+        // release the request
+        moveTimeForward(CLEANUP_VALIDATION_TIMEOUT);
+        processAllMessages();
         // Verify that validation is over.
         verify(mConnectivityManager).unregisterNetworkCallback(eq(mValidatorUT.mNetworkCallback));
         assertFalse(mValidatorUT.mHandler.hasMessagesOrCallbacks());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
index 3f2d6f2..a7bd9bc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -186,6 +186,7 @@
     private LinkBandwidthEstimatorCallback mLinkBandwidthEstimatorCallback;
 
     private boolean mIsNonTerrestrialNetwork = false;
+    private ArrayList<Integer> mCarrierSupportedServices = new ArrayList<>();
 
     private final DataProfile mGeneralPurposeDataProfile = new DataProfile.Builder()
             .setApnSetting(new ApnSetting.Builder()
@@ -691,6 +692,7 @@
                 .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
                 .setDataSpecificInfo(dsri)
                 .setIsNonTerrestrialNetwork(mIsNonTerrestrialNetwork)
+                .setAvailableServices(mCarrierSupportedServices)
                 .setEmergencyOnly(isEmergencyOnly)
                 .build());
 
@@ -700,6 +702,7 @@
                 .setRegistrationState(iwlanRegState)
                 .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
                 .setIsNonTerrestrialNetwork(mIsNonTerrestrialNetwork)
+                .setAvailableServices(mCarrierSupportedServices)
                 .setEmergencyOnly(isEmergencyOnly)
                 .build());
 
@@ -888,8 +891,8 @@
         doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
         doReturn(new SubscriptionInfoInternal.Builder().setId(1).build())
                 .when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
-        doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag();
-        doReturn(true).when(mFeatureFlags).satelliteInternet();
+        doReturn(true).when(mFeatureFlags).incallHandoverPolicy();
+
         when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
         doReturn(true).when(mMockPackageManager).hasSystemFeature(anyString());
 
@@ -1118,6 +1121,12 @@
         processAllMessages();
         Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
 
+        doReturn(CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED)
+                .when(mSatelliteController)
+                .getSatelliteDataServicePolicyForPlmn(anyInt(), any());
+        mCarrierSupportedServices.add(NetworkRegistrationInfo.SERVICE_TYPE_DATA);
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
         logd("DataNetworkControllerTest -Setup!");
     }
 
@@ -1529,10 +1538,8 @@
     public void testMovingFromInServiceToNoService() throws Exception {
         testSetupDataNetwork();
 
-        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
-                NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING);
-        // Verify we don't tear down the data network.
-        verifyInternetConnected();
+        // clear available services at no service
+        mCarrierSupportedServices.clear();
 
         serviceStateChanged(TelephonyManager.NETWORK_TYPE_UNKNOWN,
                 NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING);
@@ -1541,6 +1548,137 @@
     }
 
     @Test
+    public void testInServiceAvailableServicesChanged() throws Exception {
+        testSetupDataNetwork();
+
+        List<DataDisallowedReason> reasons = mDataNetworkControllerUT
+                .getInternetDataDisallowedReasons();
+        assertThat(reasons).isEmpty();
+
+        // Add available services sms to existing available services with data
+        mCarrierSupportedServices.add(NetworkRegistrationInfo.SERVICE_TYPE_SMS);
+
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+        // Verify we don't tear down the data network.
+        verifyInternetConnected();
+
+
+        mCarrierSupportedServices.clear();
+        // Add available services data and mms
+        mCarrierSupportedServices.add(NetworkRegistrationInfo.SERVICE_TYPE_DATA);
+        mCarrierSupportedServices.add(NetworkRegistrationInfo.SERVICE_TYPE_MMS);
+
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+        // Verify we don't tear down the data network.
+        verifyInternetConnected();
+
+        // clear all available services
+        mCarrierSupportedServices.clear();
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+        // Verify internet is not connected
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+
+        reasons = mDataNetworkControllerUT.getInternetDataDisallowedReasons();
+        assertThat(reasons).contains(DataDisallowedReason.SERVICE_OPTION_NOT_SUPPORTED);
+
+    }
+
+    @Test
+    public void testHomeToRoamingAvailableServicesChangedWithDataRoamingDisabled()
+            throws Exception {
+        testSetupDataNetwork();
+
+        List<DataDisallowedReason> reasons = mDataNetworkControllerUT
+                .getInternetDataDisallowedReasons();
+        assertThat(reasons).isEmpty();
+
+        // Disable data roaming setting
+        mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
+
+        // Home to roaming with same available services
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+
+        // Verify internet is not connected due to roaming disabled
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+
+        reasons = mDataNetworkControllerUT.getInternetDataDisallowedReasons();
+        assertThat(reasons).contains(DataDisallowedReason.ROAMING_DISABLED);
+    }
+
+    @Test
+    public void testHomeToRoamingAvailableServicesChangedWithDataRoamingEnabled()
+            throws Exception {
+        testSetupDataNetwork();
+
+        List<DataDisallowedReason> reasons = mDataNetworkControllerUT
+                .getInternetDataDisallowedReasons();
+        assertThat(reasons).isEmpty();
+
+        // Enable data roaming setting
+        mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(true);
+
+        // Home to roaming with same available services
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+
+        // Verify we don't tear down the data network since available services as still data
+        // with data roaming enabled
+        verifyInternetConnected();
+
+        // clear all available services
+        mCarrierSupportedServices.clear();
+        // At roaming
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+
+        // Verify internet is not connected
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+
+        reasons = mDataNetworkControllerUT.getInternetDataDisallowedReasons();
+        assertThat(reasons).contains(DataDisallowedReason.SERVICE_OPTION_NOT_SUPPORTED);
+    }
+
+    @Test
+    public void testOnAvailableServiceChanged_WithReevaluateNetworkRequest()
+            throws Exception {
+        // clear available services at no service
+        mCarrierSupportedServices.clear();
+
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+        // Set network request transport with Internet capability
+        mDataNetworkControllerUT.addNetworkRequest(
+                createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+        processAllMessages();
+
+        // Verify internet is not connected due to roaming disabled
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+
+        List<DataDisallowedReason> reasons = mDataNetworkControllerUT
+                .getInternetDataDisallowedReasons();
+        assertThat(reasons).contains(DataDisallowedReason.SERVICE_OPTION_NOT_SUPPORTED);
+
+        // add available services with data, re-evaluate network request
+        mCarrierSupportedServices.add(NetworkRegistrationInfo.SERVICE_TYPE_DATA);
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+        // Verify now internet was connected
+        verifyInternetConnected();
+
+        reasons = mDataNetworkControllerUT.getInternetDataDisallowedReasons();
+        assertThat(reasons).isEmpty();
+    }
+
+    @Test
     public void testPsRestrictedAndLifted() throws Exception {
         testSetupDataNetwork();
         Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
@@ -1563,7 +1701,6 @@
         verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
         verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_INTERNET);
 
-
         // PS unrestricted, new setup is allowed
         mDataNetworkControllerUT.obtainMessage(7/*EVENT_PS_RESTRICT_DISABLED*/).sendToTarget();
         processAllMessages();
@@ -1988,6 +2125,195 @@
     }
 
     @Test
+    public void testIgnoreDataRoamingSettingForSatellite() throws Exception {
+        // set up satellite network and register data roaming
+        mIsNonTerrestrialNetwork = true;
+        doReturn(true).when(mServiceState).getDataRoaming();
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+
+        // Enable data roaming setting
+        mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(true);
+
+        // Set network request transport with Internet capability
+        mDataNetworkControllerUT.addNetworkRequest(
+                createNetworkRequest(true,
+                        NetworkCapabilities.NET_CAPABILITY_INTERNET,
+                        NetworkCapabilities.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED));
+        processAllMessages();
+
+        // Verify internet is connected
+        verifyInternetConnected();
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // Disable data roaming setting
+        mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
+        processAllMessages();
+
+        // Verify internet is not connected
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // Setup carrier to bypass data roaming off setting for satellite network
+        mCarrierConfig.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_IGNORE_DATA_ROAMING_SETTING_BOOL, true);
+        carrierConfigChanged();
+        processAllMessages();
+
+        // Verify internet is connected
+        verifyInternetConnected();
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // reset satellite network and roaming registration
+        mIsNonTerrestrialNetwork = false;
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+    }
+
+    @Test
+    public void testIgnoreDataRoamingSettingForSatelliteWithBandwithConstrained() throws Exception {
+        // set up satellite network and register data roaming
+        mIsNonTerrestrialNetwork = true;
+        doReturn(true).when(mServiceState).getDataRoaming();
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+
+        // Enable data roaming setting
+        mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(true);
+
+        // Set network request transport with Internet capability
+        mDataNetworkControllerUT.addNetworkRequest(
+                createNetworkRequest(true, NetworkCapabilities.NET_CAPABILITY_INTERNET));
+        processAllMessages();
+
+        // Verify internet is connected
+        verifyInternetConnected();
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // Disable data roaming setting
+        mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
+        processAllMessages();
+
+        // Verify internet is not connected
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // Setup carrier to bypass data roaming off setting for satellite network
+        mCarrierConfig.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_IGNORE_DATA_ROAMING_SETTING_BOOL, true);
+        carrierConfigChanged();
+        processAllMessages();
+
+        // Verify internet is connected
+        verifyInternetConnected();
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // reset satellite network and roaming registration
+        mIsNonTerrestrialNetwork = false;
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+    }
+
+    @Test
+    public void testIgnoreDataRoamingSettingForSatelliteForUnrestrictedNetwork() throws Exception {
+        // set up satellite network and register data roaming
+        mIsNonTerrestrialNetwork = true;
+        doReturn(true).when(mServiceState).getDataRoaming();
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+
+        // Disable data roaming setting
+        mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
+
+        // Set network request transport with Internet capability
+        mDataNetworkControllerUT.addNetworkRequest(
+                createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+        processAllMessages();
+
+        // Verify internet is not connected
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // Setup carrier to bypass data roaming off setting for satellite network
+        mCarrierConfig.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_IGNORE_DATA_ROAMING_SETTING_BOOL, true);
+        carrierConfigChanged();
+        processAllMessages();
+
+        // Verify internet is still not connected
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        doReturn(CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL)
+                .when(mSatelliteController)
+                .getSatelliteDataServicePolicyForPlmn(anyInt(), any());
+        mDataNetworkControllerUT.obtainMessage(5 /*EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS*/,
+                DataEvaluation.DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED).sendToTarget();
+        processAllMessages();
+
+        // Verify internet is connected
+        verifyInternetConnected();
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // reset satellite network and roaming registration
+        mIsNonTerrestrialNetwork = false;
+        mCarrierSupportedServices.clear();
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+    }
+
+    @Test
+    public void testIgnoreDataRoamingSettingForSatelliteConfigForTerrestialNetwork() throws Exception {
+        // set up terrestrial network and roaming registration
+        mIsNonTerrestrialNetwork = false;
+        doReturn(true).when(mServiceState).getDataRoaming();
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+
+        // Enable data roaming setting
+        mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(true);
+
+        // Set network request transport with Internet capability
+        mDataNetworkControllerUT.addNetworkRequest(
+                createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+        processAllMessages();
+
+        // Verify internet is connected
+        verifyInternetConnected();
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // Disable data roaming setting
+        mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(false);
+        processAllMessages();
+
+        // Verify internet is not connected
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // Setup carrier to bypass data roaming off setting for satellite network
+        mCarrierConfig.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_IGNORE_DATA_ROAMING_SETTING_BOOL, true);
+        carrierConfigChanged();
+        processAllMessages();
+
+        // Verify internet is still not connected
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // Enable data roaming again
+        mDataNetworkControllerUT.getDataSettingsManager().setDataRoamingEnabled(true);
+        processAllMessages();
+
+        // Verify internet is connected again
+        verifyInternetConnected();
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // reset roaming registration
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+    }
+
+    @Test
     public void testDataEnabledChanged() throws Exception {
         mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
                 TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
@@ -2375,7 +2701,7 @@
     @Test
     public void testHandoverRuleFromString() {
         HandoverRule handoverRule = new HandoverRule("source=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, "
-                + "target=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, type=allowed");
+                + "target=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, type=allowed", mFeatureFlags);
         assertThat(handoverRule.sourceAccessNetworks).containsExactly(AccessNetworkType.GERAN,
                 AccessNetworkType.UTRAN, AccessNetworkType.EUTRAN, AccessNetworkType.NGRAN,
                 AccessNetworkType.IWLAN);
@@ -2387,7 +2713,7 @@
         assertThat(handoverRule.networkCapabilities).isEmpty();
 
         handoverRule = new HandoverRule("source=   NGRAN|     IWLAN, "
-                + "target  =    EUTRAN,    type  =    disallowed ");
+                + "target  =    EUTRAN,    type  =    disallowed ", mFeatureFlags);
         assertThat(handoverRule.sourceAccessNetworks).containsExactly(AccessNetworkType.NGRAN,
                 AccessNetworkType.IWLAN);
         assertThat(handoverRule.targetAccessNetworks).containsExactly(AccessNetworkType.EUTRAN);
@@ -2397,7 +2723,7 @@
 
         handoverRule = new HandoverRule("source=   IWLAN, "
                 + "target  =    EUTRAN,    type  =    disallowed, roaming = true,"
-                + " capabilities = IMS | EIMS ");
+                + " capabilities = IMS | EIMS ", mFeatureFlags);
         assertThat(handoverRule.sourceAccessNetworks).containsExactly(AccessNetworkType.IWLAN);
         assertThat(handoverRule.targetAccessNetworks).containsExactly(AccessNetworkType.EUTRAN);
         assertThat(handoverRule.type).isEqualTo(HandoverRule.RULE_TYPE_DISALLOWED);
@@ -2406,7 +2732,8 @@
         assertThat(handoverRule.isOnlyForRoaming).isTrue();
 
         handoverRule = new HandoverRule("source=EUTRAN|NGRAN|IWLAN|UNKNOWN, "
-                + "target=EUTRAN|NGRAN|IWLAN, type=disallowed, capabilities = IMS|EIMS");
+                + "target=EUTRAN|NGRAN|IWLAN, type=disallowed, capabilities = IMS|EIMS",
+                mFeatureFlags);
         assertThat(handoverRule.sourceAccessNetworks).containsExactly(AccessNetworkType.EUTRAN,
                 AccessNetworkType.NGRAN, AccessNetworkType.IWLAN, AccessNetworkType.UNKNOWN);
         assertThat(handoverRule.targetAccessNetworks).containsExactly(AccessNetworkType.EUTRAN,
@@ -2415,44 +2742,61 @@
         assertThat(handoverRule.networkCapabilities).containsExactly(
                 NetworkCapabilities.NET_CAPABILITY_IMS, NetworkCapabilities.NET_CAPABILITY_EIMS);
 
-        assertThrows(IllegalArgumentException.class,
-                () -> new HandoverRule("V2hhdCBUaGUgRnVjayBpcyB0aGlzIQ=="));
+        handoverRule = new HandoverRule("source=NGRAN|IWLAN, "
+                + "target  =    NGRAN|IWLAN,    type=disallowed, incall = true,"
+                + " capabilities = IMS|EIMS ", mFeatureFlags);
+        assertThat(handoverRule.sourceAccessNetworks).containsExactly(AccessNetworkType.NGRAN,
+                AccessNetworkType.IWLAN);
+        assertThat(handoverRule.sourceAccessNetworks).containsExactly(AccessNetworkType.NGRAN,
+                AccessNetworkType.IWLAN);
+        assertThat(handoverRule.type).isEqualTo(HandoverRule.RULE_TYPE_DISALLOWED);
+        assertThat(handoverRule.networkCapabilities).containsExactly(
+                NetworkCapabilities.NET_CAPABILITY_IMS, NetworkCapabilities.NET_CAPABILITY_EIMS);
+        assertThat(handoverRule.isOnlyForIncall).isTrue();
 
         assertThrows(IllegalArgumentException.class,
-                () -> new HandoverRule("target=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, type=allowed"));
+                () -> new HandoverRule("V2hhdCBUaGUgRnVjayBpcyB0aGlzIQ==", mFeatureFlags));
 
         assertThrows(IllegalArgumentException.class,
-                () -> new HandoverRule("source=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, type=allowed"));
+                () -> new HandoverRule("target=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, type=allowed",
+                                       mFeatureFlags));
+
+        assertThrows(IllegalArgumentException.class,
+                () -> new HandoverRule("source=GERAN|UTRAN|EUTRAN|NGRAN|IWLAN, type=allowed",
+                                        mFeatureFlags));
 
         assertThrows(IllegalArgumentException.class,
                 () -> new HandoverRule("source=GERAN, target=UNKNOWN, type=disallowed, "
-                        + "capabilities=IMS"));
+                        + "capabilities=IMS", mFeatureFlags));
 
         assertThrows(IllegalArgumentException.class,
                 () -> new HandoverRule("source=UNKNOWN, target=IWLAN, type=allowed, "
-                        + "capabilities=IMS"));
+                        + "capabilities=IMS", mFeatureFlags));
 
         assertThrows(IllegalArgumentException.class,
-                () -> new HandoverRule("source=GERAN, target=IWLAN, type=wtf"));
+                () -> new HandoverRule("source=GERAN, target=IWLAN, type=wtf", mFeatureFlags));
 
         assertThrows(IllegalArgumentException.class,
-                () -> new HandoverRule("source=GERAN, target=NGRAN, type=allowed"));
+                () -> new HandoverRule("source=GERAN, target=NGRAN, type=allowed", mFeatureFlags));
 
         assertThrows(IllegalArgumentException.class,
-                () -> new HandoverRule("source=IWLAN, target=WTFRAN, type=allowed"));
+                () -> new HandoverRule("source=IWLAN, target=WTFRAN, type=allowed",
+                                       mFeatureFlags));
 
         assertThrows(IllegalArgumentException.class,
-                () -> new HandoverRule("source=IWLAN, target=|, type=allowed"));
+                () -> new HandoverRule("source=IWLAN, target=|, type=allowed", mFeatureFlags));
 
         assertThrows(IllegalArgumentException.class,
-                () -> new HandoverRule("source=GERAN, target=IWLAN, type=allowed, capabilities=|"));
+                () -> new HandoverRule("source=GERAN, target=IWLAN, type=allowed, capabilities=|",
+                                        mFeatureFlags));
 
         assertThrows(IllegalArgumentException.class,
-                () -> new HandoverRule("source=GERAN, target=IWLAN, type=allowed, capabilities="));
+                () -> new HandoverRule("source=GERAN, target=IWLAN, type=allowed, capabilities=",
+                                        mFeatureFlags));
 
         assertThrows(IllegalArgumentException.class,
                 () -> new HandoverRule("source=GERAN, target=IWLAN, type=allowed, "
-                        + "capabilities=wtf"));
+                        + "capabilities=wtf", mFeatureFlags));
     }
 
     @Test
@@ -2920,6 +3264,35 @@
     }
 
     @Test
+    public void testHandoverDataNetworkNotAllowedByIncallPolicy() throws Exception {
+        mCarrierConfig.putStringArray(CarrierConfigManager.KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY,
+                new String[]{"source=EUTRAN, target=IWLAN, type=disallowed, incall=true, "
+                        + "capabilities=IMS"});
+        carrierConfigChanged();
+        testSetupImsDataNetwork();
+        doReturn(PhoneConstants.State.RINGING).when(mCT).getState();
+
+        // After this, IMS data network should be disconnected, and DNC should attempt to
+        // establish a new one on IWLAN
+        updateTransport(NetworkCapabilities.NET_CAPABILITY_IMS,
+                AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
+
+        // Verify all data disconnected.
+        verify(mMockedDataNetworkControllerCallback).onAnyDataNetworkExistingChanged(eq(false));
+        verify(mMockedDataNetworkControllerCallback).onPhysicalLinkStatusChanged(
+                eq(DataCallResponse.LINK_STATUS_INACTIVE));
+
+        // A new data network should be connected on IWLAN
+        List<DataNetwork> dataNetworkList = getDataNetworks();
+        assertThat(dataNetworkList).hasSize(1);
+        assertThat(dataNetworkList.get(0).isConnected()).isTrue();
+        assertThat(dataNetworkList.get(0).getNetworkCapabilities().hasCapability(
+                NetworkCapabilities.NET_CAPABILITY_IMS)).isTrue();
+        assertThat(dataNetworkList.get(0).getTransport())
+                .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
+    }
+
+    @Test
     public void testHandoverDataNetworkRetry() throws Exception {
         testSetupImsDataNetwork();
 
@@ -3670,6 +4043,13 @@
         processAllMessages();
 
         verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(true));
+
+        // Deactivate the data, verify notify PCO gone.
+        mDataNetworkControllerUT.tearDownAllDataNetworks(
+                DataNetwork.TEAR_DOWN_REASON_AIRPLANE_MODE_ON);
+        processAllFutureMessages();
+
+        verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(false));
     }
 
     @Test
@@ -5590,4 +5970,219 @@
         processAllMessages();
         assertThat(request.getState()).isEqualTo(TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED);
     }
+
+    @Test
+    public void testNotRestrictedDataConnectionRequest_WithoutDataServiceSupport()
+            throws Exception {
+        mCarrierSupportedServices.clear();
+        mCarrierSupportedServices.add(NetworkRegistrationInfo.SERVICE_TYPE_VOICE);
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+        // Set network request transport with Internet capability + Not Restricted
+        mDataNetworkControllerUT.addNetworkRequest(
+                createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+        mDataNetworkControllerUT.obtainMessage(5 /*EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS*/,
+                DataEvaluation.DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED).sendToTarget();
+        processAllMessages();
+
+        // Verify internet is not connected
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // reset satellite network and roaming registration
+        mCarrierSupportedServices.clear();
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+    }
+
+    @Test
+    public void testConnection_WithDataServiceCheckFlagDisabled_WithoutDataServiceSupport()
+            throws Exception {
+        doReturn(false).when(mFeatureFlags).dataServiceCheck();
+        mCarrierSupportedServices.clear();
+        mCarrierSupportedServices.add(NetworkRegistrationInfo.SERVICE_TYPE_VOICE);
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+        // Set network request transport with Internet capability + Not Restricted
+        mDataNetworkControllerUT.addNetworkRequest(
+                createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+        mDataNetworkControllerUT.obtainMessage(5 /*EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS*/,
+                DataEvaluation.DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED).sendToTarget();
+        processAllMessages();
+
+        // Verify internet is connected
+        verifyInternetConnected();
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // reset satellite network and roaming registration
+        mCarrierSupportedServices.clear();
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+    }
+
+    @Test
+    public void testRestrictedDataConnectionRequest_WithoutDataServiceSupport()
+            throws Exception {
+        mCarrierSupportedServices.clear();
+        mCarrierSupportedServices.add(NetworkRegistrationInfo.SERVICE_TYPE_VOICE);
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+        // Set network request transport with Internet capability + Restricted
+        NetworkCapabilities netCaps = new NetworkCapabilities();
+        netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+        mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+                new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+                        NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
+        mDataNetworkControllerUT.obtainMessage(5 /*EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS*/,
+                DataEvaluation.DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED).sendToTarget();
+        processAllMessages();
+
+        // Verify internet is not connected
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // reset satellite network and roaming registration
+        mCarrierSupportedServices.clear();
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+    }
+
+    @Test
+    public void testNotRestrictedNetworkRequest_WithRestrictedDataPolicySupportMode()
+            throws Exception {
+        // set up satellite network and register data roaming
+        mIsNonTerrestrialNetwork = true;
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+        // Set network request transport with Internet capability + Not Restricted
+        doReturn(CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED)
+                .when(mSatelliteController)
+                .getSatelliteDataServicePolicyForPlmn(anyInt(), any());
+        mDataNetworkControllerUT.addNetworkRequest(
+                createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+        mDataNetworkControllerUT.obtainMessage(5 /*EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS*/,
+                DataEvaluation.DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED).sendToTarget();
+        processAllMessages();
+
+        // Verify internet is not connected
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // reset satellite network and roaming registration
+        mIsNonTerrestrialNetwork = false;
+        mCarrierSupportedServices.clear();
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+    }
+
+    @Test
+    public void testBandwidthConstrainedNetworkRequest_WithConstrainedDataPolicySupportMode()
+            throws Exception {
+        // set up satellite network and register data roaming
+        mIsNonTerrestrialNetwork = true;
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+        // Set network request transport with Internet capability + Not Restricted
+        doReturn(CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED)
+                .when(mSatelliteController)
+                .getSatelliteDataServicePolicyForPlmn(anyInt(), any());
+        // Set network request transport as satellite in satellite network
+        NetworkCapabilities netCaps = new NetworkCapabilities();
+        netCaps.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+        netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED);
+        mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+                new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+                        NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
+        mDataNetworkControllerUT.obtainMessage(5 /*EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS*/,
+                DataEvaluation.DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED).sendToTarget();
+        processAllMessages();
+
+        // Verify internet is connected
+        verifyInternetConnected();
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // reset satellite network and roaming registration
+        mIsNonTerrestrialNetwork = false;
+        mCarrierSupportedServices.clear();
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+    }
+
+    @Test
+    public void testBandwidthNotConstrainedNetworkRequest_WithConstrainedDataPolicySupportMode()
+            throws Exception {
+        // set up satellite network
+        mIsNonTerrestrialNetwork = true;
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+        // Set network request transport with Internet capability + Not Restricted
+        doReturn(CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED)
+                .when(mSatelliteController)
+                .getSatelliteDataServicePolicyForPlmn(anyInt(), any());
+        // Set network request transport as satellite in satellite network
+        NetworkCapabilities netCaps = new NetworkCapabilities();
+        netCaps.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+        netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED);
+        mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+                new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+                        NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
+        mDataNetworkControllerUT.obtainMessage(5 /*EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS*/,
+                DataEvaluation.DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED).sendToTarget();
+        processAllMessages();
+
+        // Verify internet is not connected
+        verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // reset satellite network and roaming registration
+        mIsNonTerrestrialNetwork = false;
+        mCarrierSupportedServices.clear();
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+    }
+
+    @Test
+    public void testWithDataServiceCheckFlagDisabled_DataPolicySupportMode()
+            throws Exception {
+        doReturn(false).when(mFeatureFlags).dataServiceCheck();
+        // set up satellite network and register data roaming
+        mIsNonTerrestrialNetwork = true;
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+        // Set network request transport with Internet capability + Not Restricted
+        mCarrierConfig.putInt(CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT,
+                CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED);
+        carrierConfigChanged();
+        // Set network request transport as satellite in satellite network
+        NetworkCapabilities netCaps = new NetworkCapabilities();
+        netCaps.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+        netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED);
+        mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+                new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+                        NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
+        mDataNetworkControllerUT.obtainMessage(5 /*EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS*/,
+                DataEvaluation.DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED).sendToTarget();
+        processAllMessages();
+
+        // Verify internet is connected
+        verifyInternetConnected();
+        Mockito.clearInvocations(mMockedDataNetworkControllerCallback);
+
+        // reset satellite network and roaming registration
+        mIsNonTerrestrialNetwork = false;
+        mCarrierSupportedServices.clear();
+        serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+                NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
index f832a6b..6e92353 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
@@ -21,9 +21,11 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Matchers.argThat;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
@@ -32,7 +34,6 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 import android.net.ConnectivityManager;
 import android.net.InetAddresses;
@@ -382,6 +383,7 @@
     public void setUp() throws Exception {
         super.setUp(getClass().getSimpleName());
         doReturn(1).when(mPhone).getSubId();
+        doReturn("12345").when(mServiceState).getOperatorNumeric();
         doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(mImsCT).when(mImsPhone).getCallTracker();
         doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState();
@@ -430,9 +432,8 @@
                 NetworkCapabilities.NET_CAPABILITY_EIMS, NetworkCapabilities.NET_CAPABILITY_XCAP))
                 .when(mDataConfigManager).getForcedCellularTransportCapabilities();
         doReturn(CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED)
-                .when(mDataConfigManager).getSatelliteDataSupportMode();
-        doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag();
-        doReturn(true).when(mFeatureFlags).satelliteInternet();
+                .when(mSatelliteController)
+                .getSatelliteDataServicePolicyForPlmn(anyInt(), anyString());
 
         serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
                 NetworkRegistrationInfo.REGISTRATION_STATE_HOME, false/*isNtn*/);
@@ -1264,7 +1265,6 @@
 
     @Test
     public void testNetworkRequestDetachedBeforeConnected() throws Exception {
-        doReturn(true).when(mFeatureFlags).keepEmptyRequestsNetwork();
         NetworkRequestList networkRequestList = new NetworkRequestList(new TelephonyNetworkRequest(
                 new NetworkRequest.Builder()
                         .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
@@ -1551,6 +1551,78 @@
     }
 
     @Test
+    public void testSetupDataCallOnRadioNotAvailable() throws Exception {
+        NetworkRequestList networkRequestList = new NetworkRequestList();
+        networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                .build(), mPhone, mFeatureFlags));
+
+        mDataNetworkUT = new DataNetwork(mPhone, mFeatureFlags, Looper.myLooper(),
+        mDataServiceManagers, mInternetDataProfile, networkRequestList,
+                AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+                DataAllowedReason.NORMAL, mDataNetworkCallback);
+        assertThat(mDataNetworkUT.isConnecting()).isTrue();
+
+        mDataNetworkUT.sendMessage(4/*EVENT_RADIO_NOT_AVAILABLE*/);
+        processAllMessages();
+
+        assertThat(mDataNetworkUT.isConnected()).isFalse();
+        verify(mDataNetworkCallback).onSetupDataFailed(eq(mDataNetworkUT), eq(
+                networkRequestList), eq(DataFailCause.RADIO_NOT_AVAILABLE), anyLong());
+    }
+
+    @Test
+    public void testHandoverToIwlanSuccessWithRadioNotAvailable() throws Exception {
+        setupDataNetwork();
+
+        setSuccessfulSetupDataResponse(mMockedWlanDataServiceManager, 456);
+        TelephonyNetworkAgent mockNetworkAgent = Mockito.mock(TelephonyNetworkAgent.class);
+        replaceInstance(DataNetwork.class, "mNetworkAgent",
+                mDataNetworkUT, mockNetworkAgent);
+        // Now handover to IWLAN
+        mDataNetworkUT.startHandover(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, null);
+        mDataNetworkUT.sendMessage(4/*EVENT_RADIO_NOT_AVAILABLE*/);
+        processAllMessages();
+
+        assertThat(mDataNetworkUT.isConnected()).isTrue();
+        assertThat(mDataNetworkUT.getTransport()).isEqualTo(
+                AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
+    }
+
+    @Test
+    public void testHandoverToIwlanFailedWithRadioNotAvailable() throws Exception {
+        setupDataNetwork();
+
+        setFailedSetupDataResponse(mMockedWlanDataServiceManager,
+                DataServiceCallback.RESULT_ERROR_TEMPORARILY_UNAVAILABLE);
+
+        TelephonyNetworkAgent mockNetworkAgent = Mockito.mock(TelephonyNetworkAgent.class);
+        replaceInstance(DataNetwork.class, "mNetworkAgent",
+                mDataNetworkUT, mockNetworkAgent);
+        // Now handover to IWLAN
+        mDataNetworkUT.startHandover(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, null);
+        mDataNetworkUT.sendMessage(4/*EVENT_RADIO_NOT_AVAILABLE*/);
+        processAllMessages();
+
+        assertThat(mDataNetworkUT.isConnected()).isFalse();
+    }
+
+    @Test
+    public void testHandoverToCellularWithRadioNotAvailable() throws Exception {
+        testCreateDataNetworkOnIwlan();
+
+        TelephonyNetworkAgent mockNetworkAgent = Mockito.mock(TelephonyNetworkAgent.class);
+        replaceInstance(DataNetwork.class, "mNetworkAgent",
+                mDataNetworkUT, mockNetworkAgent);
+        // Now handover to IWLAN
+        mDataNetworkUT.startHandover(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, null);
+        mDataNetworkUT.sendMessage(4/*EVENT_RADIO_NOT_AVAILABLE*/);
+        processAllMessages();
+
+        assertThat(mDataNetworkUT.isConnected()).isFalse();
+    }
+
+    @Test
     public void testNetworkAgentConfig() throws Exception {
         createImsDataNetwork(false/*IsMmtel*/);
 
@@ -2221,8 +2293,7 @@
     }
 
     @Test
-    public void testValidationStatusOnPreciseDataConnectionState_FlagEnabled() throws Exception {
-        when(mFeatureFlags.networkValidation()).thenReturn(true);
+    public void testValidationStatusOnPreciseDataConnectionState() throws Exception {
         setupIwlanDataNetwork();
 
         ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor =
@@ -2271,37 +2342,7 @@
     }
 
     @Test
-    public void testValidationStatus_FlagDisabled() throws Exception {
-        // network validation flag disabled
-        when(mFeatureFlags.networkValidation()).thenReturn(false);
-        setupIwlanDataNetwork();
-
-        // precise data connection state posted for setup data call response
-        ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor =
-                ArgumentCaptor.forClass(PreciseDataConnectionState.class);
-        verify(mPhone, times(2)).notifyDataConnection(pdcsCaptor.capture());
-
-        // data state updated with network validation status
-        DataCallResponse response = createDataCallResponse(123,
-                DataCallResponse.LINK_STATUS_ACTIVE, Collections.emptyList(), null,
-                PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS);
-        mDataNetworkUT.sendMessage(8 /*EVENT_DATA_STATE_CHANGED*/, new AsyncResult(
-                AccessNetworkConstants.TRANSPORT_TYPE_WLAN, List.of(response), null));
-        processAllMessages();
-
-        // Verify updated validation status at precise data connection state not posted due to flag
-        // disabled
-        pdcsCaptor = ArgumentCaptor.forClass(PreciseDataConnectionState.class);
-        verify(mPhone, times(2)).notifyDataConnection(pdcsCaptor.capture());
-        List<PreciseDataConnectionState> pdcsList = pdcsCaptor.getAllValues();
-        assertThat(pdcsList.get(1).getNetworkValidationStatus())
-                .isEqualTo(PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED);
-    }
-
-    @Test
-    public void testHandoverWithSuccessNetworkValidation_FlagEnabled() throws Exception {
-        when(mFeatureFlags.networkValidation()).thenReturn(true);
-
+    public void testHandoverWithSuccessNetworkValidation() throws Exception {
         setupDataNetwork();
 
         setSuccessfulSetupDataResponse(
@@ -2537,6 +2578,45 @@
 
         // Test constrained traffic
         doReturn(CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED)
+                .when(mSatelliteController)
+                .getSatelliteDataServicePolicyForPlmn(anyInt(), anyString());
+        mDataNetworkUT.sendMessage(22/*EVENT_VOICE_CALL_STARTED*/); // update network capabilities
+        processAllMessages();
+
+        assertThat(mDataNetworkUT.getNetworkCapabilities()
+                .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)).isTrue();
+        try {
+            assertThat(mDataNetworkUT.getNetworkCapabilities()
+                    .hasCapability(DataUtils.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED)).isFalse();
+        } catch (Exception ignored) { }
+
+        // Test unconstrained traffic
+        doReturn(CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL)
+                .when(mSatelliteController)
+                .getSatelliteDataServicePolicyForPlmn(anyInt(), anyString());
+        mDataNetworkUT.sendMessage(22/*EVENT_VOICE_CALL_STARTED*/); // update network capabilities
+        processAllMessages();
+
+        assertThat(mDataNetworkUT.getNetworkCapabilities()
+                .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)).isTrue();
+        // TODO(enable after NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED become a default cap)
+//        try {
+//            assertThat(mDataNetworkUT.getNetworkCapabilities()
+//                    .hasCapability(DataUtils.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED)).isTrue();
+//        } catch (Exception ignored) {}
+    }
+
+    @Test
+    public void testUnrestrictedSatelliteNetworkCapabilities_WithDataServiceCheckFlagDisabled() {
+        doReturn(false).when(mFeatureFlags).dataServiceCheck();
+        setupNonTerrestrialDataNetwork();
+        assertThat(mDataNetworkUT.isSatellite()).isTrue();
+
+        assertThat(mDataNetworkUT.getNetworkCapabilities()
+                .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)).isFalse();
+
+        // Test constrained traffic
+        doReturn(CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED)
                 .when(mDataConfigManager).getSatelliteDataSupportMode();
         mDataNetworkUT.sendMessage(22/*EVENT_VOICE_CALL_STARTED*/); // update network capabilities
         processAllMessages();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
index 96d0c8c..aef2fcf 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
@@ -24,7 +24,6 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
 import android.content.ContentValues;
@@ -50,6 +49,7 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
+import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.TelephonyTest;
 import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback;
 import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback;
@@ -1031,8 +1031,6 @@
 
     @Test
     public void testGetDataProfileForSatellite() {
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
-
         NetworkRequest request = new NetworkRequest.Builder()
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_RCS)
                 .build();
@@ -1356,7 +1354,7 @@
     }
 
     @Test
-    public void testSimInsertedAgain() throws Exception {
+    public void testSimInsertedAgain() {
         testSimRemoval();
         Mockito.clearInvocations(mDataProfileManagerCallback);
         Mockito.clearInvocations(mMockedWwanDataServiceManager);
@@ -1958,7 +1956,7 @@
 
     private void changeSimStateTo(@TelephonyManager.SimState int simState) {
         mSimInserted = simState == TelephonyManager.SIM_STATE_LOADED;
-        mDataNetworkControllerCallback.onSimStateChanged(simState);
+        doReturn(IccCardConstants.State.intToState(simState)).when(mIccCard).getState();
     }
 
     @Test
@@ -1982,7 +1980,6 @@
     public void testDifferentNetworkRequestProfilesOnEsimBootStrapProvisioning() {
         Mockito.clearInvocations(mDataProfileManagerCallback);
         Mockito.clearInvocations(mMockedWwanDataServiceManager);
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
 
         // SIM inserted
         mDataProfileManagerUT.obtainMessage(3 /* EVENT_SIM_REFRESH */).sendToTarget();
@@ -2051,7 +2048,6 @@
     public void testInfrastructureProfileOnEsimBootStrapProvisioning() {
         Mockito.clearInvocations(mDataProfileManagerCallback);
         Mockito.clearInvocations(mMockedWwanDataServiceManager);
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
 
         // SIM inserted
         mDataProfileManagerUT.obtainMessage(3 /* EVENT_SIM_REFRESH */).sendToTarget();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataStallRecoveryManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataStallRecoveryManagerTest.java
index 9f8b8ad..8cbd61f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataStallRecoveryManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataStallRecoveryManagerTest.java
@@ -19,10 +19,11 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertNotNull;
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
@@ -91,7 +92,6 @@
         Field field = DataStallRecoveryManager.class.getDeclaredField("mPredictWaitingMillis");
         field.setAccessible(true);
 
-        doReturn(true).when(mFeatureFlags).dsrsDiagnosticsEnabled();
         mFakeContentResolver = new FakeContentResolver();
         doReturn(mFakeContentResolver).when(mContext).getContentResolver();
         // Set the global settings for action enabled state and duration to
@@ -433,7 +433,6 @@
     @Test
     public void testSendDSRMData() throws Exception {
         ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
-        boolean isDsrsDiagnosticsEnabled = mFeatureFlags.dsrsDiagnosticsEnabled();
 
         logd("Set phone status to normal status.");
         sendOnInternetDataNetworkCallback(true);
@@ -465,13 +464,8 @@
             logd(bundle.toString());
             int size = bundle.size();
             logd("bundle size is " + size);
-            if (isDsrsDiagnosticsEnabled) {
-                // Check if bundle size is 27
-                assertThat(size).isEqualTo(27);
-            } else {
-                // Check if bundle size is 19
-                assertThat(size).isEqualTo(19);
-            }
+            // Check if bundle size is 27
+            assertThat(size).isEqualTo(27);
         }
     }
 
@@ -588,4 +582,24 @@
         // recovery action will jump to modem reset action if user doing the radio restart.
         assertThat(mDataStallRecoveryManager.getRecoveryAction()).isEqualTo(4);
     }
+
+    @Test
+    public void testDoNotDoRecoveryActionWhenActiveCall() throws Exception {
+        sendOnInternetDataNetworkCallback(true);
+        mDataStallRecoveryManager.setRecoveryAction(
+                DataStallRecoveryManager.RECOVERY_ACTION_RADIO_RESTART);
+        doReturn(mSignalStrength).when(mPhone).getSignalStrength();
+        // Simulate active call
+        doReturn(PhoneConstants.State.OFFHOOK).when(mPhone).getState();
+
+        logd("Sending validation failed callback");
+        sendValidationStatusCallback(NetworkAgent.VALIDATION_STATUS_NOT_VALID);
+        processAllFutureMessages();
+
+        verify(mSST, never()).powerOffRadioSafely();
+        verify(mPhone, never()).rebootModem(any());
+
+        assertThat(mDataStallRecoveryManager.getRecoveryAction())
+                .isEqualTo(DataStallRecoveryManager.RECOVERY_ACTION_RADIO_RESTART);
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataUtilsTest.java
index 38de618..6a19889 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataUtilsTest.java
@@ -18,8 +18,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.Mockito.doReturn;
-
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 
@@ -43,7 +41,6 @@
         logd("DataUtilsTest +Setup!");
         super.setUp(getClass().getSimpleName());
         mFeatureFlags = Mockito.mock(FeatureFlags.class);
-        doReturn(true).when(mFeatureFlags).satelliteInternet();
         logd("DataUtilsTest -Setup!");
     }
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/KeepAliveTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/KeepAliveTrackerTest.java
index ceb08bf..99308c3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/KeepAliveTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/KeepAliveTrackerTest.java
@@ -41,6 +41,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -51,6 +52,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
+@Ignore("Temporary ignore - this test is using reflection to modify the internals of NetworkAgent but these have changed for a bugfix")
 public class KeepAliveTrackerTest extends TelephonyTest {
 
     private KeepaliveTracker mKeepaliveTrackerUT;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
index 6e41448..e9b1cdf 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
@@ -42,7 +42,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
@@ -102,7 +102,6 @@
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 public class PhoneSwitcherTest extends TelephonyTest {
-    private static final int ACTIVE_PHONE_SWITCH = 1;
     private static final int EVENT_RADIO_ON = 108;
     private static final int EVENT_MODEM_COMMAND_DONE = 112;
     private static final int EVENT_EVALUATE_AUTO_SWITCH = 111;
@@ -118,7 +117,6 @@
     private ServiceStateTracker mSST2;
     private Phone mImsPhone;
     private DataSettingsManager mDataSettingsManager2;
-    private Handler mActivePhoneSwitchHandler;
     private GsmCdmaCall mActiveCall;
     private GsmCdmaCall mHoldingCall;
     private GsmCdmaCall mInactiveCall;
@@ -158,7 +156,6 @@
         mSST2 = mock(ServiceStateTracker.class);
         mImsPhone = mock(Phone.class);
         mDataSettingsManager2 = mock(DataSettingsManager.class);
-        mActivePhoneSwitchHandler = mock(Handler.class);
         mActiveCall = mock(GsmCdmaCall.class);
         mHoldingCall = mock(GsmCdmaCall.class);
         mInactiveCall = mock(GsmCdmaCall.class);
@@ -207,192 +204,6 @@
         super.tearDown();
     }
 
-    /**
-     * Test that a single phone case results in our phone being active and the RIL called
-     */
-    @Test
-    public void testRegister() throws Exception {
-        initialize();
-
-        // verify nothing has been done while there are no inputs
-        assertTrue("data should be always allowed for emergency", mDataAllowed[0]);
-        assertFalse("data allowed initially", mDataAllowed[1]);
-
-        NetworkRequest internetNetworkRequest = addInternetNetworkRequest(null, 50);
-
-        assertFalse("phone active after request", mPhoneSwitcherUT
-                .shouldApplyNetworkRequest(new TelephonyNetworkRequest(
-                        internetNetworkRequest, mPhone, mFeatureFlags), 0));
-
-        // not registered yet - shouldn't inc
-        verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
-
-        mPhoneSwitcherUT.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
-                ACTIVE_PHONE_SWITCH, null);
-
-        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
-        clearInvocations(mActivePhoneSwitchHandler);
-
-        setDefaultDataSubId(0);
-
-        verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
-
-        setSlotIndexToSubId(0, 0);
-        mSubChangedListener.onSubscriptionsChanged();
-        processAllMessages();
-
-        AsyncResult res = new AsyncResult(1, null,  null);
-        Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
-        processAllMessages();
-        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
-        clearInvocations(mActivePhoneSwitchHandler);
-        assertTrue("data not allowed", mDataAllowed[0]);
-
-        // now try various things that should cause the active phone to switch:
-        // 1 lose default via default sub change
-        // 2 gain default via default sub change
-        // 3 lose default via sub->phone change
-        // 4 gain default via sub->phone change
-        // 5 lose default network request
-        // 6 gain subscription-specific request
-        // 7 lose via sub->phone change
-        // 8 gain via sub->phone change
-        // 9 lose subscription-specific request
-        // 10 don't switch phones when in emergency mode
-
-        // 1 lose default via default sub change
-        setDefaultDataSubId(1);
-
-        Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
-        processAllMessages();
-        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
-        clearInvocations(mActivePhoneSwitchHandler);
-        assertFalse("data allowed", mDataAllowed[0]);
-
-        setSlotIndexToSubId(1, 1);
-        clearInvocations(mAutoDataSwitchController);
-        mSubChangedListener.onSubscriptionsChanged();
-        processAllMessages();
-
-        Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
-        processAllMessages();
-        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
-        verify(mAutoDataSwitchController).notifySubscriptionsMappingChanged();
-        clearInvocations(mActivePhoneSwitchHandler);
-        assertFalse("data allowed", mDataAllowed[0]);
-        assertTrue("data not allowed", mDataAllowed[1]);
-
-        // 2 gain default via default sub change
-        setDefaultDataSubId(0);
-
-        Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
-        processAllMessages();
-        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
-        clearInvocations(mActivePhoneSwitchHandler);
-        assertFalse("data allowed", mDataAllowed[1]);
-        assertTrue("data not allowed", mDataAllowed[0]);
-
-        // 3 lose default via sub->phone change
-        setSlotIndexToSubId(0, 2);
-        clearInvocations(mAutoDataSwitchController);
-        mSubChangedListener.onSubscriptionsChanged();
-        processAllMessages();
-        verify(mAutoDataSwitchController).notifySubscriptionsMappingChanged();
-        Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
-        processAllMessages();
-
-        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
-        clearInvocations(mActivePhoneSwitchHandler);
-        assertFalse("data allowed", mDataAllowed[0]);
-        assertFalse("data allowed", mDataAllowed[1]);
-
-        // 4 gain default via sub->phone change
-        setSlotIndexToSubId(0, 0);
-        mSubChangedListener.onSubscriptionsChanged();
-        processAllMessages();
-
-        Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
-        processAllMessages();
-        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
-        clearInvocations(mActivePhoneSwitchHandler);
-        assertTrue("data not allowed", mDataAllowed[0]);
-        assertFalse("data allowed", mDataAllowed[1]);
-
-        // 5 lose default network request
-        releaseNetworkRequest(internetNetworkRequest);
-
-        Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
-        processAllMessages();
-        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
-        clearInvocations(mActivePhoneSwitchHandler);
-        assertTrue("data not allowed", mDataAllowed[0]);
-        assertFalse("data allowed", mDataAllowed[1]);
-
-        // 6 gain subscription-specific request
-        NetworkRequest specificInternetRequest = addInternetNetworkRequest(0, 50);
-
-        Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
-        processAllMessages();
-        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
-        clearInvocations(mActivePhoneSwitchHandler);
-        assertTrue("data not allowed", mDataAllowed[0]);
-        assertFalse("data allowed", mDataAllowed[1]);
-
-        // 7 lose via sub->phone change
-        setSlotIndexToSubId(0, 1);
-        mSubChangedListener.onSubscriptionsChanged();
-        processAllMessages();
-
-        Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
-        processAllMessages();
-        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
-        clearInvocations(mActivePhoneSwitchHandler);
-        assertFalse("data allowed", mDataAllowed[0]);
-        assertFalse("data allowed", mDataAllowed[1]);
-
-        // 8 gain via sub->phone change
-        setSlotIndexToSubId(0, 0);
-        mSubChangedListener.onSubscriptionsChanged();
-        processAllMessages();
-
-        Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
-        processAllMessages();
-        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
-        clearInvocations(mActivePhoneSwitchHandler);
-        assertTrue("data not allowed", mDataAllowed[0]);
-        assertFalse("data allowed", mDataAllowed[1]);
-
-        // 9 lose subscription-specific request
-        releaseNetworkRequest(specificInternetRequest);
-
-        Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
-        processAllMessages();
-        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
-        clearInvocations(mActivePhoneSwitchHandler);
-        assertTrue("data not allowed", mDataAllowed[0]);
-        assertFalse("data allowed", mDataAllowed[1]);
-
-        // 10 don't switch phones when in emergency mode
-        // not ready yet - Phone turns out to be hard to stub out
-//        phones[0].setInEmergencyCall(true);
-//        connectivityServiceMock.addDefaultRequest();
-//        processAllMessages();
-//        if (testHandler.getActivePhoneSwitchCount() != 11) {
-//            fail("after release of request, ActivePhoneSwitchCount not 11!");
-//        }
-//        if (commandsInterfaces[0].isDataAllowed()) fail("data allowed");
-//        if (commandsInterfaces[1].isDataAllowed()) fail("data allowed");
-//
-//        phones[0].setInEmergencyCall(false);
-//        connectivityServiceMock.addDefaultRequest();
-//        processAllMessages();
-//        if (testHandler.getActivePhoneSwitchCount() != 12) {
-//            fail("after release of request, ActivePhoneSwitchCount not 11!");
-//        }
-//        if (commandsInterfaces[0].isDataAllowed()) fail("data allowed");
-//        if (commandsInterfaces[1].isDataAllowed()) fail("data allowed");
-    }
-
     /** Test Data Auto Switch **/
     @Test
     public void testAutoDataSwitch_retry() throws Exception {
@@ -407,7 +218,7 @@
         processAllFutureMessages();
 
         // Mock validation failed, expect retry attempt
-        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
+        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(true),
                 eq(mPhoneSwitcherUT.mValidationCallback));
         mPhoneSwitcherUT.mValidationCallback.onValidationDone(false, 2/*Phone2*/);
         processAllMessages();
@@ -416,6 +227,7 @@
 
         // Test clear failed count upon switch succeeded.
         mAutoDataSwitchCallback.onRequireValidation(1/*Phone2*/, true);
+        moveTimeForward(5100);
         processAllFutureMessages();
         mPhoneSwitcherUT.mValidationCallback.onValidationDone(true, 2/*Phone2*/);
         processAllMessages();
@@ -501,11 +313,7 @@
         setSlotIndexToSubId(0, 0);
         setSlotIndexToSubId(1, 1);
         setDefaultDataSubId(0);
-        mPhoneSwitcherUT.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
-                ACTIVE_PHONE_SWITCH, null);
         processAllMessages();
-        // verify initial conditions
-        verify(mActivePhoneSwitchHandler, times(1)).sendMessageAtTime(any(), anyLong());
 
         assertTrue("data not allowed", mDataAllowed[0]);
         assertFalse("data allowed", mDataAllowed[1]);
@@ -517,8 +325,6 @@
         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
         processAllMessages();
 
-        // After gain of network request, mActivePhoneSwitchHandler should be notified 2 times.
-        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
         assertFalse("data allowed", mDataAllowed[0]);
         assertTrue("data not allowed", mDataAllowed[1]);
     }
@@ -714,13 +520,7 @@
     public void testSetPreferredDataModemCommand() throws Exception {
         doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
         initialize();
-        mPhoneSwitcherUT.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
-                ACTIVE_PHONE_SWITCH, null);
-        mPhoneSwitcherUT.registerForActivePhoneSwitch(mActivePhoneSwitchHandler,
-                ACTIVE_PHONE_SWITCH, null);
-        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
         clearInvocations(mMockRadioConfig);
-        clearInvocations(mActivePhoneSwitchHandler);
 
         // Phone 0 has sub 1, phone 1 has sub 2.
         // Sub 1 is default data sub.
@@ -733,16 +533,13 @@
         AsyncResult res = new AsyncResult(1, null,  null);
         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
         processAllMessages();
-        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
         clearInvocations(mMockRadioConfig);
-        clearInvocations(mActivePhoneSwitchHandler);
 
         // Notify phoneSwitcher about default data sub and default network request.
         // It shouldn't change anything.
         NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
         NetworkRequest mmsRequest = addMmsNetworkRequest(2);
         verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
-        verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
@@ -764,7 +561,6 @@
         verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
         processAllMessages();
-        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
@@ -775,7 +571,6 @@
                 new TelephonyNetworkRequest(mmsRequest, mPhone, mFeatureFlags), 1));
 
         clearInvocations(mMockRadioConfig);
-        clearInvocations(mActivePhoneSwitchHandler);
 
         // Unset preferred sub should make phone0 preferredDataModem again.
         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(
@@ -787,7 +582,6 @@
         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
         Message.obtain(mPhoneSwitcherUT, EVENT_MODEM_COMMAND_DONE, res).sendToTarget();
         processAllMessages();
-        verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
         assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
                 new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
         assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
@@ -830,7 +624,7 @@
         // Set sub 2 as preferred sub should make phone 1 activated and phone 0 deactivated.
         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, true, null);
         processAllMessages();
-        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
+        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(true),
                 eq(mPhoneSwitcherUT.mValidationCallback));
         // Validation failed. Preferred data sub should remain 1, data phone should remain 0.
         mPhoneSwitcherUT.mValidationCallback.onValidationDone(false, 2);
@@ -851,7 +645,7 @@
         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(
                 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, true, null);
         processAllMessages();
-        verify(mCellularNetworkValidator).validate(eq(1), eq(timeout), eq(false),
+        verify(mCellularNetworkValidator).validate(eq(1), eq(timeout), eq(true),
                 eq(mPhoneSwitcherUT.mValidationCallback));
         mPhoneSwitcherUT.mValidationCallback.onValidationDone(true, 1);
         processAllMessages();
@@ -1081,7 +875,7 @@
 
         // verify the attempt to do auto data switch to Phone2(nDDS)
         processAllFutureMessages();
-        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
+        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(true),
                 eq(mPhoneSwitcherUT.mValidationCallback));
 
         // Phone2 has holding call on VoWifi, no need to switch data
@@ -1465,7 +1259,7 @@
         clearInvocations(mCellularNetworkValidator);
         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback1);
         processAllMessages();
-        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
+        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(true),
                 eq(mPhoneSwitcherUT.mValidationCallback));
         doReturn(true).when(mCellularNetworkValidator).isValidating();
         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback2);
@@ -1489,7 +1283,7 @@
         // Back to back call, call 1 to switch to subId 2, call 2 to switch back.
         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, true, mSetOpptDataCallback1);
         processAllMessages();
-        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(false),
+        verify(mCellularNetworkValidator).validate(eq(2), anyLong(), eq(true),
                 eq(mPhoneSwitcherUT.mValidationCallback));
         doReturn(true).when(mCellularNetworkValidator).isValidating();
         mPhoneSwitcherUT.trySetOpportunisticDataSubscription(
@@ -2209,7 +2003,8 @@
         NetworkRequest networkRequest = new NetworkRequest(netCap, ConnectivityManager.TYPE_NONE,
                 0, NetworkRequest.Type.REQUEST);
 
-        mPhoneSwitcherUT.onRequestNetwork(networkRequest);
+        mPhoneSwitcherUT.onRequestNetwork(new TelephonyNetworkRequest(
+                networkRequest, mPhone, mFeatureFlags));
         return networkRequest;
     }
 
@@ -2227,7 +2022,8 @@
         }
         NetworkRequest networkRequest = new NetworkRequest(netCap, ConnectivityManager.TYPE_NONE,
                 1, NetworkRequest.Type.REQUEST);
-        mPhoneSwitcherUT.onRequestNetwork(networkRequest);
+        mPhoneSwitcherUT.onRequestNetwork(new TelephonyNetworkRequest(
+                networkRequest, mPhone, mFeatureFlags));
         return networkRequest;
     }
 
@@ -2235,6 +2031,7 @@
      * Tell PhoneSwitcher to release a network request.
      */
     private void releaseNetworkRequest(NetworkRequest networkRequest) throws Exception {
-        mPhoneSwitcherUT.onReleaseNetwork(networkRequest);
+        mPhoneSwitcherUT.onReleaseNetwork(new TelephonyNetworkRequest(
+                networkRequest, mPhone, mFeatureFlags));
     }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/QosCallbackTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/QosCallbackTrackerTest.java
index d528d85..beb6bac 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/QosCallbackTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/QosCallbackTrackerTest.java
@@ -47,6 +47,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -56,6 +57,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
+@Ignore("Temporary ignore - this test is using reflection to modify the internals of NetworkAgent but these have changed for a bugfix")
 public class QosCallbackTrackerTest extends TelephonyTest {
 
     class Filter implements QosCallbackTracker.IFilter {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkFactoryTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkFactoryTest.java
deleted file mode 100644
index e1a0eac..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkFactoryTest.java
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.data;
-
-import static com.android.internal.telephony.NetworkFactory.CMD_CANCEL_REQUEST;
-import static com.android.internal.telephony.NetworkFactory.CMD_REQUEST_NETWORK;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import android.net.NetworkCapabilities;
-import android.net.NetworkProvider;
-import android.net.NetworkRequest;
-import android.net.TelephonyNetworkSpecifier;
-import android.os.Looper;
-import android.os.Message;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.util.ArraySet;
-
-import androidx.test.filters.FlakyTest;
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.telephony.ISub;
-import com.android.internal.telephony.RadioConfig;
-import com.android.internal.telephony.TelephonyTest;
-import com.android.telephony.Rlog;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class TelephonyNetworkFactoryTest extends TelephonyTest {
-    private static final String LOG_TAG = "TelephonyNetworkFactoryTest";
-
-    // Mocked classes
-    PhoneSwitcher mPhoneSwitcher;
-    private RadioConfig mMockRadioConfig;
-    private ISub mMockedIsub;
-
-    private String mTestName = "";
-
-    // List of all requests filed by a test
-    private final ArraySet<TelephonyNetworkRequest> mAllNetworkRequestSet = new ArraySet<>();
-    // List of requests active
-    private final ArrayList<TelephonyNetworkRequest> mNetworkRequestList = new ArrayList<>();
-    // List of complete messages associated with the network requests
-    private final Map<TelephonyNetworkRequest, Message> mNetworkRequestMessageMap = new HashMap<>();
-
-    private TelephonyNetworkFactory mTelephonyNetworkFactoryUT;
-    private int mRequestId = 0;
-
-    private void log(String str) {
-        Rlog.d(LOG_TAG + " " + mTestName, str);
-    }
-
-    private NetworkRequest makeSubSpecificInternetRequest(int subId) {
-        NetworkCapabilities netCap = (new NetworkCapabilities())
-                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
-                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
-                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
-        netCap.setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
-                .setSubscriptionId(subId).build());
-        NetworkRequest networkRequest = new NetworkRequest(netCap, -1,
-                mRequestId++, NetworkRequest.Type.REQUEST);
-        mTelephonyNetworkFactoryUT.obtainMessage(CMD_REQUEST_NETWORK, 0, 0, networkRequest)
-                .sendToTarget();
-        return networkRequest;
-    }
-
-    private NetworkRequest makeDefaultInternetRequest() {
-        NetworkCapabilities netCap = (new NetworkCapabilities())
-                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
-                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
-                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
-        NetworkRequest networkRequest = new NetworkRequest(netCap, -1,
-                mRequestId++, NetworkRequest.Type.REQUEST);
-        mTelephonyNetworkFactoryUT.obtainMessage(CMD_REQUEST_NETWORK, 0, 0, networkRequest)
-                .sendToTarget();
-        return networkRequest;
-    }
-
-    private NetworkRequest makeSubSpecificMmsRequest(int subId) {
-        NetworkCapabilities netCap = (new NetworkCapabilities())
-                .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
-                .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
-                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
-        netCap.setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
-                .setSubscriptionId(subId).build());
-        NetworkRequest networkRequest = new NetworkRequest(netCap, -1,
-                mRequestId++, NetworkRequest.Type.REQUEST);
-        mTelephonyNetworkFactoryUT.obtainMessage(CMD_REQUEST_NETWORK, 0, 0, networkRequest)
-                .sendToTarget();
-        return networkRequest;
-    }
-
-    private void releaseNetworkRequest(NetworkRequest networkRequest) {
-        mTelephonyNetworkFactoryUT.obtainMessage(CMD_CANCEL_REQUEST, 0, 0, networkRequest)
-                .sendToTarget();
-    }
-
-    private void activatePhoneInPhoneSwitcher(int phoneId, boolean active) {
-        doReturn(active).when(mPhoneSwitcher).shouldApplyNetworkRequest(any(), eq(phoneId));
-        mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(
-                TelephonyNetworkFactory.EVENT_ACTIVE_PHONE_SWITCH);
-    }
-
-    private void activatePhoneInPhoneSwitcher(int phoneId, NetworkRequest nr, boolean active) {
-        TelephonyNetworkRequest networkRequest =
-                new TelephonyNetworkRequest(nr, mPhone, mFeatureFlags);
-        doReturn(active).when(mPhoneSwitcher).shouldApplyNetworkRequest(
-                eq(networkRequest), eq(phoneId));
-        mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(
-                TelephonyNetworkFactory.EVENT_ACTIVE_PHONE_SWITCH);
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        super.setUp(getClass().getSimpleName());
-        mPhoneSwitcher = mock(PhoneSwitcher.class);
-        mMockRadioConfig = mock(RadioConfig.class);
-        mMockedIsub = mock(ISub.class);
-        replaceInstance(RadioConfig.class, "sRadioConfig", null, mMockRadioConfig);
-
-        doReturn(mMockedIsub).when(mIBinder).queryLocalInterface(anyString());
-        doReturn(mPhone).when(mPhone).getImsPhone();
-        mServiceManagerMockedServices.put("isub", mIBinder);
-
-        mContextFixture.putStringArrayResource(com.android.internal.R.array.networkAttributes,
-                new String[]{"wifi,1,1,1,-1,true", "mobile,0,0,0,-1,true",
-                        "mobile_mms,2,0,2,60000,true", "mobile_supl,3,0,2,60000,true",
-                        "mobile_dun,4,0,2,60000,true", "mobile_hipri,5,0,3,60000,true",
-                        "mobile_fota,10,0,2,60000,true", "mobile_ims,11,0,2,60000,true",
-                        "mobile_cbs,12,0,2,60000,true", "wifi_p2p,13,1,0,-1,true",
-                        "mobile_ia,14,0,2,-1,true", "mobile_emergency,15,0,2,-1,true"});
-
-        doAnswer(invocation -> {
-            final TelephonyNetworkRequest req =
-                    (TelephonyNetworkRequest) invocation.getArguments()[0];
-            //final Message msg = (Message) invocation.getArguments()[2];
-            mNetworkRequestList.add(req);
-            mAllNetworkRequestSet.add(req);
-            //mNetworkRequestMessageMap.put(req, msg);
-            return null;
-        }).when(mDataNetworkController).addNetworkRequest(any());
-
-        doAnswer(invocation -> {
-            mNetworkRequestList.remove((TelephonyNetworkRequest) invocation.getArguments()[0]);
-            return null;
-        }).when(mDataNetworkController).removeNetworkRequest(any());
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        mAllNetworkRequestSet.clear();
-        mNetworkRequestList.clear();
-        mNetworkRequestMessageMap.clear();
-        mTelephonyNetworkFactoryUT = null;
-        super.tearDown();
-    }
-
-    private void createMockedTelephonyComponents() throws Exception {
-        replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mPhoneSwitcher);
-
-        mTelephonyNetworkFactoryUT = new TelephonyNetworkFactory(Looper.myLooper(), mPhone,
-                mFeatureFlags);
-        final ArgumentCaptor<NetworkProvider> providerCaptor =
-                ArgumentCaptor.forClass(NetworkProvider.class);
-        verify(mConnectivityManager).registerNetworkProvider(providerCaptor.capture());
-        // For NetworkFactory to function as expected, the provider ID must be set to some
-        // number > 0.
-        providerCaptor.getValue().setProviderId(1);
-        verify(mPhoneSwitcher).registerForActivePhoneSwitch(any(), anyInt(), any());
-
-        // Simulate the behavior of the system server. When offerNetwork is called, it will
-        // update the factory about all requests that pass the registered filter, by calling
-        // NetworkProvider#onNetworkNeeded or onNetworkUnneeded.
-        // Note that this simulation is a little bit incomplete, as the system server will
-        // *update* only for those requests for which the status has changed, but this
-        // simulation will send REQUEST_NETWORK or CANCEL_REQUEST for all registered requests.
-        // At this time it makes no difference in this test.
-        // Also, this test reads from mAllNetworkRequestSet, which is not really the list of
-        // requests sent to the system server as the test doesn't instrument that. Instead, it's
-        // the list of requests ever sent to the factory. This also makes no difference in this
-        // test at this time.
-        doAnswer(invocation -> {
-            final NetworkCapabilities capabilitiesFilter =
-                    mTelephonyNetworkFactoryUT.makeNetworkFilter(mMockedIsub.getSubId(0));
-            for (final TelephonyNetworkRequest request : mAllNetworkRequestSet) {
-                final int message = request.canBeSatisfiedBy(capabilitiesFilter)
-                        ? CMD_REQUEST_NETWORK : CMD_CANCEL_REQUEST;
-                mTelephonyNetworkFactoryUT.obtainMessage(message, 0, 0,
-                        request.getNativeNetworkRequest()).sendToTarget();
-            }
-            return null;
-        }).when(mConnectivityManager).offerNetwork(anyInt(), any(), any(), any());
-    }
-
-    /**
-     * Test that phone active changes
-     */
-    @FlakyTest
-    @Test
-    @SmallTest
-    public void testActive() throws Exception {
-        mTestName = "testActive";
-        final int phoneId = 0;
-        final int subId = 0;
-
-        createMockedTelephonyComponents();
-
-        doReturn(false).when(mPhoneSwitcher).shouldApplyNetworkRequest(any(), anyInt());
-        doReturn(subId).when(mMockedIsub).getSubId(phoneId);
-        // fake onSubscriptionChangedListener being triggered.
-        mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(
-                TelephonyNetworkFactory.EVENT_SUBSCRIPTION_CHANGED);
-
-        log("addDefaultRequest");
-        makeDefaultInternetRequest();
-        processAllMessages();
-        assertEquals(0, mNetworkRequestList.size());
-
-        log("setPhoneActive true: phoneId = " + phoneId);
-
-        activatePhoneInPhoneSwitcher(phoneId, true);
-        processAllMessages();
-        assertEquals(1, mNetworkRequestList.size());
-
-        log("makeSubSpecificInternetRequest: subId = " + subId);
-        NetworkRequest subSpecificDefault = makeSubSpecificInternetRequest(subId);
-        processAllMessages();
-        assertEquals(2, mNetworkRequestList.size());
-
-        log("setPhoneActive false: phoneId = " + phoneId);
-        activatePhoneInPhoneSwitcher(phoneId, false);
-        processAllMessages();
-        assertEquals(0, mNetworkRequestList.size());
-
-        log("makeSubSpecificInternetRequest: subId = " + subId);
-        NetworkRequest subSpecificMms = makeSubSpecificMmsRequest(subId);
-        processAllMessages();
-        assertEquals(0, mNetworkRequestList.size());
-
-        log("setPhoneActive true: phoneId = " + phoneId);
-        activatePhoneInPhoneSwitcher(phoneId, true);
-        processAllMessages();
-        assertEquals(3, mNetworkRequestList.size());
-
-        log("releaseNetworkRequest: subSpecificDefault = " + subSpecificDefault);
-        releaseNetworkRequest(subSpecificDefault);
-        processAllMessages();
-        assertEquals(2, mNetworkRequestList.size());
-
-        log("setPhoneActive false: phoneId = " + phoneId);
-        activatePhoneInPhoneSwitcher(phoneId, false);
-        processAllMessages();
-        assertEquals(0, mNetworkRequestList.size());
-
-        log("releaseNetworkRequest: subSpecificMms = " + subSpecificMms);
-        releaseNetworkRequest(subSpecificMms);
-        processAllMessages();
-        assertEquals(0, mNetworkRequestList.size());
-
-        log("setPhoneActive true: phoneId = " + phoneId);
-        activatePhoneInPhoneSwitcher(phoneId, true);
-        processAllMessages();
-        assertEquals(1, mNetworkRequestList.size());
-    }
-
-    /**
-     * Test that network request changes
-     */
-    @Test
-    @SmallTest
-    public void testRequests() throws Exception {
-        mTestName = "testActive";
-        final int numberOfPhones = 2;
-        final int phoneId = 0;
-        final int altPhoneId = 1;
-        final int subId = 0;
-        final int altSubId = 1;
-        final int unusedSubId = 2;
-
-        createMockedTelephonyComponents();
-
-        doReturn(subId).when(mMockedIsub).getSubId(phoneId);
-        mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(
-                TelephonyNetworkFactory.EVENT_SUBSCRIPTION_CHANGED);
-        processAllMessages();
-        assertEquals(0, mNetworkRequestList.size());
-
-        activatePhoneInPhoneSwitcher(phoneId, true);
-        processAllMessages();
-        assertEquals(0, mNetworkRequestList.size());
-
-        makeDefaultInternetRequest();
-        processAllMessages();
-        assertEquals(1, mNetworkRequestList.size());
-
-        doReturn(altSubId).when(mMockedIsub).getSubId(altPhoneId);
-        processAllMessages();
-        assertEquals(1, mNetworkRequestList.size());
-
-        activatePhoneInPhoneSwitcher(phoneId, false);
-        mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(
-                TelephonyNetworkFactory.EVENT_ACTIVE_PHONE_SWITCH);
-        processAllMessages();
-        assertEquals(0, mNetworkRequestList.size());
-
-        NetworkRequest subSpecificMmsRequest = makeSubSpecificMmsRequest(subId);
-        activatePhoneInPhoneSwitcher(phoneId, subSpecificMmsRequest, true);
-        processAllMessages();
-        assertEquals(1, mNetworkRequestList.size());
-
-        doReturn(unusedSubId).when(mMockedIsub).getSubId(phoneId);
-        mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(
-                TelephonyNetworkFactory.EVENT_SUBSCRIPTION_CHANGED);
-        processAllMessages();
-        assertEquals(0, mNetworkRequestList.size());
-
-        makeSubSpecificInternetRequest(subId);
-        processAllMessages();
-        assertEquals(0, mNetworkRequestList.size());
-
-        doReturn(subId).when(mMockedIsub).getSubId(phoneId);
-        mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(
-                TelephonyNetworkFactory.EVENT_SUBSCRIPTION_CHANGED);
-        processAllMessages();
-
-        activatePhoneInPhoneSwitcher(phoneId, true);
-        processAllMessages();
-        assertEquals(3, mNetworkRequestList.size());
-    }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkProviderTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkProviderTest.java
index d62ee2f..1ab55b6 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkProviderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkProviderTest.java
@@ -391,4 +391,25 @@
         verifyRequestReleasedOnPhone(1, request);
         verifyRequestSentOnPhone(0, request);
     }
+
+    @Test
+    public void testMakeNetworkFilter() {
+        doReturn(Set.of(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH,
+                NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY,
+                NetworkCapabilities.NET_CAPABILITY_VSIM, NetworkCapabilities.NET_CAPABILITY_MMS,
+                NetworkCapabilities.NET_CAPABILITY_XCAP)).when(mDataConfigManager)
+                .getUnsupportedNetworkCapabilities();
+
+        NetworkCapabilities caps = mTelephonyNetworkProvider.makeNetworkFilter();
+        assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)).isTrue();
+        assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)).isTrue();
+        assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_IA)).isTrue();
+        assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH))
+                .isFalse();
+        assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY))
+                .isFalse();
+        assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_VSIM)).isFalse();
+        assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)).isFalse();
+        assertThat(caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_XCAP)).isFalse();
+    }
 }
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 27c87e2..cbe50d7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkRequestTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkRequestTest.java
@@ -19,7 +19,6 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.when;
 
 import android.net.ConnectivityManager;
 import android.net.NetworkCapabilities;
@@ -35,6 +34,9 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import java.util.List;
+import java.util.Set;
+
 public class TelephonyNetworkRequestTest extends TelephonyTest {
 
     private static final ApnSetting INTERNET_APN_SETTING = new ApnSetting.Builder()
@@ -402,7 +404,6 @@
 
     @Test
     public void testSatelliteNetworkRequest() {
-        when(mFeatureFlags.satelliteInternet()).thenReturn(true);
         TelephonyNetworkRequest satelliteRequest = new TelephonyNetworkRequest(
                 new NetworkRequest.Builder()
                         .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
@@ -446,7 +447,6 @@
 
     @Test
     public void testCellularNetworkRequest() {
-        doReturn(true).when(mFeatureFlags).satelliteInternet();
         TelephonyNetworkRequest cellularRequest = new TelephonyNetworkRequest(
                 new NetworkRequest.Builder()
                         .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
@@ -487,4 +487,25 @@
         assertThat(cellularRequest.canBeSatisfiedBy(cellularInternetDataProfile)).isTrue();
         assertThat(generalRequest.canBeSatisfiedBy(cellularInternetDataProfile)).isTrue();
     }
+
+    @Test
+    public void testGetAllSupportedNetworkCapabilities() {
+        doReturn(Set.of(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH,
+                NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY,
+                NetworkCapabilities.NET_CAPABILITY_VSIM, NetworkCapabilities.NET_CAPABILITY_MMS,
+                NetworkCapabilities.NET_CAPABILITY_XCAP)).when(mDataConfigManager)
+                .getUnsupportedNetworkCapabilities();
+
+        List<Integer> caps = TelephonyNetworkRequest.getAllSupportedNetworkCapabilities();
+        assertThat(caps).contains(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        assertThat(caps).contains(NetworkCapabilities.NET_CAPABILITY_FOTA);
+        assertThat(caps).contains(NetworkCapabilities.NET_CAPABILITY_SUPL);
+        assertThat(caps).contains(NetworkCapabilities.NET_CAPABILITY_CBS);
+        assertThat(caps).contains(NetworkCapabilities.NET_CAPABILITY_RCS);
+        assertThat(caps).doesNotContain(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH);
+        assertThat(caps).doesNotContain(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY);
+        assertThat(caps).doesNotContain(NetworkCapabilities.NET_CAPABILITY_VSIM);
+        assertThat(caps).doesNotContain(NetworkCapabilities.NET_CAPABILITY_MMS);
+        assertThat(caps).doesNotContain(NetworkCapabilities.NET_CAPABILITY_XCAP);
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyNumberTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyNumberTrackerTest.java
index 10dbfea..37042ee 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyNumberTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyNumberTrackerTest.java
@@ -26,15 +26,11 @@
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
-import android.content.ContextWrapper;
 import android.content.IntentFilter;
-import android.content.res.AssetManager;
-import android.content.res.Resources;
 import android.os.AsyncResult;
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
@@ -129,31 +125,19 @@
 
     private File mLocalDownloadDirectory;
     private ShortNumberInfo mShortNumberInfo;
-    private Context mMockContext;
-    private Resources mResources;
 
     @Before
     public void setUp() throws Exception {
-        logd("EmergencyNumberTrackerTest +Setup!");
         super.setUp(getClass().getSimpleName());
         mShortNumberInfo = mock(ShortNumberInfo.class);
-        mCarrierConfigManagerMock = mock(CarrierConfigManager.class);
+        mCarrierConfigManagerMock = (CarrierConfigManager) mContext.getSystemService(
+                Context.CARRIER_CONFIG_SERVICE);
 
-        mContext = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
-        mMockContext = mock(Context.class);
-        mResources = mock(Resources.class);
+        doReturn(InstrumentationRegistry.getTargetContext().getAssets()).when(mContext).getAssets();
 
-        doReturn(mContext).when(mPhone).getContext();
-        doReturn(0).when(mPhone).getPhoneId();
         doReturn(SUB_ID_PHONE_1).when(mPhone).getSubId();
-
-        doReturn(mContext).when(mPhone2).getContext();
-        doReturn(1).when(mPhone2).getPhoneId();
         doReturn(SUB_ID_PHONE_2).when(mPhone2).getSubId();
 
-        doReturn(mPackageManager).when(mContext).getPackageManager();
-        doReturn(mPackageManager).when(mMockContext).getPackageManager();
-
         initializeEmergencyNumberListTestSamples();
         mEmergencyNumberTrackerMock = new EmergencyNumberTracker(mPhone, mSimulatedCommands,
                 mFeatureFlags);
@@ -165,11 +149,7 @@
         // Copy an OTA file to the test directory to similate the OTA mechanism
         simulateOtaEmergencyNumberDb(mPhone);
 
-        AssetManager am = new AssetManager.Builder().build();
-        doReturn(am).when(mMockContext).getAssets();
-
         processAllMessages();
-        logd("EmergencyNumberTrackerTest -Setup!");
     }
 
     @After
@@ -251,20 +231,16 @@
     }
 
     private void setOtaEmergencyNumberDbFileFolderForTesting(
-            EmergencyNumberTracker emergencyNumberTrackerMock, Phone phone) {
+            EmergencyNumberTracker emergencyNumberTrackerMock, Phone phone)
+            throws FileNotFoundException {
         // Override the OTA emergency number database file path for testing
         File file = new File(Environment.getExternalStorageDirectory(), LOCAL_DOWNLOAD_DIRECTORY
                 + "/" + EMERGENCY_NUMBER_DB_OTA_FILE);
-        try {
-            mOtaParcelFileDescriptor = ParcelFileDescriptor.open(
-                    file, ParcelFileDescriptor.MODE_READ_ONLY);
-            emergencyNumberTrackerMock.obtainMessage(
-                EmergencyNumberTracker.EVENT_OVERRIDE_OTA_EMERGENCY_NUMBER_DB_FILE_PATH,
-                    mOtaParcelFileDescriptor).sendToTarget();
-            logd("Changed emergency number db file folder for testing ");
-        } catch (FileNotFoundException e) {
-            logd("Failed to open emergency number db file folder for testing " + e.toString());
-        }
+        mOtaParcelFileDescriptor = ParcelFileDescriptor.open(
+                file, ParcelFileDescriptor.MODE_READ_ONLY);
+        emergencyNumberTrackerMock.obtainMessage(
+            EmergencyNumberTracker.EVENT_OVERRIDE_OTA_EMERGENCY_NUMBER_DB_FILE_PATH,
+                mOtaParcelFileDescriptor).sendToTarget();
         processAllMessages();
     }
 
@@ -544,11 +520,8 @@
      */
     @Test
     public void testUsingEmergencyNumberDatabaseWheneverHal_1_4() {
-        doReturn(mMockContext).when(mPhone).getContext();
-        doReturn(mContext.getAssets()).when(mMockContext).getAssets();
-        doReturn(mResources).when(mMockContext).getResources();
-        doReturn(true).when(mResources).getBoolean(
-                com.android.internal.R.bool.ignore_emergency_number_routing_from_db);
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.ignore_emergency_number_routing_from_db, true);
 
         EmergencyNumberTracker emergencyNumberTrackerMock = new EmergencyNumberTracker(
                 mPhone, mSimulatedCommands, mFeatureFlags);
@@ -616,12 +589,9 @@
 
     @Test
     public void testUsingEmergencyNumberDatabaseWithRouting() {
-        doReturn(mMockContext).when(mPhone).getContext();
-        doReturn(mContext.getAssets()).when(mMockContext).getAssets();
-        doReturn(mResources).when(mMockContext).getResources();
         doReturn("05").when(mCellIdentity).getMncString();
-        doReturn(false).when(mResources).getBoolean(
-                com.android.internal.R.bool.ignore_emergency_number_routing_from_db);
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.ignore_emergency_number_routing_from_db, false);
 
         EmergencyNumberTracker emergencyNumberTrackerMock = new EmergencyNumberTracker(
                 mPhone, mSimulatedCommands, mFeatureFlags);
@@ -721,11 +691,8 @@
 
     @Test
     public void testUsingEmergencyNumberDatabaseWithRoutingInOOS() {
-        doReturn(mMockContext).when(mPhone).getContext();
-        doReturn(mContext.getAssets()).when(mMockContext).getAssets();
-        doReturn(mResources).when(mMockContext).getResources();
-        doReturn(false).when(mResources).getBoolean(
-                com.android.internal.R.bool.ignore_emergency_number_routing_from_db);
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.ignore_emergency_number_routing_from_db, false);
 
         EmergencyNumberTracker emergencyNumberTrackerMock = new EmergencyNumberTracker(
                 mPhone, mSimulatedCommands, mFeatureFlags);
@@ -776,7 +743,7 @@
      * Test OTA Emergency Number Database Update Status.
      */
     @Test
-    public void testOtaEmergencyNumberDatabase() {
+    public void testOtaEmergencyNumberDatabase() throws Exception {
         sendEmergencyNumberPrefix(mEmergencyNumberTrackerMock);
         mEmergencyNumberTrackerMock.updateEmergencyCountryIsoAllPhones("");
         processAllMessages();
@@ -841,13 +808,7 @@
     @Test
     public void testOverridingEmergencyNumberPrefixCarrierConfig() throws Exception {
         // Capture CarrierConfigChangeListener to emulate the carrier config change notification
-        doReturn(mMockContext).when(mPhone).getContext();
-        doReturn(Context.CARRIER_CONFIG_SERVICE)
-                .when(mMockContext)
-                .getSystemService(CarrierConfigManager.class);
-        doReturn(mCarrierConfigManagerMock)
-                .when(mMockContext)
-                .getSystemService(eq(Context.CARRIER_CONFIG_SERVICE));
+        Mockito.clearInvocations(mCarrierConfigManagerMock);
         ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
                 ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
         EmergencyNumberTracker localEmergencyNumberTracker =
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 9253fbf..d50e781 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
@@ -21,6 +21,7 @@
 import static android.telephony.NetworkRegistrationInfo.DOMAIN_CS_PS;
 import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
 import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_HOME;
+import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING;
 import static android.telephony.TelephonyManager.EMERGENCY_CALLBACK_MODE_CALL;
 import static android.telephony.TelephonyManager.EMERGENCY_CALLBACK_MODE_SMS;
 
@@ -38,7 +39,6 @@
 import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.anyLong;
-import static org.mockito.Mockito.anyVararg;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
@@ -75,13 +75,16 @@
 
 import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.GsmCdmaPhone;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyTest;
 import com.android.internal.telephony.data.PhoneSwitcher;
+import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
 
 import org.junit.After;
 import org.junit.Before;
@@ -89,6 +92,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
@@ -108,6 +112,12 @@
     private static final int TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS = 3000;
     private static final EmergencyRegistrationResult E_REG_RESULT = new EmergencyRegistrationResult(
             EUTRAN, REGISTRATION_STATE_HOME, DOMAIN_CS_PS, true, true, 0, 1, "001", "01", "US");
+    private static final EmergencyRegistrationResult UNKNOWN_E_REG_RESULT =
+            new EmergencyRegistrationResult(
+                    AccessNetworkConstants.AccessNetworkType.UNKNOWN,
+                    REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING,
+                    NetworkRegistrationInfo.DOMAIN_UNKNOWN,
+                    false, false, 0, 0, "", "", "");
 
     @Mock EmergencyStateTracker.PhoneFactoryProxy mPhoneFactoryProxy;
     @Mock EmergencyStateTracker.PhoneSwitcherProxy mPhoneSwitcherProxy;
@@ -125,6 +135,8 @@
         doReturn(TelephonyManager.SIM_STATE_READY)
                 .when(mTelephonyManagerProxy).getSimState(anyInt());
         doReturn(true).when(mFeatureFlags).emergencyCallbackModeNotification();
+        doReturn(true).when(mFeatureFlags).disableEcbmBasedOnRat();
+        doReturn(true).when(mFeatureFlags).performCrossStackRedialCheckForEmergencyCall();
     }
 
     @After
@@ -139,8 +151,10 @@
             EmergencyStateTracker.getInstance();
         });
 
-        EmergencyStateTracker
-                .make(mContext, true, TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS, mFeatureFlags);
+        EmergencyStateTracker.make(mContext, true, TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS,
+                true, /* turnOffOemEnabledSatelliteDuringEmergencyCall */
+                true, /* turnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall */
+                mFeatureFlags);
 
         assertNotNull(EmergencyStateTracker.getInstance());
     }
@@ -148,8 +162,10 @@
     @Test
     @SmallTest
     public void getInstance_returnsSameInstance() {
-        EmergencyStateTracker
-                .make(mContext, true, TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS, mFeatureFlags);
+        EmergencyStateTracker.make(mContext, true, TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS,
+                true, /* turnOffOemEnabledSatelliteDuringEmergencyCall */
+                true, /* turnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall */
+                mFeatureFlags);
         EmergencyStateTracker instance1 = EmergencyStateTracker.getInstance();
         EmergencyStateTracker instance2 = EmergencyStateTracker.getInstance();
 
@@ -635,67 +651,6 @@
     }
 
     /**
-     * Test that onEmergencyCallDomainUpdated updates the domain correctly so ECBM CS domain is
-     * detected.
-     */
-    @Test
-    @SmallTest
-    public void onEmergencyCallDomainUpdated_CsDomain() {
-        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
-                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
-        // Create test Phones
-        Phone testPhone = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
-                /* isRadioOn= */ true);
-        // Call startEmergencyCall() to set testPhone
-        CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone,
-                mTestConnection1, false);
-
-        // Set call to ACTIVE
-        emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
-        // set domain
-        emergencyStateTracker.onEmergencyCallDomainUpdated(PhoneConstants.PHONE_TYPE_CDMA,
-                mTestConnection1);
-        // End call to enter ECM
-        emergencyStateTracker.endCall(mTestConnection1);
-
-        // Make sure IMS ECBM is true
-        assertTrue(emergencyStateTracker.isInEcm());
-        assertTrue(emergencyStateTracker.isInCdmaEcm());
-        assertFalse(emergencyStateTracker.isInImsEcm());
-    }
-
-    /**
-     * Ensure that if for some reason we enter ECBM for CS domain and the Phone type is GSM,
-     * isInCdmaEcm returns false.
-     */
-    @Test
-    @SmallTest
-    public void onEmergencyCallDomainUpdated_CsDomain_Gsm() {
-        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
-                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
-        // Create test Phones
-        Phone testPhone = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
-                /* isRadioOn= */ true);
-        // For some reason the Phone is reporting GSM instead of CDMA.
-        doReturn(PhoneConstants.PHONE_TYPE_GSM).when(testPhone).getPhoneType();
-        // Call startEmergencyCall() to set testPhone
-        CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone,
-                mTestConnection1, false);
-
-        // Set call to ACTIVE
-        emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
-        // set domain
-        emergencyStateTracker.onEmergencyCallDomainUpdated(PhoneConstants.PHONE_TYPE_CDMA,
-                mTestConnection1);
-        // End call to enter ECM
-        emergencyStateTracker.endCall(mTestConnection1);
-
-        assertTrue(emergencyStateTracker.isInEcm());
-        assertFalse(emergencyStateTracker.isInCdmaEcm());
-        assertFalse(emergencyStateTracker.isInImsEcm());
-    }
-
-    /**
      * Test that onEmergencyTransportChanged sets the new emergency mode.
      */
     @Test
@@ -755,6 +710,8 @@
                 mTestConnection1, false);
         // Set call to ACTIVE
         emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
         // Set ecm as supported
         setEcmSupportedConfig(testPhone, true);
 
@@ -819,6 +776,8 @@
                 mTestConnection1, false);
         // Set call to ACTIVE
         emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
         // Set ecm as supported
         setEcmSupportedConfig(testPhone, /* ecmSupported= */ true);
 
@@ -857,6 +816,8 @@
                 mTestConnection1, false);
         // Set call to ACTIVE
         emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
         // Set ecm as supported
         setEcmSupportedConfig(testPhone, /* ecmSupported= */ true);
 
@@ -931,6 +892,37 @@
         verify(testPhone).exitEmergencyMode(any(Message.class));
     }
 
+    /**
+     * Test that after endCall() is called, EmergencyStateTracker will not enter ECM if the call was
+     * ACTIVE in UMTS or GSM network.
+     */
+    @Test
+    @SmallTest
+    public void endCall_callActiveInUmts_noEcm() {
+        // Setup EmergencyStateTracker
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+        // Create test Phone
+        Phone testPhone = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+                /* isRadioOn= */ true);
+        // Start emergency call then enter ECM
+        CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone,
+                mTestConnection1, false);
+        // Set call to ACTIVE
+        emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        // Make sure that the call was made in UMTS network.
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_GSM, mTestConnection1);
+        // Set ecm as supported
+        setEcmSupportedConfig(testPhone, true);
+
+        assertFalse(emergencyStateTracker.isInEcm());
+
+        emergencyStateTracker.endCall(mTestConnection1);
+
+        assertFalse(emergencyStateTracker.isInEcm());
+    }
+
     @Test
     @SmallTest
     public void testOnEmergencyTransportChangedUsingDifferentThread() {
@@ -1016,6 +1008,8 @@
         verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
 
         emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
         emergencyStateTracker.endCall(mTestConnection1);
         processAllMessages();
 
@@ -1085,6 +1079,8 @@
                 Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
 
         emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
         emergencyStateTracker.endCall(mTestConnection1);
         processAllMessages();
 
@@ -1093,6 +1089,8 @@
 
         // Second emergency call started.
         future = emergencyStateTracker.startEmergencyCall(phone0, mTestConnection2, false);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection2);
 
         assertTrue(emergencyStateTracker.isInEmergencyMode());
         assertFalse(future.isDone());
@@ -1115,6 +1113,89 @@
 
     @Test
     @SmallTest
+    public void testEndUmtsCallInEcm() {
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+        Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+                /* isRadioOn= */ true);
+        setUpAsyncResultForSetEmergencyMode(phone0, E_REG_RESULT);
+        setEcmSupportedConfig(phone0, true);
+
+        // First active call.
+        CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(phone0,
+                mTestConnection1, false);
+        processAllMessages();
+
+        assertTrue(emergencyStateTracker.isInEmergencyMode());
+        assertTrue(emergencyStateTracker.isInEmergencyCall());
+        verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+        assertEquals(future.getNow(DisconnectCause.ERROR_UNSPECIFIED),
+                Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
+
+        emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
+
+        // Ends call and enter ECBM.
+        emergencyStateTracker.endCall(mTestConnection1);
+        processAllMessages();
+
+        assertTrue(emergencyStateTracker.isInEcm());
+        assertFalse(emergencyStateTracker.isInEmergencyCall());
+
+
+        // Second emergency call start and not active.
+        future = emergencyStateTracker.startEmergencyCall(phone0, mTestConnection2, false);
+
+        // Make sure that the 2nd call was tried in UMTS network.
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_GSM, mTestConnection2);
+
+        assertTrue(emergencyStateTracker.isInEmergencyMode());
+        assertFalse(future.isDone());
+
+        emergencyStateTracker.endCall(mTestConnection2);
+        processAllMessages();
+
+        // At this time, it shouldn't recover ECM since UE is in UMTS network.
+        assertFalse(emergencyStateTracker.isInEmergencyMode());
+        // Enter ECBM once at the 1st call ends.
+        verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
+        verify(phone0).startEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_CALL), anyLong());
+        // Exit ECBM at the 2nd call starts and ends.
+        verify(phone0, times(2))
+                .stopEmergencyCallbackMode(eq(EMERGENCY_CALLBACK_MODE_CALL), anyInt());
+        verify(phone0).exitEmergencyMode(any(Message.class));
+    }
+
+    @Test
+    @SmallTest
+    public void testEndCallAfterExitEmergencyCallbackModeIsCalledInNonEcbm() throws Exception {
+        // Setup EmergencyStateTracker
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+        // Create test Phone
+        GsmCdmaPhone testPhone = (GsmCdmaPhone) setupTestPhoneForEmergencyCall(
+                /* isRoaming= */ true, /* isRadioOn= */ true);
+        setUpAsyncResultForSetEmergencyMode(testPhone, E_REG_RESULT);
+        setUpAsyncResultForExitEmergencyMode(testPhone);
+        // Start emergency call then enter ECM
+        CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone,
+                mTestConnection1, false);
+        processAllMessages();
+
+        // Exit emergency mode explicitly
+        emergencyStateTracker.exitEmergencyCallbackMode();
+
+        emergencyStateTracker.endCall(mTestConnection1);
+        processAllMessages();
+
+        // Verify exitEmergencyMode() is called.
+        verify(testPhone).exitEmergencyMode(any(Message.class));
+    }
+
+    @Test
+    @SmallTest
     public void testRecoverNormalInCellularWhenVoWiFiConnected() {
         EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
                 /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
@@ -1426,6 +1507,8 @@
         assertTrue(emergencyStateTracker.isInEmergencyCall());
 
         emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
         emergencyStateTracker.endCall(mTestConnection1);
 
         assertTrue(emergencyStateTracker.isInEcm());
@@ -1639,6 +1722,8 @@
                 Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
 
         emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
         emergencyStateTracker.endCall(mTestConnection1);
 
         assertTrue(emergencyStateTracker.isInEcm());
@@ -1733,6 +1818,8 @@
         verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
 
         emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
 
         // Emergency SMS is being started.
         CompletableFuture<Integer> future = emergencyStateTracker.startEmergencySms(phone0,
@@ -2128,6 +2215,8 @@
         verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
 
         emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
 
         // Emergency SMS is being started.
         CompletableFuture<Integer> future = emergencyStateTracker.startEmergencySms(phone0,
@@ -2169,6 +2258,8 @@
         verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
 
         emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
 
         // Emergency SMS is being started.
         CompletableFuture<Integer> future = emergencyStateTracker.startEmergencySms(phone0,
@@ -2222,6 +2313,8 @@
         verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
 
         emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
 
         // Emergency SMS is being started.
         CompletableFuture<Integer> future = emergencyStateTracker.startEmergencySms(phone0,
@@ -2282,6 +2375,8 @@
         verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
 
         emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
 
         // Emergency SMS is being started.
         CompletableFuture<Integer> future = emergencyStateTracker.startEmergencySms(phone0,
@@ -2331,6 +2426,8 @@
         verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
 
         emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
 
         // Emergency SMS is being started.
         CompletableFuture<Integer> future = emergencyStateTracker.startEmergencySms(phone0,
@@ -2393,6 +2490,8 @@
         verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
 
         emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, mTestConnection1);
+        emergencyStateTracker.onEmergencyCallDomainUpdated(
+                PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
 
         // Emergency SMS is being started.
         CompletableFuture<Integer> future = emergencyStateTracker.startEmergencySms(phone0,
@@ -2445,12 +2544,13 @@
         when(phone.getSubId()).thenReturn(1);
         setEcmSupportedConfig(phone, true);
         PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(phone.getSubId());
-        doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyVararg());
+        doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt(), any());
 
         EmergencyStateTracker testEst = setupEmergencyStateTracker(
                 false /* isSuplDdsSwitchRequiredForEmergencyCall */);
 
         assertNotNull(testEst.startEmergencyCall(phone, mTestConnection1, false));
+        testEst.onEmergencyCallDomainUpdated(PhoneConstants.PHONE_TYPE_IMS, mTestConnection1);
 
         ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
                 ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
@@ -2464,7 +2564,7 @@
                 listenerArgumentCaptor.getAllValues().get(0);
 
         // Verify carrier config for valid subscription
-        assertTrue(testEst.isEmergencyCallbackModeSupported(phone));
+        assertTrue(testEst.isEmergencyCallbackModeSupported(phone, true));
 
         // onCarrierConfigurationChanged is not called yet.
         // SIM removed
@@ -2472,7 +2572,7 @@
         setEcmSupportedConfig(phone, false);
 
         // Verify default config for invalid subscription
-        assertFalse(testEst.isEmergencyCallbackModeSupported(phone));
+        assertFalse(testEst.isEmergencyCallbackModeSupported(phone, true));
 
         // Insert SIM again
         when(phone.getSubId()).thenReturn(1);
@@ -2493,7 +2593,7 @@
                 TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID);
 
         // Verify saved config for valid subscription
-        assertTrue(testEst.isEmergencyCallbackModeSupported(phone));
+        assertTrue(testEst.isEmergencyCallbackModeSupported(phone, true));
 
         // Insert SIM in PIN locked again, but emergency callback mode not supported
         doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
@@ -2507,7 +2607,7 @@
                 TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID);
 
         // Verify carrier config for valid subscription in PIN locked state, saved configuration
-        assertTrue(testEst.isEmergencyCallbackModeSupported(phone));
+        assertTrue(testEst.isEmergencyCallbackModeSupported(phone, true));
 
         // SIM removed again
         when(phone.getSubId()).thenReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
@@ -2519,7 +2619,7 @@
                 TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID);
 
         // Verify saved config for valid subscription
-        assertTrue(testEst.isEmergencyCallbackModeSupported(phone));
+        assertTrue(testEst.isEmergencyCallbackModeSupported(phone, true));
 
         // Insert SIM, PIN verified, again, but emergency callback mode not supported
         doReturn(TelephonyManager.SIM_STATE_READY)
@@ -2533,7 +2633,7 @@
                 TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID);
 
         // Verify carrier config for valid subscription
-        assertFalse(testEst.isEmergencyCallbackModeSupported(phone));
+        assertFalse(testEst.isEmergencyCallbackModeSupported(phone, true));
 
         // SIM removed again
         when(phone.getSubId()).thenReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
@@ -2545,7 +2645,7 @@
                 TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID);
 
         // Verify saved config for valid subscription
-        assertFalse(testEst.isEmergencyCallbackModeSupported(phone));
+        assertFalse(testEst.isEmergencyCallbackModeSupported(phone, true));
     }
 
     /**
@@ -2969,7 +3069,7 @@
         PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(testPhone.getSubId());
         bundle.putBoolean(CarrierConfigManager.KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL,
                 true);
-        doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyVararg());
+        doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt(), any());
         // onCarrierConfigChanged with valid subscription
         carrierConfigChangeListener.onCarrierConfigChanged(
                 testPhone.getPhoneId(), testPhone.getSubId(),
@@ -3206,6 +3306,91 @@
                 anyBoolean(), eq(0));
     }
 
+    @Test
+    @SmallTest
+    public void testShouldExitSatelliteModeWhenSatelliteModeNotEnabled() {
+        // Satellite mode is not enabled.
+        doReturn(false).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(true);
+
+        assertFalse(emergencyStateTracker.shouldExitSatelliteMode());
+    }
+
+    @Test
+    @SmallTest
+    public void testShouldExitSatelliteModeWhenConfigTurnOffNonEmergencyNbIotNtnSessionDisabled() {
+        doReturn(true).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
+        // Config for turning off non-emergency NB-IOT NTN session for emergency call: false
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(true, true, false);
+
+        assertFalse(emergencyStateTracker.shouldExitSatelliteMode());
+    }
+
+    @Test
+    @SmallTest
+    public void testShouldExitSatelliteModeWhenSatelliteDemoModeEnabled() {
+        doReturn(true).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
+        // Satellite demo mode is enabled
+        doReturn(true).when(mSatelliteController).isDemoModeEnabled();
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(true, true, true);
+
+        assertTrue(emergencyStateTracker.shouldExitSatelliteMode());
+    }
+
+    @Test
+    @SmallTest
+    public void testShouldExitSatelliteModeWhenCarrierRoamingNbIotNtnEnabledAndNtnNonEmergency() {
+        // carrierRoamingNbIotNtn feature enabled
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        doReturn(true).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
+        doReturn(false).when(mSatelliteController).isDemoModeEnabled();
+        // NTN non-emergency session is in progress
+        doReturn(false).when(mSatelliteController).getRequestIsEmergency();
+
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(true, true, true);
+
+        assertTrue(emergencyStateTracker.shouldExitSatelliteMode());
+    }
+
+    @Test
+    @SmallTest
+    public void testShouldExitSatelliteModeWhenNtnEmergency() {
+        // carrierRoamingNbIotNtn feature enabled
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        doReturn(true).when(mSatelliteController).isSatelliteEnabledOrBeingEnabled();
+        doReturn(false).when(mSatelliteController).isDemoModeEnabled();
+        doReturn(true).when(mSatelliteController).getRequestIsEmergency();
+        doReturn(null).when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
+
+        boolean turnOffOemEnabledSatelliteDuringEmergencyCall = true;
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+                true, turnOffOemEnabledSatelliteDuringEmergencyCall, true);
+
+        // No valid subscription
+        assertFalse(emergencyStateTracker.shouldExitSatelliteMode());
+
+        SubscriptionInfoInternal subInfo = Mockito.mock(SubscriptionInfoInternal.class);
+        doReturn(1).when(subInfo).getOnlyNonTerrestrialNetwork();
+        doReturn(subInfo).when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
+
+        // Only non-terrestrial networks
+        assertEquals(turnOffOemEnabledSatelliteDuringEmergencyCall,
+                emergencyStateTracker.shouldExitSatelliteMode());
+
+        doReturn(0).when(subInfo).getOnlyNonTerrestrialNetwork();
+
+        // Not only non-terrestrial networks
+        emergencyStateTracker.shouldExitSatelliteMode();
+
+        verify(mSatelliteController).shouldTurnOffCarrierSatelliteForEmergencyCall();
+
+        // carrierRoamingNbIotNtn feature disabled
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
+
+        assertEquals(turnOffOemEnabledSatelliteDuringEmergencyCall,
+                emergencyStateTracker.shouldExitSatelliteMode());
+    }
+
     /**
      * Test Phone selection.
      * SIM absent and SIM ready on the other Phone.
@@ -3407,13 +3592,90 @@
         verify(phone1, never()).setEmergencyMode(anyInt(), any(Message.class));
     }
 
+    @Test
+    @SmallTest
+    public void testSwitchPhoneWhenNonEmergencyNtnSessionInProgress() {
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+        Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+                /* isRadioOn= */ true);
+        setUpAsyncResultForSetEmergencyMode(
+                phone0, UNKNOWN_E_REG_RESULT, RILConstants.INTERNAL_ERR);
+        // Start an emergency call over Phone0
+        CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(phone0,
+                mTestConnection1, false);
+
+        Phone phone1 = getPhone(1);
+        // Phone0: Disable NTN
+        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+                .when(phone0).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_ABSENT)
+                .when(mTelephonyManagerProxy).getSimState(eq(0));
+        // Phone1: Enable TN
+        doReturn(2).when(phone1).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_READY)
+                .when(mTelephonyManagerProxy).getSimState(eq(1));
+
+        processAllMessages();
+
+        verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+        assertFalse(emergencyStateTracker.isInEmergencyMode());
+        assertTrue(future.isDone());
+        // Expect: DisconnectCause#EMERGENCY_PERM_FAILURE
+        assertEquals(future.getNow(DisconnectCause.NOT_DISCONNECTED),
+                Integer.valueOf(DisconnectCause.EMERGENCY_PERM_FAILURE));
+    }
+
+    @Test
+    @SmallTest
+    public void testSwitchPhoneWhenNonEmergencyNtnSessionInProgressAndFlagDisabled() {
+        doReturn(false).when(mFeatureFlags).performCrossStackRedialCheckForEmergencyCall();
+        EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+                /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+        Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+                /* isRadioOn= */ true);
+        setUpAsyncResultForSetEmergencyMode(
+                phone0, UNKNOWN_E_REG_RESULT, RILConstants.INTERNAL_ERR);
+        // Start an emergency call over Phone0
+        CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(phone0,
+                mTestConnection1, false);
+
+        Phone phone1 = getPhone(1);
+        // Phone0: Disable NTN
+        doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+                .when(phone0).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_ABSENT)
+                .when(mTelephonyManagerProxy).getSimState(eq(0));
+        // Phone1: Enable TN
+        doReturn(2).when(phone1).getSubId();
+        doReturn(TelephonyManager.SIM_STATE_READY)
+                .when(mTelephonyManagerProxy).getSimState(eq(1));
+
+        processAllMessages();
+
+        verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+        assertTrue(future.isDone());
+        // Expect: DisconnectCause#NOT_DISCONNECTED
+        assertEquals(future.getNow(DisconnectCause.NOT_DISCONNECTED),
+                Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
+    }
+
     private EmergencyStateTracker setupEmergencyStateTracker(
             boolean isSuplDdsSwitchRequiredForEmergencyCall) {
+        return setupEmergencyStateTracker(isSuplDdsSwitchRequiredForEmergencyCall, true, true);
+    }
+
+    private EmergencyStateTracker setupEmergencyStateTracker(
+            boolean isSuplDdsSwitchRequiredForEmergencyCall,
+            boolean turnOffOemEnabledSatelliteDuringEmergencyCall,
+            boolean turnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall) {
         doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher();
         doNothing().when(mPhoneSwitcher).overrideDefaultDataForEmergency(
                 anyInt(), anyInt(), any());
         return new EmergencyStateTracker(mContext, mTestableLooper.getLooper(),
                 isSuplDdsSwitchRequiredForEmergencyCall, TEST_WAIT_FOR_IN_SERVICE_TIMEOUT_MS,
+                turnOffOemEnabledSatelliteDuringEmergencyCall,
+                turnOffNonEmergencyNbIotNtnSatelliteForEmergencyCall,
                 mPhoneFactoryProxy, mPhoneSwitcherProxy, mTelephonyManagerProxy, mRadioOnHelper,
                 TEST_ECM_EXIT_TIMEOUT_MS, mFeatureFlags);
     }
@@ -3487,6 +3749,17 @@
         }).when(phone).setEmergencyMode(anyInt(), any(Message.class));
     }
 
+    private void setUpAsyncResultForSetEmergencyMode(Phone phone,
+            EmergencyRegistrationResult regResult, int rilError) {
+        doAnswer((invocation) -> {
+            Object[] args = invocation.getArguments();
+            final Message msg = (Message) args[1];
+            AsyncResult.forMessage(msg, regResult, CommandException.fromRilErrno(rilError));
+            msg.sendToTarget();
+            return null;
+        }).when(phone).setEmergencyMode(anyInt(), any(Message.class));
+    }
+
     private void setUpAsyncResultForExitEmergencyMode(Phone phone) {
         doAnswer((invocation) -> {
             Object[] args = invocation.getArguments();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccConnectorTest.java b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccConnectorTest.java
index 3ec3ab5..a95d0d7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccConnectorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccConnectorTest.java
@@ -21,8 +21,8 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doThrow;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
index 569785b..4ff13de 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
@@ -1656,7 +1656,6 @@
                 vendorApiLevel);
 
         // Feature flag enabled, device has required telephony feature.
-        doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
         doReturn(true).when(mPackageManager).hasSystemFeature(
                 eq(PackageManager.FEATURE_TELEPHONY_EUICC));
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java
index 6e0d383..84dc4ba 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccSessionTest.java
@@ -107,7 +107,8 @@
 
     @Before
     public void setUp() throws Exception {
-        mEuiccSession = new EuiccSession();
+        super.setUp(getClass().getSimpleName());
+        mEuiccSession = new EuiccSession(mContext);
     }
 
     @Test
@@ -128,7 +129,25 @@
 
     @Test
     @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
+    public void startOneSession_featureOverlayDisabled_noop() throws Exception {
+        mEuiccSession.startSession(SESSION_ID_1);
+        mEuiccSession.noteChannelOpen(mApduSender);
+        mEuiccSession.noteChannelOpen(mApduSender2);
+
+        assertThat(mEuiccSession.hasSession()).isFalse();
+
+        mEuiccSession.endSession(SESSION_ID_1);
+
+        assertThat(mEuiccSession.hasSession()).isFalse();
+        verify(mApduSender, never()).closeAnyOpenChannel();
+        verify(mApduSender2, never()).closeAnyOpenChannel();
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
     public void startOneSession_endSession_hasSession() throws Exception {
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.euicc_optimize_apdu_sender, true);
         mEuiccSession.startSession(SESSION_ID_1);
         mEuiccSession.noteChannelOpen(mApduSender);
         mEuiccSession.noteChannelOpen(mApduSender2);
@@ -150,6 +169,8 @@
     @Test
     @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
     public void startTwoSession_endSession_hasSession() throws Exception {
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.euicc_optimize_apdu_sender, true);
         mEuiccSession.startSession(SESSION_ID_1);
         mEuiccSession.noteChannelOpen(mApduSender);
         mEuiccSession.startSession(SESSION_ID_2);
@@ -170,6 +191,8 @@
     @Test
     @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
     public void startTwoSessions_endAllSessions_hasSession() throws Exception {
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.euicc_optimize_apdu_sender, true);
         mEuiccSession.startSession(SESSION_ID_1);
         mEuiccSession.noteChannelOpen(mApduSender);
         mEuiccSession.startSession(SESSION_ID_2);
@@ -188,6 +211,8 @@
     @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
     public void noteChannelOpen_noSession_endSession_noop() throws Exception {
         // noteChannelOpen called without a session started
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.euicc_optimize_apdu_sender, true);
         mEuiccSession.noteChannelOpen(mApduSender);
 
         assertThat(mEuiccSession.hasSession()).isFalse();
@@ -202,6 +227,8 @@
     @EnableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER)
     public void endAllSessions_noSession_endAllSessions_noOp() throws Exception {
         // noteChannelOpen called without a session started
+        mContextFixture.putBooleanResource(
+                com.android.internal.R.bool.euicc_optimize_apdu_sender, true);
         mEuiccSession.noteChannelOpen(mApduSender);
 
         assertThat(mEuiccSession.hasSession()).isFalse();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
index e542a41..5affa6e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmInboundSmsHandlerTest.java
@@ -22,12 +22,12 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.nullable;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
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 a31be59..e99a054 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java
@@ -25,9 +25,10 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
+import static org.junit.Assume.assumeFalse;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -36,17 +37,16 @@
 import static org.mockito.Mockito.when;
 
 import android.app.Activity;
-import android.app.ActivityManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.location.Country;
 import android.location.CountryDetector;
-import android.net.Uri;
 import android.os.Binder;
 import android.os.HandlerThread;
 import android.os.Message;
@@ -56,12 +56,13 @@
 import android.service.carrier.CarrierMessagingService;
 import android.service.carrier.ICarrierMessagingCallback;
 import android.service.carrier.ICarrierMessagingService;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.ServiceState;
 import android.telephony.SmsManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
-import android.util.Singleton;
 
+import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.FlakyTest;
 import androidx.test.filters.MediumTest;
 import androidx.test.filters.SmallTest;
@@ -75,6 +76,7 @@
 import com.android.internal.telephony.TelephonyTestUtils;
 import com.android.internal.telephony.TestApplication;
 import com.android.internal.telephony.flags.Flags;
+import com.android.internal.telephony.satellite.SatelliteController;
 import com.android.internal.telephony.uicc.IccUtils;
 import com.android.internal.telephony.uicc.IsimUiccRecords;
 
@@ -103,6 +105,7 @@
     private SMSDispatcher.SmsTracker mSmsTracker;
     private ISub.Stub mISubStub;
     private ICarrierMessagingService.Stub mICarrierAppMessagingService;
+    private SatelliteController mMockSatelliteController;
 
     private Object mLock = new Object();
     private boolean mReceivedTestIntent;
@@ -139,12 +142,20 @@
     @Before
     public void setUp() throws Exception {
         super.setUp(getClass().getSimpleName());
+
+        // unmock ActivityManager to be able to register receiver, create real PendingIntent and
+        // receive TEST_INTENT
+        unmockActivityManager();
+
         mSmsDispatchersController = mock(SmsDispatchersController.class);
         mGsmInboundSmsHandler = mock(GsmInboundSmsHandler.class);
         mCountryDetector = mock(CountryDetector.class);
         mSmsTracker = mock(SMSDispatcher.SmsTracker.class);
         mISubStub = mock(ISub.Stub.class);
         mICarrierAppMessagingService = mock(ICarrierMessagingService.Stub.class);
+        mMockSatelliteController = mock(SatelliteController.class);
+        replaceInstance(SatelliteController.class, "sInstance", null,
+                mMockSatelliteController);
 
         // Note that this replaces only cached services in ServiceManager. If a service is not found
         // in the cache, a real instance is used.
@@ -233,10 +244,6 @@
     }
 
     private void registerTestIntentReceiver() throws Exception {
-        // unmock ActivityManager to be able to register receiver, create real PendingIntent and
-        // receive TEST_INTENT
-        restoreInstance(Singleton.class, "mInstance", mIActivityManagerSingleton);
-        restoreInstance(ActivityManager.class, "IActivityManagerSingleton", null);
         Context realContext = TestApplication.getAppContext();
         realContext.registerReceiver(mTestReceiver, new IntentFilter(TEST_INTENT),
                 Context.RECEIVER_EXPORTED);
@@ -536,9 +543,15 @@
         }
     }
 
+    private void skipOnAutomotive() {
+        assumeFalse(InstrumentationRegistry.getTargetContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_AUTOMOTIVE));
+    }
+
     @Test
     @SmallTest
     public void testSendMultipartSmsByCarrierAppNoResponse() throws Exception {
+        skipOnAutomotive(); // TODO(b/401440427): don't skip
         mockCarrierApp();
         // do not mock result, instead reduce the timeout for test
         mGsmSmsDispatcher.mCarrierMessagingTimeout = 100;
@@ -696,4 +709,27 @@
 
         assertFalse(isMtSmsPollingMessage);
     }
+
+    @Test
+    public void testShouldBlockPremiumSmsInSatelliteMode() {
+        doReturn(true).when(mMockSatelliteController).isSatelliteBeingEnabled();
+        assertTrue(mGsmSmsDispatcher.shouldBlockPremiumSmsInSatelliteMode());
+
+        int subId = mPhone.getSubId();
+        doReturn(subId).when(mMockSatelliteController).getSelectedSatelliteSubId();
+        doReturn(false).when(mMockSatelliteController).isSatelliteBeingEnabled();
+        doReturn(true).when(mMockSatelliteController).isSatelliteEnabled();
+        doReturn(new int[]{NetworkRegistrationInfo.SERVICE_TYPE_DATA}).when(
+                mMockSatelliteController).getSupportedServicesOnCarrierRoamingNtn(anyInt());
+        assertTrue(mGsmSmsDispatcher.shouldBlockPremiumSmsInSatelliteMode());
+
+        doReturn(true).when(mMockSatelliteController).isSatelliteEnabled();
+        doReturn(new int[]{NetworkRegistrationInfo.SERVICE_TYPE_DATA,
+                NetworkRegistrationInfo.SERVICE_TYPE_SMS}).when(
+                mMockSatelliteController).getSupportedServicesOnCarrierRoamingNtn(anyInt());
+        assertFalse(mGsmSmsDispatcher.shouldBlockPremiumSmsInSatelliteMode());
+
+        doReturn(false).when(mMockSatelliteController).isSatelliteEnabled();
+        assertFalse(mGsmSmsDispatcher.shouldBlockPremiumSmsInSatelliteMode());
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsEnablementTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsEnablementTrackerTest.java
index 270960c..62e9e87 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsEnablementTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsEnablementTrackerTest.java
@@ -23,11 +23,11 @@
 import static junit.framework.Assert.assertTrue;
 
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 
 import android.os.Handler;
 import android.os.Looper;
@@ -224,7 +224,7 @@
         mTracker.disableIms(SLOT_1, SUB_1);
         waitForHandler(mHandler);
 
-        verifyZeroInteractions(mMockServiceControllerBinder);
+        verifyNoMoreInteractions(mMockServiceControllerBinder);
         assertTrue(mTracker.isState(SLOT_1, mTracker.STATE_IMS_DISABLED));
     }
 
@@ -299,7 +299,7 @@
         mTracker.enableIms(SLOT_1, SUB_1);
         waitForHandler(mHandler);
 
-        verifyZeroInteractions(mMockServiceControllerBinder);
+        verifyNoMoreInteractions(mMockServiceControllerBinder);
         assertTrue(mTracker.isState(SLOT_1, mTracker.STATE_IMS_ENABLED));
     }
 
@@ -417,7 +417,7 @@
         mTracker.enableIms(SLOT_1, SUB_1);
         waitForHandler(mHandler);
 
-        verifyZeroInteractions(mMockServiceControllerBinder);
+        verifyNoMoreInteractions(mMockServiceControllerBinder);
         assertTrue(mTracker.isState(SLOT_1, mTracker.STATE_IMS_RESETTING));
     }
 
@@ -435,7 +435,7 @@
         mTracker.disableIms(SLOT_1, SUB_1);
         waitForHandler(mHandler);
 
-        verifyZeroInteractions(mMockServiceControllerBinder);
+        verifyNoMoreInteractions(mMockServiceControllerBinder);
         assertTrue(mTracker.isState(SLOT_1, mTracker.STATE_IMS_RESETTING));
     }
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
index 130fba8..bfc3e4a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
@@ -23,9 +23,9 @@
 import static junit.framework.TestCase.assertFalse;
 
 import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
index 5f16d9b..529acf3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
@@ -22,9 +22,9 @@
 
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsTestBase.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsTestBase.java
index c6b0fa1..43d8345 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsTestBase.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsTestBase.java
@@ -23,6 +23,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
+import android.os.SystemClock;
 import android.testing.TestableLooper;
 
 import androidx.test.InstrumentationRegistry;
@@ -31,7 +32,6 @@
 
 import org.mockito.MockitoAnnotations;
 
-import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
@@ -41,22 +41,6 @@
  * Helper class to load Mockito Resources into a test.
  */
 public class ImsTestBase {
-    private static final Field MESSAGE_QUEUE_FIELD;
-    private static final Field MESSAGE_WHEN_FIELD;
-    private static final Field MESSAGE_NEXT_FIELD;
-
-    static {
-        try {
-            MESSAGE_QUEUE_FIELD = MessageQueue.class.getDeclaredField("mMessages");
-            MESSAGE_QUEUE_FIELD.setAccessible(true);
-            MESSAGE_WHEN_FIELD = Message.class.getDeclaredField("when");
-            MESSAGE_WHEN_FIELD.setAccessible(true);
-            MESSAGE_NEXT_FIELD = Message.class.getDeclaredField("next");
-            MESSAGE_NEXT_FIELD.setAccessible(true);
-        } catch (NoSuchFieldException e) {
-            throw new RuntimeException("Failed to initialize TelephonyTest", e);
-        }
-    }
 
     protected Context mContext;
     protected List<TestableLooper> mTestableLoopers = new ArrayList<>();
@@ -131,36 +115,12 @@
     }
 
     /**
-     * @return The longest delay from all the message queues.
-     */
-    private long getLongestDelay() {
-        long delay = 0;
-        for (TestableLooper looper : mTestableLoopers) {
-            MessageQueue queue = looper.getLooper().getQueue();
-            try {
-                Message msg = (Message) MESSAGE_QUEUE_FIELD.get(queue);
-                while (msg != null) {
-                    delay = Math.max(msg.getWhen(), delay);
-                    msg = (Message) MESSAGE_NEXT_FIELD.get(msg);
-                }
-            } catch (IllegalAccessException e) {
-                throw new RuntimeException("Access failed in TelephonyTest", e);
-            }
-        }
-        return delay;
-    }
-
-    /**
      * @return {@code true} if there are any messages in the queue.
      */
     private boolean messagesExist() {
         for (TestableLooper looper : mTestableLoopers) {
-            MessageQueue queue = looper.getLooper().getQueue();
-            try {
-                Message msg = (Message) MESSAGE_QUEUE_FIELD.get(queue);
-                if (msg != null) return true;
-            } catch (IllegalAccessException e) {
-                throw new RuntimeException("Access failed in TelephonyTest", e);
+            if (looper.peekWhen() > 0) {
+                return true;
             }
         }
         return false;
@@ -170,8 +130,14 @@
      * Handle all messages including the delayed messages.
      */
     public void processAllFutureMessages() {
+        final long now = SystemClock.uptimeMillis();
         while (messagesExist()) {
-            moveTimeForward(getLongestDelay());
+            for (TestableLooper looper : mTestableLoopers) {
+                long nextDelay = looper.peekWhen() - now;
+                if (nextDelay > 0) {
+                    looper.moveTimeForward(nextDelay);
+                }
+            }
             processAllMessages();
         }
     }
@@ -196,20 +162,7 @@
      */
     public void moveTimeForward(long milliSeconds) {
         for (TestableLooper looper : mTestableLoopers) {
-            MessageQueue queue = looper.getLooper().getQueue();
-            try {
-                Message msg = (Message) MESSAGE_QUEUE_FIELD.get(queue);
-                while (msg != null) {
-                    long updatedWhen = msg.getWhen() - milliSeconds;
-                    if (updatedWhen < 0) {
-                        updatedWhen = 0;
-                    }
-                    MESSAGE_WHEN_FIELD.set(msg, updatedWhen);
-                    msg = (Message) MESSAGE_NEXT_FIELD.get(msg);
-                }
-            } catch (IllegalAccessException e) {
-                throw new RuntimeException("Access failed in TelephonyTest", e);
-            }
+            looper.moveTimeForward(milliSeconds);
         }
     }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallInfoTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallInfoTrackerTest.java
index e3fc6d3..60fe088 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallInfoTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsCallInfoTrackerTest.java
@@ -16,6 +16,7 @@
 package com.android.internal.telephony.imsphone;
 
 import static android.telephony.AccessNetworkConstants.AccessNetworkType.EUTRAN;
+import static android.telephony.AccessNetworkConstants.AccessNetworkType.IWLAN;
 
 import static junit.framework.Assert.assertNotNull;
 
@@ -25,6 +26,7 @@
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
@@ -66,9 +68,12 @@
     public void testDialingNormalCall() throws Exception {
         ArgumentCaptor<List<ImsCallInfo>> captor = ArgumentCaptor.forClass(List.class);
 
-        ImsPhoneConnection c = getConnection(Call.State.DIALING, false);
+        ImsPhoneConnection c = getConnection(Call.State.IDLE, false);
         mImsCallInfoTracker.addImsCallStatus(c);
 
+        doReturn(Call.State.DIALING).when(c).getState();
+        mImsCallInfoTracker.updateImsCallStatus(c);
+
         verify(mImsPhone, times(1)).updateImsCallStatus(captor.capture(), any());
 
         List<ImsCallInfo> imsCallInfos = captor.getValue();
@@ -91,9 +96,12 @@
     public void testDialingEmergencyCall() throws Exception {
         ArgumentCaptor<List<ImsCallInfo>> captor = ArgumentCaptor.forClass(List.class);
 
-        ImsPhoneConnection c = getConnection(Call.State.DIALING, true);
+        ImsPhoneConnection c = getConnection(Call.State.IDLE, true);
         mImsCallInfoTracker.addImsCallStatus(c);
 
+        doReturn(Call.State.DIALING).when(c).getState();
+        mImsCallInfoTracker.updateImsCallStatus(c);
+
         verify(mImsPhone, times(1)).updateImsCallStatus(captor.capture(), any());
 
         List<ImsCallInfo> imsCallInfos = captor.getValue();
@@ -367,9 +375,12 @@
     public void testSrvccCompleted() throws Exception {
         ArgumentCaptor<List<ImsCallInfo>> captor = ArgumentCaptor.forClass(List.class);
 
-        ImsPhoneConnection c = getConnection(Call.State.DIALING, false);
+        ImsPhoneConnection c = getConnection(Call.State.IDLE, false);
         mImsCallInfoTracker.addImsCallStatus(c);
 
+        doReturn(Call.State.DIALING).when(c).getState();
+        mImsCallInfoTracker.updateImsCallStatus(c);
+
         verify(mImsPhone, times(1)).updateImsCallStatus(captor.capture(), any());
 
         List<ImsCallInfo> imsCallInfos = captor.getValue();
@@ -388,12 +399,43 @@
     }
 
     @Test
+    public void testNetworkChanged() throws Exception {
+        ArgumentCaptor<List<ImsCallInfo>> captor = ArgumentCaptor.forClass(List.class);
+        ImsPhoneConnection c = getConnection(Call.State.IDLE, false);
+        mImsCallInfoTracker.addImsCallStatus(c);
+
+        doReturn(Call.State.DIALING).when(c).getState();
+        mImsCallInfoTracker.updateImsCallStatus(c);
+
+        verify(mImsPhone, times(1)).updateImsCallStatus(captor.capture(), any());
+
+        List<ImsCallInfo> imsCallInfos = captor.getValue();
+        assertNotNull(imsCallInfos);
+        assertEquals(1, imsCallInfos.size());
+
+        ImsCallInfo info = imsCallInfos.get(0);
+        assertNotNull(info);
+        assertEquals(1, info.getIndex());
+        assertEquals(EUTRAN, info.getCallRadioTech());
+
+        // The network type is changed from EUTRAN to IWLAN.
+        doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN).when(c).getCallRadioTech();
+        mImsCallInfoTracker.updateImsCallStatus(c);
+
+        verify(mImsPhone, times(2)).updateImsCallStatus(captor.capture(), any());
+        assertEquals(IWLAN, info.getCallRadioTech());
+    }
+
+    @Test
     public void testClearAllOrphanedConnections() throws Exception {
         ArgumentCaptor<List<ImsCallInfo>> captor = ArgumentCaptor.forClass(List.class);
 
-        ImsPhoneConnection c = getConnection(Call.State.DIALING, false);
+        ImsPhoneConnection c = getConnection(Call.State.IDLE, false);
         mImsCallInfoTracker.addImsCallStatus(c);
 
+        doReturn(Call.State.DIALING).when(c).getState();
+        mImsCallInfoTracker.updateImsCallStatus(c);
+
         verify(mImsPhone, times(1)).updateImsCallStatus(captor.capture(), any());
 
         List<ImsCallInfo> imsCallInfos = captor.getValue();
@@ -417,10 +459,32 @@
         assertEquals(Call.State.IDLE, info.getCallState());
     }
 
+    @Test
+    public void testAddImsCallStatus() throws Exception {
+        ArgumentCaptor<List<ImsCallInfo>> captor = ArgumentCaptor.forClass(List.class);
+
+        ImsPhoneConnection c = getConnection(Call.State.DIALING, false);
+        mImsCallInfoTracker.addImsCallStatus(c);
+        verify(mImsPhone, never()).updateImsCallStatus(any(), any());
+
+        c = getConnection(Call.State.INCOMING, false);
+        mImsCallInfoTracker.addImsCallStatus(c);
+        verify(mImsPhone, times(1)).updateImsCallStatus(captor.capture(), any());
+
+        List<ImsCallInfo> imsCallInfos = captor.getValue();
+        assertNotNull(imsCallInfos);
+        assertEquals(1, imsCallInfos.size());
+
+        ImsCallInfo info = imsCallInfos.get(0);
+        assertNotNull(info);
+        assertEquals(Call.State.INCOMING, info.getCallState());
+    }
+
     private ImsPhoneConnection getConnection(Call.State state, boolean isEmergency) {
         ImsPhoneConnection c = mock(ImsPhoneConnection.class);
         doReturn(isEmergency).when(c).isEmergencyCall();
         doReturn(state).when(c).getState();
+        doReturn(true).when(c).isAlive();
         doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_LTE).when(c).getCallRadioTech();
         switch (state) {
             case INCOMING:
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsNrSaModeHandlerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsNrSaModeHandlerTest.java
index 8cf422e..9ed8cd0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsNrSaModeHandlerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsNrSaModeHandlerTest.java
@@ -36,6 +36,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.os.Handler;
+import android.os.Message;
 import android.telephony.CarrierConfigManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -79,12 +80,29 @@
     private int mAnyInt = 0;
     private final Set<String> mFeatureTags = new ArraySet<String>();
 
+    private class N1ModeHandlerCaptor implements ImsNrSaModeHandler.N1ModeSetter {
+        private boolean mIsN1ModeEnabled = false;
+
+        public void setN1ModeEnabled(boolean enabled, Message message) {
+            mIsN1ModeEnabled = enabled;
+            mSimulatedCommands.setN1ModeEnabled(enabled, message);
+        }
+
+        public boolean isN1ModeEnabled() {
+            return mIsN1ModeEnabled;
+        };
+    };
+
+    private N1ModeHandlerCaptor mN1ModeCaptor;
+
     @Before
     public void setUp() throws Exception {
         super.setUp(getClass().getSimpleName());
         MockitoAnnotations.initMocks(this);
 
         mTestImsNrSaModeHandler = new ImsNrSaModeHandler(mImsPhone, mTestableLooper.getLooper());
+        mN1ModeCaptor = new N1ModeHandlerCaptor();
+        mTestImsNrSaModeHandler.setN1ModeSetter(mN1ModeCaptor);
 
         verify(mCarrierConfigManager).registerCarrierConfigChangeListener(
                 any(), mCarrierConfigChangeListenerCaptor.capture());
@@ -128,14 +146,13 @@
                 mPreciseCallStateHandlerCaptor.capture(), anyInt(), any());
         mPreciseCallStateHandler = mPreciseCallStateHandlerCaptor.getValue();
 
-        mSimulatedCommands.setN1ModeEnabled(false, null);
         mTestImsNrSaModeHandler.setNrSaDisabledForWfc(true);
 
         mTestImsNrSaModeHandler.tearDown();
 
         verify(mCarrierConfigManager).unregisterCarrierConfigChangeListener(any());
         verify(mImsPhone).unregisterForPreciseCallStateChanged(mPreciseCallStateHandler);
-        assertTrue(mSimulatedCommands.isN1ModeEnabled());
+        assertTrue(mN1ModeCaptor.isN1ModeEnabled());
     }
 
     @Test
@@ -166,19 +183,19 @@
 
         verify(mImsPhone).registerForPreciseCallStateChanged(any(), anyInt(), any());
 
-        mSimulatedCommands.setN1ModeEnabled(false, null);
+        mN1ModeCaptor.setN1ModeEnabled(false, null);
         mTestImsNrSaModeHandler.setNrSaDisabledForWfc(true);
         mTestImsNrSaModeHandler.setWifiRegStatus(true);
         mTestImsNrSaModeHandler.setImsCallStatus(true);
 
         mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_NONE, mFeatureTags);
 
-        assertTrue(mSimulatedCommands.isN1ModeEnabled());
+        assertTrue(mN1ModeCaptor.isN1ModeEnabled());
         assertFalse(mTestImsNrSaModeHandler.isWifiRegistered());
 
         mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
 
-        assertFalse(mSimulatedCommands.isN1ModeEnabled());
+        assertFalse(mN1ModeCaptor.isN1ModeEnabled());
         assertTrue(mTestImsNrSaModeHandler.isWifiRegistered());
     }
 
@@ -195,7 +212,7 @@
 
         verify(mImsPhone).registerForPreciseCallStateChanged(any(), anyInt(), any());
 
-        mSimulatedCommands.setN1ModeEnabled(true, null);
+        mN1ModeCaptor.setN1ModeEnabled(true, null);
         mTestImsNrSaModeHandler.setWifiRegStatus(false);
         mTestImsNrSaModeHandler.setImsCallStatus(true);
         mSimulatedCommands.setVonrEnabled(true);
@@ -203,10 +220,10 @@
         mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
         processAllMessages();
 
-        assertTrue(mSimulatedCommands.isN1ModeEnabled());
+        assertTrue(mN1ModeCaptor.isN1ModeEnabled());
         assertTrue(mTestImsNrSaModeHandler.isWifiRegistered());
 
-        mSimulatedCommands.setN1ModeEnabled(true, null);
+        mN1ModeCaptor.setN1ModeEnabled(true, null);
         mTestImsNrSaModeHandler.setWifiRegStatus(false);
         mTestImsNrSaModeHandler.setImsCallStatus(true);
         mSimulatedCommands.setVonrEnabled(false);
@@ -214,10 +231,10 @@
         mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
         processAllMessages();
 
-        assertFalse(mSimulatedCommands.isN1ModeEnabled());
+        assertFalse(mN1ModeCaptor.isN1ModeEnabled());
         assertTrue(mTestImsNrSaModeHandler.isWifiRegistered());
 
-        mSimulatedCommands.setN1ModeEnabled(true, null);
+        mN1ModeCaptor.setN1ModeEnabled(true, null);
         mTestImsNrSaModeHandler.setWifiRegStatus(false);
         mTestImsNrSaModeHandler.setImsCallStatus(true);
         mSimulatedCommands.setVonrEnabled(true);
@@ -225,7 +242,7 @@
         mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_NONE, mFeatureTags);
         processAllMessages();
 
-        assertTrue(mSimulatedCommands.isN1ModeEnabled());
+        assertTrue(mN1ModeCaptor.isN1ModeEnabled());
         assertFalse(mTestImsNrSaModeHandler.isWifiRegistered());
     }
 
@@ -241,20 +258,20 @@
 
         verify(mImsPhone).unregisterForPreciseCallStateChanged(mTestImsNrSaModeHandler);
 
-        mSimulatedCommands.setN1ModeEnabled(true, null);
+        mN1ModeCaptor.setN1ModeEnabled(true, null);
         mTestImsNrSaModeHandler.setWifiRegStatus(false);
 
         mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
 
-        assertFalse(mSimulatedCommands.isN1ModeEnabled());
+        assertFalse(mN1ModeCaptor.isN1ModeEnabled());
         assertTrue(mTestImsNrSaModeHandler.isWifiRegistered());
 
-        mSimulatedCommands.setN1ModeEnabled(false, null);
+        mN1ModeCaptor.setN1ModeEnabled(false, null);
         mTestImsNrSaModeHandler.setWifiRegStatus(true);
 
         mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_NONE, mFeatureTags);
 
-        assertTrue(mSimulatedCommands.isN1ModeEnabled());
+        assertTrue(mN1ModeCaptor.isN1ModeEnabled());
         assertFalse(mTestImsNrSaModeHandler.isWifiRegistered());
     }
 
@@ -270,12 +287,12 @@
 
         verify(mImsPhone, times(0)).unregisterForPreciseCallStateChanged(mTestImsNrSaModeHandler);
 
-        mSimulatedCommands.setN1ModeEnabled(true, null);
+        mN1ModeCaptor.setN1ModeEnabled(true, null);
         mTestImsNrSaModeHandler.setWifiRegStatus(false);
 
         mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
 
-        assertTrue(mSimulatedCommands.isN1ModeEnabled());
+        assertTrue(mN1ModeCaptor.isN1ModeEnabled());
         assertFalse(mTestImsNrSaModeHandler.isWifiRegistered());
     }
 
@@ -290,12 +307,12 @@
 
         verify(mImsPhone).unregisterForPreciseCallStateChanged(mTestImsNrSaModeHandler);
 
-        mSimulatedCommands.setN1ModeEnabled(true, null);
+        mN1ModeCaptor.setN1ModeEnabled(true, null);
         mTestImsNrSaModeHandler.setWifiRegStatus(false);
 
         mTestImsNrSaModeHandler.onImsRegistered(REGISTRATION_TECH_IWLAN, mFeatureTags);
 
-        assertTrue(mSimulatedCommands.isN1ModeEnabled());
+        assertTrue(mN1ModeCaptor.isN1ModeEnabled());
         assertTrue(mTestImsNrSaModeHandler.isWifiRegistered());
     }
 
@@ -374,13 +391,13 @@
         mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
         mTestImsNrSaModeHandler.updateImsCapability(CAPABILITY_TYPE_VOICE);
 
-        mSimulatedCommands.setN1ModeEnabled(false, null);
+        mN1ModeCaptor.setN1ModeEnabled(false, null);
         mTestImsNrSaModeHandler.setNrSaDisabledForWfc(true);
         mTestImsNrSaModeHandler.setWifiRegStatus(true);
 
         mTestImsNrSaModeHandler.onImsUnregistered(REGISTRATION_TECH_IWLAN);
 
-        assertTrue(mSimulatedCommands.isN1ModeEnabled());
+        assertTrue(mN1ModeCaptor.isN1ModeEnabled());
         assertFalse(mTestImsNrSaModeHandler.isWifiRegistered());
     }
 
@@ -399,19 +416,19 @@
         mPreciseCallStateHandler = mPreciseCallStateHandlerCaptor.getValue();
 
         mTestImsNrSaModeHandler.setWifiRegStatus(true);
-        mSimulatedCommands.setN1ModeEnabled(true, null);
+        mN1ModeCaptor.setN1ModeEnabled(true, null);
 
         mPreciseCallStateHandler.handleMessage(mPreciseCallStateHandler.obtainMessage(101));
 
         assertTrue(mTestImsNrSaModeHandler.isImsCallOngoing());
-        assertFalse(mSimulatedCommands.isN1ModeEnabled());
+        assertFalse(mN1ModeCaptor.isN1ModeEnabled());
 
         doReturn(mIdleState).when(mForegroundCall).getState();
         doReturn(mIdleState).when(mBackgroundCall).getState();
         mPreciseCallStateHandler.handleMessage(mPreciseCallStateHandler.obtainMessage(101));
 
         assertFalse(mTestImsNrSaModeHandler.isImsCallOngoing());
-        assertTrue(mSimulatedCommands.isN1ModeEnabled());
+        assertTrue(mN1ModeCaptor.isN1ModeEnabled());
     }
 
     @Test
@@ -430,19 +447,19 @@
         mPreciseCallStateHandler = mPreciseCallStateHandlerCaptor.getValue();
 
         mTestImsNrSaModeHandler.setWifiRegStatus(true);
-        mSimulatedCommands.setN1ModeEnabled(true, null);
+        mN1ModeCaptor.setN1ModeEnabled(true, null);
         mSimulatedCommands.setVonrEnabled(false);
 
         mPreciseCallStateHandler.handleMessage(mPreciseCallStateHandler.obtainMessage(101));
         processAllMessages();
 
-        assertFalse(mSimulatedCommands.isN1ModeEnabled());
+        assertFalse(mN1ModeCaptor.isN1ModeEnabled());
 
         doReturn(mIdleState).when(mForegroundCall).getState();
         doReturn(mIdleState).when(mBackgroundCall).getState();
         mPreciseCallStateHandler.handleMessage(mPreciseCallStateHandler.obtainMessage(101));
 
-        assertTrue(mSimulatedCommands.isN1ModeEnabled());
+        assertTrue(mN1ModeCaptor.isN1ModeEnabled());
 
         doReturn(mActiveState).when(mForegroundCall).getState();
         doReturn(mActiveState).when(mBackgroundCall).getState();
@@ -450,7 +467,7 @@
         mTestImsNrSaModeHandler.setImsCallStatus(false);
         processAllMessages();
 
-        assertTrue(mSimulatedCommands.isN1ModeEnabled());
+        assertTrue(mN1ModeCaptor.isN1ModeEnabled());
     }
 
     @Test
@@ -483,21 +500,21 @@
 
         mCarrierConfigChangeListener.onCarrierConfigChanged(mAnyInt, mAnyInt, mAnyInt, mAnyInt);
 
+        mN1ModeCaptor.setN1ModeEnabled(true, null);
         verify(mImsPhone).registerForPreciseCallStateChanged(
                 mPreciseCallStateHandlerCaptor.capture(), anyInt(), any());
         mPreciseCallStateHandler = mPreciseCallStateHandlerCaptor.getValue();
 
         mTestImsNrSaModeHandler.setWifiRegStatus(true);
-        mSimulatedCommands.setN1ModeEnabled(true, null);
         mPreciseCallStateHandler.handleMessage(mPreciseCallStateHandler.obtainMessage(101));
 
         assertTrue(mTestImsNrSaModeHandler.isImsCallOngoing());
-        assertTrue(mSimulatedCommands.isN1ModeEnabled());
+        assertTrue(mN1ModeCaptor.isN1ModeEnabled());
 
         mTestImsNrSaModeHandler.updateImsCapability(CAPABILITY_TYPE_VOICE);
-        assertFalse(mSimulatedCommands.isN1ModeEnabled());
+        assertFalse(mN1ModeCaptor.isN1ModeEnabled());
 
         mTestImsNrSaModeHandler.updateImsCapability(0);
-        assertTrue(mSimulatedCommands.isN1ModeEnabled());
+        assertTrue(mN1ModeCaptor.isN1ModeEnabled());
     }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
index a74a408..2fc44fb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
@@ -2554,10 +2554,14 @@
         // Dialing
         ImsPhoneConnection connection = placeCall();
 
+        ImsCall imsCall = connection.getImsCall();
+        imsCall.getImsCallSessionListenerProxy().callSessionInitiating(imsCall.getSession(),
+                new ImsCallProfile());
+
         verify(mImsPhone, times(1)).updateImsCallStatus(any(), any());
 
         // Alerting
-        ImsCall imsCall = connection.getImsCall();
+        imsCall = connection.getImsCall();
         imsCall.getImsCallSessionListenerProxy().callSessionProgressing(imsCall.getSession(),
                 new ImsStreamMediaProfile());
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
index 992f50a..26ef9b9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
@@ -43,11 +43,11 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyChar;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.nullable;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyChar;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
@@ -464,6 +464,30 @@
 
     @Test
     @SmallTest
+    public void testDialWithShortEmergencyNumber() throws Exception {
+        // Pre-condition
+        // Exist active call, try to set up 2-digit emergency number.
+        doReturn(Call.State.ACTIVE).when(mForegroundCall).getState();
+
+        String dialString = "17";
+        int videoState = 0;
+        ImsPhone.ImsDialArgs imsDialArgs = new ImsPhone.ImsDialArgs.Builder()
+                .setVideoState(videoState)
+                .setIsEmergency(true)
+                .build();
+
+        Connection connection = mImsPhoneUT.dial(dialString, imsDialArgs);
+        assertEquals(null, connection);
+        verify(mImsCT, never()).dial(eq(dialString), any(ImsPhone.ImsDialArgs.class));
+
+        doReturn(true).when(mFeatureFlags).skipMmiCodeCheckForEmergencyCall();
+
+        mImsPhoneUT.dial(dialString, imsDialArgs);
+        verify(mImsCT).dial(eq(dialString), any(ImsPhone.ImsDialArgs.class));
+    }
+
+    @Test
+    @SmallTest
     public void testDtmf() {
         // case 1
         doReturn(PhoneConstants.State.IDLE).when(mImsCT).getState();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelperTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelperTest.java
index 451c315..6cc2f4f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelperTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsRegistrationCallbackHelperTest.java
@@ -26,7 +26,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Matchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java
index 7374aef..c389ce4 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java
@@ -408,4 +408,50 @@
 
         assertFalse(stats.isProvisioningProfile);
     }
+
+    @Test
+    public void testIsNbIotNtn() {
+        when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
+        when(mSatelliteController.isInCarrierRoamingNbIotNtn(any())).thenReturn(true);
+
+        mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false);
+        mDataCallSessionStats.onSetupDataCallResponse(
+                mDefaultImsResponse,
+                TelephonyManager.NETWORK_TYPE_LTE,
+                ApnSetting.TYPE_IMS,
+                ApnSetting.PROTOCOL_IP,
+                DataFailCause.NONE);
+
+        mDataCallSessionStats.setTimeMillis(60000L);
+        mDataCallSessionStats.conclude();
+
+        ArgumentCaptor<DataCallSession> callCaptor =
+                ArgumentCaptor.forClass(DataCallSession.class);
+        verify(mPersistAtomsStorage).addDataCallSession(callCaptor.capture());
+        DataCallSession stats = callCaptor.getValue();
+
+        assertTrue(stats.isNbIotNtn);
+
+        reset(mPersistAtomsStorage);
+
+        when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(false);
+        when(mSatelliteController.isInCarrierRoamingNbIotNtn(any())).thenReturn(false);
+
+        mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false);
+        mDataCallSessionStats.onSetupDataCallResponse(
+                mDefaultImsResponse,
+                TelephonyManager.NETWORK_TYPE_LTE,
+                ApnSetting.TYPE_IMS,
+                ApnSetting.PROTOCOL_IP,
+                DataFailCause.NONE);
+
+        mDataCallSessionStats.setTimeMillis(60000L);
+        mDataCallSessionStats.conclude();
+
+
+        verify(mPersistAtomsStorage).addDataCallSession(callCaptor.capture());
+        stats = callCaptor.getValue();
+
+        assertFalse(stats.isNbIotNtn);
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
index 1c0febf..1e384c1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
@@ -1153,6 +1153,13 @@
         mSatelliteController1.countOfP2PSmsAvailableNotificationShown = 3;
         mSatelliteController1.countOfP2PSmsAvailableNotificationRemoved = 5;
         mSatelliteController1.isNtnOnlyCarrier = false;
+        mSatelliteController1.versionOfSatelliteAccessConfig = 10;
+        mSatelliteController1.countOfIncomingDatagramTypeSosSmsSuccess = 1;
+        mSatelliteController1.countOfIncomingDatagramTypeSosSmsFail = 2;
+        mSatelliteController1.countOfOutgoingDatagramTypeSmsSuccess = 3;
+        mSatelliteController1.countOfOutgoingDatagramTypeSmsFail = 4;
+        mSatelliteController1.countOfIncomingDatagramTypeSmsSuccess = 5;
+        mSatelliteController1.countOfIncomingDatagramTypeSmsFail = 6;
 
         mSatelliteController2 = new SatelliteController();
         mSatelliteController2.countOfSatelliteServiceEnablementsSuccess = 2 + 1;
@@ -1187,6 +1194,13 @@
         mSatelliteController2.countOfP2PSmsAvailableNotificationShown = 30;
         mSatelliteController2.countOfP2PSmsAvailableNotificationRemoved = 50;
         mSatelliteController2.isNtnOnlyCarrier = true;
+        mSatelliteController2.versionOfSatelliteAccessConfig = 12;
+        mSatelliteController2.countOfIncomingDatagramTypeSosSmsSuccess = 11;
+        mSatelliteController2.countOfIncomingDatagramTypeSosSmsFail = 12;
+        mSatelliteController2.countOfOutgoingDatagramTypeSmsSuccess = 31;
+        mSatelliteController2.countOfOutgoingDatagramTypeSmsFail = 14;
+        mSatelliteController2.countOfIncomingDatagramTypeSmsSuccess = 15;
+        mSatelliteController2.countOfIncomingDatagramTypeSmsFail = 16;
 
         // SatelliteController atom has one data point
         mSatelliteControllers =
@@ -1358,6 +1372,8 @@
         mCarrierRoamingSatelliteSession1.countOfOutgoingSms = 4;
         mCarrierRoamingSatelliteSession1.countOfIncomingMms = 1;
         mCarrierRoamingSatelliteSession1.countOfOutgoingMms = 1;
+        mCarrierRoamingSatelliteSession1.isMultiSim = false;
+        mCarrierRoamingSatelliteSession1.isNbIotNtn = false;
 
         mCarrierRoamingSatelliteSession2 = new CarrierRoamingSatelliteSession();
         mCarrierRoamingSatelliteSession2.carrierId = 2;
@@ -1376,6 +1392,8 @@
         mCarrierRoamingSatelliteSession2.countOfOutgoingSms = 4;
         mCarrierRoamingSatelliteSession2.countOfIncomingMms = 1;
         mCarrierRoamingSatelliteSession2.countOfOutgoingMms = 1;
+        mCarrierRoamingSatelliteSession2.isMultiSim = true;
+        mCarrierRoamingSatelliteSession2.isNbIotNtn = true;
 
         mCarrierRoamingSatelliteSessions = new CarrierRoamingSatelliteSession[] {
                 mCarrierRoamingSatelliteSession1, mCarrierRoamingSatelliteSession2};
@@ -1391,6 +1409,9 @@
         mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapMaxSec = 4;
         mCarrierRoamingSatelliteControllerStats1.carrierId = 1;
         mCarrierRoamingSatelliteControllerStats1.isDeviceEntitled = true;
+        mCarrierRoamingSatelliteControllerStats1.isMultiSim = false;
+        mCarrierRoamingSatelliteControllerStats1.countOfSatelliteSessions = 1;
+        mCarrierRoamingSatelliteControllerStats1.isNbIotNtn = false;
 
         mCarrierRoamingSatelliteControllerStats2 = new CarrierRoamingSatelliteControllerStats();
         mCarrierRoamingSatelliteControllerStats2.configDataSource =
@@ -1403,6 +1424,9 @@
         mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMaxSec = 15;
         mCarrierRoamingSatelliteControllerStats2.carrierId = 10;
         mCarrierRoamingSatelliteControllerStats2.isDeviceEntitled = false;
+        mCarrierRoamingSatelliteControllerStats2.isMultiSim = true;
+        mCarrierRoamingSatelliteControllerStats2.countOfSatelliteSessions = 2;
+        mCarrierRoamingSatelliteControllerStats2.isNbIotNtn = true;
 
         // CarrierRoamingSatelliteController has one data point
         mCarrierRoamingSatelliteControllerStats = new CarrierRoamingSatelliteControllerStats[] {
@@ -4452,6 +4476,20 @@
         expected.countOfP2PSmsAvailableNotificationRemoved =
                 mSatelliteController1.countOfP2PSmsAvailableNotificationRemoved * 2;
         expected.isNtnOnlyCarrier = mSatelliteController1.isNtnOnlyCarrier;
+        expected.versionOfSatelliteAccessConfig =
+                mSatelliteController1.versionOfSatelliteAccessConfig;
+        expected.countOfIncomingDatagramTypeSosSmsSuccess =
+                mSatelliteController1.countOfIncomingDatagramTypeSosSmsSuccess * 2;
+        expected.countOfIncomingDatagramTypeSosSmsFail =
+                mSatelliteController1.countOfIncomingDatagramTypeSosSmsFail * 2;
+        expected.countOfOutgoingDatagramTypeSmsSuccess =
+                mSatelliteController1.countOfOutgoingDatagramTypeSmsSuccess * 2;
+        expected.countOfOutgoingDatagramTypeSmsFail =
+                mSatelliteController1.countOfOutgoingDatagramTypeSmsFail * 2;
+        expected.countOfIncomingDatagramTypeSmsSuccess =
+                mSatelliteController1.countOfIncomingDatagramTypeSmsSuccess * 2;
+        expected.countOfIncomingDatagramTypeSmsFail =
+                mSatelliteController1.countOfIncomingDatagramTypeSmsFail * 2;
 
         // Service state and service switch should be added successfully
         verifyCurrentStateSavedToFileOnce();
@@ -4604,6 +4642,26 @@
                 satelliteController1.countOfP2PSmsAvailableNotificationRemoved
                         + satelliteController2.countOfP2PSmsAvailableNotificationRemoved;
         expected.isNtnOnlyCarrier = false;
+        expected.versionOfSatelliteAccessConfig =
+                mSatelliteController2.versionOfSatelliteAccessConfig;
+        expected.countOfIncomingDatagramTypeSosSmsSuccess =
+                mSatelliteController1.countOfIncomingDatagramTypeSosSmsSuccess
+                        + mSatelliteController2.countOfIncomingDatagramTypeSosSmsSuccess;
+        expected.countOfIncomingDatagramTypeSosSmsFail =
+                mSatelliteController1.countOfIncomingDatagramTypeSosSmsFail
+                        + mSatelliteController2.countOfIncomingDatagramTypeSosSmsFail;
+        expected.countOfOutgoingDatagramTypeSmsSuccess =
+                mSatelliteController1.countOfOutgoingDatagramTypeSmsSuccess
+                        + mSatelliteController2.countOfOutgoingDatagramTypeSmsSuccess;
+        expected.countOfOutgoingDatagramTypeSmsFail =
+                mSatelliteController1.countOfOutgoingDatagramTypeSmsFail
+                        + mSatelliteController2.countOfOutgoingDatagramTypeSmsFail;
+        expected.countOfIncomingDatagramTypeSmsSuccess =
+                mSatelliteController1.countOfIncomingDatagramTypeSmsSuccess
+                        + mSatelliteController2.countOfIncomingDatagramTypeSmsSuccess;
+        expected.countOfIncomingDatagramTypeSmsFail =
+                mSatelliteController1.countOfIncomingDatagramTypeSmsFail
+                        + mSatelliteController2.countOfIncomingDatagramTypeSmsFail;
 
         // Service state and service switch should be added successfully
         verifyCurrentStateSavedToFileOnce();
@@ -5153,6 +5211,9 @@
                 mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapMaxSec;
         expected.carrierId = mCarrierRoamingSatelliteControllerStats1.carrierId;
         expected.isDeviceEntitled = mCarrierRoamingSatelliteControllerStats1.isDeviceEntitled;
+        expected.isMultiSim = mCarrierRoamingSatelliteControllerStats1.isMultiSim;
+        expected.countOfSatelliteSessions =
+                mCarrierRoamingSatelliteControllerStats1.countOfSatelliteSessions * 2;
         verifyCurrentStateSavedToFileOnce();
         CarrierRoamingSatelliteControllerStats[] output =
                 mPersistAtomsStorage.getCarrierRoamingSatelliteControllerStats(0L);
@@ -6049,6 +6110,20 @@
                         stats.countOfP2PSmsAvailableNotificationShown);
                 assertEquals(expectedStats.countOfP2PSmsAvailableNotificationRemoved,
                         stats.countOfP2PSmsAvailableNotificationRemoved);
+                assertEquals(expectedStats.versionOfSatelliteAccessConfig,
+                        stats.versionOfSatelliteAccessConfig);
+                assertEquals(expectedStats.countOfIncomingDatagramTypeSosSmsSuccess,
+                        stats.countOfIncomingDatagramTypeSosSmsSuccess);
+                assertEquals(expectedStats.countOfIncomingDatagramTypeSosSmsFail,
+                        stats.countOfIncomingDatagramTypeSosSmsFail);
+                assertEquals(expectedStats.countOfOutgoingDatagramTypeSmsSuccess,
+                        stats.countOfOutgoingDatagramTypeSmsSuccess);
+                assertEquals(expectedStats.countOfOutgoingDatagramTypeSmsFail,
+                        stats.countOfOutgoingDatagramTypeSmsFail);
+                assertEquals(expectedStats.countOfIncomingDatagramTypeSmsSuccess,
+                        stats.countOfIncomingDatagramTypeSmsSuccess);
+                assertEquals(expectedStats.countOfIncomingDatagramTypeSmsFail,
+                        stats.countOfIncomingDatagramTypeSmsFail);
                 actualCount++;
             }
         }
@@ -6428,7 +6503,9 @@
                     && stats.countOfIncomingSms == expectedStats.countOfIncomingSms
                     && stats.countOfOutgoingSms == expectedStats.countOfOutgoingSms
                     && stats.countOfIncomingMms == expectedStats.countOfIncomingMms
-                    && stats.countOfOutgoingMms == expectedStats.countOfOutgoingMms) {
+                    && stats.countOfOutgoingMms == expectedStats.countOfOutgoingMms
+                    && stats.isMultiSim == expectedStats.isMultiSim
+                    && stats.isNbIotNtn == expectedStats.isNbIotNtn) {
                 actualCount++;
             }
         }
@@ -6455,6 +6532,10 @@
                 assertEquals(expectedStats.satelliteSessionGapMaxSec,
                         stats.satelliteSessionGapMaxSec);
                 assertEquals(expectedStats.isDeviceEntitled, stats.isDeviceEntitled);
+                assertEquals(expectedStats.isMultiSim, stats.isMultiSim);
+                assertEquals(expectedStats.countOfSatelliteSessions,
+                        stats.countOfSatelliteSessions);
+                assertEquals(expectedStats.isNbIotNtn, stats.isNbIotNtn);
                 count++;
             }
         }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java
index e981e88..4c24d40 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java
@@ -48,6 +48,7 @@
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 
+import java.util.Arrays;
 import java.util.concurrent.TimeUnit;
 
 public class SatelliteStatsTest extends TelephonyTest {
@@ -110,6 +111,13 @@
                         .setCountOfP2PSmsAvailableNotificationShown(3)
                         .setCountOfP2PSmsAvailableNotificationRemoved(3)
                         .setIsNtnOnlyCarrier(false)
+                        .setVersionOfSatelliteAccessControl(10)
+                        .setCountOfIncomingDatagramTypeSosSmsSuccess(1)
+                        .setCountOfIncomingDatagramTypeSmsFail(2)
+                        .setCountOfOutgoingDatagramTypeSmsSuccess(3)
+                        .setCountOfOutgoingDatagramTypeSmsFail(4)
+                        .setCountOfIncomingDatagramTypeSmsSuccess(5)
+                        .setCountOfIncomingDatagramTypeSmsFail(6)
                         .build();
 
         mSatelliteStats.onSatelliteControllerMetrics(param);
@@ -181,6 +189,20 @@
                 stats.countOfP2PSmsAvailableNotificationRemoved);
         assertEquals(SatelliteStats.SatelliteControllerParams.isNtnOnlyCarrier(),
                 stats.isNtnOnlyCarrier);
+        assertEquals(SatelliteStats.SatelliteControllerParams.getVersionSatelliteAccessConfig(),
+                stats.versionOfSatelliteAccessConfig);
+        assertEquals(param.getCountOfIncomingDatagramTypeSosSmsSuccess(),
+                stats.countOfIncomingDatagramTypeSosSmsSuccess);
+        assertEquals(param.getCountOfIncomingDatagramTypeSosSmsFail(),
+                stats.countOfIncomingDatagramTypeSosSmsFail);
+        assertEquals(param.getCountOfOutgoingDatagramTypeSmsSuccess(),
+                stats.countOfOutgoingDatagramTypeSmsSuccess);
+        assertEquals(param.getCountOfOutgoingDatagramTypeSmsFail(),
+                stats.countOfOutgoingDatagramTypeSmsFail);
+        assertEquals(param.getCountOfIncomingDatagramTypeSmsSuccess(),
+                stats.countOfIncomingDatagramTypeSmsSuccess);
+        assertEquals(param.getCountOfIncomingDatagramTypeSmsSuccess(),
+                stats.countOfIncomingDatagramTypeSmsSuccess);
 
         verifyNoMoreInteractions(mPersistAtomsStorage);
     }
@@ -417,6 +439,8 @@
                         .setCountOfOutgoingSms(11)
                         .setCountOfIncomingMms(9)
                         .setCountOfOutgoingMms(14)
+                        .setIsMultiSim(false)
+                        .setIsNbIotNtn(false)
                         .build();
 
         mSatelliteStats.onCarrierRoamingSatelliteSessionMetrics(param);
@@ -442,6 +466,8 @@
         assertEquals(param.getCountOfOutgoingSms(), stats.countOfOutgoingSms);
         assertEquals(param.getCountOfIncomingMms(), stats.countOfIncomingMms);
         assertEquals(param.getCountOfOutgoingMms(), stats.countOfOutgoingMms);
+        assertEquals(param.isMultiSim(), stats.isMultiSim);
+        assertEquals(param.isNbIotNtn(), stats.isNbIotNtn);
 
         verifyNoMoreInteractions(mPersistAtomsStorage);
     }
@@ -459,6 +485,9 @@
                         .setSatelliteSessionGapMaxSec(45)
                         .setCarrierId(10)
                         .setIsDeviceEntitled(true)
+                        .setIsMultiSim(true)
+                        .increaseCountOfSatelliteSessions()
+                        .setIsNbIotNtn(true)
                         .build();
 
         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(param);
@@ -479,6 +508,9 @@
         assertEquals(param.getSatelliteSessionGapMaxSec(), stats.satelliteSessionGapMaxSec);
         assertEquals(param.getCarrierId(), stats.carrierId);
         assertEquals(param.isDeviceEntitled(), stats.isDeviceEntitled);
+        assertEquals(param.isMultiSim(), stats.isMultiSim);
+        assertEquals(param.getCountOfSatelliteSessions(), stats.countOfSatelliteSessions);
+        assertEquals(param.isNbIotNtn(), stats.isNbIotNtn);
 
         verifyNoMoreInteractions(mPersistAtomsStorage);
     }
@@ -497,6 +529,9 @@
                         .setSatelliteSessionGapMaxSec(45)
                         .setCarrierId(10)
                         .setIsDeviceEntitled(true)
+                        .setIsMultiSim(true)
+                        .increaseCountOfSatelliteSessions()
+                        .setIsNbIotNtn(true)
                         .build();
         mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(param);
 
@@ -541,6 +576,8 @@
         // static values should be updated
         assertEquals(20, stats.carrierId);
         assertEquals(false, stats.isDeviceEntitled);
+        assertEquals(param.isMultiSim(), stats.isMultiSim);
+        assertEquals(param.getCountOfSatelliteSessions(), stats.countOfSatelliteSessions);
 
         verifyNoMoreInteractions(mPersistAtomsStorage);
     }
@@ -628,4 +665,38 @@
         assertEquals(param.getConfigDataSource(), stats.configDataSource);
         verifyNoMoreInteractions(mPersistAtomsStorage);
     }
+
+    @Test
+    public void testReportRepeatedDataWithAscendingOrder() {
+        int[] supportedSatelliteServicesArray = {3, 2, 1};
+        SatelliteStats.CarrierRoamingSatelliteSessionParams sessionParams =
+                new SatelliteStats.CarrierRoamingSatelliteSessionParams.Builder()
+                        .setSupportedSatelliteServices(supportedSatelliteServicesArray)
+                        .build();
+        mSatelliteStats.onCarrierRoamingSatelliteSessionMetrics(sessionParams);
+        ArgumentCaptor<CarrierRoamingSatelliteSession> sessionArgumentCaptor =
+                ArgumentCaptor.forClass(CarrierRoamingSatelliteSession.class);
+        verify(mPersistAtomsStorage).addCarrierRoamingSatelliteSessionStats(
+                sessionArgumentCaptor.capture());
+        CarrierRoamingSatelliteSession sessionStats = sessionArgumentCaptor.getValue();
+
+        Arrays.sort(supportedSatelliteServicesArray);
+        assertEquals(supportedSatelliteServicesArray, sessionStats.supportedSatelliteServices);
+        verifyNoMoreInteractions(mPersistAtomsStorage);
+
+        int[] entitlementServiceTypeArray = {2, 3, 1};
+        SatelliteStats.SatelliteEntitlementParams entitlementParams =
+                new SatelliteStats.SatelliteEntitlementParams.Builder()
+                        .setEntitlementServiceType(entitlementServiceTypeArray)
+                        .build();
+        mSatelliteStats.onSatelliteEntitlementMetrics(entitlementParams);
+        ArgumentCaptor<SatelliteEntitlement> entitlementArgumentCaptor =
+                ArgumentCaptor.forClass(SatelliteEntitlement.class);
+        verify(mPersistAtomsStorage).addSatelliteEntitlementStats(
+                entitlementArgumentCaptor.capture());
+        SatelliteEntitlement entitlementStats = entitlementArgumentCaptor.getValue();
+        Arrays.sort(entitlementServiceTypeArray);
+        assertEquals(entitlementServiceTypeArray, entitlementStats.entitlementServiceType);
+        verifyNoMoreInteractions(mPersistAtomsStorage);
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java
index 27878d1..f140df0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java
@@ -1361,6 +1361,35 @@
         assertTrue(state.isNtn);
     }
 
+    @Test
+    public void testIsNbIotNtn() {
+        // Using default service state for LTE
+        mServiceStateStats.onServiceStateChanged(mServiceState);
+        mServiceStateStats.incTimeMillis(100L);
+        mServiceStateStats.conclude();
+
+        ArgumentCaptor<CellularServiceState> captor =
+                ArgumentCaptor.forClass(CellularServiceState.class);
+        verify(mPersistAtomsStorage)
+                .addCellularServiceStateAndCellularDataServiceSwitch(captor.capture(), eq(null));
+        CellularServiceState state = captor.getValue();
+        assertFalse(state.isNtn);
+
+        reset(mPersistAtomsStorage);
+        reset(mServiceState);
+
+        when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
+        when(mSatelliteController.isInCarrierRoamingNbIotNtn(any())).thenReturn(true);
+        mServiceStateStats.onServiceStateChanged(mServiceState);
+        mServiceStateStats.incTimeMillis(100L);
+        mServiceStateStats.conclude();
+
+        verify(mPersistAtomsStorage)
+                .addCellularServiceStateAndCellularDataServiceSwitch(captor.capture(), eq(null));
+        state = captor.getValue();
+        assertTrue(state.isNbIotNtn);
+    }
+
     private void mockWwanPsRat(@NetworkType int rat) {
         mockWwanRat(
                 NetworkRegistrationInfo.DOMAIN_PS,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
index 4347869..e56a8d6 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
@@ -235,8 +235,6 @@
         mVoiceCallSessionStats1 = new TestableVoiceCallSessionStats(
                 1, mSecondPhone, mFeatureFlags);
         mVoiceCallSessionStats1.onServiceStateChanged(mSecondServiceState);
-
-        doReturn(true).when(mFeatureFlags).vonrEnabledMetric();
     }
 
     @After
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/VonrHelperTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/VonrHelperTest.java
index ddc29de..89ec8d9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/VonrHelperTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/VonrHelperTest.java
@@ -53,7 +53,6 @@
         doReturn(SUBID).when(mPhone).getSubId();
         doReturn(false).when(mTelephonyManager).isVoNrEnabled();
         mVonrHelper = new TestableVonrHelper(mFeatureFlags);
-        doReturn(true).when(mFeatureFlags).vonrEnabledMetric();
     }
 
     @After
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/CarrierRoamingSatelliteControllerStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/CarrierRoamingSatelliteControllerStatsTest.java
new file mode 100644
index 0000000..456fe74
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/CarrierRoamingSatelliteControllerStatsTest.java
@@ -0,0 +1,642 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.satellite;
+
+import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
+
+import static com.android.internal.telephony.satellite.SatelliteConstants.CONFIG_DATA_SOURCE_CONFIG_UPDATER;
+import static com.android.internal.telephony.satellite.SatelliteConstants.CONFIG_DATA_SOURCE_ENTITLEMENT;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.metrics.SatelliteStats;
+import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteControllerStats;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
+import com.android.telephony.Rlog;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class CarrierRoamingSatelliteControllerStatsTest extends TelephonyTest {
+    private static final String TAG = "CarrierRoamingSatelliteControllerStatsTest";
+    private static final int TEST_SUB_ID_0 = 0;
+    private static final int TEST_SUB_ID_1 = 1;
+    private static final int TEST_CARRIER_ID_0 = 1000;
+    private static final int TEST_CARRIER_ID_1 = 1111;
+    private static final long SESSION_TIME = 100L;
+    private static final long SESSION_GAP_1 = 1000000L;
+    private static final long SESSION_GAP_2 = 2000000L;
+    private static final long SESSION_GAP_3 = 4000000L;
+
+    private TestCarrierRoamingSatelliteControllerStats mTestCarrierRoamingSatelliteControllerStats;
+    @Mock
+    private SatelliteStats mMockSatelliteStats;
+    @Mock
+    private SubscriptionManagerService mMockSubscriptionManagerService;
+    @Mock
+    private SatelliteController mMockSatellitecontroller;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp(getClass().getSimpleName());
+        MockitoAnnotations.initMocks(this);
+        logd(TAG + " Setup!");
+        BackupAndRestoreCarrierRoamContParam.backUpStaticParams();
+        replaceInstance(SatelliteStats.class, "sInstance", null, mMockSatelliteStats);
+        mTestCarrierRoamingSatelliteControllerStats =
+                new TestCarrierRoamingSatelliteControllerStats();
+        replaceInstance(SubscriptionManagerService.class, "sInstance", null,
+                mMockSubscriptionManagerService);
+        replaceInstance(SatelliteController.class, "sInstance", null, mMockSatellitecontroller);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        Rlog.d(TAG, "tearDown()");
+        BackupAndRestoreCarrierRoamContParam.restoreStaticParams();
+        super.tearDown();
+    }
+
+    @Test
+    public void testReportConfigDataSource() {
+        final ExpectedCarrierRoamingSatelliteControllerStatsParam expected =
+                new ExpectedCarrierRoamingSatelliteControllerStatsParam();
+        doReturn(new int[]{TEST_SUB_ID_0}).when(
+                mMockSubscriptionManagerService).getActiveSubIdList(anyBoolean());
+        doReturn(false).when(mMockSatellitecontroller).isInCarrierRoamingNbIotNtn(any());
+
+        initializeStaticParams();
+        expected.initializeParams();
+        expected.setConfigDataSource(CONFIG_DATA_SOURCE_ENTITLEMENT);
+        expected.setCarrierId(TEST_CARRIER_ID_0);
+        expected.setIsMultiSim(false);
+        expected.setIsNbIotNtn(false);
+        clearInvocations(mMockSatelliteStats);
+        mTestCarrierRoamingSatelliteControllerStats.reportConfigDataSource(TEST_SUB_ID_0,
+                CONFIG_DATA_SOURCE_ENTITLEMENT);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+
+        doReturn(new int[]{TEST_SUB_ID_0, TEST_SUB_ID_1}).when(
+                mMockSubscriptionManagerService).getActiveSubIdList(anyBoolean());
+        doReturn(true).when(mMockSatellitecontroller).isInCarrierRoamingNbIotNtn(any());
+
+        initializeStaticParams();
+        expected.initializeParams();
+        expected.setConfigDataSource(CONFIG_DATA_SOURCE_CONFIG_UPDATER);
+        expected.setCarrierId(TEST_CARRIER_ID_1);
+        expected.setIsMultiSim(true);
+        expected.setIsNbIotNtn(true);
+        clearInvocations(mMockSatelliteStats);
+        mTestCarrierRoamingSatelliteControllerStats.reportConfigDataSource(TEST_SUB_ID_1,
+                CONFIG_DATA_SOURCE_CONFIG_UPDATER);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+    }
+
+    @Test
+    public void testReportCountOfEntitlementStatusQueryRequest() {
+        final ExpectedCarrierRoamingSatelliteControllerStatsParam expected =
+                new ExpectedCarrierRoamingSatelliteControllerStatsParam();
+        doReturn(new int[]{TEST_SUB_ID_0}).when(
+                mMockSubscriptionManagerService).getActiveSubIdList(anyBoolean());
+        doReturn(false).when(mMockSatellitecontroller).isInCarrierRoamingNbIotNtn(any());
+
+        initializeStaticParams();
+        expected.initializeParams();
+        expected.setCountOfEntitlementStatusQueryRequest(1);
+        expected.setCarrierId(TEST_CARRIER_ID_0);
+        expected.setIsMultiSim(false);
+        expected.setIsNbIotNtn(false);
+        clearInvocations(mMockSatelliteStats);
+        mTestCarrierRoamingSatelliteControllerStats.reportCountOfEntitlementStatusQueryRequest(
+                TEST_SUB_ID_0);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+
+        doReturn(new int[]{TEST_SUB_ID_0, TEST_SUB_ID_1}).when(
+                mMockSubscriptionManagerService).getActiveSubIdList(anyBoolean());
+        doReturn(true).when(mMockSatellitecontroller).isInCarrierRoamingNbIotNtn(any());
+
+        initializeStaticParams();
+        expected.initializeParams();
+        expected.setCountOfEntitlementStatusQueryRequest(1);
+        expected.setCarrierId(TEST_CARRIER_ID_1);
+        expected.setIsMultiSim(true);
+        expected.setIsNbIotNtn(true);
+        clearInvocations(mMockSatelliteStats);
+        mTestCarrierRoamingSatelliteControllerStats.reportCountOfEntitlementStatusQueryRequest(
+                TEST_SUB_ID_1);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+    }
+
+    @Test
+    public void testReportCountOfSatelliteConfigUpdateRequest() {
+        final ExpectedCarrierRoamingSatelliteControllerStatsParam expected =
+                new ExpectedCarrierRoamingSatelliteControllerStatsParam();
+        doReturn(new int[]{TEST_SUB_ID_0}).when(
+                mMockSubscriptionManagerService).getActiveSubIdList(anyBoolean());
+
+        initializeStaticParams();
+        expected.initializeParams();
+        expected.setCountOfSatelliteConfigUpdateRequest(1);
+        expected.setCarrierId(UNKNOWN_CARRIER_ID);
+        expected.setIsMultiSim(false);
+
+        clearInvocations(mMockSatelliteStats);
+        mTestCarrierRoamingSatelliteControllerStats.reportCountOfSatelliteConfigUpdateRequest();
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+
+        doReturn(new int[]{TEST_SUB_ID_0, TEST_SUB_ID_1}).when(
+                mMockSubscriptionManagerService).getActiveSubIdList(anyBoolean());
+
+        initializeStaticParams();
+        expected.initializeParams();
+        expected.setCountOfSatelliteConfigUpdateRequest(1);
+        expected.setCarrierId(UNKNOWN_CARRIER_ID);
+        expected.setIsMultiSim(true);
+
+        clearInvocations(mMockSatelliteStats);
+        mTestCarrierRoamingSatelliteControllerStats.reportCountOfSatelliteConfigUpdateRequest();
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+    }
+
+    @Test
+    public void testReportCountOfSatelliteNotificationDisplayed() {
+        final ExpectedCarrierRoamingSatelliteControllerStatsParam expected =
+                new ExpectedCarrierRoamingSatelliteControllerStatsParam();
+        doReturn(new int[]{TEST_SUB_ID_0}).when(
+                mMockSubscriptionManagerService).getActiveSubIdList(anyBoolean());
+        doReturn(false).when(mMockSatellitecontroller).isInCarrierRoamingNbIotNtn(any());
+
+        initializeStaticParams();
+        expected.initializeParams();
+        expected.setCountOfSatelliteNotificationDisplayed(1);
+        expected.setCarrierId(TEST_CARRIER_ID_0);
+        expected.setIsMultiSim(false);
+        expected.setIsNbIotNtn(false);
+
+        clearInvocations(mMockSatelliteStats);
+        mTestCarrierRoamingSatelliteControllerStats.reportCountOfSatelliteNotificationDisplayed(
+                TEST_SUB_ID_0);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+
+        doReturn(new int[]{TEST_SUB_ID_0, TEST_SUB_ID_1}).when(
+                mMockSubscriptionManagerService).getActiveSubIdList(anyBoolean());
+        doReturn(true).when(mMockSatellitecontroller).isInCarrierRoamingNbIotNtn(any());
+
+        initializeStaticParams();
+        expected.initializeParams();
+        expected.setCountOfSatelliteNotificationDisplayed(1);
+        expected.setCarrierId(TEST_CARRIER_ID_1);
+        expected.setIsMultiSim(true);
+        expected.setIsNbIotNtn(true);
+        clearInvocations(mMockSatelliteStats);
+        mTestCarrierRoamingSatelliteControllerStats.reportCountOfSatelliteNotificationDisplayed(
+                TEST_SUB_ID_1);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+    }
+
+    @Test
+    public void testReportCarrierId() {
+        final ExpectedCarrierRoamingSatelliteControllerStatsParam expected =
+                new ExpectedCarrierRoamingSatelliteControllerStatsParam();
+        doReturn(new int[]{TEST_SUB_ID_0}).when(
+                mMockSubscriptionManagerService).getActiveSubIdList(anyBoolean());
+
+        initializeStaticParams();
+        expected.initializeParams();
+        expected.setCarrierId(TEST_CARRIER_ID_0);
+        expected.setIsMultiSim(false);
+
+        clearInvocations(mMockSatelliteStats);
+        mTestCarrierRoamingSatelliteControllerStats.reportCarrierId(TEST_CARRIER_ID_0);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+
+        doReturn(new int[]{TEST_SUB_ID_0, TEST_SUB_ID_1}).when(
+                mMockSubscriptionManagerService).getActiveSubIdList(anyBoolean());
+
+        initializeStaticParams();
+        expected.initializeParams();
+        expected.setCarrierId(TEST_CARRIER_ID_1);
+        expected.setIsMultiSim(true);
+        clearInvocations(mMockSatelliteStats);
+        mTestCarrierRoamingSatelliteControllerStats.reportCarrierId(TEST_CARRIER_ID_1);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+    }
+
+    @Test
+    public void testReportIsDeviceEntitled() {
+        final ExpectedCarrierRoamingSatelliteControllerStatsParam expected =
+                new ExpectedCarrierRoamingSatelliteControllerStatsParam();
+        doReturn(new int[]{TEST_SUB_ID_0}).when(
+                mMockSubscriptionManagerService).getActiveSubIdList(anyBoolean());
+        doReturn(false).when(mMockSatellitecontroller).isInCarrierRoamingNbIotNtn(any());
+
+        initializeStaticParams();
+        expected.initializeParams();
+        expected.setIsDeviceEntitled(true);
+        expected.setCarrierId(TEST_CARRIER_ID_0);
+        expected.setIsMultiSim(false);
+        expected.setIsNbIotNtn(false);
+
+        clearInvocations(mMockSatelliteStats);
+        mTestCarrierRoamingSatelliteControllerStats.reportIsDeviceEntitled(TEST_SUB_ID_0, true);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+
+        doReturn(new int[]{TEST_SUB_ID_0, TEST_SUB_ID_1}).when(
+                mMockSubscriptionManagerService).getActiveSubIdList(anyBoolean());
+        doReturn(true).when(mMockSatellitecontroller).isInCarrierRoamingNbIotNtn(any());
+
+        initializeStaticParams();
+        expected.initializeParams();
+        expected.setIsDeviceEntitled(false);
+        expected.setCarrierId(TEST_CARRIER_ID_1);
+        expected.setIsMultiSim(true);
+        expected.setIsNbIotNtn(true);
+        clearInvocations(mMockSatelliteStats);
+        mTestCarrierRoamingSatelliteControllerStats.reportIsDeviceEntitled(TEST_SUB_ID_1, false);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+    }
+
+    @Test
+    public void testSatelliteSessionGaps() {
+        final ExpectedCarrierRoamingSatelliteControllerStatsParam expected =
+                new ExpectedCarrierRoamingSatelliteControllerStatsParam();
+        doReturn(new int[]{TEST_SUB_ID_0}).when(
+                mMockSubscriptionManagerService).getActiveSubIdList(anyBoolean());
+        doReturn(false).when(mMockSatellitecontroller).isInCarrierRoamingNbIotNtn(any());
+
+        initializeStaticParams();
+        expected.initializeParams();
+        expected.setCarrierId(TEST_CARRIER_ID_0);
+        expected.setIsMultiSim(false);
+        expected.setIsNbIotNtn(false);
+        clearInvocations(mMockSatelliteStats);
+        // first satellite session starts
+        mTestCarrierRoamingSatelliteControllerStats.setCurrentTime(0L);
+        // session counter is increased when session starts
+        expected.setCountOfSatelliteSessions(1);
+        mTestCarrierRoamingSatelliteControllerStats.onSessionStart(TEST_SUB_ID_0);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+
+        clearInvocations(mMockSatelliteStats);
+        // first satellite session ends
+        mTestCarrierRoamingSatelliteControllerStats.increaseCurrentTime(SESSION_TIME);
+        mTestCarrierRoamingSatelliteControllerStats.onSessionEnd(TEST_SUB_ID_0);
+
+        // session gaps would be 0
+        expected.setSatelliteSessionGapMinSec(0);
+        expected.setSatelliteSessionGapAvgSec(0);
+        expected.setSatelliteSessionGapMaxSec(0);
+        // session counter is not reported when session ends
+        expected.setCountOfSatelliteSessions(0);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+
+        clearInvocations(mMockSatelliteStats);
+        // second session starts, gap between 1st and 2nd session is 1000sec
+        mTestCarrierRoamingSatelliteControllerStats.increaseCurrentTime(SESSION_GAP_1);
+        expected.setCountOfSatelliteSessions(1);
+        mTestCarrierRoamingSatelliteControllerStats.onSessionStart(TEST_SUB_ID_0);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+
+        clearInvocations(mMockSatelliteStats);
+        // second session end
+        mTestCarrierRoamingSatelliteControllerStats.increaseCurrentTime(SESSION_TIME);
+        mTestCarrierRoamingSatelliteControllerStats.onSessionEnd(TEST_SUB_ID_0);
+
+        // session gap min / avg / max would be 1000 each
+        expected.setSatelliteSessionGapMinSec(1000);
+        expected.setSatelliteSessionGapAvgSec(1000);
+        expected.setSatelliteSessionGapMaxSec(1000);
+        expected.setCountOfSatelliteSessions(0);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+
+        clearInvocations(mMockSatelliteStats);
+        // 3rd session starts, gap between 2nd and 3rd session is 2000
+        mTestCarrierRoamingSatelliteControllerStats.increaseCurrentTime(SESSION_GAP_2);
+        expected.setCountOfSatelliteSessions(1);
+        mTestCarrierRoamingSatelliteControllerStats.onSessionStart(TEST_SUB_ID_0);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+
+        clearInvocations(mMockSatelliteStats);
+        // 3rd session end
+        mTestCarrierRoamingSatelliteControllerStats.increaseCurrentTime(SESSION_TIME);
+        mTestCarrierRoamingSatelliteControllerStats.onSessionEnd(TEST_SUB_ID_0);
+
+        // session gap min would be 1000
+        expected.setSatelliteSessionGapMinSec(1000);
+        // session gap avg would be 1500
+        int avgGapSec = (int) ((SESSION_GAP_1 + SESSION_GAP_2) / (2 * 1000));
+        expected.setSatelliteSessionGapAvgSec(avgGapSec);
+        // session gap max would be 2000
+        expected.setSatelliteSessionGapMaxSec(2000);
+        expected.setCountOfSatelliteSessions(0);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+
+        clearInvocations(mMockSatelliteStats);
+        // 4th session starts, gap between 3rd and 4th session is 4000
+        mTestCarrierRoamingSatelliteControllerStats.increaseCurrentTime(SESSION_GAP_3);
+        expected.setCountOfSatelliteSessions(1);
+        mTestCarrierRoamingSatelliteControllerStats.onSessionStart(TEST_SUB_ID_0);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+
+        clearInvocations(mMockSatelliteStats);
+        // 4th session end
+        mTestCarrierRoamingSatelliteControllerStats.increaseCurrentTime(SESSION_TIME);
+        mTestCarrierRoamingSatelliteControllerStats.onSessionEnd(TEST_SUB_ID_0);
+
+        // session gap min would be 1000
+        expected.setSatelliteSessionGapMinSec(1000);
+        // session gap avg would be 2333
+        avgGapSec = (int) ((SESSION_GAP_1 + SESSION_GAP_2 + SESSION_GAP_3) / (3 * 1000));
+        expected.setSatelliteSessionGapAvgSec(avgGapSec);
+        // session gap max would be 4000
+        expected.setSatelliteSessionGapMaxSec(4000);
+        expected.setCountOfSatelliteSessions(0);
+        verify(mMockSatelliteStats, times(1)).onCarrierRoamingSatelliteControllerStatsMetrics(
+                ArgumentMatchers.argThat(argument -> verifyAssets(expected, argument)));
+    }
+
+    private static class BackupAndRestoreCarrierRoamContParam {
+        private static int sSatelliteSessionGapMinSec;
+        private static int sSatelliteSessionGapAvgSec;
+        private static int sSatelliteSessionGapMaxSec;
+        private static int sCarrierId;
+        private static boolean sIsDeviceEntitled;
+        private static boolean sIsMultiSim;
+        private static boolean sIsNbIotNtn;
+
+        public static void backUpStaticParams() {
+            SatelliteStats.CarrierRoamingSatelliteControllerStatsParams param =
+                    new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+                            .build();
+            sSatelliteSessionGapMinSec = param.getSatelliteSessionGapMinSec();
+            sSatelliteSessionGapAvgSec = param.getSatelliteSessionGapAvgSec();
+            sSatelliteSessionGapMaxSec = param.getSatelliteSessionGapMaxSec();
+            sCarrierId = param.getCarrierId();
+            sIsDeviceEntitled = param.isDeviceEntitled();
+            sIsMultiSim = param.isMultiSim();
+            sIsNbIotNtn = param.isNbIotNtn();
+        }
+
+        public static void restoreStaticParams() {
+            SatelliteStats.getInstance().onCarrierRoamingSatelliteControllerStatsMetrics(
+                    new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+                            .setSatelliteSessionGapMinSec(sSatelliteSessionGapMinSec)
+                            .setSatelliteSessionGapAvgSec(sSatelliteSessionGapAvgSec)
+                            .setSatelliteSessionGapMaxSec(sSatelliteSessionGapMaxSec)
+                            .setCarrierId(sCarrierId)
+                            .setIsDeviceEntitled(sIsDeviceEntitled)
+                            .setIsMultiSim(sIsMultiSim)
+                            .setIsNbIotNtn(sIsNbIotNtn)
+                            .build());
+        }
+    }
+
+    private void initializeStaticParams() {
+        SatelliteStats.getInstance().onCarrierRoamingSatelliteControllerStatsMetrics(
+                new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+                        .setSatelliteSessionGapMinSec(0)
+                        .setSatelliteSessionGapAvgSec(0)
+                        .setSatelliteSessionGapMaxSec(0)
+                        .setCarrierId(UNKNOWN_CARRIER_ID)
+                        .setIsDeviceEntitled(false)
+                        .setIsMultiSim(false)
+                        .setIsNbIotNtn(false)
+                        .build());
+    }
+
+    private boolean verifyAssets(ExpectedCarrierRoamingSatelliteControllerStatsParam expected,
+            SatelliteStats.CarrierRoamingSatelliteControllerStatsParams actual) {
+        assertEquals(expected.getConfigDataSource(), actual.getConfigDataSource());
+        assertEquals(expected.getCountOfEntitlementStatusQueryRequest(),
+                actual.getCountOfEntitlementStatusQueryRequest());
+        assertEquals(expected.getCountOfSatelliteConfigUpdateRequest(),
+                actual.getCountOfSatelliteConfigUpdateRequest());
+        assertEquals(expected.getCountOfSatelliteNotificationDisplayed(),
+                actual.getCountOfSatelliteNotificationDisplayed());
+        assertEquals(expected.getSatelliteSessionGapMinSec(),
+                actual.getSatelliteSessionGapMinSec());
+        assertEquals(expected.getSatelliteSessionGapAvgSec(),
+                actual.getSatelliteSessionGapAvgSec());
+        assertEquals(expected.getSatelliteSessionGapMaxSec(),
+                actual.getSatelliteSessionGapMaxSec());
+        assertEquals(expected.getCarrierId(), actual.getCarrierId());
+        assertEquals(expected.isDeviceEntitled(), actual.isDeviceEntitled());
+        assertEquals(expected.isMultiSim(), actual.isMultiSim());
+        assertEquals(expected.getCountOfSatelliteSessions(), actual.getCountOfSatelliteSessions());
+        assertEquals(expected.isNbIotNtn(), actual.isNbIotNtn());
+        return true;
+    }
+
+    private static class ExpectedCarrierRoamingSatelliteControllerStatsParam {
+        private int mConfigDataSource;
+        private int mCountOfEntitlementStatusQueryRequest;
+        private int mCountOfSatelliteConfigUpdateRequest;
+        private int mCountOfSatelliteNotificationDisplayed;
+        private int mSatelliteSessionGapMinSec;
+        private int mSatelliteSessionGapAvgSec;
+        private int mSatelliteSessionGapMaxSec;
+        private int mCarrierId;
+        private boolean mIsDeviceEntitled;
+        private boolean mIsMultiSim;
+        private int mCountOfSatelliteSessions;
+        private boolean mIsNbIotNtn;
+
+        public int getConfigDataSource() {
+            return mConfigDataSource;
+        }
+
+        public int getCountOfEntitlementStatusQueryRequest() {
+            return mCountOfEntitlementStatusQueryRequest;
+        }
+
+        public int getCountOfSatelliteConfigUpdateRequest() {
+            return mCountOfSatelliteConfigUpdateRequest;
+        }
+
+        public int getCountOfSatelliteNotificationDisplayed() {
+            return mCountOfSatelliteNotificationDisplayed;
+        }
+
+        public int getSatelliteSessionGapMinSec() {
+            return mSatelliteSessionGapMinSec;
+        }
+
+        public int getSatelliteSessionGapAvgSec() {
+            return mSatelliteSessionGapAvgSec;
+        }
+
+        public int getSatelliteSessionGapMaxSec() {
+            return mSatelliteSessionGapMaxSec;
+        }
+
+        public int getCarrierId() {
+            return mCarrierId;
+        }
+
+        public boolean isDeviceEntitled() {
+            return mIsDeviceEntitled;
+        }
+
+        public boolean isMultiSim() {
+            return mIsMultiSim;
+        }
+
+        public int getCountOfSatelliteSessions() {
+            return mCountOfSatelliteSessions;
+        }
+
+        public boolean isNbIotNtn() {
+            return mIsNbIotNtn;
+        }
+
+        public void setConfigDataSource(int configDataSource) {
+            mConfigDataSource = configDataSource;
+        }
+
+        public void setCountOfEntitlementStatusQueryRequest(
+                int countOfEntitlementStatusQueryRequest) {
+            mCountOfEntitlementStatusQueryRequest = countOfEntitlementStatusQueryRequest;
+        }
+
+        public void setCountOfSatelliteConfigUpdateRequest(
+                int countOfSatelliteConfigUpdateRequest) {
+            mCountOfSatelliteConfigUpdateRequest = countOfSatelliteConfigUpdateRequest;
+        }
+
+        public void setCountOfSatelliteNotificationDisplayed(
+                int countOfSatelliteNotificationDisplayed) {
+            mCountOfSatelliteNotificationDisplayed = countOfSatelliteNotificationDisplayed;
+        }
+
+        public void setSatelliteSessionGapMinSec(int satelliteSessionGapMinSec) {
+            mSatelliteSessionGapMinSec = satelliteSessionGapMinSec;
+        }
+
+        public void setSatelliteSessionGapAvgSec(int satelliteSessionGapAvgSec) {
+            mSatelliteSessionGapAvgSec = satelliteSessionGapAvgSec;
+        }
+
+        public void setSatelliteSessionGapMaxSec(int satelliteSessionGapMaxSec) {
+            mSatelliteSessionGapMaxSec = satelliteSessionGapMaxSec;
+        }
+
+        public void setCarrierId(int carrierId) {
+            mCarrierId = carrierId;
+        }
+
+        public void setIsDeviceEntitled(boolean isDeviceEntitled) {
+            mIsDeviceEntitled = isDeviceEntitled;
+        }
+
+        public void setIsMultiSim(boolean isMultiSim) {
+            mIsMultiSim = isMultiSim;
+        }
+
+        public void setCountOfSatelliteSessions(int countOfSatelliteSessions) {
+            mCountOfSatelliteSessions = countOfSatelliteSessions;
+        }
+
+        public void setIsNbIotNtn(boolean isNbIotNtn) {
+            mIsNbIotNtn = isNbIotNtn;
+        }
+
+        public void initializeParams() {
+            mConfigDataSource = SatelliteConstants.CONFIG_DATA_SOURCE_UNKNOWN;
+            mCountOfEntitlementStatusQueryRequest = 0;
+            mCountOfSatelliteConfigUpdateRequest = 0;
+            mCountOfSatelliteNotificationDisplayed = 0;
+            mSatelliteSessionGapMinSec = 0;
+            mSatelliteSessionGapAvgSec = 0;
+            mSatelliteSessionGapMaxSec = 0;
+            mCarrierId = UNKNOWN_CARRIER_ID;
+            mIsDeviceEntitled = false;
+            mIsMultiSim = false;
+            mCountOfSatelliteSessions = 0;
+            mIsNbIotNtn = false;
+        }
+    }
+
+    static class TestCarrierRoamingSatelliteControllerStats extends
+            CarrierRoamingSatelliteControllerStats {
+        private long mCurrentTime;
+        TestCarrierRoamingSatelliteControllerStats() {
+            super();
+            logd("constructing TestCarrierRoamingSatelliteControllerStats");
+        }
+
+        @Override
+        public int getCarrierIdFromSubscription(int subId) {
+            logd("getCarrierIdFromSubscription()");
+            if (subId == TEST_SUB_ID_0) {
+                return TEST_CARRIER_ID_0;
+            } else if (subId == TEST_SUB_ID_1) {
+                return TEST_CARRIER_ID_1;
+            } else {
+                return UNKNOWN_CARRIER_ID;
+            }
+        }
+
+        @Override
+        public long getElapsedRealtime() {
+            return mCurrentTime;
+        }
+
+        public void setCurrentTime(long currentTime) {
+            mCurrentTime = currentTime;
+        }
+
+        public void increaseCurrentTime(long incTime) {
+            mCurrentTime += incTime;
+        }
+    }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java
index fdb94c9..123bb39 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java
@@ -584,14 +584,14 @@
         doReturn(false).when(mSpyControllerMetricsStats).isSatelliteModemOn();
 
         doNothing().when(mSpyControllerMetricsStats).startCaptureBatteryLevel();
-        doReturn(MODEM_ENABLED_TIME).when(mSpyControllerMetricsStats).getCurrentTime();
+        doReturn(MODEM_ENABLED_TIME).when(mSpyControllerMetricsStats).getElapsedRealtime();
 
         // test object
         mSpyControllerMetricsStats.onSatelliteEnabled();
 
         // verification
         verify(mSpyControllerMetricsStats).startCaptureBatteryLevel();
-        verify(mSpyControllerMetricsStats).getCurrentTime();
+        verify(mSpyControllerMetricsStats).getElapsedRealtime();
     }
 
     @Test
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 271e0ad..f4d7e61 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
@@ -35,7 +35,7 @@
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -87,7 +87,6 @@
                 mMockSatelliteController);
         replaceInstance(SatelliteSessionController.class, "sInstance", null,
                 mMockSatelliteSessionController);
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
         mDatagramControllerUT = new DatagramController(
                 mContext, Looper.myLooper(), mFeatureFlags, mMockPointingAppController);
@@ -149,9 +148,9 @@
         int errorCode = SATELLITE_RESULT_SUCCESS;
         mDatagramControllerUT.updateSendStatus(SUB_ID, DATAGRAM_TYPE_KEEP_ALIVE,
                 SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, sendPendingCount, errorCode);
-        verifyZeroInteractions(mMockSatelliteSessionController);
-        verifyZeroInteractions(mMockPointingAppController);
-        verifyZeroInteractions(mMockDatagramReceiver);
+        verifyNoMoreInteractions(mMockSatelliteSessionController);
+        verifyNoMoreInteractions(mMockPointingAppController);
+        verifyNoMoreInteractions(mMockDatagramReceiver);
     }
 
     @Test
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 b4de672..745a5b2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -43,7 +43,6 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
@@ -166,8 +165,6 @@
         replaceInstance(SessionMetricsStats.class, "sInstance", null,
                 mMockSessionMetricsStats);
 
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
-        when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         mDatagramDispatcherUT = new TestDatagramDispatcher(mContext, Looper.myLooper(),
                 mFeatureFlags,
@@ -232,7 +229,7 @@
                     eq(SATELLITE_RESULT_SUCCESS));
             mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(
                     eq(SatelliteServiceUtils.isLastSosMessage(datagramType)));
-            verifyZeroInteractions(mMockSatelliteModemInterface);
+            verifyNoMoreInteractions(mMockSatelliteModemInterface);
             assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
 
             doReturn(false).when(mMockDatagramController)
@@ -275,7 +272,7 @@
             mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
                     true, mResultListener::offer);
             processAllMessages();
-            verifyZeroInteractions(mMockSatelliteModemInterface);
+            verifyNoMoreInteractions(mMockSatelliteModemInterface);
             mInOrder.verify(mMockDatagramController)
                     .needsWaitingForSatelliteConnected(eq(datagramType));
             mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(
@@ -284,7 +281,7 @@
 
             moveTimeForward(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
             processAllMessages();
-            verifyZeroInteractions(mMockSatelliteModemInterface);
+            verifyNoMoreInteractions(mMockSatelliteModemInterface);
             mInOrder.verify(mMockDatagramController)
                     .updateSendStatus(eq(mPhone.getSubId()),
                             eq(datagramType),
@@ -307,7 +304,7 @@
             mDatagramDispatcherUT.onSatelliteModemStateChanged(
                     SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
             processAllMessages();
-            verifyZeroInteractions(mMockSatelliteModemInterface);
+            verifyNoMoreInteractions(mMockSatelliteModemInterface);
             assertEquals(0, mResultListener.size());
 
             clearInvocations(mMockSatelliteModemInterface);
@@ -317,7 +314,7 @@
             mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
                     true, mResultListener::offer);
             processAllMessages();
-            verifyZeroInteractions(mMockSatelliteModemInterface);
+            verifyNoMoreInteractions(mMockSatelliteModemInterface);
             mInOrder.verify(mMockDatagramController)
                     .needsWaitingForSatelliteConnected(eq(datagramType));
             mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(
@@ -331,7 +328,7 @@
             mDatagramDispatcherUT.onSatelliteModemStateChanged(
                     SatelliteManager.SATELLITE_MODEM_STATE_OFF);
             processAllMessages();
-            verifyZeroInteractions(mMockSatelliteModemInterface);
+            verifyNoMoreInteractions(mMockSatelliteModemInterface);
             assertEquals(1, mResultListener.size());
             assertThat(mResultListener.peek()).isEqualTo(
                     SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED);
@@ -691,8 +688,6 @@
 
     @Test
     public void testSendSatelliteDatagramToModemInDemoMode() throws Exception {
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
-
         mDatagramDispatcherUT.setDemoMode(true);
         mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
 
@@ -809,7 +804,7 @@
                 eq(SATELLITE_RESULT_SUCCESS));
         mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(
                 eq(SatelliteServiceUtils.isLastSosMessage(datagramType)));
-        verifyZeroInteractions(mMockSmsDispatchersController);
+        verifyNoMoreInteractions(mMockSmsDispatchersController);
         assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
 
         doReturn(false).when(mMockDatagramController)
@@ -903,7 +898,7 @@
                 eq(SATELLITE_RESULT_SUCCESS));
         mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(
                 eq(SatelliteServiceUtils.isLastSosMessage(datagramType)));
-        verifyZeroInteractions(mMockSmsDispatchersController);
+        verifyNoMoreInteractions(mMockSmsDispatchersController);
         assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
 
         moveTimeForward(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
@@ -926,7 +921,7 @@
         mDatagramDispatcherUT.onSatelliteModemStateChanged(
                 SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
         processAllMessages();
-        verifyZeroInteractions(mMockSmsDispatchersController);
+        verifyNoMoreInteractions(mMockSmsDispatchersController);
     }
 
     @Test
@@ -951,7 +946,7 @@
                 eq(SATELLITE_RESULT_SUCCESS));
         mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(
                 eq(SatelliteServiceUtils.isLastSosMessage(datagramType)));
-        verifyZeroInteractions(mMockSmsDispatchersController);
+        verifyNoMoreInteractions(mMockSmsDispatchersController);
         assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
 
         mDatagramDispatcherUT.onSatelliteModemStateChanged(
@@ -1012,7 +1007,7 @@
                 eq(SATELLITE_RESULT_SUCCESS));
         mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(
                 eq(SatelliteServiceUtils.isLastSosMessage(datagramTypeSms)));
-        verifyZeroInteractions(mMockSmsDispatchersController);
+        verifyNoMoreInteractions(mMockSmsDispatchersController);
         assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
 
         mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramTypeSos, mDatagram,
@@ -1024,7 +1019,7 @@
                 eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT),
                 eq(2),
                 eq(SATELLITE_RESULT_SUCCESS));
-        verifyZeroInteractions(mMockSatelliteModemInterface);
+        verifyNoMoreInteractions(mMockSatelliteModemInterface);
         assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
 
         doReturn(false).when(mMockDatagramController)
@@ -1112,7 +1107,7 @@
         mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramTypeSos, mDatagram,
                 true, mResultListener::offer);
         processAllMessages();
-        verifyZeroInteractions(mMockSatelliteModemInterface);
+        verifyNoMoreInteractions(mMockSatelliteModemInterface);
 
         mDatagramDispatcherUT.onSendSmsDone(mPhone.getSubId(), mPendingSms.uniqueMessageId, true);
         processAllMessages();
@@ -1150,13 +1145,12 @@
    public void testHandleMessage_eventMtSmsPollingThrottleTimedOut_sendsMtSmsPollInNotConnected() {
         setShouldPollMtSmsTrue();
         mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
-        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         mContextFixture.putBooleanResource(
                 R.bool.config_satellite_allow_check_message_in_not_connected, true);
 
-        mDatagramDispatcherUT.handleMessage(
-                mDatagramDispatcherUT.obtainMessage(10 /*EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT*/,
-                        new AsyncResult(null, null, null)));
+        mDatagramDispatcherUT.obtainMessage(10 /*EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT*/,
+                new AsyncResult(null, null, null)).sendToTarget();
+        processAllMessages();
 
         verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
    }
@@ -1166,16 +1160,15 @@
             testHandleMessage_eventMtSmsPollingThrottleTimedOut_configDisabled_doesNotSendMtSmsPoll() {
         setShouldPollMtSmsTrue();
         mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
-        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         // Set config_satellite_allow_check_message_in_not_connected to false
         mContextFixture.putBooleanResource(
                 R.bool.config_satellite_allow_check_message_in_not_connected, false);
 
-        mDatagramDispatcherUT.handleMessage(
-                mDatagramDispatcherUT.obtainMessage(10 /*EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT*/,
-                        new AsyncResult(null, null, null)));
+        mDatagramDispatcherUT.obtainMessage(10 /*EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT*/,
+                new AsyncResult(null, null, null)).sendToTarget();
+        processAllMessages();
 
-        verifyZeroInteractions(mMockSmsDispatchersController);
+        verifyNoMoreInteractions(mMockSmsDispatchersController);
    }
 
     @Test
@@ -1183,16 +1176,14 @@
             testHandleMessage_eventMtSmsPollingThrottleTimedOut_flagDisabled_doesNotSendMtSmsPoll() {
         setShouldPollMtSmsTrue();
         mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
-        // Set flag to false
-        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
         mContextFixture.putBooleanResource(
                 R.bool.config_satellite_allow_check_message_in_not_connected, true);
 
-        mDatagramDispatcherUT.handleMessage(
-                mDatagramDispatcherUT.obtainMessage(10 /*EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT*/,
-                        new AsyncResult(null, null, null)));
+        mDatagramDispatcherUT.obtainMessage(10 /*EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT*/,
+                new AsyncResult(null, null, null)).sendToTarget();
+        processAllMessages();
 
-        verifyZeroInteractions(mMockSmsDispatchersController);
+        verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
    }
 
 
@@ -1200,11 +1191,11 @@
     @Test
     public void testSetDeviceAlignedWithSatellite_isAligned_notConnected_sendsMtSmsPoll() {
         setShouldPollMtSmsTrue();
-        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         mContextFixture.putBooleanResource(
                 R.bool.config_satellite_allow_check_message_in_not_connected, true);
 
         mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+        processAllMessages();
 
         verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
     }
@@ -1212,25 +1203,25 @@
     @Test
     public void testSetDeviceAlignedWithSatellite_notAligned_doesNotSendsMtSmsPoll() {
         setShouldPollMtSmsTrue();
-        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         mContextFixture.putBooleanResource(
                 R.bool.config_satellite_allow_check_message_in_not_connected, true);
 
         mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
+        processAllMessages();
 
-        verifyZeroInteractions(mMockSmsDispatchersController);
+        verifyNoMoreInteractions(mMockSmsDispatchersController);
     }
 
     @Test
     public void testOnSatelliteModemStateChanged_notConnected_sendsMtSmsPoll() {
         setShouldPollMtSmsTrue();
         mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
-        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         mContextFixture.putBooleanResource(
                 R.bool.config_satellite_allow_check_message_in_not_connected, true);
 
         mDatagramDispatcherUT.onSatelliteModemStateChanged(
                 SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+        processAllMessages();
 
         verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
     }
@@ -1239,10 +1230,10 @@
     public void testOnSatelliteModemStateChanged_connected_sendsMtSmsPoll() {
         setShouldPollMtSmsTrue();
         mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
-        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
 
         mDatagramDispatcherUT.onSatelliteModemStateChanged(
                 SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+        processAllMessages();
 
         verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
     }
@@ -1251,10 +1242,10 @@
     public void testOnSatelliteModemStateChanged_transferring_sendsMtSmsPoll() {
         setShouldPollMtSmsTrue();
         mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
-        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
 
         mDatagramDispatcherUT.onSatelliteModemStateChanged(
                 SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+        processAllMessages();
 
         verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
     }
@@ -1264,12 +1255,11 @@
         startMtSmsPollingThrottle();
         setShouldPollMtSmsTrue();
         mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
-        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         mContextFixture.putBooleanResource(
                 R.bool.config_satellite_allow_check_message_in_not_connected, true);
-
         mDatagramDispatcherUT.onSatelliteModemStateChanged(
                 SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+        processAllMessages();
 
         verify(mMockSmsDispatchersController, times(0)).sendMtSmsPollingMessage();
     }
@@ -1277,7 +1267,6 @@
     @Test
     public void testOnSatelliteModemStateChanged_onFirstConnected_sendsMtSmsPoll() {
         mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
-        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         // Set the following so shouldPollMtSms returns true
         mContextFixture.putBooleanResource(R.bool.config_enabled_mt_sms_polling, true);
         when(mMockSatelliteController.shouldSendSmsToDatagramDispatcher(any(Phone.class)))
@@ -1285,6 +1274,33 @@
 
         mDatagramDispatcherUT.onSatelliteModemStateChanged(
                 SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+        processAllMessages();
+
+        verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
+    }
+
+    @Test
+    public void testSendsMtSmsPoll_P2PSmsAllowed() {
+        mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+        mContextFixture.putBooleanResource(R.bool.config_enabled_mt_sms_polling, true);
+        when(mMockSatelliteController.shouldSendSmsToDatagramDispatcher(any(Phone.class)))
+                .thenReturn(true);
+
+        // Set P2P SMS disallowed
+        when(mMockSatelliteController.isP2PSmsDisallowedOnCarrierRoamingNtn(anyInt()))
+                .thenReturn(true);
+        mDatagramDispatcherUT.onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+        processAllMessages();
+
+        verify(mMockSmsDispatchersController, times(0)).sendMtSmsPollingMessage();
+
+        // Set P2P SMS allowed
+        when(mMockSatelliteController.isP2PSmsDisallowedOnCarrierRoamingNtn(anyInt()))
+                .thenReturn(false);
+        mDatagramDispatcherUT.onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+        processAllMessages();
 
         verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
     }
@@ -1300,6 +1316,8 @@
         mContextFixture.putBooleanResource(R.bool.config_enabled_mt_sms_polling, true);
         when(mMockSatelliteController.shouldSendSmsToDatagramDispatcher(any(Phone.class)))
                 .thenReturn(true);
+        when(mMockSatelliteController.isP2PSmsDisallowedOnCarrierRoamingNtn(anyInt()))
+                .thenReturn(false);
         // This will trigger mShouldPollMtSms = shouldPollMtSms
         setModemState(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
     }
@@ -1317,8 +1335,7 @@
         args.arg2 = pendingRequest.uniqueMessageId;
         args.arg3 = true;
         // EVENT_SEND_SMS_DONE to trigger handleEventSendSmsDone which will start the throttle
-        mDatagramDispatcherUT.handleMessage(
-                mDatagramDispatcherUT.obtainMessage(9 /*EVENT_SEND_SMS_DONE*/, args));
+        mDatagramDispatcherUT.obtainMessage(9 /*EVENT_SEND_SMS_DONE*/, args).sendToTarget();
     }
 
     private boolean waitForIntegerConsumerResult(int expectedNumberOfEvents) {
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 a1f63d0..b72cff8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
@@ -38,7 +38,6 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
@@ -130,7 +129,6 @@
         replaceInstance(SessionMetricsStats.class, "sInstance", null,
                 mMockSessionMetricsStats);
 
-        when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
         mDatagramReceiverUT = DatagramReceiver.make(mContext, Looper.myLooper(), mFeatureFlags,
                 mMockDatagramController);
         mTestDemoModeDatagramReceiver = new TestDatagramReceiver(mContext, Looper.myLooper(),
@@ -191,7 +189,7 @@
                 eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT), eq(0),
                 eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
         mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(eq(false));
-        verifyZeroInteractions(mMockSatelliteModemInterface);
+        verifyNoMoreInteractions(mMockSatelliteModemInterface);
         assertTrue(mDatagramReceiverUT.isDatagramWaitForConnectedStateTimerStarted());
 
         doReturn(false).when(mMockDatagramController)
@@ -221,7 +219,7 @@
         mInOrder.verify(mMockDatagramController)
                 .needsWaitingForSatelliteConnected(eq(SatelliteManager.DATAGRAM_TYPE_UNKNOWN));
         mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(eq(false));
-        verifyZeroInteractions(mMockSatelliteModemInterface);
+        verifyNoMoreInteractions(mMockSatelliteModemInterface);
         assertTrue(mDatagramReceiverUT.isDatagramWaitForConnectedStateTimerStarted());
 
         moveTimeForward(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
@@ -234,7 +232,7 @@
                 eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE),
                 eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
                 eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
-        verifyZeroInteractions(mMockSatelliteModemInterface);
+        verifyNoMoreInteractions(mMockSatelliteModemInterface);
         assertEquals(1, mResultListener.size());
         assertThat(mResultListener.peek()).isEqualTo(
                 SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
@@ -245,7 +243,7 @@
         mDatagramReceiverUT.onSatelliteModemStateChanged(
                 SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
         processAllMessages();
-        verifyZeroInteractions(mMockSatelliteModemInterface);
+        verifyNoMoreInteractions(mMockSatelliteModemInterface);
         assertEquals(0, mResultListener.size());
     }
 
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 a228617..93af153 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/PointingAppControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/PointingAppControllerTest.java
@@ -101,7 +101,6 @@
         super.setUp(getClass().getSimpleName());
         MockitoAnnotations.initMocks(this);
         logd(TAG + " Setup!");
-        when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
         mInOrderForPointingUi = inOrder(mContext);
         replaceInstance(SatelliteModemInterface.class, "sInstance", null,
                 mMockSatelliteModemInterface);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteConfigParserTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteConfigParserTest.java
index 7b4cf8d..62181bd 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteConfigParserTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteConfigParserTest.java
@@ -23,15 +23,21 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 
+import android.content.Context;
 import android.testing.AndroidTestingRunner;
 
+import androidx.test.InstrumentationRegistry;
+
 import com.android.internal.telephony.TelephonyTest;
 
+import com.google.protobuf.ByteString;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -39,8 +45,10 @@
 import org.mockito.MockitoAnnotations;
 
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.Base64;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -49,38 +57,68 @@
 import java.util.Set;
 
 @RunWith(AndroidTestingRunner.class)
-
 public class SatelliteConfigParserTest extends TelephonyTest {
-
-    /**
-     * satelliteConfigBuilder.setVersion(4);
-     *
-     * carrierSupportedSatelliteServiceBuilder.setCarrierId(1);
-     *
-     * satelliteProviderCapabilityBuilder.setCarrierPlmn("310160");
-     * satelliteProviderCapabilityBuilder.addAllowedServices(1);
-     * satelliteProviderCapabilityBuilder.addAllowedServices(2);
-     * satelliteProviderCapabilityBuilder.addAllowedServices(3);
-     *
-     * satelliteProviderCapabilityBuilder.setCarrierPlmn("310220");
-     * satelliteProviderCapabilityBuilder.addAllowedServices(3);
-     *
-     * String test = "0123456789";
-     * bigString.append(test.repeat(1));
-     * satelliteRegionBuilder.setS2CellFile(ByteString.copyFrom(bigString.toString().getBytes()));
-     * satelliteRegionBuilder.addCountryCodes("US");
-     * satelliteRegionBuilder.setIsAllowed(true);
-     */
-    private String mBase64StrForPBByteArray =
-            "CjYIBBIeCAESDgoGMzEwMTYwEAEQAhADEgoKBjMxMDIyMBADGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
-    private byte[] mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
-
+    private byte[] mBytesProtoBuffer;
 
     @Before
     public void setUp() throws Exception {
         super.setUp(getClass().getSimpleName());
         MockitoAnnotations.initMocks(this);
         logd(TAG + " Setup!");
+
+        SatelliteConfigData.TelephonyConfigProto.Builder telephonyConfigBuilder =
+                SatelliteConfigData.TelephonyConfigProto.newBuilder();
+        SatelliteConfigData.SatelliteConfigProto.Builder satelliteConfigBuilder =
+                SatelliteConfigData.SatelliteConfigProto.newBuilder();
+
+        // version
+        satelliteConfigBuilder.setVersion(4);
+
+        // carriersupportedservices
+        SatelliteConfigData.CarrierSupportedSatelliteServicesProto.Builder
+                carrierSupportedSatelliteServiceBuilder =
+                        SatelliteConfigData.CarrierSupportedSatelliteServicesProto.newBuilder();
+
+        // carriersupportedservices#carrier_id
+        carrierSupportedSatelliteServiceBuilder.setCarrierId(1);
+
+        // carriersupportedservices#providercapability
+        SatelliteConfigData.SatelliteProviderCapabilityProto.Builder
+                satelliteProviderCapabilityBuilder =
+                        SatelliteConfigData.SatelliteProviderCapabilityProto.newBuilder();
+        satelliteProviderCapabilityBuilder.setCarrierPlmn("310160");
+        satelliteProviderCapabilityBuilder.addAllowedServices(1);
+        satelliteProviderCapabilityBuilder.addAllowedServices(2);
+        satelliteProviderCapabilityBuilder.addAllowedServices(3);
+        carrierSupportedSatelliteServiceBuilder.addSupportedSatelliteProviderCapabilities(
+                satelliteProviderCapabilityBuilder);
+        satelliteProviderCapabilityBuilder.clear();
+
+        satelliteProviderCapabilityBuilder.setCarrierPlmn("310220");
+        satelliteProviderCapabilityBuilder.addAllowedServices(3);
+        carrierSupportedSatelliteServiceBuilder.addSupportedSatelliteProviderCapabilities(
+                satelliteProviderCapabilityBuilder);
+        satelliteProviderCapabilityBuilder.clear();
+
+        satelliteConfigBuilder.addCarrierSupportedSatelliteServices(
+                carrierSupportedSatelliteServiceBuilder);
+
+        // satelliteregion
+        SatelliteConfigData.SatelliteRegionProto.Builder satelliteRegionBuilder =
+                SatelliteConfigData.SatelliteRegionProto.newBuilder();
+        String testS2Content = "0123456789", testSatelliteAccessConfigContent = "sac";
+        satelliteRegionBuilder.setS2CellFile(ByteString.copyFrom(testS2Content.getBytes()));
+        satelliteRegionBuilder.setSatelliteAccessConfigFile(
+                ByteString.copyFrom(testSatelliteAccessConfigContent.getBytes()));
+        satelliteRegionBuilder.addCountryCodes("US");
+        satelliteRegionBuilder.setIsAllowed(true);
+        satelliteConfigBuilder.setDeviceSatelliteRegion(satelliteRegionBuilder);
+
+        telephonyConfigBuilder.setSatellite(satelliteConfigBuilder);
+
+        SatelliteConfigData.TelephonyConfigProto telephonyConfigData =
+                telephonyConfigBuilder.build();
+        mBytesProtoBuffer = telephonyConfigData.toByteArray();
     }
 
     @After
@@ -187,25 +225,61 @@
         assertNotNull(spySatelliteConfigParserNull);
         assertNull(spySatelliteConfigParserNull.getConfig());
 
-        SatelliteConfigParser spySatelliteConfigParserPlaceholder = spy(
-                new SatelliteConfigParser("test".getBytes()));
+        SatelliteConfigParser spySatelliteConfigParserPlaceholder =
+                spy(new SatelliteConfigParser("test".getBytes()));
         assertNotNull(spySatelliteConfigParserPlaceholder);
         assertNull(spySatelliteConfigParserPlaceholder.getConfig());
 
         SatelliteConfigParser spySatelliteConfigParser =
                 spy(new SatelliteConfigParser(mBytesProtoBuffer));
         assertNotNull(spySatelliteConfigParser.getConfig());
-        assertFalse(spySatelliteConfigParser.getConfig().isFileExist(null));
 
         SatelliteConfig mockedSatelliteConfig = mock(SatelliteConfig.class);
         File mMockSatS2File = mock(File.class);
         doReturn(mMockSatS2File).when(mockedSatelliteConfig).getSatelliteS2CellFile(any());
         doReturn(mockedSatelliteConfig).when(spySatelliteConfigParser).getConfig();
-        assertEquals(mMockSatS2File,
+        assertEquals(
+                mMockSatS2File,
                 spySatelliteConfigParser.getConfig().getSatelliteS2CellFile(mContext));
     }
 
     @Test
+    public void testSatelliteS2FileParsing() {
+        SatelliteConfigParser satelliteConfigParser = new SatelliteConfigParser(mBytesProtoBuffer);
+        assertNotNull(satelliteConfigParser);
+        assertNotNull(satelliteConfigParser.getConfig());
+
+        Context instrumentationContext = InstrumentationRegistry.getContext();
+        File actualS2File =
+                satelliteConfigParser.getConfig().getSatelliteS2CellFile(instrumentationContext);
+        logd("actualS2File's path: " + actualS2File.getAbsolutePath());
+        assertNotNull(actualS2File);
+        assertTrue(actualS2File.exists());
+
+        // Verify the content of actualS2File
+        InputStream inputStream = null;
+        try {
+            inputStream = new FileInputStream(actualS2File);
+            byte[] buffer = new byte[inputStream.available()];
+            inputStream.read(buffer);
+            String actualS2FileContent = new String(buffer);
+            assertNotNull(actualS2FileContent);
+            assertFalse(actualS2FileContent.isEmpty());
+            assertEquals("0123456789", actualS2FileContent);
+        } catch (IOException e) {
+            fail("Failed to read file content: " + e.getMessage());
+        } finally {
+            try {
+                if (inputStream != null) {
+                    inputStream.close();
+                }
+            } catch (IOException e) {
+                fail("Failed to close input stream: " + e.getMessage());
+            }
+        }
+    }
+
+    @Test
     public void testGetSatelliteAccessAllow() {
         SatelliteConfigParser satelliteConfigParserNull = new SatelliteConfigParser((byte[]) null);
         assertNotNull(satelliteConfigParserNull);
@@ -221,4 +295,88 @@
         assertNotNull(satelliteConfigParser.getConfig());
         assertTrue(satelliteConfigParser.getConfig().isSatelliteDataForAllowedRegion());
     }
+
+    @Test
+    public void testGetSatelliteAccessConfigJsonFile() {
+        SatelliteConfigParser spySatelliteConfigParserNull =
+                spy(new SatelliteConfigParser((byte[]) null));
+        assertNotNull(spySatelliteConfigParserNull);
+        assertNull(spySatelliteConfigParserNull.getConfig());
+
+        SatelliteConfigParser spySatelliteConfigParserPlaceholder =
+                spy(new SatelliteConfigParser("test".getBytes()));
+        assertNotNull(spySatelliteConfigParserPlaceholder);
+        assertNull(spySatelliteConfigParserPlaceholder.getConfig());
+
+        SatelliteConfigParser spySatelliteConfigParser =
+                spy(new SatelliteConfigParser(mBytesProtoBuffer));
+        assertNotNull(spySatelliteConfigParser.getConfig());
+
+        SatelliteConfig mockedSatelliteConfig = mock(SatelliteConfig.class);
+        File mMockSatelliteAccessConfigFile = mock(File.class);
+        doReturn(mMockSatelliteAccessConfigFile)
+                .when(mockedSatelliteConfig)
+                .getSatelliteAccessConfigJsonFile(any());
+        doReturn(mockedSatelliteConfig).when(spySatelliteConfigParser).getConfig();
+        assertEquals(
+                mMockSatelliteAccessConfigFile,
+                spySatelliteConfigParser.getConfig().getSatelliteAccessConfigJsonFile(mContext));
+    }
+
+    @Test
+    public void testSatelliteAccessConfigJsonFileParsing() {
+        SatelliteConfigParser satelliteConfigParser = new SatelliteConfigParser(mBytesProtoBuffer);
+        assertNotNull(satelliteConfigParser);
+        assertNotNull(satelliteConfigParser.getConfig());
+
+        Context instrumentationContext = InstrumentationRegistry.getContext();
+        File actualSatelliteAccessConfigFile =
+                satelliteConfigParser
+                        .getConfig()
+                        .getSatelliteAccessConfigJsonFile(instrumentationContext);
+        logd(
+                "actualSatelliteAccessConfigFile's path: "
+                        + actualSatelliteAccessConfigFile.getAbsolutePath());
+        assertNotNull(actualSatelliteAccessConfigFile);
+        assertTrue(actualSatelliteAccessConfigFile.exists());
+
+        // Verify the content of actualSatelliteAccessConfigFile
+        InputStream inputStream = null;
+        try {
+            inputStream = new FileInputStream(actualSatelliteAccessConfigFile);
+            byte[] buffer = new byte[inputStream.available()];
+            inputStream.read(buffer);
+            String actualSatelliteAccessConfigFileContent = new String(buffer);
+            assertNotNull(actualSatelliteAccessConfigFileContent);
+            assertFalse(actualSatelliteAccessConfigFileContent.isEmpty());
+            assertEquals("sac", actualSatelliteAccessConfigFileContent);
+        } catch (IOException e) {
+            fail("Failed to read file content: " + e.getMessage());
+        } finally {
+            try {
+                if (inputStream != null) {
+                    inputStream.close();
+                }
+            } catch (IOException e) {
+                fail("Failed to close input stream: " + e.getMessage());
+            }
+        }
+    }
+
+    @Test
+    public void testGetSatelliteConfigVersion() {
+        SatelliteConfigParser satelliteConfigParserNull = new SatelliteConfigParser((byte[]) null);
+        assertNotNull(satelliteConfigParserNull);
+        assertNull(satelliteConfigParserNull.getConfig());
+
+        SatelliteConfigParser satelliteConfigParserPlaceholder =
+                new SatelliteConfigParser("test".getBytes());
+        assertNotNull(satelliteConfigParserPlaceholder);
+        assertNull(satelliteConfigParserPlaceholder.getConfig());
+
+        SatelliteConfigParser satelliteConfigParser = new SatelliteConfigParser(mBytesProtoBuffer);
+        assertNotNull(satelliteConfigParser);
+        assertNotNull(satelliteConfigParser.getConfig());
+        assertEquals(4, satelliteConfigParser.getConfig().getSatelliteConfigDataVersion());
+    }
 }
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 d142386..7bdb3d2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -35,7 +35,9 @@
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL;
 import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL;
 import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED;
+import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED;
 import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_MMS;
 import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS;
 import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_VOICE;
 import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS;
@@ -73,7 +75,6 @@
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
-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_NOT_SUPPORTED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NO_RESOURCES;
@@ -106,7 +107,6 @@
 import static org.mockito.ArgumentMatchers.anyList;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.anyVararg;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.clearInvocations;
@@ -118,12 +118,12 @@
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.NotificationManager;
+import android.app.usage.NetworkStatsManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -133,6 +133,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.hardware.devicestate.DeviceState;
+import android.location.LocationManager;
 import android.net.Uri;
 import android.os.AsyncResult;
 import android.os.Bundle;
@@ -164,7 +165,6 @@
 import android.telephony.satellite.ISatelliteDatagramCallback;
 import android.telephony.satellite.ISatelliteModemStateCallback;
 import android.telephony.satellite.ISatelliteProvisionStateCallback;
-import android.telephony.satellite.ISatelliteSupportedStateCallback;
 import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
 import android.telephony.satellite.ISelectedNbIotSatelliteSubscriptionCallback;
 import android.telephony.satellite.NtnSignalStrength;
@@ -187,6 +187,7 @@
 import android.util.SparseBooleanArray;
 
 import com.android.internal.R;
+import com.android.internal.telephony.IBooleanConsumer;
 import com.android.internal.telephony.IIntegerConsumer;
 import com.android.internal.telephony.IVoidConsumer;
 import com.android.internal.telephony.Phone;
@@ -207,6 +208,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatchers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -246,6 +248,8 @@
             (int) TimeUnit.SECONDS.toMillis(60);
     private static final int TEST_WAIT_FOR_CELLULAR_MODEM_OFF_TIMEOUT_MILLIS =
             (int) TimeUnit.SECONDS.toMillis(60);
+    private static final Set<String> TEST_ALL_SATELLITE_PLMN_SET = new HashSet<>(
+            Arrays.asList("310830", "313210"));
 
 
     private static final String SATELLITE_PLMN = "00103";
@@ -260,7 +264,7 @@
     private SubscriptionInfo testSubscriptionInfo;
     private SubscriptionInfo testSubscriptionInfo2;
 
-    @Mock private SatelliteController mMockSatelliteController;
+    @Mock private TestSatelliteController mMockSatelliteController;
     @Mock private DatagramController mMockDatagramController;
     @Mock private SatelliteModemInterface mMockSatelliteModemInterface;
     @Mock private SatelliteSessionController mMockSatelliteSessionController;
@@ -283,6 +287,7 @@
     @Mock private SubscriptionManager mSubscriptionManager;
     @Mock private SubscriptionInfo mSubscriptionInfo;
     @Mock private PackageManager mMockPManager;
+    @Mock private Intent mMockLocationIntent;
 
     private Semaphore mIIntegerConsumerSemaphore = new Semaphore(0);
     private IIntegerConsumer mIIntegerConsumer = new IIntegerConsumer.Stub() {
@@ -612,14 +617,22 @@
                 SATELLITE_RESULT_REQUEST_ABORTED);
         mServiceState2 = mock(ServiceState.class);
         when(mPhone.getServiceState()).thenReturn(mServiceState);
-        when(mPhone.getSubId()).thenReturn(SUB_ID);
+        doReturn(SUB_ID).when(mPhone).getSubId();
         when(mPhone.getPhoneId()).thenReturn(0);
         when(mPhone.getSignalStrengthController()).thenReturn(mSignalStrengthController);
         when(mPhone2.getServiceState()).thenReturn(mServiceState2);
-        when(mPhone2.getSubId()).thenReturn(SUB_ID1);
+        doReturn(SUB_ID1).when(mPhone2).getSubId();
         when(mPhone2.getPhoneId()).thenReturn(1);
         when(mPhone2.getSignalStrengthController()).thenReturn(mSignalStrengthController);
 
+        doReturn(Context.NETWORK_STATS_SERVICE).when(mContext).getSystemServiceName(
+                NetworkStatsManager.class);
+        doReturn(mStatsManager).when(mContext).getSystemService(Context.NETWORK_STATS_SERVICE);
+        if (mContext.getSystemService(NetworkStatsManager.class) == null) {
+            // Test is using mockito-extended
+            doReturn(mStatsManager).when(mContext).getSystemService(NetworkStatsManager.class);
+        }
+
         mContextFixture.putStringArrayResource(
                 R.array.config_satellite_providers,
                 EMPTY_STRING_ARRAY);
@@ -632,11 +645,13 @@
         mContextFixture.putIntArrayResource(
                 R.array.config_foldedDeviceStates,
                 new int[0]);
+        mContextFixture.putBooleanResource(
+            R.bool.config_support_disable_satellite_while_enable_in_progress, true);
         doReturn(ACTIVE_SUB_IDS).when(mMockSubscriptionManagerService).getActiveSubIdList(true);
 
         mCarrierConfigBundle = mContextFixture.getCarrierConfigBundle();
         doReturn(mCarrierConfigBundle)
-                .when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyVararg());
+                .when(mCarrierConfigManager).getConfigForSubId(anyInt(), any());
         doAnswer(invocation -> {
             Executor executor = invocation.getArgument(0);
             CarrierConfigManager.CarrierConfigChangeListener listener = invocation.getArgument(1);
@@ -693,7 +708,6 @@
                 .setIsNtnOnlyCarrier(anyBoolean());
         doNothing().when(mMockProvisionMetricsStats).reportProvisionMetrics();
         doNothing().when(mMockControllerMetricsStats).reportDeprovisionCount(anyInt());
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         doReturn(mSST).when(mPhone).getServiceStateTracker();
         doReturn(mSST).when(mPhone2).getServiceStateTracker();
@@ -712,12 +726,12 @@
                 any(Handler.class),
                 eq(28) /* EVENT_SATELLITE_MODEM_STATE_CHANGED */,
                 eq(null));
-
         doReturn(mMockConfigParser).when(mMockTelephonyConfigUpdateInstallReceiver)
                 .getConfigParser(ConfigProviderAdaptor.DOMAIN_SATELLITE);
         doReturn(mSubscriptionInfo).when(mMockSubscriptionManagerService).getSubscriptionInfo(
                 anyInt());
         doReturn("").when(mSubscriptionInfo).getIccId();
+        doReturn(TEST_ALL_SATELLITE_PLMN_SET).when(mMockSatelliteController).getAllPlmnSet();
     }
 
     @After
@@ -965,7 +979,6 @@
 
     @Test
     public void testRadioPowerOff() {
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         NetworkRegistrationInfo satelliteNri = new NetworkRegistrationInfo.Builder()
                 .setIsNonTerrestrialNetwork(true)
                 .setAvailableServices(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA))
@@ -999,6 +1012,7 @@
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         when(mFeatureFlags.satelliteStateChangeListener()).thenReturn(true);
         mIsSatelliteEnabledSemaphore.drainPermits();
+        mSatelliteControllerUT.handleSatelliteAccessAllowedStateChanged(true);
 
         // Fail to enable satellite when SatelliteController is not fully loaded yet.
         mIIntegerConsumerResults.clear();
@@ -1312,16 +1326,11 @@
         mSatelliteControllerUT.allRadiosDisabled = true;
 
         resetSatelliteControllerUTToOnAndProvisionedState();
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
         mSatelliteControllerUT.onSetCellularRadioPowerStateRequested(false);
         processAllMessages();
-        // Satellite should not be powered off since the feature flag oemEnabledSatelliteFlag is
-        // disabled
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
 
         // Successfully disable satellite.
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         mIIntegerConsumerResults.clear();
         mIIntegerConsumerSemaphore.drainPermits();
         setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
@@ -2081,14 +2090,6 @@
 
     @Test
     public void testSupportedSatelliteServices() throws Exception {
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
-        List<String> satellitePlmnList = mSatelliteControllerUT.getSatellitePlmnsForCarrier(
-                SUB_ID);
-        assertEquals(EMPTY_STRING_ARRAY.length, satellitePlmnList.size());
-        List<Integer> supportedSatelliteServices =
-                mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(SUB_ID, "00101");
-        assertTrue(supportedSatelliteServices.isEmpty());
-
         String[] satelliteProviderStrArray = {"00101", "00102"};
         mContextFixture.putStringArrayResource(
                 R.array.config_satellite_providers, satelliteProviderStrArray);
@@ -2110,39 +2111,6 @@
         TestSatelliteController testSatelliteController =
                 new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
 
-        satellitePlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
-        assertTrue(satellitePlmnList.isEmpty());
-        supportedSatelliteServices =
-                testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00101");
-        assertTrue(supportedSatelliteServices.isEmpty());
-
-        // Add entitlement provided PLMNs.
-        setEntitlementPlmnList(testSatelliteController, SUB_ID,
-                Arrays.asList("00102", "00104", "00105"));
-        // Carrier config changed with carrierEnabledSatelliteFlag disabled
-        for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
-                : mCarrierConfigChangedListenerList) {
-            pair.first.execute(() -> pair.second.onCarrierConfigChanged(
-                    /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
-            );
-        }
-        processAllMessages();
-
-        supportedSatelliteServices =
-                testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
-        assertTrue(supportedSatelliteServices.isEmpty());
-        supportedSatelliteServices =
-                testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
-        assertTrue(supportedSatelliteServices.isEmpty());
-        supportedSatelliteServices =
-                testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00104");
-        assertTrue(supportedSatelliteServices.isEmpty());
-        supportedSatelliteServices =
-                testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00105");
-        assertTrue(supportedSatelliteServices.isEmpty());
-
-        // Trigger carrier config changed with carrierEnabledSatelliteFlag enabled
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
                 true);
         for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
@@ -2153,35 +2121,31 @@
         }
         processAllMessages();
 
-        satellitePlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
-        assertTrue(Arrays.equals(
-                expectedSupportedSatellitePlmns, satellitePlmnList.stream().toArray()));
-        supportedSatelliteServices =
+        List<String> satellitePlmnList = testSatelliteController.getSatellitePlmnsForCarrier(
+                SUB_ID);
+        assertArrayEquals(expectedSupportedSatellitePlmns, satellitePlmnList.stream().toArray());
+        List<Integer> supportedSatelliteServices =
                 mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
         // "00101" should return carrier config assigned value, though it is in allowed list.
-        assertTrue(Arrays.equals(expectedSupportedServices2,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
+        assertArrayEquals(expectedSupportedServices2, supportedSatelliteServices.stream()
+                .mapToInt(Integer::intValue)
+                .toArray());
         supportedSatelliteServices =
                 mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
-        assertTrue(Arrays.equals(expectedSupportedServices3,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
+        assertArrayEquals(expectedSupportedServices3, supportedSatelliteServices.stream()
+                .mapToInt(Integer::intValue)
+                .toArray());
         // "00104", and "00105" should return default supported service.
         supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00104");
-        assertTrue(Arrays.equals(defaultSupportedServices,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
+        assertArrayEquals(defaultSupportedServices, supportedSatelliteServices.stream()
+                .mapToInt(Integer::intValue)
+                .toArray());
         supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00105");
-        assertTrue(Arrays.equals(defaultSupportedServices,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
+        assertArrayEquals(defaultSupportedServices, supportedSatelliteServices.stream()
+                .mapToInt(Integer::intValue)
+                .toArray());
 
         // Subscriptions changed
         int[] newActiveSubIds = {SUB_ID1};
@@ -2199,64 +2163,55 @@
         // "00102" and "00103" should return default supported service for SUB_ID.
         supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
-        assertTrue(Arrays.equals(defaultSupportedServices,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
+        assertArrayEquals(defaultSupportedServices, supportedSatelliteServices.stream()
+                .mapToInt(Integer::intValue)
+                .toArray());
         supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
-        assertTrue(Arrays.equals(defaultSupportedServices,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
+        assertArrayEquals(defaultSupportedServices, supportedSatelliteServices.stream()
+                .mapToInt(Integer::intValue)
+                .toArray());
         // "00104", and "00105" should return default supported service for SUB_ID.
         supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00104");
-        assertTrue(Arrays.equals(defaultSupportedServices,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
+        assertArrayEquals(defaultSupportedServices, supportedSatelliteServices.stream()
+                .mapToInt(Integer::intValue)
+                .toArray());
         supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID, "00105");
-        assertTrue(Arrays.equals(defaultSupportedServices,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
+        assertArrayEquals(defaultSupportedServices, supportedSatelliteServices.stream()
+                .mapToInt(Integer::intValue)
+                .toArray());
 
         supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00102");
         assertNotNull(supportedSatelliteServices);
-        assertTrue(Arrays.equals(expectedSupportedServices2,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
+        assertArrayEquals(expectedSupportedServices2, supportedSatelliteServices.stream()
+                .mapToInt(Integer::intValue)
+                .toArray());
 
         supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00103");
-        assertTrue(Arrays.equals(expectedSupportedServices3,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
+        assertArrayEquals(expectedSupportedServices3, supportedSatelliteServices.stream()
+                .mapToInt(Integer::intValue)
+                .toArray());
         /* "00104", and "00105" should return default supported service. */
         supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00104");
-        assertTrue(Arrays.equals(defaultSupportedServices,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
+        assertArrayEquals(defaultSupportedServices, supportedSatelliteServices.stream()
+                .mapToInt(Integer::intValue)
+                .toArray());
         supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServicesForPlmn(SUB_ID1, "00105");
-        assertTrue(Arrays.equals(defaultSupportedServices,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
+        assertArrayEquals(defaultSupportedServices, supportedSatelliteServices.stream()
+                .mapToInt(Integer::intValue)
+                .toArray());
     }
 
     @Test
     public void testConfigureSatellitePlmnOnCarrierConfigChanged() {
         logd("testConfigureSatellitePlmnOnCarrierConfigChanged");
 
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
         String[] satelliteProviderStrArray =
                 {"00101", "00102", "00103", "00104", "00105"};
         List<String> satellitePlmnListFromOverlayConfig =
@@ -2273,7 +2228,7 @@
         processAllMessages();
         List<String> carrierPlmnList = testSatelliteController.getSatellitePlmnsForCarrier(
                 SUB_ID);
-        verify(mMockSatelliteModemInterface, never()).setSatellitePlmn(
+        verify(mPhone, never()).setSatellitePlmn(
                 anyInt(), anyList(), anyList(), any(Message.class));
         assertTrue(carrierPlmnList.isEmpty());
         reset(mMockSatelliteModemInterface);
@@ -2289,31 +2244,14 @@
         carrierSupportedSatelliteServicesPerProvider.putIntArray(
                 "00103", supportedServices3);
         List<String> expectedCarrierPlmnList = Arrays.asList("00102", "00103");
-        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
-                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
-                carrierSupportedSatelliteServicesPerProvider);
-        for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
-                : mCarrierConfigChangedListenerList) {
-            pair.first.execute(() -> pair.second.onCarrierConfigChanged(
-                    /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
-            );
-        }
-        processAllMessages();
-        carrierPlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
-        verify(mMockSatelliteModemInterface, never()).setSatellitePlmn(
-                anyInt(), anyList(), anyList(), any(Message.class));
-        assertTrue(carrierPlmnList.isEmpty());
-        reset(mMockSatelliteModemInterface);
 
-        // Reset TestSatelliteController so that device satellite PLMNs is loaded when
-        // carrierEnabledSatelliteFlag is enabled.
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         mCarrierConfigChangedListenerList.clear();
+        when(mPhone.getSignalStrengthController()).thenReturn(mSignalStrengthController);
+        when(mPhone.getDeviceStateMonitor()).thenReturn(mDeviceStateMonitor);
         testSatelliteController =
                 new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
 
-        // Trigger carrier config changed with carrierEnabledSatelliteFlag enabled and empty
-        // carrier supported satellite services.
+        // Trigger carrier config changed with empty carrier supported satellite services.
         mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
                         .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
                 new PersistableBundle());
@@ -2329,12 +2267,12 @@
         assertTrue(carrierPlmnList.isEmpty());
         List<String> allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
                 carrierPlmnList, satellitePlmnListFromOverlayConfig);
-        verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
+        verify(mPhone, times(1)).setSatellitePlmn(anyInt(),
                 eq(EMPTY_STRING_LIST), eq(allSatellitePlmnList), any(Message.class));
         reset(mMockSatelliteModemInterface);
+        reset(mPhone);
 
-        // Trigger carrier config changed with carrierEnabledSatelliteFlag enabled and non-empty
-        // carrier supported satellite services.
+        // Trigger carrier config changed with non-empty carrier supported satellite services.
         mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
                         .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
                 carrierSupportedSatelliteServicesPerProvider);
@@ -2349,11 +2287,12 @@
         allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
                 carrierPlmnList, satellitePlmnListFromOverlayConfig);
         assertEquals(expectedCarrierPlmnList, carrierPlmnList);
-        verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
+        verify(mPhone, times(1)).setSatellitePlmn(anyInt(),
                 eq(carrierPlmnList), eq(allSatellitePlmnList), any(Message.class));
         reset(mMockSatelliteModemInterface);
+        reset(mPhone);
 
-        /* setSatellitePlmn() is called regardless whether satellite attach for carrier is
+         /* setSatellitePlmn() is called regardless whether satellite attach for carrier is
            supported. */
         mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
                 false);
@@ -2364,14 +2303,18 @@
             );
         }
         processAllMessages();
-        verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
+        verify(mPhone, times(1)).setSatellitePlmn(anyInt(),
                 eq(carrierPlmnList), eq(allSatellitePlmnList), any(Message.class));
         reset(mMockSatelliteModemInterface);
+        reset(mPhone);
 
         // Test empty config_satellite_providers and empty carrier PLMN list
+        // allSatellitePlmnList is stored in shared preference, so plmns will not be removed
         mCarrierConfigChangedListenerList.clear();
         mContextFixture.putStringArrayResource(
                 R.array.config_satellite_providers, EMPTY_STRING_ARRAY);
+        when(mPhone.getSignalStrengthController()).thenReturn(mSignalStrengthController);
+        when(mPhone.getDeviceStateMonitor()).thenReturn(mDeviceStateMonitor);
         testSatelliteController =
                 new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
         mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
@@ -2386,14 +2329,14 @@
         processAllMessages();
         carrierPlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
         assertTrue(carrierPlmnList.isEmpty());
-        verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
-                eq(EMPTY_STRING_LIST), eq(EMPTY_STRING_LIST), any(Message.class));
+        verify(mPhone, times(1)).setSatellitePlmn(anyInt(),
+                eq(EMPTY_STRING_LIST), eq(allSatellitePlmnList), any(Message.class));
         reset(mMockSatelliteModemInterface);
+        reset(mPhone);
     }
 
     @Test
     public void testSatelliteCommunicationRestriction() {
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         mCarrierConfigBundle.putBoolean(
                 CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
         for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
@@ -2435,8 +2378,8 @@
                 SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, mIIntegerConsumer);
         processAllMessages();
         assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
-        verify(mMockSatelliteModemInterface, never())
-                .requestSetSatelliteEnabledForCarrier(anyInt(), anyBoolean(), any(Message.class));
+        verify(mPhone, never())
+                .setSatelliteEnabledForCarrier(anyInt(), anyBoolean(), any(Message.class));
         assertTrue(waitForIIntegerConsumerResult(1));
         restrictionSet =
                 mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
@@ -2455,8 +2398,8 @@
         restrictionSet =
                 mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
         assertTrue(!restrictionSet.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER));
-        verify(mMockSatelliteModemInterface, times(1))
-                .requestSetSatelliteEnabledForCarrier(anyInt(), anyBoolean(), any(Message.class));
+        verify(mPhone, times(1))
+                .setSatelliteEnabledForCarrier(anyInt(), anyBoolean(), any(Message.class));
 
         // Add satellite attach restriction reason by user
         mIIntegerConsumerResults.clear();
@@ -2471,12 +2414,13 @@
         restrictionSet =
                 mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
         assertTrue(restrictionSet.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER));
-        verify(mMockSatelliteModemInterface, times(1))
-                .requestSetSatelliteEnabledForCarrier(anyInt(), eq(false), any(Message.class));
+        verify(mPhone, times(1))
+                .setSatelliteEnabledForCarrier(anyInt(), eq(false), any(Message.class));
 
         // add satellite attach restriction reason by geolocation
         mIIntegerConsumerResults.clear();
         reset(mMockSatelliteModemInterface);
+        reset(mPhone);
         setUpResponseForRequestSetSatelliteEnabledForCarrier(false, SATELLITE_RESULT_SUCCESS);
         mSatelliteControllerUT.addAttachRestrictionForCarrier(SUB_ID,
                 SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION, mIIntegerConsumer);
@@ -2487,8 +2431,8 @@
         restrictionSet =
                 mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
         assertTrue(restrictionSet.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION));
-        verify(mMockSatelliteModemInterface, never())
-                .requestSetSatelliteEnabledForCarrier(anyInt(), anyBoolean(), any(Message.class));
+        verify(mPhone, never())
+                .setSatelliteEnabledForCarrier(anyInt(), anyBoolean(), any(Message.class));
 
         // remove satellite attach restriction reason by geolocation
         mIIntegerConsumerResults.clear();
@@ -2504,8 +2448,8 @@
                 mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
         assertTrue(!restrictionSet.contains(
                 SATELLITE_COMMUNICATION_RESTRICTION_REASON_GEOLOCATION));
-        verify(mMockSatelliteModemInterface, never())
-                .requestSetSatelliteEnabledForCarrier(anyInt(), anyBoolean(), any(Message.class));
+        verify(mPhone, never())
+                .setSatelliteEnabledForCarrier(anyInt(), anyBoolean(), any(Message.class));
 
         // remove satellite restriction reason by user
         mIIntegerConsumerResults.clear();
@@ -2520,33 +2464,9 @@
         restrictionSet =
                 mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
         assertTrue(!restrictionSet.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER));
-        verify(mMockSatelliteModemInterface, times(1))
-                .requestSetSatelliteEnabledForCarrier(anyInt(), eq(true), any(Message.class));
+        verify(mPhone, times(1))
+                .setSatelliteEnabledForCarrier(anyInt(), eq(true), any(Message.class));
         reset(mMockSatelliteModemInterface);
-
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
-
-        mIIntegerConsumerResults.clear();
-        mSatelliteControllerUT.removeAttachRestrictionForCarrier(SUB_ID,
-                SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, mIIntegerConsumer);
-        processAllMessages();
-        assertTrue(waitForIIntegerConsumerResult(1));
-        assertEquals(
-                SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, (long) mIIntegerConsumerResults.get(0));
-        verifyZeroInteractions(mMockSatelliteModemInterface);
-
-        mIIntegerConsumerResults.clear();
-        mSatelliteControllerUT.addAttachRestrictionForCarrier(SUB_ID,
-                SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, mIIntegerConsumer);
-        processAllMessages();
-        assertTrue(waitForIIntegerConsumerResult(1));
-        assertEquals(
-                SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, (long) mIIntegerConsumerResults.get(0));
-        verifyZeroInteractions(mMockSatelliteModemInterface);
-
-        Set<Integer> satelliteRestrictionReasons =
-                mSatelliteControllerUT.getAttachRestrictionReasonsForCarrier(SUB_ID);
-        assertTrue(satelliteRestrictionReasons.isEmpty());
     }
 
     @Test
@@ -2595,9 +2515,6 @@
                         satelliteController.getSupportedNtnRadioTechnology()));
         assertEquals(mQueriedSatelliteCapabilities.getMaxBytesPerOutgoingDatagram(), 255);
         assertTrue(satelliteController.isSatelliteAttachRequired());
-
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
-        assertFalse(satelliteController.isSatelliteAttachRequired());
     }
 
     @Test
@@ -2636,7 +2553,6 @@
 
     @Test
     public void testRequestNtnSignalStrengthWithFeatureFlagEnabled() {
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         resetSatelliteControllerUT();
 
         mRequestNtnSignalStrengthSemaphore.drainPermits();
@@ -2672,39 +2588,7 @@
     }
 
     @Test
-    public void testRequestNtnSignalStrengthWithFeatureFlagDisabled() {
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
-
-        resetSatelliteControllerUT();
-        mRequestNtnSignalStrengthSemaphore.drainPermits();
-        doReturn(false).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
-
-        @NtnSignalStrength.NtnSignalStrengthLevel int expectedLevel = NTN_SIGNAL_STRENGTH_GREAT;
-        setUpResponseForRequestNtnSignalStrength(expectedLevel, SATELLITE_RESULT_SUCCESS);
-        verifyRequestNtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE,
-                SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
-
-        doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
-        setUpResponseForRequestNtnSignalStrength(expectedLevel, SATELLITE_RESULT_SUCCESS);
-        verifyRequestNtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE,
-                SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
-
-        expectedLevel = NTN_SIGNAL_STRENGTH_POOR;
-        doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
-        setUpResponseForRequestNtnSignalStrength(expectedLevel, SATELLITE_RESULT_SUCCESS);
-        verifyRequestNtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE,
-                SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
-
-        doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
-        setUpResponseForRequestNtnSignalStrength(expectedLevel, SATELLITE_RESULT_MODEM_ERROR);
-        verifyRequestNtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE,
-                SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
-    }
-
-    @Test
     public void testRegisterForNtnSignalStrengthChangedWithFeatureFlagEnabled() {
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
-
         Semaphore semaphore = new Semaphore(0);
         final NtnSignalStrength[] signalStrength = new NtnSignalStrength[1];
         INtnSignalStrengthCallback callback =
@@ -2773,60 +2657,7 @@
     }
 
     @Test
-    public void testRegisterForNtnSignalStrengthChangedWithFeatureFlagDisabled() {
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
-
-        Semaphore semaphore = new Semaphore(0);
-        final NtnSignalStrength[] signalStrength = new NtnSignalStrength[1];
-        INtnSignalStrengthCallback callback =
-                new INtnSignalStrengthCallback.Stub() {
-                    @Override
-                    public void onNtnSignalStrengthChanged(NtnSignalStrength ntnSignalStrength) {
-                        logd("onNtnSignalStrengthChanged: ntnSignalStrength="
-                                + ntnSignalStrength);
-                        try {
-                            signalStrength[0] = ntnSignalStrength;
-                            semaphore.release();
-                        } catch (Exception ex) {
-                            loge("onNtnSignalStrengthChanged: Got exception in releasing "
-                                    + "semaphore, ex=" + ex);
-                        }
-                    }
-                };
-
-        verifyRegisterForNtnSignalStrengthChanged(SUB_ID, callback,
-                SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
-
-        setUpResponseForRequestIsSatelliteSupported(false,
-                SATELLITE_RESULT_SUCCESS);
-        verifySatelliteSupported(false, SATELLITE_RESULT_NOT_SUPPORTED);
-        verifyRegisterForNtnSignalStrengthChanged(SUB_ID, callback,
-                SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
-        setUpResponseForRequestNtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE,
-                SATELLITE_RESULT_SUCCESS);
-        verifyRequestNtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE,
-                SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
-
-        resetSatelliteControllerUT();
-        setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
-        verifySatelliteSupported(false, SATELLITE_RESULT_NOT_SUPPORTED);
-        verifyRegisterForNtnSignalStrengthChanged(SUB_ID, callback,
-                SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
-        verifyRequestNtnSignalStrength(NTN_SIGNAL_STRENGTH_NONE,
-                SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
-
-        @NtnSignalStrength.NtnSignalStrengthLevel int expectedNtnSignalStrengthLevel =
-                NTN_SIGNAL_STRENGTH_GOOD;
-        sendNtnSignalStrengthChangedEvent(expectedNtnSignalStrengthLevel, null);
-        processAllMessages();
-        assertTrue(waitForForEvents(
-                semaphore, 0, "testRegisterForNtnSignalStrengthChanged"));
-    }
-
-    @Test
     public void testSendingNtnSignalStrengthWithFeatureEnabled() {
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
-
         int expectedResult = SATELLITE_RESULT_SUCCESS;
         // startSendingNtnSignalStrength() is requested when screen on event comes.
         reset(mMockSatelliteModemInterface);
@@ -2929,41 +2760,7 @@
     }
 
     @Test
-    public void testSendingNtnSignalStrengthWithFeatureDisabled() {
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
-
-        int expectedResult = SATELLITE_RESULT_SUCCESS;
-        // startSendingNtnSignalStrength() is requested when screen on event comes.
-        reset(mMockSatelliteModemInterface);
-        doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
-        setUpResponseForRequestIsSatelliteSupported(true, expectedResult);
-        setUpResponseForRequestIsSatelliteProvisioned(true, expectedResult);
-        verifySatelliteSupported(false, SATELLITE_RESULT_NOT_SUPPORTED);
-        verifySatelliteProvisioned(false, SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
-        setUpResponseForStartSendingNtnSignalStrength(expectedResult);
-        sendCmdStartSendingNtnSignalStrengthChangedEvent(true);
-        processAllMessages();
-        verify(mMockSatelliteModemInterface, never())
-                .startSendingNtnSignalStrength(any(Message.class));
-
-        // stopSendingNtnSignalStrength() is requested when screen off event comes.
-        reset(mMockSatelliteModemInterface);
-        setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
-        setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
-        doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
-        setUpResponseForStopSendingNtnSignalStrength(expectedResult);
-        sendCmdStartSendingNtnSignalStrengthChangedEvent(false);
-        processAllMessages();
-        verify(mMockSatelliteModemInterface, never())
-                .stopSendingNtnSignalStrength(any(Message.class));
-    }
-
-    @Test
     public void testIsSatelliteSupportedViaCarrier() {
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
-        assertFalse(mSatelliteControllerUT.isSatelliteSupportedViaCarrier());
-
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         assertFalse(mSatelliteControllerUT.isSatelliteSupportedViaCarrier());
 
         mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
@@ -2979,13 +2776,8 @@
 
     @Test
     public void testCarrierEnabledSatelliteConnectionHysteresisTime() throws Exception {
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
-        assertFalse(mSatelliteControllerUT
-                        .isSatelliteConnectedViaCarrierWithinHysteresisTime().first);
-
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
         when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         mCarrierConfigBundle.putInt(KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT, 1 * 60);
         mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
         for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
@@ -3063,8 +2855,6 @@
 
     @Test
     public void testRegisterForSatelliteCapabilitiesChangedWithFeatureFlagEnabled() {
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
-
         Semaphore semaphore = new Semaphore(0);
         final SatelliteCapabilities[] satelliteCapabilities = new SatelliteCapabilities[1];
         ISatelliteCapabilitiesCallback callback =
@@ -3118,52 +2908,8 @@
     }
 
     @Test
-    public void testRegisterForSatelliteCapabilitiesChangedWithFeatureFlagDisabled() {
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
-
-        Semaphore semaphore = new Semaphore(0);
-        final SatelliteCapabilities[] satelliteCapabilities = new SatelliteCapabilities[1];
-        ISatelliteCapabilitiesCallback callback =
-                new ISatelliteCapabilitiesCallback.Stub() {
-                    @Override
-                    public void onSatelliteCapabilitiesChanged(SatelliteCapabilities capabilities) {
-                        logd("onSatelliteCapabilitiesChanged: " + capabilities);
-                        try {
-                            satelliteCapabilities[0] = capabilities;
-                            semaphore.release();
-                        } catch (Exception ex) {
-                            loge("onSatelliteCapabilitiesChanged: Got exception in releasing "
-                                    + "semaphore, ex=" + ex);
-                        }
-                    }
-                };
-
-        int errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(callback);
-        assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, errorCode);
-
-        setUpResponseForRequestIsSatelliteSupported(false,
-                SATELLITE_RESULT_SUCCESS);
-        verifySatelliteSupported(false, SATELLITE_RESULT_NOT_SUPPORTED);
-        errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(callback);
-        assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, errorCode);
-
-        resetSatelliteControllerUT();
-        setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
-        verifySatelliteSupported(false, SATELLITE_RESULT_NOT_SUPPORTED);
-        errorCode = mSatelliteControllerUT.registerForCapabilitiesChanged(callback);
-        assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, errorCode);
-
-        SatelliteCapabilities expectedCapabilities = mSatelliteCapabilities;
-        sendSatelliteCapabilitiesChangedEvent(expectedCapabilities, null);
-        processAllMessages();
-        assertTrue(waitForForEvents(
-                semaphore, 0, "testRegisterForSatelliteCapabilitiesChanged"));
-    }
-
-    @Test
     public void testSatelliteCommunicationRestrictionForEntitlement() throws Exception {
         logd("testSatelliteCommunicationRestrictionForEntitlement");
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
 
         mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
                 true);
@@ -3191,8 +2937,8 @@
 
         assertTrue(waitForIIntegerConsumerResult(1));
         assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
-        verify(mMockSatelliteModemInterface, times(1))
-                .requestSetSatelliteEnabledForCarrier(anyInt(), eq(true), any(Message.class));
+        verify(mPhone, times(1))
+                .setSatelliteEnabledForCarrier(anyInt(), eq(true), any(Message.class));
 
         // Verify call the requestSetSatelliteEnabledForCarrier to disable the satellite when
         // satellite service is disabled by entitlement server.
@@ -3212,15 +2958,14 @@
 
         assertTrue(waitForIIntegerConsumerResult(1));
         assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
-        verify(mMockSatelliteModemInterface, times(1))
-                .requestSetSatelliteEnabledForCarrier(anyInt(), eq(false), any(Message.class));
+        verify(mPhone, times(1))
+                .setSatelliteEnabledForCarrier(anyInt(), eq(false), any(Message.class));
     }
 
     @Test
     public void testPassSatellitePlmnToModemAfterUpdateSatelliteEntitlementStatus()
             throws Exception {
         logd("testPassSatellitePlmnToModemAfterUpdateSatelliteEntitlementStatus");
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
 
         replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
                 mSatelliteControllerUT, new SparseArray<>());
@@ -3258,6 +3003,7 @@
         // If the entitlement plmn list, the overlay config plmn list and the carrier plmn list
         // are available and the barred plmn list is empty, verify passing to the modem.
         reset(mMockSatelliteModemInterface);
+        reset(mPhone);
         Map<Integer, Map<String, Set<Integer>>>
                 satelliteServicesSupportedByCarriers = new HashMap<>();
         List<String> carrierConfigPlmnList = Arrays.stream(new String[]{"00105", "00106"}).toList();
@@ -3265,7 +3011,8 @@
         plmnAndService.put(carrierConfigPlmnList.get(0), new HashSet<>(Arrays.asList(3, 5)));
         plmnAndService.put(carrierConfigPlmnList.get(1), new HashSet<>(Arrays.asList(3)));
         satelliteServicesSupportedByCarriers.put(SUB_ID, plmnAndService);
-        replaceInstance(SatelliteController.class, "mSatelliteServicesSupportedByCarriers",
+        replaceInstance(SatelliteController.class,
+                "mSatelliteServicesSupportedByCarriersFromConfig",
                 mSatelliteControllerUT, satelliteServicesSupportedByCarriers);
         verifyPassingToModemAfterQueryCompleted(entitlementPlmnList, mergedPlmnList,
                 overlayConfigPlmnList, barredPlmnList);
@@ -3273,14 +3020,17 @@
         // If the entitlement plmn list is empty and the overlay config plmn list and the carrier
         // plmn list are available, verify passing to the modem.
         reset(mMockSatelliteModemInterface);
+        reset(mPhone);
         entitlementPlmnList = new ArrayList<>();
         mergedPlmnList = carrierConfigPlmnList;
         verifyPassingToModemAfterQueryCompleted(entitlementPlmnList, mergedPlmnList,
                 overlayConfigPlmnList, barredPlmnList);
 
+
         // If the entitlement plmn list is empty and the overlay config plmn list, the carrier
         // plmn list and the barred plmn list are available, verify passing to the modem.
         reset(mMockSatelliteModemInterface);
+        reset(mPhone);
         barredPlmnList = Arrays.stream(new String[]{"00105", "00107"}).toList();
         verifyPassingToModemAfterQueryCompleted(entitlementPlmnList, mergedPlmnList,
                 overlayConfigPlmnList, barredPlmnList);
@@ -3288,6 +3038,7 @@
         // If the entitlement plmn list is null and the overlay config plmn list and the carrier
         // plmn list are available, verify passing to the modem.
         reset(mMockSatelliteModemInterface);
+        reset(mPhone);
         entitlementPlmnList = null;
         mergedPlmnList = carrierConfigPlmnList;
         verifyPassingToModemAfterQueryCompleted(entitlementPlmnList, mergedPlmnList,
@@ -3295,6 +3046,7 @@
 
         // If the entitlement plmn list is invalid, verify not passing to the modem.
         reset(mMockSatelliteModemInterface);
+        reset(mPhone);
         entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", ""}).toList();
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
                 entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
@@ -3304,6 +3056,7 @@
 
         // If the entitlement plmn list is invalid, verify not passing to the modem.
         reset(mMockSatelliteModemInterface);
+        reset(mPhone);
         entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "123456789"}).toList();
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
                 entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
@@ -3313,6 +3066,7 @@
 
         // If the entitlement plmn list is invalid, verify not passing to the modem.
         reset(mMockSatelliteModemInterface);
+        reset(mPhone);
         entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "12"}).toList();
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
                 entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
@@ -3322,6 +3076,7 @@
 
         // If the entitlement plmn list is invalid, verify not passing to the modem.
         reset(mMockSatelliteModemInterface);
+        reset(mPhone);
         entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "1234"}).toList();
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
                 entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
@@ -3346,8 +3101,8 @@
         if (overlayConfigPlmnList.isEmpty()) {
             assertEquals(plmnListPerCarrier, allSatellitePlmnList);
         }
-        verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
-                eq(plmnListPerCarrier), eq(allSatellitePlmnList), any(Message.class));
+        verify(mPhone, times(1)).setSatellitePlmn(anyInt(),
+                eq(plmnListPerCarrier), anyList(), any(Message.class));
     }
 
     private void setConfigData(List<String> plmnList) {
@@ -3370,10 +3125,10 @@
     @Test
     public void testUpdateSupportedSatelliteServices() throws Exception {
         logd("testUpdateSupportedSatelliteServices");
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
                 mSatelliteControllerUT, new SparseArray<>());
-        replaceInstance(SatelliteController.class, "mSatelliteServicesSupportedByCarriers",
+        replaceInstance(SatelliteController.class,
+                "mSatelliteServicesSupportedByCarriersFromConfig",
                 mSatelliteControllerUT, new HashMap<>());
         List<Integer> servicesPerPlmn;
 
@@ -3491,7 +3246,6 @@
     @Test
     public void testUpdatePlmnListPerCarrier() throws Exception {
         logd("testUpdatePlmnListPerCarrier");
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
 
         replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
                 mSatelliteControllerUT, new SparseArray<>());
@@ -3550,7 +3304,6 @@
     @Test
     public void testEntitlementStatus() throws Exception {
         logd("testEntitlementStatus");
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         SparseBooleanArray satelliteEnabledPerCarrier = new SparseBooleanArray();
         replaceInstance(SatelliteController.class, "mSatelliteEntitlementStatusPerCarrier",
                 mSatelliteControllerUT, satelliteEnabledPerCarrier);
@@ -3583,7 +3336,6 @@
     @Test
     public void testUpdateRestrictReasonForEntitlementPerCarrier() throws Exception {
         logd("testUpdateRestrictReasonForEntitlementPerCarrier");
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
 
         // Verify that the entitlement restriction reason is added before the entitlement query,
         // When the Satellite entitlement status value read from DB is disabled.
@@ -3611,9 +3363,26 @@
     }
 
     @Test
+    public void testVerifyEntitlementDataInPersistenceMemory() throws Exception {
+        // When the entitlement data was not set, verify for not null and empty data sets.
+        assertEquals(new ArrayList<>(),
+                mMockSubscriptionManagerService.getSatelliteEntitlementBarredPlmnList(anyInt()));
+        assertEquals(new HashMap<>(),
+                mMockSubscriptionManagerService.getSatelliteEntitlementDataPlanForPlmns(anyInt()));
+        assertEquals(new HashMap<>(),
+                mMockSubscriptionManagerService.getSatelliteEntitlementPlmnServiceTypeMap(
+                        anyInt()));
+        assertEquals(new HashMap<>(),
+                mMockSubscriptionManagerService.getSatelliteEntitlementPlmnDataServicePolicy(
+                        anyInt()));
+        assertEquals(new HashMap<>(),
+                mMockSubscriptionManagerService.getSatelliteEntitlementPlmnVoiceServicePolicy(
+                        anyInt()));
+    }
+
+    @Test
     public void testUpdateEntitlementPlmnListPerCarrier() throws Exception {
         logd("testUpdateEntitlementPlmnListPerCarrier");
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
 
         // If the Satellite entitlement plmn list read from the DB is empty list and carrier
         // config plmn list also is empty , check whether an empty list is returned when calling
@@ -3622,7 +3391,8 @@
                 mMockSubscriptionManagerService).getSatelliteEntitlementPlmnList(anyInt());
         replaceInstance(SatelliteController.class, "mEntitlementPlmnListPerCarrier",
                 mSatelliteControllerUT, new SparseArray<>());
-        replaceInstance(SatelliteController.class, "mSatelliteServicesSupportedByCarriers",
+        replaceInstance(SatelliteController.class,
+                "mSatelliteServicesSupportedByCarriersFromConfig",
                 mSatelliteControllerUT, new HashMap<>());
         mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
                 true);
@@ -3708,7 +3478,6 @@
     public void testHandleEventServiceStateChanged() {
         mContextFixture.putBooleanResource(
             R.bool.config_satellite_should_notify_availability, true);
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
                 CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC);
@@ -3773,8 +3542,8 @@
                 enableSatelliteResponse.capture());
         SatelliteModemEnableRequestAttributes request = enableSatelliteRequest.getValue();
         assertTrue(request.isEnabled());
-        assertFalse(request.isDemoMode());
-        assertFalse(request.isEmergencyMode());
+        assertFalse(request.isForDemoMode());
+        assertFalse(request.isForEmergencyMode());
 
         clearInvocations(mMockSatelliteModemInterface);
         moveTimeForward(TEST_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMEOUT_MILLIS);
@@ -3835,11 +3604,10 @@
 
     @Test
     public void testUpdateNtnSignalStrentghReportWithFeatureFlagEnabled() {
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
-
         mIsSatelliteEnabledSemaphore.drainPermits();
         mIIntegerConsumerResults.clear();
         resetSatelliteControllerUT();
+        mSatelliteControllerUT.handleSatelliteAccessAllowedStateChanged(true);
 
         // Successfully provisioned
         reset(mMockSatelliteModemInterface);
@@ -3928,14 +3696,12 @@
 
     @Test
     public void testRegisterForSatelliteSupportedStateChanged_WithFeatureFlagEnabled() {
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
-
         Semaphore semaphore = new Semaphore(0);
         final boolean[] isSupported  = new boolean[1];
-        ISatelliteSupportedStateCallback callback =
-                new ISatelliteSupportedStateCallback.Stub() {
+        IBooleanConsumer callback =
+                new IBooleanConsumer.Stub() {
                     @Override
-                    public void onSatelliteSupportedStateChanged(boolean supported) {
+                    public void accept(boolean supported) {
                         logd("onSatelliteSupportedStateChanged: supported=" + supported);
                         isSupported[0] = supported;
                         try {
@@ -4020,29 +3786,6 @@
     }
 
     @Test
-    public void testRegisterForSatelliteSupportedStateChanged_WithFeatureFlagDisabled() {
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
-
-        Semaphore semaphore = new Semaphore(0);
-        ISatelliteSupportedStateCallback callback =
-                new ISatelliteSupportedStateCallback.Stub() {
-                    @Override
-                    public void onSatelliteSupportedStateChanged(boolean supported) {
-                        logd("onSatelliteSupportedStateChanged: supported=" + supported);
-                        try {
-                            semaphore.release();
-                        } catch (Exception ex) {
-                            loge("onSatelliteSupportedStateChanged: Got exception in releasing "
-                                    + "semaphore, ex=" + ex);
-                        }
-                    }
-                };
-        int errorCode = mSatelliteControllerUT.registerForSatelliteSupportedStateChanged(
-                callback);
-        assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, errorCode);
-    }
-
-    @Test
     public void testRegisterForSelectedNbIotSatelliteSubscriptionChanged_WithFeatureFlagEnabled() {
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
 
@@ -4134,12 +3877,7 @@
 
     @Test
     public void testIsSatelliteEmergencyMessagingSupportedViaCarrier() {
-        // Carrier-enabled flag is off
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
-        assertFalse(mSatelliteControllerUT.isSatelliteEmergencyMessagingSupportedViaCarrier());
-
-        // Carrier-enabled flag is on and satellite attach is not supported
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+        // Satellite attach is not supported
         assertFalse(mSatelliteControllerUT.isSatelliteEmergencyMessagingSupportedViaCarrier());
 
         // Trigger carrier config changed to enable satellite attach
@@ -4171,13 +3909,6 @@
 
     @Test
     public void testGetCarrierEmergencyCallWaitForConnectionTimeoutMillis() {
-        // Carrier-enabled flag is off
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
-        assertEquals(DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS,
-                mSatelliteControllerUT.getCarrierEmergencyCallWaitForConnectionTimeoutMillis());
-
-        // Carrier-enabled flag is on
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         assertEquals(DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS,
                 mSatelliteControllerUT.getCarrierEmergencyCallWaitForConnectionTimeoutMillis());
 
@@ -4192,7 +3923,7 @@
                 KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT,
                 timeoutMillisForCarrier1);
         doReturn(carrierConfigBundle1)
-                .when(mCarrierConfigManager).getConfigForSubId(eq(SUB_ID), anyVararg());
+                .when(mCarrierConfigManager).getConfigForSubId(eq(SUB_ID), any());
 
         int timeoutMillisForCarrier2 = 2000;
         PersistableBundle carrierConfigBundle2 = new PersistableBundle();
@@ -4204,7 +3935,7 @@
                 KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT,
                 timeoutMillisForCarrier2);
         doReturn(carrierConfigBundle2)
-                .when(mCarrierConfigManager).getConfigForSubId(eq(SUB_ID1), anyVararg());
+                .when(mCarrierConfigManager).getConfigForSubId(eq(SUB_ID1), any());
 
         for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
                 : mCarrierConfigChangedListenerList) {
@@ -4237,9 +3968,10 @@
         assertFalse(mSatelliteControllerUT.isCarrierRoamingNtnEligible(null));
 
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
         when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        when(mServiceState.getNetworkRegistrationInfo(anyInt(), anyInt())).thenReturn(null);
+        when(mServiceState2.getNetworkRegistrationInfo(anyInt(), anyInt())).thenReturn(null);
         mSatelliteControllerUT.mIsApplicationSupportsP2P = true;
         mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
         mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 1);
@@ -4301,9 +4033,10 @@
         mContextFixture.putBooleanResource(
             R.bool.config_satellite_should_notify_availability, true);
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        when(mServiceState.getNetworkRegistrationInfo(anyInt(), anyInt())).thenReturn(null);
+        when(mServiceState2.getNetworkRegistrationInfo(anyInt(), anyInt())).thenReturn(null);
         mSatelliteControllerUT.mIsApplicationSupportsP2P = true;
         mSatelliteControllerUT.setIsSatelliteSupported(true);
         mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
@@ -4344,6 +4077,7 @@
         // 2 minutes later and hysteresis timeout is 1 minute
         mSatelliteControllerUT.elapsedRealtime = 2 * 60 * 1000;
         moveTimeForward(2 * 60 * 1000);
+        mSatelliteControllerUT.selectedSatelliteSubId = SUB_ID1;
         processAllMessages();
         assertTrue(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
         verify(mPhone, times(1)).notifyCarrierRoamingNtnEligibleStateChanged(eq(true));
@@ -4363,7 +4097,6 @@
     @Test
     public void testNotifyCarrierRoamingNtnSignalStrengthChanged() {
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
 
         sendSignalStrengthChangedEvent(mPhone.getPhoneId());
         processAllMessages();
@@ -4617,7 +4350,6 @@
     @Test
     public void testRequestSatelliteSubscriberProvisionStatus() throws Exception {
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         verifyRequestSatelliteSubscriberProvisionStatus();
     }
 
@@ -4651,7 +4383,6 @@
     @Test
     public void testProvisionSatellite() throws Exception {
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         verifyRequestSatelliteSubscriberProvisionStatus();
         List<SatelliteSubscriberInfo> inputList = getExpectedSatelliteSubscriberInfoList();
         verifyProvisionSatellite(inputList);
@@ -4674,7 +4405,6 @@
     @Test
     public void testRegisterForSatelliteSubscriptionProvisionStateChanged() throws Exception {
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
 
         Semaphore semaphore = new Semaphore(0);
         SatelliteSubscriberProvisionStatus[] resultArray =
@@ -4817,7 +4547,6 @@
     @Test
     public void testDeprovisionSatellite() throws Exception {
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         verifyRequestSatelliteSubscriberProvisionStatus();
         List<SatelliteSubscriberInfo> inputList = getExpectedSatelliteSubscriberInfoList();
         verifyProvisionSatellite(inputList);
@@ -4893,16 +4622,18 @@
                 eq(R.string.config_satellite_gateway_service_package));
         doReturn("className").when(mResources).getString(
                 eq(R.string.config_satellite_carrier_roaming_esos_provisioned_class));
+        doReturn(true).when(mResources).getBoolean(
+                eq(R.bool.config_support_disable_satellite_while_enable_in_progress));
     }
 
     private List<SatelliteSubscriberInfo> getExpectedSatelliteSubscriberInfoList() {
         List<SatelliteSubscriberInfo> list = new ArrayList<>();
         list.add(new SatelliteSubscriberInfo.Builder().setSubscriberId(mSubscriberId).setCarrierId(
-                mCarrierId).setNiddApn(mNiddApn).setSubId(SUB_ID).setSubscriberIdType(
-                SatelliteSubscriberInfo.IMSI_MSISDN).build());
+                mCarrierId).setNiddApn(mNiddApn).setSubscriptionId(SUB_ID).setSubscriberIdType(
+                SatelliteSubscriberInfo.SUBSCRIBER_ID_TYPE_IMSI_MSISDN).build());
         list.add(new SatelliteSubscriberInfo.Builder().setSubscriberId(mSubscriberId2).setCarrierId(
-                mCarrierId).setNiddApn(mNiddApn).setSubId(SUB_ID1).setSubscriberIdType(
-                SatelliteSubscriberInfo.ICCID).build());
+                mCarrierId).setNiddApn(mNiddApn).setSubscriptionId(SUB_ID1).setSubscriberIdType(
+                SatelliteSubscriberInfo.SUBSCRIBER_ID_TYPE_ICCID).build());
         return list;
     }
 
@@ -5006,7 +4737,7 @@
     }
 
     @Test
-    public void testRegisterForSatelliteCommunicationAllowedStateChanged() throws Exception {
+    public void testRegisterForSatelliteCommunicationAccessStateChanged() throws Exception {
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         mContextFixture.putIntArrayResource(
                 R.array.config_verizon_satellite_enabled_tagids,
@@ -5038,7 +4769,7 @@
         setComponentName();
         mSatelliteControllerUT.setIsSatelliteAllowedState(true);
 
-        mSatelliteControllerUT.registerForSatelliteCommunicationAllowedStateChanged();
+        mSatelliteControllerUT.registerForSatelliteCommunicationAccessStateChanged();
 
         // Test satelliteAccessConfigCallback.onSuccess
         // with current location NOT supporting carrier satellite
@@ -5052,6 +4783,7 @@
                         getKeyPriority(testSubscriptionInfo2), k -> new ArrayList<>())
                 .add(testSubscriptionInfo2);
 
+        mSatelliteControllerUT.selectedSatelliteSubId = SUB_ID1;
         mSatelliteControllerUT.evaluateESOSProfilesPrioritizationTest();
         processAllMessages();
         assertEquals(oemSubId, mSatelliteControllerUT.getSelectedSatelliteSubId());
@@ -5068,6 +4800,7 @@
                         getKeyPriority(testSubscriptionInfo2), k -> new ArrayList<>())
                 .add(testSubscriptionInfo2);
 
+        mSatelliteControllerUT.selectedSatelliteSubId = SUB_ID;
         mSatelliteControllerUT.evaluateESOSProfilesPrioritizationTest();
         processAllMessages();
         assertEquals(carrierSubId, mSatelliteControllerUT.getSelectedSatelliteSubId());
@@ -5103,7 +4836,6 @@
     @Test
     public void testIsCarrierRoamingNtnAvailableServicesForManualConnect() {
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
         // CARRIER_ROAMING_NTN_CONNECT_MANUAL: 1
         mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 1);
@@ -5124,7 +4856,6 @@
     @Test
     public void testIsCarrierRoamingNtnAvailableServicesForAutomaticConnect() {
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
         // CARRIER_ROAMING_NTN_CONNECT_AUTOMATIC: 0
         mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 0);
@@ -5230,7 +4961,6 @@
 
     @Test
     public void testUpdateSystemSelectionChannels() {
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
 
         String mccmnc = "123455";
@@ -5555,8 +5285,8 @@
             AsyncResult.forMessage(message, null, exception);
             message.sendToTarget();
             return null;
-        }).when(mMockSatelliteModemInterface)
-                .requestSetSatelliteEnabledForCarrier(anyInt(), eq(enabled), any(Message.class));
+        }).when(mPhone)
+                .setSatelliteEnabledForCarrier(anyInt(), eq(enabled), any(Message.class));
     }
 
     private void setUpNoResponseForRequestSatelliteEnabled(boolean enabled, boolean demoMode,
@@ -5966,6 +5696,22 @@
                 61 /* CMD_EVALUATE_CARRIER_ROAMING_NTN_ELIGIBILITY_CHANGE */).sendToTarget();
     }
 
+    private void sendCmdGetSatelliteEnabledForCarrier(Phone phone) {
+        SatelliteController.SatelliteControllerHandlerRequest request =
+                new SatelliteController.SatelliteControllerHandlerRequest(null, phone);
+        Message msg = mSatelliteControllerUT.obtainMessage(
+                64 /* CMD_GET_SATELLITE_ENABLED_FOR_CARRIER */, request);
+        msg.sendToTarget();
+    }
+
+    private void sendEventGetSatelliteEnabledForCarrierDone(int subId, Boolean result,
+            Throwable exception) {
+        Message msg = mSatelliteControllerUT.obtainMessage(
+                65 /* EVENT_GET_SATELLITE_ENABLED_FOR_CARRIER_DONE */, subId);
+        msg.obj = new AsyncResult(subId, result, exception);
+        msg.sendToTarget();
+    }
+
     private void setRadioPower(boolean on) {
         mSimulatedCommands.setRadioPower(on, false, false, null);
     }
@@ -6168,7 +5914,7 @@
         }
     }
 
-    private class TestSatelliteController extends SatelliteController {
+    public class TestSatelliteController extends SatelliteController {
         public boolean setSettingsKeyForSatelliteModeCalled = false;
         public boolean allRadiosDisabled = true;
         public long elapsedRealtime = 0;
@@ -6181,9 +5927,13 @@
         public boolean mIsApplicationSupportsP2P = false;
         public int selectedSatelliteSubId = -1;
         public boolean isSatelliteProvisioned;
+
+        private boolean callOnlySuperMethod = false;
         public boolean isSatelliteEnabledOrBeingEnabled = false;
 
-        TestSatelliteController(
+        private boolean mLocationServiceEnabled = true;
+
+        public TestSatelliteController(
                 Context context, Looper looper, @NonNull FeatureFlags featureFlags) {
             super(context, looper, featureFlags);
             logd("Constructing TestSatelliteController");
@@ -6227,8 +5977,8 @@
         }
 
         @Override
-        protected void registerForSatelliteCommunicationAllowedStateChanged() {
-            logd("registerForSatelliteCommunicationAllowedStateChanged");
+        protected void registerForSatelliteCommunicationAccessStateChanged() {
+            logd("registerForSatelliteCommunicationAccessStateChanged");
         }
 
         void setSatelliteSessionController(SatelliteSessionController satelliteSessionController) {
@@ -6279,7 +6029,11 @@
 
         @Override
         protected void handleCarrierRoamingNtnAvailableServicesChanged(int subId) {
-            isApplicationUpdated = true;
+            if (callOnlySuperMethod) {
+                super.handleCarrierRoamingNtnAvailableServicesChanged(subId);
+            } else {
+                isApplicationUpdated = true;
+            }
         }
 
         @Override
@@ -6289,9 +6043,26 @@
 
         @Override
         public int[] getSupportedServicesOnCarrierRoamingNtn(int subId) {
+            if (callOnlySuperMethod) {
+                return super.getSupportedServicesOnCarrierRoamingNtn(subId);
+            }
             return new int[]{3, 5};
         }
 
+        @Override
+        public int getSelectedSatelliteSubId() {
+            return selectedSatelliteSubId;
+        }
+
+        @Override
+        protected boolean isLocationServiceEnabled() {
+            return mLocationServiceEnabled;
+        }
+
+        @Override
+        protected boolean isSatelliteAvailableAtCurrentLocation(@Nullable SubscriptionInfo info) {
+            return super.isSatelliteAvailableAtCurrentLocation(info);
+        }
 
         void setSatelliteProvisioned(@Nullable Boolean isProvisioned) {
             synchronized (mDeviceProvisionLock) {
@@ -6305,6 +6076,11 @@
             }
         }
 
+        @Override
+        protected Set<String> getAllPlmnSet() {
+            return super.getAllPlmnSet();
+        }
+
         public boolean isRadioOn() {
             synchronized (mIsRadioOnLock) {
                 return mIsRadioOn;
@@ -6366,6 +6142,18 @@
                 mSatelliteAccessAllowed = isAllowed;
             }
         }
+
+        public void setCallOnlySuperMethod() {
+            callOnlySuperMethod = true;
+        }
+
+        public void  setLocationServiceEnabled(boolean locationServiceEnabled) {
+            mLocationServiceEnabled = locationServiceEnabled;
+        }
+
+        public BroadcastReceiver getLocationReceiver() {
+            return mLocationServiceStateChangedReceiver;
+        }
     }
 
     @Test
@@ -6459,7 +6247,6 @@
     @Test
     public void testGetSatelliteDataPlanForPlmn_WithEntitlement() throws Exception {
         logd("testGetSatelliteDataPlanForPlmn_WithEntitlement");
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
 
         replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
                 mSatelliteControllerUT, new SparseArray<>());
@@ -6493,7 +6280,6 @@
     @Test
     public void testGetSatelliteDataPlanForPlmn_WithoutEntitlement() throws Exception {
         logd("testGetSatelliteDataPlanForPlmn_WithoutEntitlement");
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
 
         replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
                 mSatelliteControllerUT, new SparseArray<>());
@@ -6519,9 +6305,9 @@
     }
 
     @Test
-    public void TestGetSupportedSatelliteServicesForPlmn_WithEntitlement() throws Exception {
+    public void testSupportedSatelliteServices_WithoutDataEntitlement_WithNoDataServiceWithConfig()
+            throws Exception {
         logd("TestGetSupportedSatelliteServicesForPlmn_WithEntitlement");
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
 
         replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
                 mSatelliteControllerUT, new SparseArray<>());
@@ -6532,15 +6318,31 @@
                 CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
         mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
                 true);
+        mCarrierConfigBundle.putInt(
+                CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT,
+                SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED);
+        PersistableBundle carrierSupportedSatelliteServicesPerProvider =
+                new PersistableBundle();
+        List<String> carrierConfigPlmnList = List.of("00101", "00102", "00103");
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                carrierConfigPlmnList.get(0), new int[]{3, 6});
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                carrierConfigPlmnList.get(1), new int[]{3, 6});
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                carrierConfigPlmnList.get(2), new int[]{3, 6});
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                carrierSupportedSatelliteServicesPerProvider);
+        invokeCarrierConfigChanged();
 
         List<String> entitlementPlmnList =
                 Arrays.stream(new String[]{"00101", "00102", "00103", "00104"})
                         .toList();
         List<String> barredPlmnList = new ArrayList<>();
         Map<String, List<Integer>> serviceTypeListMap = Map.of(
-                "00101", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS),
+                "00101", List.of(SERVICE_TYPE_SMS),
                 "00102", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS),
-                "00103", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS));
+                "00103", List.of());
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
                 entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap,
                 new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
@@ -6548,7 +6350,7 @@
         List<Integer> allowedServiceForPlmn;
         allowedServiceForPlmn = mSatelliteControllerUT
                 .getSupportedSatelliteServicesForPlmn(SUB_ID, "00101");
-        assertEquals(List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS), allowedServiceForPlmn);
+        assertEquals(List.of(SERVICE_TYPE_SMS), allowedServiceForPlmn);
 
         allowedServiceForPlmn = mSatelliteControllerUT
                 .getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
@@ -6556,14 +6358,191 @@
 
         allowedServiceForPlmn = mSatelliteControllerUT
                 .getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
-        assertEquals(List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS),
+        assertEquals(List.of(SERVICE_TYPE_SMS, SERVICE_TYPE_MMS),
                 allowedServiceForPlmn);
     }
 
     @Test
-    public void TestGetSupportedSatelliteServicesForPlmn_WithoutEntitlement() throws Exception {
+    public void testSupportedSatelliteServices_WithoutDataEntitlement_WithDataServiceConfig()
+            throws Exception {
+        logd("TestGetSupportedSatelliteServicesForPlmn_WithEntitlement");
+
+        replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+                mSatelliteControllerUT, new SparseArray<>());
+        List<String> overlayConfigPlmnList = new ArrayList<>();
+        replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+                mSatelliteControllerUT, overlayConfigPlmnList);
+        mCarrierConfigBundle.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                true);
+        mCarrierConfigBundle.putInt(
+                CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT,
+                SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED);
+        PersistableBundle carrierSupportedSatelliteServicesPerProvider =
+                new PersistableBundle();
+        List<String> carrierConfigPlmnList = List.of("00101", "00102", "00103");
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                carrierConfigPlmnList.get(0), new int[]{2, 3, 6});
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                carrierConfigPlmnList.get(1), new int[]{2, 3, 6});
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                carrierConfigPlmnList.get(2), new int[]{2, 3});
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                carrierSupportedSatelliteServicesPerProvider);
+        invokeCarrierConfigChanged();
+
+        List<String> entitlementPlmnList =
+                Arrays.stream(new String[]{"00101", "00102", "00103", "00104"})
+                        .toList();
+        List<String> barredPlmnList = new ArrayList<>();
+        Map<String, List<Integer>> serviceTypeListMap = Map.of(
+                "00101", List.of(SERVICE_TYPE_SMS),
+                "00102", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS),
+                "00103", List.of());
+        mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap,
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
+
+        List<Integer> allowedServiceForPlmn;
+        allowedServiceForPlmn = mSatelliteControllerUT
+                .getSupportedSatelliteServicesForPlmn(SUB_ID, "00101");
+        assertEquals(List.of(SERVICE_TYPE_SMS, SERVICE_TYPE_DATA, SERVICE_TYPE_MMS),
+                allowedServiceForPlmn);
+
+        allowedServiceForPlmn = mSatelliteControllerUT
+                .getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
+        assertEquals(List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS, SERVICE_TYPE_DATA,
+                        SERVICE_TYPE_MMS),
+                allowedServiceForPlmn);
+
+        allowedServiceForPlmn = mSatelliteControllerUT
+                .getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
+        assertEquals(List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS),
+                allowedServiceForPlmn);
+    }
+
+    @Test
+    public void testSupportedSatelliteServices_WithoutDataEntitlement_NoMmsServiceWithConfig()
+            throws Exception {
+        logd("TestGetSupportedSatelliteServicesForPlmn_WithEntitlement");
+
+        replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+                mSatelliteControllerUT, new SparseArray<>());
+        List<String> overlayConfigPlmnList = new ArrayList<>();
+        replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+                mSatelliteControllerUT, overlayConfigPlmnList);
+        mCarrierConfigBundle.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                true);
+        mCarrierConfigBundle.putInt(
+                CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT,
+                SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED);
+        PersistableBundle carrierSupportedSatelliteServicesPerProvider =
+                new PersistableBundle();
+        List<String> carrierConfigPlmnList = List.of("00101", "00102", "00103");
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                carrierConfigPlmnList.get(0), new int[]{2, 3});
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                carrierConfigPlmnList.get(1), new int[]{2, 3});
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                carrierConfigPlmnList.get(2), new int[]{2, 3});
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                carrierSupportedSatelliteServicesPerProvider);
+        invokeCarrierConfigChanged();
+
+        List<String> entitlementPlmnList =
+                Arrays.stream(new String[]{"00101", "00102", "00103", "00104"})
+                        .toList();
+        List<String> barredPlmnList = new ArrayList<>();
+        Map<String, List<Integer>> serviceTypeListMap = Map.of(
+                "00101", List.of(SERVICE_TYPE_SMS),
+                "00102", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS),
+                "00103", List.of());
+        mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap,
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
+
+        List<Integer> allowedServiceForPlmn;
+        allowedServiceForPlmn = mSatelliteControllerUT
+                .getSupportedSatelliteServicesForPlmn(SUB_ID, "00101");
+        assertEquals(List.of(SERVICE_TYPE_SMS, SERVICE_TYPE_DATA), allowedServiceForPlmn);
+
+        allowedServiceForPlmn = mSatelliteControllerUT
+                .getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
+        assertEquals(List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS, SERVICE_TYPE_DATA),
+                allowedServiceForPlmn);
+
+        allowedServiceForPlmn = mSatelliteControllerUT
+                .getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
+        assertEquals(List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS), allowedServiceForPlmn);
+    }
+
+    @Test
+    public void testSupportedSatelliteServices_WithoutDataEntitlement_NonRestrictedMode()
+            throws Exception {
+        logd("TestGetSupportedSatelliteServicesForPlmn_WithEntitlement");
+
+        replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+                mSatelliteControllerUT, new SparseArray<>());
+        List<String> overlayConfigPlmnList = new ArrayList<>();
+        replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+                mSatelliteControllerUT, overlayConfigPlmnList);
+        mCarrierConfigBundle.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                true);
+        mCarrierConfigBundle.putInt(
+                CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT,
+                SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED);
+        PersistableBundle carrierSupportedSatelliteServicesPerProvider =
+                new PersistableBundle();
+        List<String> carrierConfigPlmnList = List.of("00101", "00102", "00103");
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                carrierConfigPlmnList.get(0), new int[]{2, 3, 6});
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                carrierConfigPlmnList.get(1), new int[]{2, 3, 6});
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                carrierConfigPlmnList.get(2), new int[]{2, 3, 6});
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                carrierSupportedSatelliteServicesPerProvider);
+        invokeCarrierConfigChanged();
+
+        List<String> entitlementPlmnList =
+                Arrays.stream(new String[]{"00101", "00102", "00103", "00104"})
+                        .toList();
+        List<String> barredPlmnList = new ArrayList<>();
+        Map<String, List<Integer>> serviceTypeListMap = Map.of(
+                "00101", List.of(SERVICE_TYPE_SMS),
+                "00102", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS),
+                "00103", List.of());
+        mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap,
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
+
+        List<Integer> allowedServiceForPlmn;
+        allowedServiceForPlmn = mSatelliteControllerUT
+                .getSupportedSatelliteServicesForPlmn(SUB_ID, "00101");
+        assertEquals(List.of(SERVICE_TYPE_SMS), allowedServiceForPlmn);
+
+        allowedServiceForPlmn = mSatelliteControllerUT
+                .getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
+        assertEquals(List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS),
+                allowedServiceForPlmn);
+
+        allowedServiceForPlmn = mSatelliteControllerUT
+                .getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
+        assertEquals(List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS, SERVICE_TYPE_MMS),
+                allowedServiceForPlmn);
+    }
+
+    @Test
+    public void testGetSupportedSatelliteServicesForPlmn_WithoutEntitlement() throws Exception {
         logd("TestGetSupportedSatelliteServicesForPlmn_WithoutAllowedServices");
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
 
         replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
                 mSatelliteControllerUT, new SparseArray<>());
@@ -6595,7 +6574,7 @@
                 new PersistableBundle();
         List<String> carrierConfigPlmnList = List.of("00101");
         carrierSupportedSatelliteServicesPerProvider.putIntArray(
-                carrierConfigPlmnList.get(0), new int[]{2});
+                carrierConfigPlmnList.get(0), new int[]{2, 3, 6});
         mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
                         .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
                 carrierSupportedSatelliteServicesPerProvider);
@@ -6604,14 +6583,13 @@
         List<Integer> servicesPerPlmn;
         servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
                 SUB_ID, "00101");
-        assertEquals(Arrays.asList(2).stream().sorted().toList(),
-                servicesPerPlmn.stream().sorted().toList());
+        assertEquals(Arrays.asList(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS, SERVICE_TYPE_MMS).stream()
+                        .sorted().toList(), servicesPerPlmn.stream().sorted().toList());
     }
 
     @Test
     public void testGetSupportedSatelliteDataModeForPlmn_WithEntitlement() throws Exception {
         logd("testGetSupportedSatelliteDataModeForPlmn_WithEntitlement");
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
 
         replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
                 mSatelliteControllerUT, new SparseArray<>());
@@ -6644,12 +6622,18 @@
                 .getSatelliteDataServicePolicyForPlmn(SUB_ID, "00102");
         assertEquals(SATELLITE_DATA_SUPPORT_ALL, dataSupportModeForPlmn);
 
+        dataSupportModeForPlmn = mSatelliteControllerUT
+                .getSatelliteDataServicePolicyForPlmn(SUB_ID, "");
+        assertEquals(SATELLITE_DATA_SUPPORT_ALL, dataSupportModeForPlmn);
+
+        dataSupportModeForPlmn = mSatelliteControllerUT
+                .getSatelliteDataServicePolicyForPlmn(SUB_ID, null);
+        assertEquals(SATELLITE_DATA_SUPPORT_ALL, dataSupportModeForPlmn);
     }
 
     @Test
     public void testGetSupportedSatelliteDataModeForPlmn_WithoutEntitlement() throws Exception {
         logd("testGetSupportedSatelliteDataModeForPlmn_WithoutEntitlement");
-        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
 
         replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
                 mSatelliteControllerUT, new SparseArray<>());
@@ -6670,12 +6654,227 @@
                 entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
                 dataServicePolicyMap, new HashMap<>(), mIIntegerConsumer);
 
+        // when Available satellite services is not configured with data service
         mCarrierConfigBundle.putInt(
                 CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT,
                 SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED);
         int dataSupportModeForPlmn = mSatelliteControllerUT
                 .getSatelliteDataServicePolicyForPlmn(SUB_ID, "00101");
+        assertEquals(SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED, dataSupportModeForPlmn);
+
+        dataSupportModeForPlmn = mSatelliteControllerUT
+                .getSatelliteDataServicePolicyForPlmn(SUB_ID, "");
+        assertEquals(SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED, dataSupportModeForPlmn);
+
+        dataSupportModeForPlmn = mSatelliteControllerUT
+                .getSatelliteDataServicePolicyForPlmn(SUB_ID, null);
+        assertEquals(SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED, dataSupportModeForPlmn);
+
+        setConfigData(new ArrayList<>());
+        PersistableBundle carrierSupportedSatelliteServicesPerProvider =
+                new PersistableBundle();
+        List<String> carrierConfigPlmnList = List.of("00101");
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                carrierConfigPlmnList.get(0), new int[]{2, 3, 5});
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                carrierSupportedSatelliteServicesPerProvider);
+        invokeCarrierConfigChanged();
+
+        // when Available satellite services support data service
+        dataSupportModeForPlmn = mSatelliteControllerUT
+                .getSatelliteDataServicePolicyForPlmn(SUB_ID, "00101");
         assertEquals(SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED, dataSupportModeForPlmn);
+
+        dataSupportModeForPlmn = mSatelliteControllerUT
+                .getSatelliteDataServicePolicyForPlmn(SUB_ID, "");
+        assertEquals(SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED, dataSupportModeForPlmn);
+
+        dataSupportModeForPlmn = mSatelliteControllerUT
+                .getSatelliteDataServicePolicyForPlmn(SUB_ID, null);
+        assertEquals(SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED, dataSupportModeForPlmn);
+    }
+
+    @Test
+    public void testNotifyCarrierRoamingNtnAvailableServicesChanged_noServices() throws Exception {
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        mSatelliteControllerUT.setCallOnlySuperMethod();
+        List<String> overlayConfigPlmnList = new ArrayList<>();
+        replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+                mSatelliteControllerUT, overlayConfigPlmnList);
+        mCarrierConfigBundle.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                true);
+        mCarrierConfigBundle.putIntArray(
+                CarrierConfigManager.KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY,
+                new int[]{});
+        invokeCarrierConfigChanged();
+        List<String> entitlementPlmnList = Arrays.stream(
+                new String[]{"00101", "00102", "00103", "00104"}).toList();
+        mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+                entitlementPlmnList, new ArrayList<>(), new HashMap<>(),
+                new HashMap<>() /*serviceTypeListMap*/, new HashMap<>(), new HashMap<>(),
+                mIIntegerConsumer);
+        verify(mPhone, times(2)).notifyCarrierRoamingNtnAvailableServicesChanged(
+                (int[]) ArgumentMatchers.any());
+    }
+
+    @Test
+    public void testNotifyCarrierRoamingNtnAvailableServicesChanged() throws Exception {
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        mSatelliteControllerUT.setCallOnlySuperMethod();
+        List<String> overlayConfigPlmnList = new ArrayList<>();
+        replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+                mSatelliteControllerUT, overlayConfigPlmnList);
+        mCarrierConfigBundle.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                true);
+        invokeCarrierConfigChanged();
+
+        List<String> entitlementPlmnList = Arrays.stream(
+                new String[]{"00101", "00102", "00103", "00104"}).toList();
+        List<String> barredPlmnList = new ArrayList<>();
+        Map<String, List<Integer>> serviceTypeListMap = Map.of("00101",
+                List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS), "00102",
+                List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS), "00103",
+                List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS));
+        mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap,
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
+        int[] expectedServices = new int[]{1, 2, 3};
+        int[] supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn(
+                SUB_ID);
+        assertArrayEquals(expectedServices, supportedServices);
+        verify(mPhone, times(2)).notifyCarrierRoamingNtnAvailableServicesChanged(
+                (int[]) ArgumentMatchers.any());
+    }
+
+    @Test
+    public void testNotifyCarrierRoamingNtnAvailableServicesChange_duplicateUpdates()
+            throws Exception {
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        mSatelliteControllerUT.setCallOnlySuperMethod();
+        List<String> overlayConfigPlmnList = new ArrayList<>();
+        replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+                mSatelliteControllerUT, overlayConfigPlmnList);
+        mCarrierConfigBundle.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                true);
+        invokeCarrierConfigChanged();
+
+        List<String> entitlementPlmnList = Arrays.stream(
+                new String[]{"00101", "00102", "00103", "00104"}).toList();
+        List<String> barredPlmnList = new ArrayList<>();
+        Map<String, List<Integer>> serviceTypeListMap = Map.of("00101",
+                List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS), "00102",
+                List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS), "00103",
+                List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS));
+        mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap,
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
+        int[] expectedServices = new int[]{1, 2, 3};
+        int[] supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn(
+                SUB_ID);
+        assertArrayEquals(expectedServices, supportedServices);
+        verify(mPhone, times(2)).notifyCarrierRoamingNtnAvailableServicesChanged(
+                (int[]) ArgumentMatchers.any());
+
+        mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap,
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
+        // There is no change in services between 2 calls, so notify should not invoke again.
+        supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn(SUB_ID);
+        assertArrayEquals(expectedServices, supportedServices);
+        verify(mPhone, times(2)).notifyCarrierRoamingNtnAvailableServicesChanged(
+                (int[]) ArgumentMatchers.any());
+    }
+
+    @Test
+    public void testNotifyCarrierRoamingNtnAvailableServicesChange_multipleUpdates()
+            throws Exception {
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        mSatelliteControllerUT.setCallOnlySuperMethod();
+        List<String> overlayConfigPlmnList = new ArrayList<>();
+        replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+                mSatelliteControllerUT, overlayConfigPlmnList);
+        mCarrierConfigBundle.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                true);
+        invokeCarrierConfigChanged();
+
+        List<String> entitlementPlmnList = Arrays.stream(
+                new String[]{"00101", "00102", "00103", "00104"}).toList();
+        List<String> barredPlmnList = new ArrayList<>();
+        Map<String, List<Integer>> serviceTypeListMap = Map.of("00101",
+                List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS), "00102",
+                List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS), "00103",
+                List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS));
+        mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap,
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
+        int[] expectedServices = new int[]{1, 2, 3};
+        int[] supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn(
+                SUB_ID);
+        assertArrayEquals(expectedServices, supportedServices);
+        verify(mPhone, times(2)).notifyCarrierRoamingNtnAvailableServicesChanged(
+                (int[]) ArgumentMatchers.any());
+
+        serviceTypeListMap = Map.of("00101", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS), "00102",
+                List.of(SERVICE_TYPE_SMS), "00103", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS));
+        mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap,
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
+        expectedServices = new int[]{1, 3};
+        supportedServices = mSatelliteControllerUT.getSupportedServicesOnCarrierRoamingNtn(SUB_ID);
+        assertArrayEquals(expectedServices, supportedServices);
+        // 2 times notify called due to previous and current changes
+        verify(mPhone, times(3)).notifyCarrierRoamingNtnAvailableServicesChanged(
+                (int[]) ArgumentMatchers.any());
+    }
+
+    @Test
+    public void testGetPhoneNumberBasedCarrier() throws Exception {
+        assertEquals("", mSatelliteControllerUT.getPhoneNumberBasedCarrier(-1));
+
+        int carrierId_subID = 0;
+        SubscriptionInfoInternal subInfoInternal =
+                new SubscriptionInfoInternal.Builder().setCarrierId(
+                        carrierId_subID).setImsi("").setIccId(mIccId).build();
+        doReturn(subInfoInternal).when(mMockSubscriptionManagerService)
+                .getSubscriptionInfoInternal(eq(SUB_ID));
+
+        // subscriptionManager is null
+        Field field = SatelliteController.class.getDeclaredField("mInjectSubscriptionManager");
+        field.setAccessible(true);
+        field.set(mSatelliteControllerUT, null);
+        assertEquals("", mSatelliteControllerUT.getPhoneNumberBasedCarrier(SUB_ID));
+
+        // phoneNumber is empty
+        field.set(mSatelliteControllerUT, mSubscriptionManager);
+        doReturn("").when(mSubscriptionManager).getPhoneNumber(eq(SUB_ID));
+        assertEquals("", mSatelliteControllerUT.getPhoneNumberBasedCarrier(SUB_ID));
+
+        // IMSI is empty
+        doReturn(mMsisdn).when(mSubscriptionManager).getPhoneNumber(eq(SUB_ID));
+        assertEquals("", mSatelliteControllerUT.getPhoneNumberBasedCarrier(SUB_ID));
+
+        // IMSI length is less than 6
+        subInfoInternal = new SubscriptionInfoInternal.Builder().setCarrierId(
+                        carrierId_subID).setImsi("12345").setIccId(mIccId).build();
+        doReturn(subInfoInternal).when(mMockSubscriptionManagerService)
+                .getSubscriptionInfoInternal(eq(SUB_ID));
+        assertEquals("", mSatelliteControllerUT.getPhoneNumberBasedCarrier(SUB_ID));
+
+        subInfoInternal = new SubscriptionInfoInternal.Builder().setCarrierId(
+                carrierId_subID).setImsi(mImsi).setIccId(mIccId).build();
+        doReturn(subInfoInternal).when(mMockSubscriptionManagerService)
+                .getSubscriptionInfoInternal(eq(SUB_ID));
+        String expectedResult = "123456" + "0987654321";
+        assertEquals(expectedResult, mSatelliteControllerUT.getPhoneNumberBasedCarrier(SUB_ID));
     }
 
     @Test
@@ -6693,4 +6892,228 @@
         processAllMessages();
         verify(mPhone, times(0)).notifyCarrierRoamingNtnEligibleStateChanged(anyBoolean());
     }
+
+    @Test
+    public void testExitOutOfP2pSessionIfSatelliteIsNotAllowed() throws Exception {
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        when(mFeatureFlags.satelliteExitP2pSessionOutsideGeofence()).thenReturn(true);
+
+        // Enable satellite P2P session
+        setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+        verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+        setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+        verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+        setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+        mSatelliteControllerUT.requestSatelliteEnabled(true, false, false, mIIntegerConsumer);
+        processAllMessages();
+        assertTrue(waitForIIntegerConsumerResult(1));
+        assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+        verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+
+        ArgumentCaptor<SatelliteModemEnableRequestAttributes> enableSatelliteRequest =
+                ArgumentCaptor.forClass(SatelliteModemEnableRequestAttributes.class);
+        ArgumentCaptor<Message> enableSatelliteResponse = ArgumentCaptor.forClass(Message.class);
+
+        reset(mMockSatelliteModemInterface);
+        doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+        // Set access allowed to false
+        final int carrierSubId = SUB_ID;
+        final int oemSubId = SUB_ID1;
+        setSatelliteSubscriberTesting(false);
+        mSatelliteControllerUT.subsInfoListPerPriority().computeIfAbsent(
+                        getKeyPriority(testSubscriptionInfo), k -> new ArrayList<>())
+                .add(testSubscriptionInfo);
+        mSatelliteControllerUT.subsInfoListPerPriority().computeIfAbsent(
+                        getKeyPriority(testSubscriptionInfo2), k -> new ArrayList<>())
+                .add(testSubscriptionInfo2);
+        mSatelliteControllerUT.selectedSatelliteSubId = SUB_ID1;
+        mSatelliteControllerUT.handleSatelliteAccessAllowedStateChanged(false);
+        processAllMessages();
+        verify(mMockSatelliteModemInterface).requestSatelliteEnabled(
+                enableSatelliteRequest.capture(), enableSatelliteResponse.capture());
+
+        // Disable satellite request is sent to modem
+        SatelliteModemEnableRequestAttributes request = enableSatelliteRequest.getValue();
+        assertFalse(request.isEnabled());
+        assertFalse(request.isForDemoMode());
+        assertFalse(request.isForEmergencyMode());
+        // OEM satellite subscription should be selected as current location is not supported
+        assertEquals(oemSubId, mSatelliteControllerUT.getSelectedSatelliteSubId());
+
+        // As current location is allowed, carrier subscription should be selected
+        mSatelliteControllerUT.selectedSatelliteSubId = SUB_ID;
+        mSatelliteControllerUT.handleSatelliteAccessAllowedStateChanged(true);
+        processAllMessages();
+        assertEquals(carrierSubId, mSatelliteControllerUT.getSelectedSatelliteSubId());
+
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        when(mServiceState.getNetworkRegistrationInfo(anyInt(), anyInt())).thenReturn(null);
+        when(mServiceState2.getNetworkRegistrationInfo(anyInt(), anyInt())).thenReturn(null);
+        mSatelliteControllerUT.mIsApplicationSupportsP2P = true;
+        mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT, 1);
+        mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL, true);
+        int[] supportedServices2 = {2};
+        int[] supportedServices3 = {1, 3};
+        PersistableBundle carrierSupportedSatelliteServicesPerProvider = new PersistableBundle();
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                "00102", supportedServices2);
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                "00103", supportedServices3);
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                carrierSupportedSatelliteServicesPerProvider);
+        for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+                : mCarrierConfigChangedListenerList) {
+            pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+                    /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+            );
+        }
+        mSatelliteControllerUT.setSatellitePhone(1);
+        mSatelliteControllerUT.setSelectedSatelliteSubId(SUB_ID);
+        mSatelliteControllerUT.isSatelliteProvisioned = true;
+        processAllMessages();
+
+        assertTrue(mSatelliteControllerUT.isCarrierRoamingNtnEligible(mPhone));
+    }
+
+    @Test
+    public void testIsSatelliteAvailableAtCurrentLocation() throws Exception {
+        SubscriptionInfo ntnOnlySubscriptionInfo = new SubscriptionInfo.Builder()
+                .setOnlyNonTerrestrialNetwork(true)
+                .build();
+        SubscriptionInfo esosSubscriptionInfo = new SubscriptionInfo.Builder()
+                .setSatelliteESOSSupported(true)
+                .build();
+        Field currentLocationTagIdsField = SatelliteController.class.getDeclaredField(
+                "mCurrentLocationTagIds");
+        currentLocationTagIdsField.setAccessible(true);
+
+        // Null subscription info
+        assertFalse(mSatelliteControllerUT.isSatelliteAvailableAtCurrentLocation(null));
+
+        // Satellite is not allowed
+        mSatelliteControllerUT.setIsSatelliteAllowedState(false);
+        assertFalse(mSatelliteControllerUT.isSatelliteAvailableAtCurrentLocation(
+                ntnOnlySubscriptionInfo));
+        assertFalse(mSatelliteControllerUT.isSatelliteAvailableAtCurrentLocation(
+                esosSubscriptionInfo));
+
+        // Satellite is allowed
+        mSatelliteControllerUT.setIsSatelliteAllowedState(true);
+        assertTrue(mSatelliteControllerUT.isSatelliteAvailableAtCurrentLocation(
+                ntnOnlySubscriptionInfo));
+
+        // Both config_verizon_satellite_enabled_tagids and satellite_access_config_file
+        // are not configured
+        assertTrue(mSatelliteControllerUT.isSatelliteAvailableAtCurrentLocation(
+                esosSubscriptionInfo));
+
+        // config_verizon_satellite_enabled_tagids is not configured whereas
+        // satellite_access_config_file is configured
+        mContextFixture.putResource(
+                com.android.internal.R.string.satellite_access_config_file,
+                "test_satellite_access_config_file");
+        assertFalse(mSatelliteControllerUT.isSatelliteAvailableAtCurrentLocation(
+                esosSubscriptionInfo));
+
+        // Both config_verizon_satellite_enabled_tagids and satellite_access_config_file
+        // are configured, but mCurrentLocationTagIds is empty
+        mContextFixture.putIntArrayResource(
+                R.array.config_verizon_satellite_enabled_tagids,
+                new int[]{1001});
+        assertFalse(mSatelliteControllerUT.isSatelliteAvailableAtCurrentLocation(
+                esosSubscriptionInfo));
+
+        // Both config_verizon_satellite_enabled_tagids and satellite_access_config_file
+        // are configured, and mCurrentLocationTagIds contains the carrier tag id
+        currentLocationTagIdsField.set(mSatelliteControllerUT, Arrays.asList(1001));
+        assertTrue(mSatelliteControllerUT.isSatelliteAvailableAtCurrentLocation(
+                esosSubscriptionInfo));
+    }
+
+    public void testNotifyNtnEligibilityLocationServiceStatusChanged() {
+        // Enable CarrierRoamingNtn
+        mContextFixture.putBooleanResource(
+                R.bool.config_satellite_should_notify_availability, true);
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        mSatelliteControllerUT.mIsApplicationSupportsP2P = true;
+        mSatelliteControllerUT.setIsSatelliteSupported(true);
+        mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT,
+                CARRIER_ROAMING_NTN_CONNECT_MANUAL);
+        mCarrierConfigBundle.putInt(
+                KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT, 1 * 60);
+        mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL, true);
+        int[] supportedServices2 = {2};
+        int[] supportedServices3 = {1, 3};
+        PersistableBundle carrierSupportedSatelliteServicesPerProvider = new PersistableBundle();
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                "00102", supportedServices2);
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                "00103", supportedServices3);
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                carrierSupportedSatelliteServicesPerProvider);
+        for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+                : mCarrierConfigChangedListenerList) {
+            pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+                    /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+            );
+        }
+        mSatelliteControllerUT.setSatellitePhone(1);
+        mSatelliteControllerUT.setSelectedSatelliteSubId(SUB_ID);
+        mSatelliteControllerUT.isSatelliteProvisioned = true;
+        mSatelliteControllerUT.isSatelliteAllowedCallback = null;
+        mSatelliteControllerUT.setIsSatelliteAllowedState(true);
+        processAllMessages();
+        clearInvocations(mPhone);
+
+        doReturn(LocationManager.MODE_CHANGED_ACTION).when(mMockLocationIntent).getAction();
+
+        // Location service off
+        mSatelliteControllerUT.setLocationServiceEnabled(false);
+        BroadcastReceiver receiver = mSatelliteControllerUT.getLocationReceiver();
+        receiver.onReceive(mContext, mMockLocationIntent);
+
+        processAllMessages();
+
+        verify(mPhone, times(1)).notifyCarrierRoamingNtnEligibleStateChanged(eq(false));
+        clearInvocations(mPhone);
+
+        // Location service off
+        mSatelliteControllerUT.setLocationServiceEnabled(true);
+        receiver.onReceive(mContext, mMockLocationIntent);
+
+        processAllMessages();
+
+        verify(mPhone, times(1)).notifyCarrierRoamingNtnEligibleStateChanged(eq(true));
+    }
+
+    @Test
+    public void testGetSatelliteEnabledForCarrier() {
+        reset(mPhone);
+        sendCmdGetSatelliteEnabledForCarrier(mPhone);
+        processAllMessages();
+        verify(mPhone, times(1)).isSatelliteEnabledForCarrier(anyInt(), any());
+        reset(mPhone);
+
+        sendEventGetSatelliteEnabledForCarrierDone(mPhone.getSubId(), false,
+                new SatelliteException(SATELLITE_RESULT_ERROR));
+        processAllMessages();
+        assertFalse(mSatelliteControllerUT.isSatelliteEnabledForCarrierAtModem(mPhone.getSubId()));
+
+        sendEventGetSatelliteEnabledForCarrierDone(mPhone.getSubId(), true, null);
+        processAllMessages();
+        assertTrue(mSatelliteControllerUT.isSatelliteEnabledForCarrierAtModem(mPhone.getSubId()));
+
+        sendEventGetSatelliteEnabledForCarrierDone(mPhone.getSubId(), false, null);
+        processAllMessages();
+        assertFalse(mSatelliteControllerUT.isSatelliteEnabledForCarrierAtModem(mPhone.getSubId()));
+    }
+
 }
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 a5fd30d..ed709fc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
@@ -31,6 +31,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
@@ -46,10 +47,10 @@
 import android.hardware.devicestate.DeviceState;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.Looper;
 import android.os.OutcomeReceiver;
 import android.os.RemoteException;
-import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.telecom.Connection;
 import android.telecom.TelecomManager;
@@ -88,6 +89,7 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -122,6 +124,8 @@
     private static final String DEFAULT_SATELLITE_SOS_HANDOVER_CLASS =
             "android.com.vendor.message.SosHandoverApp";
     private static final String DEFAULT_T911_HANDOVER_INTENT_ACTION = Intent.ACTION_SENDTO;
+    private static final Set<String> TEST_ALL_SATELLITE_PLMN_SET = new HashSet<>(
+            Arrays.asList("310830", "313210"));
     private TestSatelliteController mTestSatelliteController;
     private TestImsManager mTestImsManager;
     @Mock
@@ -139,6 +143,7 @@
     @Mock
     private SatelliteStats mMockSatelliteStats;
     @Mock private SubscriptionManagerService mMockSubscriptionManagerService;
+    @Mock private SatelliteControllerTest.TestSatelliteController mMockSatelliteController;
 
     @Before
     public void setUp() throws Exception {
@@ -155,7 +160,6 @@
                 .thenReturn(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
         when(mResources.getString(R.string.config_oem_enabled_satellite_sos_handover_app))
                 .thenReturn(DEFAULT_SOS_HANDOVER_APP);
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         mTestSatelliteController = new TestSatelliteController(mContext,
                 Looper.myLooper(), mFeatureFlags);
@@ -176,12 +180,16 @@
                 mTestSatelliteController, mTestImsManager);
         when(mServiceState.getState()).thenReturn(STATE_OUT_OF_SERVICE);
         when(mServiceState2.getState()).thenReturn(STATE_OUT_OF_SERVICE);
+        when(mServiceState.getNetworkRegistrationInfo(anyInt(), anyInt())).thenReturn(null);
+        when(mServiceState2.getNetworkRegistrationInfo(anyInt(), anyInt())).thenReturn(null);
         when(mPhone.isImsRegistered()).thenReturn(false);
         when(mPhone2.isImsRegistered()).thenReturn(false);
         replaceInstance(SatelliteStats.class, "sInstance", null,
                 mMockSatelliteStats);
         replaceInstance(SubscriptionManagerService.class, "sInstance", null,
                 mMockSubscriptionManagerService);
+        replaceInstance(SatelliteController.class, "sInstance", null,
+                mMockSatelliteController);
         doNothing().when(mMockSatelliteStats).onSatelliteSosMessageRecommender(
                 any(SatelliteStats.SatelliteSosMessageRecommenderParams.class));
         mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(
@@ -193,6 +201,7 @@
                 .setId(SUB_ID1).setOnlyNonTerrestrialNetwork(true).build();
         when(mMockSubscriptionManagerService.getSubscriptionInfo(eq(SUB_ID1)))
             .thenReturn(subscriptionInfo);
+        doReturn(TEST_ALL_SATELLITE_PLMN_SET).when(mMockSatelliteController).getAllPlmnSet();
     }
 
     @After
@@ -333,6 +342,43 @@
     }
 
     @Test
+    public void testTimeoutBeforeEmergencyCallEnd_EventDisplayEmergencyMessageNotSent_Test2() {
+        /*
+         * This test is to test the case where the device is provisioned, supports satellite
+         * via OEM, and is connected via carrier within the hysteresis time. However, satellite
+         * is not allowed at current location and emergency messaing via carrier is not supported.
+         * In this case, the EVENT_DISPLAY_EMERGENCY_MESSAGE should not be sent.
+         */
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true, SUB_ID1);
+        mTestSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier = false;
+        mTestSatelliteController.isOemEnabledSatelliteSupported = true;
+        mTestSatelliteController.setDeviceProvisioned(true);
+        mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
+        mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
+        processAllMessages();
+        assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
+        assertRegisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertRegisterForStateChangedEventsTriggered(mPhone2, 1, 1);
+        assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
+
+        // Move Location service to emergency mode
+        mTestSOSMessageRecommender.onEmergencyCallConnectionStateChanged(
+                mTestConnection.getTelecomCallId(), Connection.STATE_DIALING);
+        processAllMessages();
+        assertNotNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
+
+        // Wait for the timeout to expires
+        mTestSOSMessageRecommender.isSatelliteAllowedCallback.onResult(false);
+        moveTimeForward(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
+        processAllMessages();
+        assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE));
+        assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
+        assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
+        verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
+        assertFalse(mTestSOSMessageRecommender.isDialerNotified());
+    }
+
+    @Test
     public void testTimeoutBeforeEmergencyCallEnd_T911_FromNotConnectedToConnected() {
         mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
         mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false, -1);
@@ -685,6 +731,20 @@
         processAllMessages();
         assertEquals(carrierTimeoutMillis, mTestSOSMessageRecommender.getTimeOutMillis());
         verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
+
+        // OEM supports satellite, device is connected to carrier satellite within hysteresis time,
+        // but emergency messaging via carrier is not supported. Thus, OEM timer will be used.
+        mTestSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier = false;
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true, SUB_ID1);
+        subscriptionInfo = new SubscriptionInfo.Builder()
+                .setId(SUB_ID1).setOnlyNonTerrestrialNetwork(true).build();
+        when(mMockSubscriptionManagerService.getSubscriptionInfo(eq(SUB_ID1)))
+            .thenReturn(subscriptionInfo);
+        mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
+        processAllMessages();
+        assertEquals(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS,
+                mTestSOSMessageRecommender.getTimeOutMillis());
+        verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
     }
 
     @Test
@@ -718,6 +778,22 @@
     }
 
     @Test
+    public void testGetEmergencyCallToSatelliteHandoverType_OnlySatelliteViaOemAvailable() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
+
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true, SUB_ID1);
+        mTestSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier = false;
+        mTestSatelliteController.isOemEnabledSatelliteSupported = true;
+        mTestSatelliteController.setDeviceProvisioned(true);
+        mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
+        assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
+                mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
+        verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
+
+        mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
+    }
+
+    @Test
     public void testGetEmergencyCallToSatelliteHandoverType_OemAndCarrierNotAvailable() {
         mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
 
@@ -816,8 +892,9 @@
             int registerForProvisionCount, int registerForCellularCount) {
         assertEquals(registerForProvisionCount,
                 mTestSatelliteController.getRegisterForSatelliteProvisionStateChangedCalls());
+        Handler handler = mTestSOSMessageRecommender.getTestHandler();
         verify(phone, times(registerForCellularCount))
-                .registerForServiceStateChanged(any(), anyInt(), any());
+                .registerForServiceStateChanged(eq(handler), anyInt(), any());
     }
 
     private void assertUnregisterForStateChangedEventsTriggered(
@@ -877,8 +954,8 @@
         }
 
         @Override
-        protected void registerForSatelliteCommunicationAllowedStateChanged() {
-            logd("registerForSatelliteCommunicationAllowedStateChanged");
+        protected void registerForSatelliteCommunicationAccessStateChanged() {
+            logd("registerForSatelliteCommunicationAccessStateChanged");
         }
 
         @Override
@@ -1004,8 +1081,8 @@
         }
 
         @Override
-        protected void registerForSatelliteCommunicationAllowedStateChanged() {
-            logd("registerForSatelliteCommunicationAllowedStateChanged");
+        protected void registerForSatelliteCommunicationAccessStateChanged() {
+            logd("registerForSatelliteCommunicationAccessStateChanged");
         }
     }
 
@@ -1154,6 +1231,10 @@
             mIsSatelliteConnectedViaCarrierWithinHysteresisTime.set(connectedViaCarrier);
             mSubIdOfSatelliteConnectedViaCarrierWithinHysteresisTime.set(subId);
         }
+
+        public Handler getTestHandler() {
+            return this;
+        }
     }
 
     private static class TestConnection extends Connection {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java
index 7bf8ab4..c27103a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.when;
 
@@ -42,6 +43,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -54,6 +56,8 @@
     private static final int SUB_ID1 = 1;
     @Mock private ServiceState mServiceState2;
 
+    @Mock SatelliteControllerTest.TestSatelliteController mMockSatelliteController;
+
     @Before
     public void setUp() throws Exception {
         super.setUp(getClass().getSimpleName());
@@ -67,6 +71,8 @@
         when(mPhone2.getServiceState()).thenReturn(mServiceState2);
         when(mPhone2.getSubId()).thenReturn(SUB_ID1);
         when(mPhone2.getPhoneId()).thenReturn(1);
+        replaceInstance(SatelliteController.class, "sInstance", null,
+                mMockSatelliteController);
     }
 
     @After
@@ -144,6 +150,8 @@
     public void testIsCellularAvailable() {
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
         when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        when(mServiceState.getNetworkRegistrationInfo(anyInt(), anyInt())).thenReturn(null);
+        when(mServiceState2.getNetworkRegistrationInfo(anyInt(), anyInt())).thenReturn(null);
         assertFalse(SatelliteServiceUtils.isCellularAvailable());
 
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_EMERGENCY_ONLY);
@@ -157,14 +165,30 @@
         when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
         when(mServiceState2.isEmergencyOnly()).thenReturn(true);
         assertTrue(SatelliteServiceUtils.isCellularAvailable());
+
+        NetworkRegistrationInfo dataNri = new NetworkRegistrationInfo.Builder()
+                .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+                .build();
+        when(mServiceState.getNetworkRegistrationInfo(anyInt(), anyInt())).thenReturn(dataNri);
+        when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        when(mServiceState2.isEmergencyOnly()).thenReturn(false);
+        assertTrue(SatelliteServiceUtils.isCellularAvailable());
+
+        dataNri = new NetworkRegistrationInfo.Builder()
+                .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_EMERGENCY)
+                .build();
+        when(mServiceState.getNetworkRegistrationInfo(anyInt(), anyInt())).thenReturn(dataNri);
+        when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+        when(mServiceState2.isEmergencyOnly()).thenReturn(false);
+        assertFalse(SatelliteServiceUtils.isCellularAvailable());
     }
 
     @Test
     public void testIsSatellitePlmn() {
         int subId = 1;
 
-        when(mSatelliteController.getSatellitePlmnsForCarrier(eq(subId)))
-                .thenReturn(new ArrayList<>());
+        when(mMockSatelliteController.getAllPlmnSet())
+                .thenReturn(new HashSet<>(new ArrayList<>()));
         assertFalse(SatelliteServiceUtils.isSatellitePlmn(subId, mServiceState));
 
         // registered PLMN is null
@@ -177,8 +201,8 @@
         assertFalse(SatelliteServiceUtils.isSatellitePlmn(subId, mServiceState));
 
         // cell identity is null
-        when(mSatelliteController.getSatellitePlmnsForCarrier(eq(subId))).thenReturn(
-                List.of("120260"));
+        when(mMockSatelliteController.getAllPlmnSet()).thenReturn(
+                new HashSet<>(List.of("120260")));
         nri = new NetworkRegistrationInfo.Builder()
                 .setRegisteredPlmn("123456")
                 .setCellIdentity(null)
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 54cf227..65bfb83 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
@@ -153,7 +153,6 @@
         when(resources.getBoolean(
                  R.bool.config_satellite_allow_tn_scanning_during_satellite_session))
             .thenReturn(true);
-        when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
         when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(false);
         when(mMockSatelliteController.isSatelliteRoamingP2pSmSSupported(
                 anyInt())).thenReturn(false);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifierTest.java b/tests/telephonytests/src/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifierTest.java
index aba8164..faf816b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifierTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/security/CellularIdentifierDisclosureNotifierTest.java
@@ -116,6 +116,44 @@
     }
 
     @Test
+    public void testAddDisclosureBenignNop() {
+        CellularIdentifierDisclosureNotifier notifier = getNotifier();
+
+        CellularIdentifierDisclosure emergencyDisclosure =
+                new CellularIdentifierDisclosure(
+                        CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_THREAT_IDENTIFIER_FALSE,
+                        CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI,
+                        "001001",
+                        false);
+
+        notifier.enable(mContext);
+        notifier.addDisclosure(mContext, SUB_ID_1, emergencyDisclosure);
+
+        assertEquals(0, notifier.getCurrentDisclosureCount(SUB_ID_1));
+        verify(mSafetySource, never())
+                .setIdentifierDisclosure(any(), anyInt(), anyInt(), any(), any());
+    }
+
+    @Test
+    public void testAddDisclosureHarmful() {
+        CellularIdentifierDisclosureNotifier notifier = getNotifier();
+
+        CellularIdentifierDisclosure emergencyDisclosure =
+                new CellularIdentifierDisclosure(
+                        CellularIdentifierDisclosure.NAS_PROTOCOL_MESSAGE_THREAT_IDENTIFIER_TRUE,
+                        CellularIdentifierDisclosure.CELLULAR_IDENTIFIER_IMSI,
+                        "001001",
+                        false);
+
+        notifier.enable(mContext);
+        notifier.addDisclosure(mContext, SUB_ID_1, emergencyDisclosure);
+
+        assertEquals(1, notifier.getCurrentDisclosureCount(SUB_ID_1));
+        verify(mSafetySource, times(1))
+                .setIdentifierDisclosure(any(), eq(SUB_ID_1), eq(1), any(), any());
+    }
+
+    @Test
     public void testAddDisclosureCountIncrements() {
         CellularIdentifierDisclosureNotifier notifier = getNotifier();
         notifier.enable(mContext);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/security/CellularNetworkSecuritySafetySourceTest.java b/tests/telephonytests/src/com/android/internal/telephony/security/CellularNetworkSecuritySafetySourceTest.java
index e409b8d..0578ef9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/security/CellularNetworkSecuritySafetySourceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/security/CellularNetworkSecuritySafetySourceTest.java
@@ -31,13 +31,11 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import android.app.ActivityManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.safetycenter.SafetySourceData;
 import android.safetycenter.SafetySourceIssue;
-import android.util.Singleton;
 
 import com.android.internal.R;
 import com.android.internal.telephony.TelephonyTest;
@@ -61,9 +59,7 @@
     public void setUp() throws Exception {
         super.setUp(getClass().getSimpleName());
 
-        // unmock ActivityManager to be able to register receiver, create real PendingIntents.
-        restoreInstance(Singleton.class, "mInstance", mIActivityManagerSingleton);
-        restoreInstance(ActivityManager.class, "IActivityManagerSingleton", null);
+        unmockActivityManager();
 
         SubscriptionInfoInternal info0 = new SubscriptionInfoInternal.Builder()
                 .setId(0)
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
index 5e560bc..9890f21 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
@@ -26,7 +26,6 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -134,6 +133,18 @@
     static final String FAKE_SATELLITE_ENTITLEMENT_PLMNS2 = "";
     static final int FAKE_SATELLITE_ESOS_SUPPORTED_ENABLED = 1;
     static final int FAKE_SATELLITE_ESOS_SUPPORTED_DISABLED = 0;
+    static final String FAKE_SATELLITE_ENTITLEMENT_BARRED_PLMNS1 = "321321,32101";
+    static final String FAKE_SATELLITE_ENTITLEMENT_BARRED_PLMNS2 = "";
+    static final String FAKE_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS1 =
+            "{\"302820\":0,\"31026\":1,\"40445\":0}";
+    static final String FAKE_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS2 = "";
+    static final String FAKE_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP1 =
+            "{\"302820\":[1,3],\"31026\":[2,3],\"40445\":[1,3]}";
+    static final String FAKE_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP2 = "";
+    static final String FAKE_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY1 = "{\"31026\":1}";
+    static final String FAKE_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY2 = "";
+    static final String FAKE_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY1 = "{\"31234\":2}";
+    static final String FAKE_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY2 = "";
 
     static final String FAKE_MAC_ADDRESS1 = "DC:E5:5B:38:7D:40";
     static final String FAKE_MAC_ADDRESS2 = "DC:B5:4F:47:F3:4C";
@@ -298,6 +309,16 @@
                     .setSatelliteEntitlementPlmns(FAKE_SATELLITE_ENTITLEMENT_PLMNS1)
                     .setSatelliteESOSSupported(FAKE_SATELLITE_ESOS_SUPPORTED_ENABLED)
                     .setIsSatelliteProvisionedForNonIpDatagram(FAKE_SATELLITE_PROVISIONED)
+                    .setSatelliteEntitlementBarredPlmnsList(
+                            FAKE_SATELLITE_ENTITLEMENT_BARRED_PLMNS1)
+                    .setSatelliteEntitlementDataPlanForPlmns(
+                            FAKE_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS1)
+                    .setSatelliteEntitlementPlmnServiceTypes(
+                            FAKE_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP1)
+                    .setSatellitePlmnsDataServicePolicy(
+                            FAKE_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY1)
+                    .setSatellitePlmnsVoiceServicePolicy(
+                            FAKE_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY1)
                     .build();
 
     private SubscriptionDatabaseManager mDatabaseManagerUT;
@@ -456,7 +477,6 @@
 
         doReturn(1).when(mUiccController).convertToPublicCardId(eq(FAKE_ICCID1));
         doReturn(2).when(mUiccController).convertToPublicCardId(eq(FAKE_ICCID2));
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         when(mFeatureFlags.supportPsimToEsimConversion()).thenReturn(true);
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         mDatabaseManagerUT = new SubscriptionDatabaseManager(mContext, Looper.myLooper(),
@@ -2074,51 +2094,6 @@
     }
 
     @Test
-    public void testUpdateSatelliteNtnWithFeatureDisabled() throws Exception {
-        assertThrows(IllegalArgumentException.class,
-                () -> mDatabaseManagerUT.setSatelliteAttachEnabledForCarrier(
-                        FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
-                        FAKE_SATELLITE_ATTACH_FOR_CARRIER_ENABLED));
-
-        SubscriptionInfoInternal subInfo = insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
-        mDatabaseManagerUT.setSatelliteAttachEnabledForCarrier(
-                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
-                FAKE_SATELLITE_IS_ONLY_NTN_DISABLED);
-        processAllMessages();
-
-        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
-        reset(mSubscriptionDatabaseManagerCallback);
-        subInfo = new SubscriptionInfoInternal.Builder(subInfo)
-                .setOnlyNonTerrestrialNetwork(FAKE_SATELLITE_IS_ONLY_NTN_ENABLED)
-                .build();
-
-        int subId = subInfo.getSubscriptionId();
-        // Verify the cache value is not same as the inserted one.
-        assertWithMessage("Subscription info cache value is not different.")
-                .that(mDatabaseManagerUT.getSubscriptionInfoInternal(subId)).isNotEqualTo(subInfo);
-
-        // Load subscription info from the database.
-        mDatabaseManagerUT.reloadDatabaseSync();
-        processAllMessages();
-
-        // Verify the database value is not same as the inserted one.
-        assertWithMessage("Subscription info database value is not different.")
-                .that(mDatabaseManagerUT.getSubscriptionInfoInternal(subId)).isNotEqualTo(subInfo);
-
-        verify(mSubscriptionDatabaseManagerCallback, never()).onSubscriptionChanged(eq(1));
-
-        assertThat(mDatabaseManagerUT.getSubscriptionProperty(
-                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
-                SimInfo.COLUMN_IS_ONLY_NTN)).isNotEqualTo(FAKE_SATELLITE_IS_ONLY_NTN_ENABLED);
-
-        mDatabaseManagerUT.setSubscriptionProperty(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
-                SimInfo.COLUMN_IS_ONLY_NTN, FAKE_SATELLITE_IS_ONLY_NTN_ENABLED);
-        assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
-                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId()).getOnlyNonTerrestrialNetwork())
-                .isNotEqualTo(FAKE_SATELLITE_IS_ONLY_NTN_ENABLED);
-    }
-
-    @Test
     public void testUpdateSubscriptionsInGroup() throws Exception {
         insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
         insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO2);
@@ -2431,4 +2406,172 @@
                 .getIsSatelliteProvisionedForNonIpDatagram())
                 .isEqualTo(FAKE_SATELLITE_NOT_PROVISIONED);
     }
+
+    @Test
+    public void testUpdateSatelliteEntitlementBarredPlmns() throws Exception {
+        // exception is expected if there is nothing in the database.
+        assertThrows(IllegalArgumentException.class,
+                () -> mDatabaseManagerUT.setSatelliteEntitlementBarredPlmns(
+                        FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                        FAKE_SATELLITE_ENTITLEMENT_BARRED_PLMNS1));
+
+        SubscriptionInfoInternal subInfo = insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
+        mDatabaseManagerUT.setSatelliteEntitlementBarredPlmns(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                FAKE_SATELLITE_ENTITLEMENT_BARRED_PLMNS1);
+        processAllMessages();
+
+        subInfo = new SubscriptionInfoInternal.Builder(
+                subInfo).setSatelliteEntitlementBarredPlmnsList(
+                FAKE_SATELLITE_ENTITLEMENT_BARRED_PLMNS1).build();
+        verifySubscription(subInfo);
+        verify(mSubscriptionDatabaseManagerCallback, times(2)).onSubscriptionChanged(eq(1));
+
+        assertThat(mDatabaseManagerUT.getSubscriptionProperty(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_BARRED_PLMNS)).isEqualTo(
+                FAKE_SATELLITE_ENTITLEMENT_BARRED_PLMNS1);
+
+        mDatabaseManagerUT.setSubscriptionProperty(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_BARRED_PLMNS,
+                FAKE_SATELLITE_ENTITLEMENT_BARRED_PLMNS2);
+        assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId())
+                .getSatelliteEntitlementBarredPlmnsList()).isEqualTo(
+                FAKE_SATELLITE_ENTITLEMENT_BARRED_PLMNS2);
+    }
+
+    @Test
+    public void testUpdateSatelliteEntitlementDataPlanForPlmns() throws Exception {
+        // exception is expected if there is nothing in the database.
+        assertThrows(IllegalArgumentException.class,
+                () -> mDatabaseManagerUT.setSatelliteEntitlementDataPlanForPlmns(
+                        FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                        FAKE_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS1));
+
+        SubscriptionInfoInternal subInfo = insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
+        mDatabaseManagerUT.setSatelliteEntitlementDataPlanForPlmns(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                FAKE_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS1);
+        processAllMessages();
+
+        subInfo = new SubscriptionInfoInternal.Builder(
+                subInfo).setSatelliteEntitlementDataPlanForPlmns(
+                FAKE_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS1).build();
+        verifySubscription(subInfo);
+        verify(mSubscriptionDatabaseManagerCallback, times(2)).onSubscriptionChanged(eq(1));
+
+        assertThat(mDatabaseManagerUT.getSubscriptionProperty(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS)).isEqualTo(
+                FAKE_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS1);
+
+        mDatabaseManagerUT.setSubscriptionProperty(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS,
+                FAKE_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS2);
+        assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId())
+                .getSatelliteEntitlementDataPlanForPlmns()).isEqualTo(
+                FAKE_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS2);
+    }
+
+    @Test
+    public void testUpdateSatelliteEntitlementPlmnServiceTypeMap() throws Exception {
+        // exception is expected if there is nothing in the database.
+        assertThrows(IllegalArgumentException.class,
+                () -> mDatabaseManagerUT.setSatelliteEntitlementPlmnServiceTypeMap(
+                        FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                        FAKE_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP1));
+
+        SubscriptionInfoInternal subInfo = insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
+        mDatabaseManagerUT.setSatelliteEntitlementPlmnServiceTypeMap(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                FAKE_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP1);
+        processAllMessages();
+
+        subInfo = new SubscriptionInfoInternal.Builder(
+                subInfo).setSatelliteEntitlementPlmnServiceTypes(
+                FAKE_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP1).build();
+        verifySubscription(subInfo);
+        verify(mSubscriptionDatabaseManagerCallback, times(2)).onSubscriptionChanged(eq(1));
+
+        assertThat(mDatabaseManagerUT.getSubscriptionProperty(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP)).isEqualTo(
+                FAKE_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP1);
+
+        mDatabaseManagerUT.setSubscriptionProperty(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP,
+                FAKE_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP2);
+        assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId())
+                .getSatelliteEntitlementPlmnsServiceTypes()).isEqualTo(
+                FAKE_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP2);
+    }
+
+    @Test
+    public void testUpdateSatelliteEntitlementPlmnDataServicePolicy() throws Exception {
+        // exception is expected if there is nothing in the database.
+        assertThrows(IllegalArgumentException.class,
+                () -> mDatabaseManagerUT.setSatelliteEntitlementPlmnDataServicePolicy(
+                        FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                        FAKE_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY1));
+
+        SubscriptionInfoInternal subInfo = insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
+        mDatabaseManagerUT.setSatelliteEntitlementPlmnDataServicePolicy(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                FAKE_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY1);
+        processAllMessages();
+
+        subInfo = new SubscriptionInfoInternal.Builder(subInfo).setSatellitePlmnsDataServicePolicy(
+                FAKE_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY1).build();
+        verifySubscription(subInfo);
+        verify(mSubscriptionDatabaseManagerCallback, times(2)).onSubscriptionChanged(eq(1));
+
+        assertThat(mDatabaseManagerUT.getSubscriptionProperty(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY)).isEqualTo(
+                FAKE_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY1);
+
+        mDatabaseManagerUT.setSubscriptionProperty(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY,
+                FAKE_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY2);
+        assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId())
+                .getSatellitePlmnsDataServicePolicy()).isEqualTo(
+                FAKE_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY2);
+    }
+
+    @Test
+    public void testUpdateSatelliteEntitlementPlmnVoiceServicePolicy() throws Exception {
+        // exception is expected if there is nothing in the database.
+        assertThrows(IllegalArgumentException.class,
+                () -> mDatabaseManagerUT.setSatelliteEntitlementPlmnVoiceServicePolicy(
+                        FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                        FAKE_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY1));
+
+        SubscriptionInfoInternal subInfo = insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
+        mDatabaseManagerUT.setSatelliteEntitlementPlmnVoiceServicePolicy(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                FAKE_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY1);
+        processAllMessages();
+
+        subInfo = new SubscriptionInfoInternal.Builder(subInfo).setSatellitePlmnsVoiceServicePolicy(
+                FAKE_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY1).build();
+        verifySubscription(subInfo);
+        verify(mSubscriptionDatabaseManagerCallback, times(2)).onSubscriptionChanged(eq(1));
+
+        assertThat(mDatabaseManagerUT.getSubscriptionProperty(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY)).isEqualTo(
+                FAKE_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY1);
+
+        mDatabaseManagerUT.setSubscriptionProperty(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                SimInfo.COLUMN_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY,
+                FAKE_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY2);
+        assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId())
+                .getSatellitePlmnsVoiceServicePolicy()).isEqualTo(
+                FAKE_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY2);
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
index f639a51..7e67676 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
@@ -124,6 +124,21 @@
                             SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ESOS_SUPPORTED_ENABLED)
                     .setIsSatelliteProvisionedForNonIpDatagram(
                             SubscriptionDatabaseManagerTest.FAKE_SATELLITE_PROVISIONED)
+                    .setSatelliteEntitlementBarredPlmnsList(
+                            SubscriptionDatabaseManagerTest
+                                    .FAKE_SATELLITE_ENTITLEMENT_BARRED_PLMNS1)
+                    .setSatelliteEntitlementDataPlanForPlmns(
+                            SubscriptionDatabaseManagerTest
+                                    .FAKE_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS1)
+                    .setSatelliteEntitlementPlmnServiceTypes(
+                            SubscriptionDatabaseManagerTest
+                                    .FAKE_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP1)
+                    .setSatellitePlmnsDataServicePolicy(
+                            SubscriptionDatabaseManagerTest
+                                    .FAKE_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY1)
+                    .setSatellitePlmnsVoiceServicePolicy(
+                            SubscriptionDatabaseManagerTest
+                                    .FAKE_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY1)
                     .build();
 
     private final SubscriptionInfoInternal mSubInfoNull =
@@ -257,6 +272,21 @@
                 .isEqualTo(SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ESOS_SUPPORTED_ENABLED);
         assertThat(mSubInfo.getIsSatelliteProvisionedForNonIpDatagram())
                 .isEqualTo(SubscriptionDatabaseManagerTest.FAKE_SATELLITE_PROVISIONED);
+        assertThat(mSubInfo.getSatelliteEntitlementBarredPlmnsList())
+                .isEqualTo(SubscriptionDatabaseManagerTest
+                        .FAKE_SATELLITE_ENTITLEMENT_BARRED_PLMNS1);
+        assertThat(mSubInfo.getSatelliteEntitlementDataPlanForPlmns())
+                .isEqualTo(SubscriptionDatabaseManagerTest
+                        .FAKE_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS1);
+        assertThat(mSubInfo.getSatelliteEntitlementPlmnsServiceTypes())
+                .isEqualTo(SubscriptionDatabaseManagerTest
+                        .FAKE_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP1);
+        assertThat(mSubInfo.getSatellitePlmnsDataServicePolicy())
+                .isEqualTo(SubscriptionDatabaseManagerTest
+                        .FAKE_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY1);
+        assertThat(mSubInfo.getSatellitePlmnsVoiceServicePolicy())
+                .isEqualTo(SubscriptionDatabaseManagerTest
+                        .FAKE_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY1);
     }
 
     @Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
index fa72021..492b94e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
@@ -43,7 +43,12 @@
 import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_PHONE_NUMBER2;
 import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_RCS_CONFIG1;
 import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_RCS_CONFIG2;
+import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ENTITLEMENT_BARRED_PLMNS1;
+import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS1;
+import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY1;
 import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ENTITLEMENT_PLMNS1;
+import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP1;
+import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY1;
 import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_IS_ONLY_NTN_DISABLED;
 import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SUBSCRIPTION_INFO1;
 import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SUBSCRIPTION_INFO2;
@@ -118,7 +123,6 @@
 import com.android.internal.telephony.uicc.IccCardStatus;
 import com.android.internal.telephony.uicc.UiccSlot;
 
-import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
 
 import org.junit.After;
@@ -137,7 +141,9 @@
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
@@ -204,6 +210,8 @@
         doReturn(true).when(mUiccSlot).isActive();
         doReturn(FAKE_ICCID1).when(mUiccController).convertToCardString(eq(1));
         doReturn(FAKE_ICCID2).when(mUiccController).convertToCardString(eq(2));
+        doReturn(true).when(mPackageManager).hasSystemFeature(
+                eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
 
         mBinder = Mockito.mock(BinderWrapper.class);
         doReturn(FAKE_USER_HANDLE).when(mBinder).getCallingUserHandle();
@@ -214,16 +222,16 @@
         ((MockContentResolver) mContext.getContentResolver()).addProvider(
                 Telephony.Carriers.CONTENT_URI.getAuthority(), mSubscriptionProvider);
 
-        doReturn(true).when(mFeatureFlags).saferGetPhoneNumber();
-        doReturn(true).when(mFeatureFlags).uiccPhoneNumberFix();
         doReturn(true).when(mFeatureFlags).ddsCallback();
-        doReturn(true).when(mFeatureFlags).oemEnabledSatelliteFlag();
 
         mSubscriptionManagerServiceUT = new SubscriptionManagerService(mContext, Looper.myLooper(),
                 mFeatureFlags);
 
         monitorTestableLooper(new TestableLooper(getBackgroundHandler().getLooper()));
-        monitorTestableLooper(new TestableLooper(getSubscriptionDatabaseManager().getLooper()));
+
+        if (!mFeatureFlags.threadShred()) {
+            monitorTestableLooper(new TestableLooper(getSubscriptionDatabaseManager().getLooper()));
+        }
 
         doAnswer(invocation -> {
             ((Runnable) invocation.getArguments()[0]).run();
@@ -243,8 +251,6 @@
         doReturn(true).when(mUserManager)
                 .isManagedProfile(eq(FAKE_MANAGED_PROFILE_USER_HANDLE.getIdentifier()));
 
-        doReturn(true).when(mPackageManager).hasSystemFeature(
-                eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
         logd("SubscriptionManagerServiceTest -Setup!");
     }
 
@@ -327,6 +333,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testBroadcastOnInitialization() {
         ArgumentCaptor<Intent> captorIntent = ArgumentCaptor.forClass(Intent.class);
         verify(mContext, times(3)).sendBroadcastAsUser(
@@ -338,6 +345,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testAddSubInfo() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1,
@@ -361,6 +369,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetMccMnc() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1,
@@ -381,6 +390,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetCountryIso() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1,
@@ -400,6 +410,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetCarrierId() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1,
@@ -419,6 +430,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetAdminOwned() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1, 0,
@@ -436,6 +448,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGroupOwner_callerMissingpPermission_throws() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1, 0,
@@ -450,51 +463,8 @@
     }
 
     @Test
-    @DisableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
-    public void testSetPhoneNumber() {
-        doReturn(false).when(mFeatureFlags).enforceTelephonyFeatureMapping();
-        doReturn(true).when(mPackageManager).hasSystemFeature(
-                eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
-
-        mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
-        mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1,
-                0, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
-        processAllMessages();
-
-        verify(mMockedSubscriptionManagerServiceCallback).onSubscriptionChanged(eq(1));
-        Mockito.clearInvocations(mMockedSubscriptionManagerServiceCallback);
-
-        // Caller does not have carrier privilege
-        assertThrows(SecurityException.class,
-                () -> mSubscriptionManagerServiceUT.setPhoneNumber(1,
-                        SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER, FAKE_PHONE_NUMBER2,
-                        CALLING_PACKAGE, CALLING_FEATURE));
-
-        // Grant carrier privilege
-        setCarrierPrivilegesForSubId(true, 1);
-
-        // Source IMS is not acceptable
-        assertThrows(IllegalArgumentException.class,
-                () -> mSubscriptionManagerServiceUT.setPhoneNumber(1,
-                        SubscriptionManager.PHONE_NUMBER_SOURCE_IMS, FAKE_PHONE_NUMBER2,
-                        CALLING_PACKAGE, CALLING_FEATURE));
-
-        mSubscriptionManagerServiceUT.setPhoneNumber(1,
-                SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER, FAKE_PHONE_NUMBER2,
-                CALLING_PACKAGE, CALLING_FEATURE);
-        processAllMessages();
-
-        SubscriptionInfoInternal subInfo = mSubscriptionManagerServiceUT
-                .getSubscriptionInfoInternal(1);
-        assertThat(subInfo).isNotNull();
-        assertThat(subInfo.getNumberFromCarrier()).isEqualTo(FAKE_PHONE_NUMBER2);
-        verify(mMockedSubscriptionManagerServiceCallback).onSubscriptionChanged(eq(1));
-    }
-
-    @Test
     @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
-    public void testSetPhoneNumber_EnabledEnforceTelephonyFeatureMappingForPublicApis()
-            throws Exception {
+    public void testSetPhoneNumber() throws Exception {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1,
                 0, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
@@ -511,8 +481,7 @@
         replaceInstance(SubscriptionManagerService.class, "mVendorApiLevel",
                 mSubscriptionManagerServiceUT, vendorApiLevel);
 
-        // Enabled FeatureFlags and ENABLE_FEATURE_MAPPING, telephony features are defined
-        doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
+        // Enabled ENABLE_FEATURE_MAPPING, telephony features are defined
         doReturn(true).when(mPackageManager).hasSystemFeature(
                 eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
         try {
@@ -533,6 +502,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetAllSubInfoList() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
@@ -663,6 +633,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetAvailableSubscriptionInfoList() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         SubscriptionInfoInternal anotherSubInfo =
@@ -698,6 +669,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetDefaultVoiceSubId() throws Exception {
         clearInvocations(mContext);
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
@@ -740,6 +712,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetDefaultDataSubId() throws Exception {
         clearInvocations(mContext);
         doReturn(false).when(mTelephonyManager).isVoiceCapable();
@@ -786,6 +759,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSingleSimSetDefaultDataSubId() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
@@ -806,6 +780,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetDefaultSmsSubId() throws Exception {
         clearInvocations(mContext);
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
@@ -837,6 +812,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testIsActiveSubId() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(new SubscriptionInfoInternal.Builder(FAKE_SUBSCRIPTION_INFO2)
@@ -855,6 +831,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetActiveSubscriptionInfoList() {
         // Grant MODIFY_PHONE_STATE permission for insertion.
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
@@ -893,6 +870,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetActiveSubscriptionInfoForSimSlotIndex() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -924,6 +902,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testUpdateEmbeddedSubscriptions() {
         EuiccProfileInfo profileInfo1 = new EuiccProfileInfo.Builder(FAKE_ICCID1)
                 .setIccid(FAKE_ICCID1)
@@ -999,6 +978,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testUpdateEmbeddedSubscriptionsNullResult() {
         // Grant READ_PHONE_STATE permission.
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE);
@@ -1018,6 +998,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetActiveSubscriptionInfo() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1048,6 +1029,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetDisplayNameUsingSrc() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1075,6 +1057,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetActiveSubInfoCount() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -1089,6 +1072,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetIconTint() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1108,6 +1092,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetActiveSubscriptionInfoForIccId() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1122,6 +1107,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetAccessibleSubscriptionInfoList() {
         doReturn(true).when(mEuiccManager).isEnabled();
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -1160,6 +1146,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testIsSubscriptionEnabled() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1173,6 +1160,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetEnabledSubscriptionId() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1192,12 +1180,14 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetActiveDataSubscriptionId() {
         doReturn(12345).when(mPhoneSwitcher).getActiveDataSubId();
         assertThat(mSubscriptionManagerServiceUT.getActiveDataSubscriptionId()).isEqualTo(12345);
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetSubscriptionUserHandle() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1231,6 +1221,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSubscriptionUserHandleUnknownSubscription() {
         mContextFixture.addCallingOrSelfPermission(
                 Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
@@ -1244,6 +1235,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testIsSubscriptionAssociatedWithUser() {
         // Should fail without MANAGE_SUBSCRIPTION_USER_ASSOCIATION
         assertThrows(SecurityException.class, () -> mSubscriptionManagerServiceUT
@@ -1621,6 +1613,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetUsageSetting() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1645,6 +1638,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetDisplayNumber() {
         insertSubscription(new SubscriptionInfoInternal.Builder(FAKE_SUBSCRIPTION_INFO1)
                 .setNumberFromCarrier("")
@@ -1667,6 +1661,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetOpportunistic() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1686,6 +1681,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetOpportunisticSubscriptions() {
         testSetOpportunistic();
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -1713,6 +1709,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetPreferredDataSubscriptionId() {
         // Should fail without MODIFY_PHONE_STATE
         assertThrows(SecurityException.class, () -> mSubscriptionManagerServiceUT
@@ -1725,6 +1722,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetPreferredDataSubscriptionId() {
         // Should fail without READ_PRIVILEGED_PHONE_STATE
         assertThrows(SecurityException.class, () -> mSubscriptionManagerServiceUT
@@ -1737,6 +1735,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testAddSubscriptionsIntoGroup() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -1761,6 +1760,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetDeviceToDeviceStatusSharing() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1784,6 +1784,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetDeviceToDeviceStatusSharingContacts() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1804,6 +1805,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetPhoneNumberFromFirstAvailableSource() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1818,6 +1820,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetPhoneNumberSourcePriority() throws Exception {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_NUMBERS);
 
@@ -1857,6 +1860,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetUiccApplicationsEnabled() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1886,6 +1890,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testCanDisablePhysicalSubscription() {
         // Should fail without READ_PRIVILEGED_PHONE_STATE
         assertThrows(SecurityException.class, () -> mSubscriptionManagerServiceUT
@@ -1901,6 +1906,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetEnhanced4GModeEnabled() throws Exception {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1926,6 +1932,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetVideoTelephonyEnabled() throws Exception {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1951,6 +1958,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetWifiCallingEnabled() throws Exception {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -1976,6 +1984,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetWifiCallingMode() throws Exception {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2001,6 +2010,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetWifiCallingModeForRoaming() throws Exception {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2026,6 +2036,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetEnabledMobileDataPolicies() throws Exception {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2052,6 +2063,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetRcsUceEnabled() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2080,6 +2092,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetCrossSimCallingEnabled() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2106,6 +2119,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetRcsConfig() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2132,6 +2146,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetDeviceToDeviceStatusSharingPreference() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2157,6 +2172,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetVoImsOptInEnabled() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2182,6 +2198,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetDeviceToDeviceStatusSharingContacts() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2209,6 +2226,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetGetNrAdvancedCallingEnabled() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2235,6 +2253,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSetSubscriptionPropertyInvalidField() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
@@ -2244,6 +2263,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetNumberWithCarrierNumber() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2277,6 +2297,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetNonAccessibleFields() throws Exception {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -2300,6 +2321,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSyncToGroup() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -2384,6 +2406,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testRemoveSubInfo() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -2405,6 +2428,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testUserUnlockUpdateEmbeddedSubscriptions() {
         doReturn(true).when(mUiccSlot).isEuicc();
         doReturn(1).when(mUiccController).convertToPublicCardId(FAKE_ICCID1);
@@ -2449,6 +2473,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testInsertNewSim() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
@@ -2510,6 +2535,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGroupDisable() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(new SubscriptionInfoInternal.Builder(FAKE_SUBSCRIPTION_INFO2)
@@ -2520,10 +2546,12 @@
     }
 
     @Test
-    @DisableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
-    public void testGetPhoneNumber() {
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
+    public void testGetPhoneNumber() throws Exception {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         testSetPhoneNumber();
+        doReturn(true).when(mPackageManager).hasSystemFeature(
+                eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
         assertThat(mSubscriptionManagerServiceUT.getPhoneNumber(1,
                 SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER, CALLING_PACKAGE, CALLING_FEATURE))
                 .isEqualTo(FAKE_PHONE_NUMBER2);
@@ -2534,9 +2562,12 @@
     }
 
     @Test
-    public void testGetPhoneNumberFromUicc() {
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
+    public void testGetPhoneNumberFromUicc() throws Exception {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         testSetPhoneNumber();
+        doReturn(true).when(mPackageManager).hasSystemFeature(
+                eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
         // Number from line1Number should be FAKE_PHONE_NUMBER1 instead of FAKE_PHONE_NUMBER2
         assertThat(mSubscriptionManagerServiceUT.getPhoneNumber(1,
                 SubscriptionManager.PHONE_NUMBER_SOURCE_UICC, CALLING_PACKAGE, CALLING_FEATURE))
@@ -2547,10 +2578,11 @@
         // If getLine1Number is empty, then the number should be from the sub info.
         assertThat(mSubscriptionManagerServiceUT.getPhoneNumber(1,
                 SubscriptionManager.PHONE_NUMBER_SOURCE_UICC, CALLING_PACKAGE, CALLING_FEATURE))
-                .isEqualTo(FAKE_PHONE_NUMBER2);
+                .isEqualTo("");
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetPhoneNumberFromInactiveSubscription() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         testInactiveSimRemoval();
@@ -2569,6 +2601,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetPhoneNumberFromDefaultSubscription() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
@@ -2600,6 +2633,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testEsimActivation() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
@@ -2681,6 +2715,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testDeleteEsim() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         // pSIM with ICCID2
@@ -2739,6 +2774,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testEsimSwitch() {
         setIdentifierAccess(true);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
@@ -2789,6 +2825,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testDump() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
@@ -2806,6 +2843,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testOnSubscriptionChanged() {
         CountDownLatch latch = new CountDownLatch(1);
         SubscriptionManagerServiceCallback callback =
@@ -2823,6 +2861,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testOnUiccApplicationsEnabled() {
         CountDownLatch latch = new CountDownLatch(1);
         Executor executor = Runnable::run;
@@ -2852,6 +2891,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testDeactivatePsim() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         testInsertNewSim();
@@ -2870,6 +2910,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testRemoteSim() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
@@ -2884,7 +2925,8 @@
                 .getSubscriptionInfoInternal(1);
         assertThat(subInfo.getIccId()).isEqualTo(FAKE_MAC_ADDRESS1);
         assertThat(subInfo.getDisplayName()).isEqualTo(FAKE_CARRIER_NAME1);
-        assertThat(subInfo.getSimSlotIndex()).isEqualTo(0);
+        assertThat(subInfo.getSimSlotIndex()).isEqualTo(
+                SubscriptionManager.INVALID_SIM_SLOT_INDEX);
         assertThat(subInfo.getSubscriptionType()).isEqualTo(
                 SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM);
 
@@ -2908,6 +2950,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testRemoveSubscriptionsFromGroup() {
         testAddSubscriptionsIntoGroup();
 
@@ -2936,6 +2979,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testUpdateSimStateForInactivePort() {
         testSetUiccApplicationsEnabled();
 
@@ -2949,6 +2993,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testInactiveSimInserted() {
         doReturn(0).when(mUiccSlot).getPortIndexFromIccId(eq(FAKE_ICCID1));
 
@@ -2966,6 +3011,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testRestoreAllSimSpecificSettingsFromBackup() throws Exception {
         assertThrows(SecurityException.class, ()
                 -> mSubscriptionManagerServiceUT.restoreAllSimSpecificSettingsFromBackup(
@@ -3003,6 +3049,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSubscriptionMap() {
         SubscriptionMap<Integer, Integer> map = new SubscriptionMap<>();
         map.put(1, 1);
@@ -3016,6 +3063,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSimNotReady() {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         mSubscriptionManagerServiceUT.updateSimState(
@@ -3026,6 +3074,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testSimNotReadyBySimDeactivate() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -3039,6 +3088,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testInactiveSimRemoval() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO2);
 
@@ -3074,6 +3124,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testEmbeddedProfilesUpdateFailed() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
 
@@ -3117,6 +3168,7 @@
 
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testNonNullSubInfoBuilderFromEmbeddedProfile() {
         EuiccProfileInfo profileInfo1 = new EuiccProfileInfo.Builder(FAKE_ICCID1)
                 .setIccid(FAKE_ICCID1) //can't build profile with null iccid.
@@ -3174,6 +3226,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetActiveSubscriptionInfoListNoSecurityException() {
         // Grant MODIFY_PHONE_STATE permission for insertion.
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
@@ -3200,6 +3253,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testUpdateGroupDisabled() {
         insertSubscription(FAKE_SUBSCRIPTION_INFO1);
         insertSubscription(new SubscriptionInfoInternal
@@ -3213,6 +3267,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testIsSatelliteSpn() {
         mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
                 FAKE_CARRIER_NAME1);
@@ -3249,6 +3304,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testIsSatelliteSpnWithEmptySpn() {
         mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier, ""); // Empty
         System.setProperty("persist.radio.allow_mock_modem", "true");
@@ -3310,6 +3366,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testIsSatelliteSpnWithNullCarrierIdentifier() {
         mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
                 FAKE_CARRIER_NAME1);
@@ -3345,6 +3402,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testIsSatelliteSpnWithWrongSpn() {
         mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
                 FAKE_CARRIER_NAME1);
@@ -3381,6 +3439,7 @@
     }
 
     @Test
+    @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
     public void testGetSatelliteEntitlementPlmnList() throws Exception {
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
 
@@ -3390,12 +3449,32 @@
         List<String> expectedPlmnList = new ArrayList<>();
         int subId = 1;
 
-        SubscriptionInfoInternal subInfo = mSubscriptionManagerServiceUT
-                .getSubscriptionInfoInternal(subId);
+        SubscriptionInfoInternal subInfo =
+                mSubscriptionManagerServiceUT.getSubscriptionInfoInternal(subId);
         assertTrue(subInfo.getSatelliteEntitlementPlmns().isEmpty());
         assertEquals(expectedPlmnList,
                 mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnList(subId));
 
+        assertTrue(subInfo.getSatelliteEntitlementBarredPlmnsList().isEmpty());
+        assertEquals(expectedPlmnList,
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementBarredPlmnList(subId));
+
+        assertTrue(subInfo.getSatelliteEntitlementDataPlanForPlmns().isEmpty());
+        assertEquals(new HashMap<>(),
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementDataPlanForPlmns(subId));
+
+        assertTrue(subInfo.getSatelliteEntitlementPlmnsServiceTypes().isEmpty());
+        assertEquals(new HashMap<>(),
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnServiceTypeMap(subId));
+
+        assertTrue(subInfo.getSatellitePlmnsDataServicePolicy().isEmpty());
+        assertEquals(new HashMap<>(),
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnDataServicePolicy(subId));
+
+        assertTrue(subInfo.getSatellitePlmnsVoiceServicePolicy().isEmpty());
+        assertEquals(new HashMap<>(),
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnVoiceServicePolicy(subId));
+
         // When the list is stored as [123123,12310], verify whether SubscriptionInfoInternal
         // returns the string as "123123,12310" and SubscriptionManagerService returns the List as
         // [123123,12310].
@@ -3403,12 +3482,57 @@
         String expectedPlmn = FAKE_SATELLITE_ENTITLEMENT_PLMNS1;
         expectedPlmnList = Arrays.stream(expectedPlmn.split(",")).collect(Collectors.toList());
         subId = 2;
-
         subInfo = mSubscriptionManagerServiceUT.getSubscriptionInfoInternal(subId);
         assertEquals(expectedPlmn, subInfo.getSatelliteEntitlementPlmns());
         assertEquals(expectedPlmnList,
                 mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnList(subId));
 
+        // When the list is stored as [123123,12310], verify whether SubscriptionInfoInternal
+        // returns the string as "123123,12310" and SubscriptionManagerService returns the List as
+        // [123123,12310].
+        expectedPlmn = FAKE_SATELLITE_ENTITLEMENT_BARRED_PLMNS1;
+        expectedPlmnList = Arrays.stream(expectedPlmn.split(",")).collect(Collectors.toList());
+        assertEquals(expectedPlmn, subInfo.getSatelliteEntitlementBarredPlmnsList());
+        assertEquals(expectedPlmnList,
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementBarredPlmnList(subId));
+
+        // When the Map is stored as {"302820":0,"31026":1,"40445":0}, verify whether
+        // SubscriptionInfoInternal returns the Map as {"302820":0,"31026":1,"40445":0} and
+        // SubscriptionManagerService returns the Map as {"302820":0,"31026":1,"40445":0}.
+        String entitlementInfo = FAKE_SATELLITE_ENTITLEMENT_DATA_PLAN_PLMNS1;
+        Map<String, Integer> entitlementInfoMap = mSubscriptionManagerServiceUT.deSerializeCVToMap(
+                entitlementInfo);
+        assertEquals(entitlementInfo, subInfo.getSatelliteEntitlementDataPlanForPlmns());
+        assertEquals(entitlementInfoMap,
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementDataPlanForPlmns(subId));
+
+        // When the Map is stored as {"302820":[1,3],"31026":[2,3],"40445":[1,3]}, verify whether
+        // SubscriptionInfoInternal returns the Map as {"302820":[1,3],"31026":[2,3],"40445":[1,
+        // 3]} and SubscriptionManagerService returns the Map as {"302820":[1,3],"31026":[2,3],
+        // "40445":[1,3]}.
+        entitlementInfo = FAKE_SATELLITE_ENTITLEMENT_SERVICE_TYPE_MAP1;
+        Map<String, List<Integer>> entitlementInfoMapList =
+                mSubscriptionManagerServiceUT.deSerializeCVToMapList(entitlementInfo);
+        assertEquals(entitlementInfo, subInfo.getSatelliteEntitlementPlmnsServiceTypes());
+        assertEquals(entitlementInfoMapList,
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnServiceTypeMap(subId));
+
+        // When the Map is stored as {"31026":1}, verify whether SubscriptionInfoInternal returns
+        // the Map as {"31026":1} and SubscriptionManagerService returns the Map as {"31026":1}.
+        entitlementInfo = FAKE_SATELLITE_ENTITLEMENT_DATA_SERVICE_POLICY1;
+        entitlementInfoMap = mSubscriptionManagerServiceUT.deSerializeCVToMap(entitlementInfo);
+        assertEquals(entitlementInfo, subInfo.getSatellitePlmnsDataServicePolicy());
+        assertEquals(entitlementInfoMap,
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnDataServicePolicy(subId));
+
+        // When the Map is stored as {"31234":2}, verify whether SubscriptionInfoInternal returns
+        // the Map as {"31234":2} and SubscriptionManagerService returns the Map as {"31234":2}.
+        entitlementInfo = FAKE_SATELLITE_ENTITLEMENT_VOICE_SERVICE_POLICY1;
+        entitlementInfoMap = mSubscriptionManagerServiceUT.deSerializeCVToMap(entitlementInfo);
+        assertEquals(entitlementInfo, subInfo.getSatellitePlmnsVoiceServicePolicy());
+        assertEquals(entitlementInfoMap,
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnVoiceServicePolicy(subId));
+
         // When calling SubscriptionDatabaseManager#getSubscriptionInfoInternalreturns returns a
         // null, then verify the SubscriptionManagerService returns an empty List.
         SubscriptionDatabaseManager mockSubscriptionDatabaseManager = Mockito.mock(
@@ -3423,6 +3547,21 @@
         assertEquals(expectedPlmnList,
                 mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnList(subId));
 
+        assertEquals(expectedPlmnList,
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementBarredPlmnList(subId));
+
+        assertEquals(new HashMap<>(),
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementDataPlanForPlmns(subId));
+
+        assertEquals(new HashMap<>(),
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnServiceTypeMap(subId));
+
+        assertEquals(new HashMap<>(),
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnDataServicePolicy(subId));
+
+        assertEquals(new HashMap<>(),
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnVoiceServicePolicy(subId));
+
         // When calling SubscriptionDatabaseManager#getSubscriptionInfoInternalreturns returns a
         // non null. And when calling SubscriptionInfoInternal#getSatelliteEntitlementPlmns
         // returns a null, then verify the SubscriptionManagerService returns an empty List.
@@ -3430,10 +3569,31 @@
                 SubscriptionInfoInternal.class);
         doReturn(mockSubscriptionInfoInternal).when(
                 mockSubscriptionDatabaseManager).getSubscriptionInfoInternal(anyInt());
-        doReturn(null).when(mockSubscriptionInfoInternal).getSatelliteEntitlementPlmns();
 
+        doReturn(null).when(mockSubscriptionInfoInternal).getSatelliteEntitlementPlmns();
         assertEquals(expectedPlmnList,
                 mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnList(subId));
+
+        doReturn(null).when(mockSubscriptionInfoInternal).getSatelliteEntitlementBarredPlmnsList();
+        assertEquals(expectedPlmnList,
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementBarredPlmnList(subId));
+
+        doReturn(null).when(mockSubscriptionInfoInternal).getSatelliteEntitlementDataPlanForPlmns();
+        assertEquals(new HashMap<>(),
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementDataPlanForPlmns(subId));
+
+        doReturn(null).when(
+                mockSubscriptionInfoInternal).getSatelliteEntitlementPlmnsServiceTypes();
+        assertEquals(new HashMap<>(),
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnServiceTypeMap(subId));
+
+        doReturn(null).when(mockSubscriptionInfoInternal).getSatellitePlmnsDataServicePolicy();
+        assertEquals(new HashMap<>(),
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnDataServicePolicy(subId));
+
+        doReturn(null).when(mockSubscriptionInfoInternal).getSatellitePlmnsVoiceServicePolicy();
+        assertEquals(new HashMap<>(),
+                mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnVoiceServicePolicy(subId));
     }
 
     public void testIsSatelliteProvisionedForNonIpDatagram() {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/IccPhoneBookInterfaceManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/IccPhoneBookInterfaceManagerTest.java
index 53627ca..8cf8c6e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/IccPhoneBookInterfaceManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/IccPhoneBookInterfaceManagerTest.java
@@ -18,8 +18,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyObject;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
@@ -87,7 +86,7 @@
                 response.sendToTarget();
                 return null;
             }
-        }).when(mAdnRecordCache).requestLoadAllAdnLike(anyInt(), anyInt(), (Message) anyObject());
+        }).when(mAdnRecordCache).requestLoadAllAdnLike(anyInt(), anyInt(), (Message) any());
 
         doAnswer(invocation -> {
             Message response = (Message) invocation.getArguments()[0];
@@ -95,7 +94,7 @@
             AsyncResult.forMessage(response).result = mAdnList;
             response.sendToTarget();
             return null;
-        }).when(mSimPhonebookRecordCache).requestLoadAllPbRecords((Message)anyObject());
+        }).when(mSimPhonebookRecordCache).requestLoadAllPbRecords((Message)any());
         mIccPhoneBookInterfaceManagerHandler = new IccPhoneBookInterfaceManagerHandler(TAG);
         mIccPhoneBookInterfaceManagerHandler.start();
 
@@ -131,7 +130,7 @@
                 response.sendToTarget();
                 return null;
             }
-        }).when(mAdnRecordCache).requestLoadAllAdnLike(anyInt(), anyInt(), (Message) anyObject());
+        }).when(mAdnRecordCache).requestLoadAllAdnLike(anyInt(), anyInt(), (Message) any());
         List<AdnRecord> adnListResultNew = mIccPhoneBookInterfaceMgr.getAdnRecordsInEf(
                 IccConstants.EF_ADN);
         //the later read return null due to exception
@@ -153,7 +152,7 @@
             AsyncResult.forMessage(response).exception = new RuntimeException();
             response.sendToTarget();
             return null;
-        }).when(mSimPhonebookRecordCache).requestLoadAllPbRecords((Message) anyObject());
+        }).when(mSimPhonebookRecordCache).requestLoadAllPbRecords((Message) any());
         List<AdnRecord> adnListResultNew = mIccPhoneBookInterfaceMgr.getAdnRecordsInEf(
                 IccConstants.EF_ADN);
         //the later read return null due to exception
@@ -177,7 +176,7 @@
             }
         }).when(mAdnRecordCache).updateAdnBySearch(
             anyInt(), any(), any(),
-            any(), (Message) anyObject());
+            any(), (Message) any());
 
         ContentValues values = new ContentValues();
         values.put(IccProvider.STR_TAG, "");
@@ -206,7 +205,7 @@
             response.sendToTarget();
             return null;
         }).when(mSimPhonebookRecordCache).updateSimPbAdnBySearch(any(),
-            any(), (Message) anyObject());
+            any(), (Message) any());
 
         ContentValues values = new ContentValues();
         values.put(IccProvider.STR_TAG, "");
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/RuimRecordsTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/RuimRecordsTest.java
deleted file mode 100644
index a9b433f..0000000
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/RuimRecordsTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony.uicc;
-
-import static org.junit.Assert.*;
-
-import android.os.AsyncResult;
-import android.os.HandlerThread;
-
-import com.android.internal.telephony.TelephonyTest;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class RuimRecordsTest extends TelephonyTest {
-
-    private RuimRecords mRuimRecords;
-
-    private class RuimRecordsTestHandler extends HandlerThread {
-        private RuimRecordsTestHandler(String name) {
-            super(name);
-        }
-
-        @Override
-        public void onLooperPrepared() {
-            mRuimRecords = new RuimRecords(mUiccCardApplication3gpp2, mContext, mSimulatedCommands);
-            setReady(true);
-        }
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        super.setUp(getClass().getSimpleName());
-        new RuimRecordsTestHandler(TAG).start();
-        waitUntilReady();
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        mRuimRecords = null;
-        super.tearDown();
-    }
-
-    @Test
-    public void testCsimImsiLoaded() {
-        RuimRecords.EfCsimImsimLoaded mImsiLoaded = mRuimRecords.new EfCsimImsimLoaded();
-        AsyncResult ar = new AsyncResult(null, null, null);
-        mImsiLoaded.onRecordLoaded(ar);
-        String mccmnc = mRuimRecords.getRUIMOperatorNumeric();
-        assertNull(mccmnc);
-
-        byte[] byteArray = new byte[]{0, 19, 3, 75, 68, 88, 99, (byte)128, (byte)209, 0};
-        AsyncResult ar2 = new AsyncResult(null, byteArray, null);
-        mImsiLoaded.onRecordLoaded(ar2);
-        mccmnc = mRuimRecords.getRUIMOperatorNumeric();
-        assertNotNull(mccmnc);
-        assertEquals("310008", mccmnc);
-    }
-
-    @Test
-    public void testCsimImsiDecode() {
-        RuimRecords.EfCsimImsimLoaded efCsimImsimLoaded = mRuimRecords.new EfCsimImsimLoaded();
-
-        // mcc + mnc + min
-        byte[] byteArray = new byte[]{0, 19, 3, 75, 68, 88, 99, (byte)128, (byte)209, 0};
-        String imsi = efCsimImsimLoaded.decodeImsi(byteArray);
-
-        assertEquals("310008984641186", imsi);
-    }
-}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/SIMRecordsTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/SIMRecordsTest.java
index e109ebb..7dc13a0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/SIMRecordsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/SIMRecordsTest.java
@@ -23,7 +23,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java
index 9a444d7..7e95107 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java
@@ -17,8 +17,8 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.doAnswer;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
index 47b7c53..ac11c92 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
@@ -23,7 +23,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java
index ca322e0..2ccafde 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccProfileTest.java
@@ -34,7 +34,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.Message;
 import android.os.PersistableBundle;
@@ -488,34 +487,6 @@
 
     @Test
     @SmallTest
-    public void testUpdateUiccProfileApplicationCdmaSupported() {
-        // CDMA supported
-        doReturn(true)
-            .when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA);
-
-        testWithCsimApp();
-
-        // CDMA is supported and CSIM app is not ready, so state should be NOT_READY
-        assertEquals(State.NOT_READY, mUiccProfile.getState());
-    }
-
-    @Test
-    @SmallTest
-    public void testUpdateUiccProfileApplicationCdmaNotSupported() {
-        // CDMA not supported
-        doReturn(false)
-            .when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA);
-
-        testWithCsimApp();
-
-        // state is loaded as all records are loaded right away as SimulatedCommands returns
-        // response for them right away. Ideally applications and records should be mocked.
-        // CSIM is not ready but that should not matter since CDMA is not supported.
-        assertEquals(State.LOADED, mUiccProfile.getState());
-    }
-
-    @Test
-    @SmallTest
     public void testUpdateExternalState() {
         // IO_ERROR
         doReturn(IccCardStatus.CardState.CARDSTATE_ERROR).when(mUiccCard).getCardState();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
index 8449ecc..1de15fe 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccSlotTest.java
@@ -21,7 +21,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyObject;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -428,8 +428,8 @@
         mIccCardStatus.mSlotPortMapping.mPortIndex = 0;
         mUiccSlot.update(mSimulatedCommands, mIccCardStatus, phoneId, slotIndex);
         verify(mTelephonyComponentFactory).makeUiccProfile(
-                anyObject(), eq(mSimulatedCommands), eq(mIccCardStatus), anyInt(), anyObject(),
-                anyObject(), anyObject());
+                any(), eq(mSimulatedCommands), eq(mIccCardStatus), anyInt(), any(),
+                any(), any());
         assertEquals(IccCardStatus.CardState.CARDSTATE_PRESENT, mUiccSlot.getCardState());
         assertNotNull(mUiccSlot.getUiccCard());
 
@@ -451,8 +451,8 @@
         mIccCardStatus.mCardState = IccCardStatus.CardState.CARDSTATE_PRESENT;
         mUiccSlot.update(mSimulatedCommands, mIccCardStatus, phoneId, slotIndex);
         verify(mTelephonyComponentFactory).makeUiccProfile(
-                anyObject(), eq(mSimulatedCommands), eq(mIccCardStatus), anyInt(), anyObject(),
-                anyObject(), anyObject());
+                any(), eq(mSimulatedCommands), eq(mIccCardStatus), anyInt(), any(),
+                any(), any());
         assertEquals(IccCardStatus.CardState.CARDSTATE_PRESENT, mUiccSlot.getCardState());
         assertNotNull(mUiccSlot.getUiccCard());
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
index c9b159c..5eeb949 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccStateChangedLauncherTest.java
@@ -19,7 +19,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyObject;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -99,7 +98,7 @@
         ArgumentCaptor<Integer> integerArgumentCaptor = ArgumentCaptor.forClass(Integer.class);
         verify(UiccController.getInstance(), times(1)).registerForIccChanged(eq(uiccLauncher),
                 integerArgumentCaptor.capture(),
-                anyObject());
+                any());
         Message msg = Message.obtain();
         msg.what = integerArgumentCaptor.getValue();
 
@@ -163,6 +162,6 @@
         UiccStateChangedLauncher uiccLauncher =
                 new UiccStateChangedLauncher(mContext, UiccController.getInstance(), mFeatureFlags);
         verify(UiccController.getInstance(), never()).registerForIccChanged(eq(uiccLauncher),
-                anyInt(), anyObject());
+                anyInt(), any());
     }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
index 1252ff8..88e9142 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
@@ -33,6 +33,7 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
 import android.platform.test.flag.junit.SetFlagsRule;
@@ -106,23 +107,29 @@
     private ResponseCaptor mResponseCaptor;
     private byte[] mSelectResponse;
     private ApduSender mSender;
+    private Context mContext;
 
     @Before
     public void setUp() {
         mSetFlagsRule.enableFlags(Flags.FLAG_OPTIMIZATION_APDU_SENDER);
 
+        mContext = InstrumentationRegistry.getContext();
         mMockCi = mock(CommandsInterface.class);
         mLooper = TestableLooper.get(this);
         mHandler = new Handler(mLooper.getLooper());
         mResponseCaptor = new ResponseCaptor();
         mSelectResponse = null;
 
-        mSender = new ApduSender(InstrumentationRegistry.getContext(), PHONE_ID,
+        mSender = new ApduSender(mContext, PHONE_ID,
                             mMockCi, ApduSender.ISD_R_AID, false /* supportExtendedApdu */);
     }
 
     @After
-    public void tearDown() {
+    public void tearDown() throws InterruptedException {
+        // Send an APDU to verify that the channel lock is not stuck (b/382549728).
+        // Sameas testSend(), but not verifying mMockCi interactions.
+        checkChannelLock();
+
         mHandler.removeCallbacksAndMessages(null);
         mHandler = null;
         mLooper = null;
@@ -130,7 +137,7 @@
         mSelectResponse = null;
         mSender = null;
 
-        EuiccSession.get().endSession(SESSION_ID);
+        EuiccSession.get(mContext).endSession(SESSION_ID);
         clearSharedPreferences();
     }
 
@@ -454,7 +461,7 @@
         int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
         LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, "A1A1A19000");
         LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
-        EuiccSession.get().startSession(SESSION_ID);
+        EuiccSession.get(mContext).startSession(SESSION_ID);
 
         mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
                 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
@@ -465,7 +472,7 @@
         inOrder.verify(mMockCi).iccOpenLogicalChannel(eq(ApduSender.ISD_R_AID), anyInt(), any());
         inOrder.verify(mMockCi).iccTransmitApduLogicalChannel(eq(channel), eq(channel | 10),
                 eq(1), eq(2), eq(3), eq(0), eq("a"), anyBoolean(), any());
-        // No iccCloseLogicalChannel
+        inOrder.verify(mMockCi).iccCloseLogicalChannel(eq(channel), eq(true /*isEs10*/), any());
         inOrder.verifyNoMoreInteractions();
     }
 
@@ -476,7 +483,7 @@
         LogicalChannelMocker.mockSendToLogicalChannel(
                     mMockCi, channel, "A1A1A19000", "A1A1A19000");
         LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
-        EuiccSession.get().startSession(SESSION_ID);
+        EuiccSession.get(mContext).startSession(SESSION_ID);
 
         mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
                 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
@@ -492,7 +499,7 @@
         // iccTransmitApduLogicalChannel twice
         inOrder.verify(mMockCi, times(2)).iccTransmitApduLogicalChannel(eq(channel),
                  eq(channel | 10), eq(1), eq(2), eq(3), eq(0), eq("a"), anyBoolean(), any());
-        // No iccCloseLogicalChannel
+        inOrder.verify(mMockCi).iccCloseLogicalChannel(eq(channel), eq(true /*isEs10*/), any());
         inOrder.verifyNoMoreInteractions();
     }
 
@@ -502,7 +509,7 @@
         LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel,
                 "A1A1A19000", "A1A1A19000");
         LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
-        EuiccSession.get().startSession(SESSION_ID);
+        EuiccSession.get(mContext).startSession(SESSION_ID);
 
         mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
                 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
@@ -510,7 +517,7 @@
         mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
                 10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
         mLooper.processAllMessages();
-        EuiccSession.get().endSession(SESSION_ID);
+        EuiccSession.get(mContext).endSession(SESSION_ID);
         mLooper.processAllMessages();
 
         assertEquals("A1A1A1", IccUtils.bytesToHexString(mResponseCaptor.response));
@@ -536,4 +543,20 @@
                 .remove(SHARED_PREFS_KEY_CHANNEL_RESPONSE)
                 .apply();
     }
+
+    /**
+     * Send an APDU to verify that the channel lock is not stuck (b/382549728).
+     * Same as testSend(), but not verifying mMockCi interactions.
+     */
+    private void checkChannelLock() throws InterruptedException {
+        int channel = LogicalChannelMocker.mockOpenLogicalChannelResponse(mMockCi, "9000");
+        LogicalChannelMocker.mockSendToLogicalChannel(mMockCi, channel, "A1A1A19000");
+        LogicalChannelMocker.mockCloseLogicalChannel(mMockCi, channel, /* error= */ null);
+
+        mSender.send((selectResponse, requestBuilder) -> requestBuilder.addApdu(
+                10, 1, 2, 3, 0, "a"), mResponseCaptor, mHandler);
+        mLooper.processAllMessages();
+
+        assertEquals("A1A1A1", IccUtils.bytesToHexString(mResponseCaptor.response));
+    }
 }