Merge "Added 5G SA components to ACTS"
diff --git a/acts_tests/acts_contrib/test_utils/tel/tel_5g_utils.py b/acts_tests/acts_contrib/test_utils/tel/tel_5g_utils.py
index d5d6f76..a9d5af7 100644
--- a/acts_tests/acts_contrib/test_utils/tel/tel_5g_utils.py
+++ b/acts_tests/acts_contrib/test_utils/tel/tel_5g_utils.py
@@ -21,6 +21,7 @@
 from queue import Empty
 from acts.utils import rand_ascii_str
 from acts_contrib.test_utils.tel.tel_defines import NETWORK_MODE_NR_LTE_GSM_WCDMA
+from acts_contrib.test_utils.tel.tel_defines import NETWORK_MODE_NR_ONLY
 from acts_contrib.test_utils.tel.tel_defines import OverrideNetworkContainer
 from acts_contrib.test_utils.tel.tel_defines import DisplayInfoContainer
 from acts_contrib.test_utils.tel.tel_defines import EventDisplayInfoChanged
@@ -66,28 +67,59 @@
     return None
 
 
-def provision_device_for_5g(log, ad):
-    # Mode Pref
-    set_preferred_mode_for_5g(ad)
+def provision_device_for_5g(log, ads, sa_5g=False):
+    """Provision Devices for 5G
 
-    # Attach nsa5g
-    if not is_current_network_5g_nsa(ad):
-        ad.log.error("Phone not attached on nsa 5g")
-        return False
+    Args:
+        log: Log object.
+        ads: android device object(s).
+        sa_5g: Check for provision on sa_5G or not
+
+    Returns:
+        True: Device(s) are provisioned on 5G
+        False: Device(s) are not provisioned on 5G
+    """
+    if sa_5g:
+        if not provision_device_for_5g_sa(log, ads):
+            return False
+    else:
+        if not provision_device_for_5g_nsa(log, ads):
+            return False
     return True
 
-def provision_both_devices_for_5g(log, ads):
-    # Mode Pref
-    tasks = [(set_preferred_mode_for_5g, [ad]) for ad in ads]
-    if not multithread_func(log, tasks):
-        log.error("failed to set preferred network mode on 5g")
-        return False
-    # Attach
-    tasks = [(is_current_network_5g_nsa, [ad]) for ad in ads]
-    if not multithread_func(log, tasks):
-        log.error("phone not on 5g nsa")
-        return False
-    return True
+
+def provision_device_for_5g_nsa(log, ads):
+    """Provision Devices for 5G NSA
+
+    Args:
+        log: Log object.
+        ads: android device object(s).
+
+    Returns:
+        True: Device(s) are provisioned on 5G NSA
+        False: Device(s) are not provisioned on 5G NSA
+    """
+    if isinstance(ads, list):
+        # Mode Pref
+        tasks = [(set_preferred_mode_for_5g, [ad]) for ad in ads]
+        if not multithread_func(log, tasks):
+            log.error("failed to set preferred network mode on 5g")
+            return False
+        # Attach
+        tasks = [(is_current_network_5g_nsa, [ad]) for ad in ads]
+        if not multithread_func(log, tasks):
+            log.error("phone not on 5g nsa")
+            return False
+        return True
+    else:
+        # Mode Pref
+        set_preferred_mode_for_5g(ads)
+
+        # Attach nsa5g
+        if not is_current_network_5g_nsa(ads):
+            ads.log.error("Phone not attached on nsa 5g")
+            return False
+        return True
 
 
 def provision_both_devices_for_volte(log, ads):
@@ -109,15 +141,6 @@
     return True
 
 
-def verify_5g_attach_for_both_devices(log, ads):
-    # Attach
-    tasks = [(is_current_network_5g_nsa, [ad]) for ad in ads]
-    if not multithread_func(log, tasks):
-        log.error("phone not on 5g nsa")
-        return False
-    return True
-
-
 def provision_both_devices_for_wfc_cell_pref(log,
                                              ads,
                                              wifi_ssid,
@@ -175,6 +198,34 @@
     return True
 
 
+def verify_5g_attach_for_both_devices(log, ads, sa_5g=False):
+    """Verify the network is attached
+
+    Args:
+        log: Log object.
+        ads: android device object(s).
+        sa_5g: Check for verify data network type is on 5G SA or not
+
+    Returns:
+        True: Device(s) are attached on 5G
+        False: Device(s) are not attached on 5G NSA
+    """
+    if sa_5g:
+        # Attach
+        tasks = [(is_current_network_5g_sa, [ad]) for ad in ads]
+        if not multithread_func(log, tasks):
+            log.error("phone not on 5g sa")
+            return False
+        return True
+    else:
+        # Attach
+        tasks = [(is_current_network_5g_nsa, [ad]) for ad in ads]
+        if not multithread_func(log, tasks):
+            log.error("phone not on 5g nsa")
+            return False
+        return True
+
+
 def set_preferred_mode_for_5g(ad, sub_id=None, mode=None):
     """Set Preferred Network Mode for 5G NSA
     Args:
@@ -189,5 +240,75 @@
     return set_preferred_network_mode_pref(ad.log, ad, sub_id, mode)
 
 
+def is_current_network_5g_sa(ad):
+    """Verifies 5G SA override network type
 
+    Args:
+        ad: android device object.
+
+    Returns:
+        True: if data is on 5g SA
+        False: if data is not on 5g SA
+    """
+    network_connected = ad.droid.telephonyGetCurrentDataNetworkType()
+    if network_connected == 'NR':
+        ad.log.debug("Network is currently connected to %s", network_connected)
+        return True
+    else:
+        ad.log.error("Network is currently connected to %s, Expected on NR", network_connected)
+        return False
+
+
+def provision_device_for_5g_sa(log, ads):
+    """Provision Devices for 5G SA
+
+    Args:
+        log: Log object.
+        ads: android device object(s).
+
+    Returns:
+        True: Device(s) are provisioned on 5G SA
+        False: Device(s) are not provisioned on 5G SA
+    """
+    if isinstance(ads, list):
+        # Mode Pref
+        tasks = [(set_preferred_mode_for_5g, [ad, None, NETWORK_MODE_NR_ONLY]) for ad in ads]
+        if not multithread_func(log, tasks):
+            log.error("failed to set preferred network mode on 5g SA")
+            return False
+
+        tasks = [(is_current_network_5g_sa, [ad]) for ad in ads]
+        if not multithread_func(log, tasks):
+            log.error("phone not on 5g SA")
+            return False
+        return True
+    else:
+        # Mode Pref
+        set_preferred_mode_for_5g(ads, None, NETWORK_MODE_NR_ONLY)
+
+        if not is_current_network_5g_sa(ads):
+            ads.log.error("Phone not attached on SA 5g")
+            return False
+        return True
+
+
+def check_current_network_5g(ad, timeout=30, sa_5g=False):
+    """Verifies data network type is on 5G
+
+    Args:
+        ad: android device object.
+        timeout: max time to wait for event
+        sa_5g: Check for verify data network type is on 5G SA or not
+
+    Returns:
+        True: if data is on 5g
+        False: if data is not on 5g
+    """
+    if sa_5g:
+        if not is_current_network_5g_sa(ad):
+            return False
+    else:
+        if not is_current_network_5g_nsa(ad, timeout):
+            return False
+    return True
 
diff --git a/acts_tests/acts_contrib/test_utils/tel/tel_data_utils.py b/acts_tests/acts_contrib/test_utils/tel/tel_data_utils.py
index 9210d39..53d191e 100644
--- a/acts_tests/acts_contrib/test_utils/tel/tel_data_utils.py
+++ b/acts_tests/acts_contrib/test_utils/tel/tel_data_utils.py
@@ -93,8 +93,8 @@
 from acts_contrib.test_utils.tel.tel_test_utils import ensure_phones_default_state
 from acts_contrib.test_utils.tel.tel_test_utils import WIFI_SSID_KEY
 from acts_contrib.test_utils.tel.tel_test_utils import is_phone_in_call_active
+from acts_contrib.test_utils.tel.tel_5g_utils import check_current_network_5g
 from acts_contrib.test_utils.tel.tel_5g_utils import is_current_network_5g_nsa
-from acts_contrib.test_utils.tel.tel_5g_utils import provision_both_devices_for_5g
 from acts_contrib.test_utils.tel.tel_5g_utils import provision_device_for_5g
 from acts_contrib.test_utils.tel.tel_5g_utils import verify_5g_attach_for_both_devices
 from acts_contrib.test_utils.tel.tel_voice_utils import phone_setup_voice_general
@@ -287,7 +287,7 @@
     return False
 
 
-def wifi_cell_switching(log, ad, nw_gen, wifi_network_ssid=None, wifi_network_pass=None):
+def wifi_cell_switching(log, ad, nw_gen, wifi_network_ssid=None, wifi_network_pass=None, sa_5g=False):
     """Test data connection network switching when phone on <nw_gen>.
 
     Ensure phone is on <nw_gen>
@@ -309,7 +309,7 @@
     """
     try:
         if nw_gen == GEN_5G:
-            if not provision_device_for_5g(log, ad):
+            if not provision_device_for_5g(log, ad, sa_5g):
                 return False
         elif nw_gen:
             if not ensure_network_generation_for_subscription(
@@ -443,7 +443,7 @@
         toggle_airplane_mode(log, ad, False)
 
 
-def data_connectivity_single_bearer(log, ad, nw_gen=None):
+def data_connectivity_single_bearer(log, ad, nw_gen=None, sa_5g=False):
     """Test data connection: single-bearer (no voice).
 
     Turn off airplane mode, enable Cellular Data.
@@ -467,7 +467,7 @@
         wait_time = 2 * wait_time
 
     if nw_gen == GEN_5G:
-        if not provision_device_for_5g(log, ad):
+        if not provision_device_for_5g(log, ad, sa_5g):
             return False
     elif nw_gen:
         if not ensure_network_generation_for_subscription(
@@ -512,7 +512,7 @@
             return False
 
         if nw_gen == GEN_5G:
-            if not is_current_network_5g_nsa(ad):
+            if not check_current_network_5g(ad, sa_5g):
                 return False
         else:
             if not is_droid_in_network_generation_for_subscription(
@@ -834,7 +834,8 @@
         android_devices,
         nw_gen=None,
         simultaneous_voice_data=True,
-        call_direction=DIRECTION_MOBILE_ORIGINATED):
+        call_direction=DIRECTION_MOBILE_ORIGINATED,
+        sa_5g=False):
     """Test data connection before call and in call.
 
     Turn off airplane mode, disable WiFi, enable Cellular Data.
@@ -860,7 +861,7 @@
     ensure_phones_idle(log, ad_list)
 
     if nw_gen == GEN_5G:
-        if not provision_both_devices_for_5g(log, android_devices):
+        if not provision_device_for_5g(log, android_devices, sa_5g):
             return False
     elif nw_gen:
         if not ensure_network_generation_for_subscription(
@@ -994,7 +995,7 @@
     return True
 
 
-def test_setup_tethering(log, provider, clients, network_generation=None):
+def test_setup_tethering(log, provider, clients, network_generation=None, sa_5g=False):
     """Pre setup steps for WiFi tethering test.
 
     Ensure all ads are idle.
@@ -1011,7 +1012,7 @@
     ensure_phones_idle(log, clients)
     wifi_toggle_state(log, provider, False)
     if network_generation == RAT_5G:
-        if not provision_device_for_5g(log, provider):
+        if not provision_device_for_5g(log, provider, sa_5g):
             return False
     elif network_generation:
         if not ensure_network_generation(
@@ -1225,7 +1226,8 @@
 def test_tethering_wifi_and_voice_call(log, provider, clients,
                                         provider_data_rat,
                                         provider_setup_func,
-                                        provider_in_call_check_func):
+                                        provider_in_call_check_func,
+                                        sa_5g=False):
 
     if not test_setup_tethering(log, provider, clients, provider_data_rat):
         log.error("Verify 4G Internet access failed.")
@@ -1238,7 +1240,7 @@
         return False
 
     if provider_setup_func == RAT_5G:
-        if not provision_device_for_5g(log, provider):
+        if not provision_device_for_5g(log, provider, sa_5g):
             return False
     try:
         log.info("1. Setup WiFi Tethering.")
@@ -1349,7 +1351,8 @@
         ads,
         nw_gen=None,
         call_direction=DIRECTION_MOBILE_ORIGINATED,
-        allow_data_transfer_interruption=False):
+        allow_data_transfer_interruption=False,
+        sa_5g=False):
     """Test call can be established during active data connection.
 
     Turn off airplane mode, disable WiFi, enable Cellular Data.
@@ -1382,10 +1385,8 @@
                                    wait_time_in_call)
 
     if nw_gen == GEN_5G:
-        if not provision_device_for_5g(log, ads[0]):
-            ads[0].log.error("Phone not attached on 5G NSA before call.")
+        if not provision_device_for_5g(log, ads[0], sa_5g):
             return False
-
     elif nw_gen:
         if not ensure_network_generation(log, ads[0], nw_gen,
                                          MAX_WAIT_TIME_NW_SELECTION,
@@ -1439,8 +1440,8 @@
             return False
     # Disable airplane mode if test under apm on.
     toggle_airplane_mode(log, ads[0], False)
-    if nw_gen == GEN_5G and not is_current_network_5g_nsa(ads[0]):
-        ads[0].log.error("Phone not attached on 5G NSA after call.")
+    if nw_gen == GEN_5G and not check_current_network_5g(ads[0], sa_5g):
+        ads[0].log.error("Phone not attached on 5G after call.")
         return False
     return True
 
@@ -1450,7 +1451,8 @@
         ads,
         nw_gen=None,
         call_direction=DIRECTION_MOBILE_ORIGINATED,
-        allow_data_transfer_interruption=False):
+        allow_data_transfer_interruption=False,
+        sa_5g=False):
     """Test call can be established during active data connection.
 
     Turn off airplane mode, disable WiFi, enable Cellular Data.
@@ -1469,10 +1471,8 @@
         False if failed.
     """
     if nw_gen == GEN_5G:
-        if not provision_device_for_5g(log, ads[0]):
-            ads[0].log.error("Phone not attached on 5G NSA before call.")
+        if not provision_device_for_5g(log, ads[0], sa_5g):
             return False
-
     elif nw_gen:
         if not ensure_network_generation(log, ads[0], nw_gen,
                                          MAX_WAIT_TIME_NW_SELECTION,
@@ -1518,8 +1518,8 @@
     ad_download.force_stop_apk("com.google.android.youtube")
     # Disable airplane mode if test under apm on.
     toggle_airplane_mode(log, ads[0], False)
-    if nw_gen == GEN_5G and not is_current_network_5g_nsa(ads[0]):
-        ads[0].log.error("Phone not attached on 5G NSA after call.")
+    if nw_gen == GEN_5G and not check_current_network_5g(ads[0], sa_5g):
+        ads[0].log.error("Phone not attached on 5G after call.")
         result = False
     return result
 
@@ -1530,7 +1530,8 @@
                           wfc_mode,
                           wifi_ssid,
                           wifi_pwd,
-                          nw_gen=None):
+                          nw_gen=None,
+                          sa_5g=False):
     """ Test epdg<->epdg call functionality.
 
     Make Sure PhoneA is set to make epdg call.
@@ -1564,8 +1565,7 @@
         if not multithread_func(log, tasks):
             log.error("Failed to turn off airplane mode")
             return False
-        if not provision_both_devices_for_5g(log, ads):
-            log.error("Phone not attached on 5G NSA before epdg call.")
+        if not provision_device_for_5g(log, ad, sa_5g):
             return False
 
     tasks = [(phone_setup_iwlan, (log, ads[0], apm_mode, wfc_mode,
@@ -1588,8 +1588,8 @@
 
     time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING)
 
-    if nw_gen == GEN_5G and not verify_5g_attach_for_both_devices(log, ads):
-        log.error("Phone not attached on 5G NSA after epdg call.")
+    if nw_gen == GEN_5G and not verify_5g_attach_for_both_devices(log, ads, sa_5g):
+        log.error("Phone not attached on 5G after epdg call.")
         return False
 
     if not results[1]:
diff --git a/acts_tests/tests/google/nr/nsa5g/Nsa5gImsSettingsTest.py b/acts_tests/tests/google/nr/nsa5g/Nsa5gImsSettingsTest.py
index 6b38879..33d0c76 100644
--- a/acts_tests/tests/google/nr/nsa5g/Nsa5gImsSettingsTest.py
+++ b/acts_tests/tests/google/nr/nsa5g/Nsa5gImsSettingsTest.py
@@ -34,7 +34,6 @@
 from acts_contrib.test_utils.tel.tel_voice_utils import phone_setup_csfb
 from acts_contrib.test_utils.tel.tel_voice_utils import phone_setup_volte
 from acts_contrib.test_utils.tel.tel_5g_utils import is_current_network_5g_nsa
-from acts_contrib.test_utils.tel.tel_5g_utils import provision_both_devices_for_5g
 from acts_contrib.test_utils.tel.tel_5g_utils import provision_device_for_5g
 from acts_contrib.test_utils.tel.tel_5g_utils import set_preferred_mode_for_5g
 from acts_contrib.test_utils.tel.tel_ims_utils import change_ims_setting
@@ -223,7 +222,7 @@
             return False
 
         ads = self.android_devices
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not change_ims_setting(log=self.log,
diff --git a/acts_tests/tests/google/nr/nsa5g/Nsa5gMmsTest.py b/acts_tests/tests/google/nr/nsa5g/Nsa5gMmsTest.py
index 2d812e3..4eded92 100755
--- a/acts_tests/tests/google/nr/nsa5g/Nsa5gMmsTest.py
+++ b/acts_tests/tests/google/nr/nsa5g/Nsa5gMmsTest.py
@@ -31,7 +31,7 @@
 from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call_csfb
 from acts_contrib.test_utils.tel.tel_5g_utils import connect_both_devices_to_wifi
 from acts_contrib.test_utils.tel.tel_5g_utils import disable_apm_mode_both_devices
-from acts_contrib.test_utils.tel.tel_5g_utils import provision_both_devices_for_5g
+from acts_contrib.test_utils.tel.tel_5g_utils import provision_device_for_5g
 from acts_contrib.test_utils.tel.tel_5g_utils import provision_both_devices_for_volte
 from acts_contrib.test_utils.tel.tel_5g_utils import provision_both_devices_for_wfc_cell_pref
 from acts_contrib.test_utils.tel.tel_5g_utils import provision_both_devices_for_wfc_wifi_pref
@@ -42,6 +42,7 @@
 from acts_contrib.test_utils.tel.tel_mms_utils import _long_mms_test_mo
 from acts_contrib.test_utils.tel.tel_mms_utils import test_mms_mo_in_call
 
+
 class Nsa5gMmsTest(TelephonyBaseTest):
     def setup_class(self):
         super().setup_class()
@@ -85,7 +86,7 @@
             False if failed.
         """
         ads = self.android_devices
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not _mms_test_mo(self.log, ads):
@@ -117,7 +118,7 @@
         if not provision_both_devices_for_volte(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not _mms_test_mo(self.log, ads):
@@ -148,7 +149,7 @@
         if not provision_both_devices_for_volte(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         self.log.info("Begin Incall mms test.")
@@ -189,7 +190,7 @@
         if not disable_apm_mode_both_devices(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not provision_both_devices_for_wfc_cell_pref(self.log,
@@ -226,7 +227,7 @@
         if not disable_apm_mode_both_devices(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not provision_both_devices_for_wfc_wifi_pref(self.log,
@@ -267,7 +268,7 @@
         if not disable_apm_mode_both_devices(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not provision_both_devices_for_wfc_wifi_pref(self.log,
@@ -309,7 +310,7 @@
         if not provision_both_devices_for_volte(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not connect_both_devices_to_wifi(self.log,
@@ -355,7 +356,7 @@
         if not disable_apm_mode_both_devices(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         return _long_mms_test_mo(self.log, ads)
@@ -381,7 +382,7 @@
         if not disable_apm_mode_both_devices(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         ensure_wifi_connected(self.log, ads[0], self.wifi_network_ssid,
@@ -410,7 +411,7 @@
         if not disable_apm_mode_both_devices(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         ensure_wifi_connected(self.log, ads[0], self.wifi_network_ssid,
@@ -419,6 +420,7 @@
         return _mms_test_mt(self.log, ads)
 
 
+    @test_tracker_info(uuid="156bf832-acc2-4729-a69d-b471cd5cfbde")
     @TelephonyBaseTest.tel_test_wrap
     def test_5g_nsa_mms_mo_mt_in_call_csfb_wifi(self):
         """ Test MO/MT MMS during a MO csfb call and devices connect to Wifi.
diff --git a/acts_tests/tests/google/nr/nsa5g/Nsa5gSmsTest.py b/acts_tests/tests/google/nr/nsa5g/Nsa5gSmsTest.py
index 3620c96..ffa4c6e 100755
--- a/acts_tests/tests/google/nr/nsa5g/Nsa5gSmsTest.py
+++ b/acts_tests/tests/google/nr/nsa5g/Nsa5gSmsTest.py
@@ -28,7 +28,7 @@
 from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call_volte
 from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call_csfb
 from acts_contrib.test_utils.tel.tel_5g_utils import disable_apm_mode_both_devices
-from acts_contrib.test_utils.tel.tel_5g_utils import provision_both_devices_for_5g
+from acts_contrib.test_utils.tel.tel_5g_utils import provision_device_for_5g
 from acts_contrib.test_utils.tel.tel_5g_utils import provision_both_devices_for_volte
 from acts_contrib.test_utils.tel.tel_5g_utils import provision_both_devices_for_wfc_cell_pref
 from acts_contrib.test_utils.tel.tel_5g_utils import provision_both_devices_for_wfc_wifi_pref
@@ -67,7 +67,7 @@
             False if failed.
         """
         ads = self.android_devices
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not _sms_test_mo(self.log, ads):
@@ -99,7 +99,7 @@
         if not provision_both_devices_for_volte(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not _sms_test_mo(self.log, ads):
@@ -135,7 +135,7 @@
             return False
         time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING)
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not test_sms_mo_in_call(self.log,
@@ -167,7 +167,7 @@
         if not disable_apm_mode_both_devices(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not provision_both_devices_for_wfc_cell_pref(self.log,
@@ -204,7 +204,7 @@
         if not disable_apm_mode_both_devices(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not provision_both_devices_for_wfc_wifi_pref(self.log,
@@ -245,7 +245,7 @@
         if not disable_apm_mode_both_devices(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not provision_both_devices_for_wfc_wifi_pref(self.log,
@@ -280,12 +280,13 @@
         if not disable_apm_mode_both_devices(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         return _long_sms_test_mo(self.log, ads)
 
 
+    @test_tracker_info(uuid="45dbd61a-6a90-473e-9cfa-03e2408d5f15")
     @TelephonyBaseTest.tel_test_wrap
     def test_5g_nsa_sms_mo_mt_in_call_csfb(self):
         """ Test MO/MT SMS during a MO csfb call over 5G NSA.
diff --git a/acts_tests/tests/google/nr/nsa5g/Nsa5gVoiceTest.py b/acts_tests/tests/google/nr/nsa5g/Nsa5gVoiceTest.py
index 4b924a8..df07120 100755
--- a/acts_tests/tests/google/nr/nsa5g/Nsa5gVoiceTest.py
+++ b/acts_tests/tests/google/nr/nsa5g/Nsa5gVoiceTest.py
@@ -64,7 +64,6 @@
 from acts_contrib.test_utils.tel.tel_voice_utils import two_phone_call_long_seq
 from acts_contrib.test_utils.tel.tel_voice_utils import two_phone_call_short_seq
 from acts_contrib.test_utils.tel.tel_5g_utils import is_current_network_5g_nsa
-from acts_contrib.test_utils.tel.tel_5g_utils import provision_both_devices_for_5g
 from acts_contrib.test_utils.tel.tel_5g_utils import provision_both_devices_for_volte
 from acts_contrib.test_utils.tel.tel_5g_utils import provision_device_for_5g
 from acts_contrib.test_utils.tel.tel_5g_utils import set_preferred_mode_for_5g
@@ -115,7 +114,7 @@
         if not provision_both_devices_for_volte(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         # VoLTE calls
@@ -196,7 +195,7 @@
         if not provision_both_devices_for_volte(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not phone_setup_call_hold_unhold_test(self.log,
@@ -228,7 +227,7 @@
         if not provision_both_devices_for_volte(self.log, ads):
             return False
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not phone_setup_call_hold_unhold_test(self.log,
@@ -322,7 +321,7 @@
 
         time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING)
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
 
         if not verify_5g_attach_for_both_devices(self.log, ads):
@@ -923,7 +922,7 @@
             data_usage = get_mobile_data_usage(ads[0], subscriber_id)
             set_mobile_data_usage_limit(ads[0], data_usage, subscriber_id)
 
-            if not provision_both_devices_for_5g(self.log, ads):
+            if not provision_device_for_5g(self.log, ads):
                 self.log.error("Phone Failed to Set Up Properly.")
                 self.tel_logger.set_result(CallResult("CALL_SETUP_FAILURE"))
                 raise signals.TestFailure("Failed",
@@ -960,7 +959,7 @@
         ads = self.android_devices
         result = True
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
                 self.log.error("Phone Failed to Set Up Properly.")
                 self.tel_logger.set_result(CallResult("CALL_SETUP_FAILURE"))
                 raise signals.TestFailure("Failed",
@@ -1175,7 +1174,7 @@
 
         ads = self.android_devices
 
-        if not provision_both_devices_for_5g(self.log, ads):
+        if not provision_device_for_5g(self.log, ads):
             return False
         tasks = [(phone_setup_iwlan,
                   (self.log, ads[0], False, WFC_MODE_WIFI_PREFERRED,
diff --git a/acts_tests/tests/google/nr/sa5g/Sa5gDataTest.py b/acts_tests/tests/google/nr/sa5g/Sa5gDataTest.py
new file mode 100755
index 0000000..825fdd1
--- /dev/null
+++ b/acts_tests/tests/google/nr/sa5g/Sa5gDataTest.py
@@ -0,0 +1,238 @@
+#!/usr/bin/env python3.4
+#
+#   Copyright 2021 - Google
+#
+#   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.
+"""
+    Test Script for 5G SA Data scenarios
+"""
+
+import time
+
+from acts.test_decorators import test_tracker_info
+from acts_contrib.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest
+from acts_contrib.test_utils.tel.tel_defines import GEN_5G
+from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_USER_PLANE_DATA
+from acts_contrib.test_utils.tel.tel_defines import NETWORK_MODE_NR_ONLY
+from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_ANDROID_STATE_SETTLING
+from acts_contrib.test_utils.tel.tel_test_utils import break_internet_except_sl4a_port
+from acts_contrib.test_utils.tel.tel_test_utils import check_data_stall_detection
+from acts_contrib.test_utils.tel.tel_test_utils import check_data_stall_recovery
+from acts_contrib.test_utils.tel.tel_test_utils import check_network_validation_fail
+from acts_contrib.test_utils.tel.tel_test_utils import get_current_override_network_type
+from acts_contrib.test_utils.tel.tel_test_utils import get_device_epoch_time
+from acts_contrib.test_utils.tel.tel_test_utils import resume_internet_with_sl4a_port
+from acts_contrib.test_utils.tel.tel_test_utils import set_preferred_network_mode_pref
+from acts_contrib.test_utils.tel.tel_test_utils import test_data_browsing_failure_using_sl4a
+from acts_contrib.test_utils.tel.tel_test_utils import test_data_browsing_success_using_sl4a
+from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode
+from acts_contrib.test_utils.tel.tel_test_utils import verify_internet_connection
+from acts_contrib.test_utils.tel.tel_test_utils import wifi_reset
+from acts_contrib.test_utils.tel.tel_test_utils import wifi_toggle_state
+from acts_contrib.test_utils.tel.tel_data_utils import browsing_test
+from acts_contrib.test_utils.tel.tel_data_utils import data_connectivity_single_bearer
+from acts_contrib.test_utils.tel.tel_data_utils import test_wifi_connect_disconnect
+from acts_contrib.test_utils.tel.tel_data_utils import wifi_cell_switching
+from acts_contrib.test_utils.tel.tel_5g_utils import is_current_network_5g_sa
+from acts_contrib.test_utils.tel.tel_5g_utils import provision_device_for_5g
+
+
+class Sa5gDataTest(TelephonyBaseTest):
+    def setup_class(self):
+        super().setup_class()
+
+    def setup_test(self):
+        TelephonyBaseTest.setup_test(self)
+        self.provider = self.android_devices[0]
+        self.clients = self.android_devices[1:]
+
+    def teardown_class(self):
+        TelephonyBaseTest.teardown_class(self)
+
+
+    """ Tests Begin """
+
+    @test_tracker_info(uuid="2bb5fa22-d931-426f-a11d-22f514d867d0")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_5g_sa_data_browsing(self):
+        """ Verifying connectivity of internet and  browsing websites on 5G SA network.
+
+        Ensure
+            1. ping to IP of websites is successful.
+            2. http ping to IP of websites is successful.
+            3. browsing websites is successful.
+        Returns:
+            True if pass; False if fail.
+        """
+        ad = self.android_devices[0]
+        wifi_toggle_state(ad.log, ad, False)
+        sub_id = ad.droid.subscriptionGetDefaultSubId()
+        if not set_preferred_network_mode_pref(ad.log, ad, sub_id,
+                                               NETWORK_MODE_NR_ONLY):
+            ad.log.error("Failed to set network mode to SA")
+            return False
+        ad.log.info("Set network mode to SA successfully")
+        ad.log.info("Waiting for 5g SA attach for 60 secs")
+        if is_current_network_5g_sa(ad):
+            ad.log.info("Success! attached on 5g SA")
+        else:
+            ad.log.error("Failure - expected NR, current %s",
+                         get_current_override_network_type(ad))
+            return False
+        for iteration in range(3):
+            connectivity = False
+            browsing = False
+            ad.log.info("Attempt %d", iteration + 1)
+            if not verify_internet_connection(self.log, ad):
+                ad.log.error("Failed to connect to internet!")
+            else:
+                ad.log.info("Connect to internet successfully!")
+                connectivity = True
+            if not browsing_test(ad.log, ad):
+                ad.log.error("Failed to browse websites!")
+            else:
+                ad.log.info("Successful to browse websites!")
+                browsing = True
+            if connectivity and browsing:
+                return True
+            time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING)
+        ad.log.error("5G SA Connectivity and Data Browsing test FAIL for all 3 iterations")
+        return False
+
+
+    @test_tracker_info(uuid="785b0ef8-b326-42f8-a399-51ebc1f9e93e")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_5g_sa_data_stall_recovery(self):
+        """ Verifies 5G SA data stall
+
+        Set Mode to 5G
+        Wait for 5G attached on SA
+        Browse websites for success
+        Trigger data stall and verify browsing fails
+        Resume data and verify browsing success
+
+        Returns:
+            True if pass; False if fail.
+        """
+        ad = self.android_devices[0]
+        result = True
+        wifi_toggle_state(ad.log, ad, False)
+        toggle_airplane_mode(ad.log, ad, False)
+
+        if not provision_device_for_5g(ad.log, ad, sa_5g=True):
+            return False
+
+        cmd = ('ss -l -p -n | grep "tcp.*droid_script" | tr -s " " '
+               '| cut -d " " -f 5 | sed s/.*://g')
+        sl4a_port = ad.adb.shell(cmd)
+
+        if not test_data_browsing_success_using_sl4a(ad.log, ad):
+            ad.log.error("Browsing failed before the test, aborting!")
+            return False
+
+        begin_time = get_device_epoch_time(ad)
+        break_internet_except_sl4a_port(ad, sl4a_port)
+
+        if not test_data_browsing_failure_using_sl4a(ad.log, ad):
+            ad.log.error("Browsing after breaking the internet, aborting!")
+            result = False
+
+        if not check_data_stall_detection(ad):
+            ad.log.warning("NetworkMonitor unable to detect Data Stall")
+
+        if not check_network_validation_fail(ad, begin_time):
+            ad.log.warning("Unable to detect NW validation fail")
+
+        if not check_data_stall_recovery(ad, begin_time):
+            ad.log.error("Recovery was not triggered")
+            result = False
+
+        resume_internet_with_sl4a_port(ad, sl4a_port)
+        time.sleep(MAX_WAIT_TIME_USER_PLANE_DATA)
+        if not test_data_browsing_success_using_sl4a(ad.log, ad):
+            ad.log.error("Browsing failed after resuming internet")
+            result = False
+        if result:
+            ad.log.info("PASS - data stall over 5G SA")
+        else:
+            ad.log.error("FAIL - data stall over 5G SA")
+        return result
+
+
+    @test_tracker_info(uuid="6c0ef257-6381-4c1d-8b8e-0371db7e08ac")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_5g_sa_wifi_connect_disconnect(self):
+        """Perform multiple connects and disconnects from WiFi and verify that
+            data switches between WiFi and Cell.
+
+        Steps:
+        1. DUT Cellular Data is on sa 5G. Reset Wifi on DUT
+        2. Connect DUT to a WiFi AP
+        3. Repeat steps 1-2, alternately disconnecting and disabling wifi
+
+        Expected Results:
+        1. Verify Data on Cell
+        2. Verify Data on Wifi
+
+        Returns:
+            True if success.
+            False if failed.
+        """
+        if not provision_device_for_5g(self.log, self.provider, sa_5g=True):
+            return False
+
+        return test_wifi_connect_disconnect(self.log, self.provider, self.wifi_network_ssid, self.wifi_network_pass)
+
+
+    @test_tracker_info(uuid="f70ad253-4b77-4d9b-b7dc-d7cd3e945e5f")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_5g_sa_wifi_switching(self):
+        """Test data connection network switching when phone camped on sa 5G.
+
+        Ensure phone is camped on sa 5G
+        Ensure WiFi can connect to live network,
+        Airplane mode is off, data connection is on, WiFi is on.
+        Turn off WiFi, verify data is on cell and browse to google.com is OK.
+        Turn on WiFi, verify data is on WiFi and browse to google.com is OK.
+        Turn off WiFi, verify data is on cell and browse to google.com is OK.
+
+        Returns:
+            True if pass.
+        """
+        ad = self.android_devices[0]
+        return wifi_cell_switching(ad.log, ad, GEN_5G, self.wifi_network_ssid,
+                                   self.wifi_network_pass, sa_5g=True)
+
+
+    @test_tracker_info(uuid="8df1b65c-197e-40b3-83a4-6da1f0a51b97")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_5g_sa_wifi_not_associated(self):
+        """Test data connection in sa 5g.
+
+        Turn off airplane mode, enable WiFi (but not connected), enable Cellular Data.
+        Ensure phone data generation is sa 5g.
+        Verify Internet.
+        Disable Cellular Data, verify Internet is inaccessible.
+        Enable Cellular Data, verify Internet.
+
+        Returns:
+            True if success.
+            False if failed.
+        """
+        ad = self.android_devices[0]
+        wifi_reset(ad.log, ad)
+        wifi_toggle_state(ad.log, ad, False)
+        wifi_toggle_state(ad.log, ad, True)
+        return data_connectivity_single_bearer(ad.log, ad, GEN_5G, sa_5g=True)
+
+    """ Tests End """
diff --git a/acts_tests/tests/google/nr/sa5g/Sa5gMmsTest.py b/acts_tests/tests/google/nr/sa5g/Sa5gMmsTest.py
new file mode 100755
index 0000000..cf4e14a
--- /dev/null
+++ b/acts_tests/tests/google/nr/sa5g/Sa5gMmsTest.py
@@ -0,0 +1,129 @@
+#!/usr/bin/env python3.4
+#
+#   Copyright 2021 - Google
+#
+#   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.
+"""
+    Test Script for 5G SA MMS scenarios
+"""
+
+import time
+
+from acts.test_decorators import test_tracker_info
+from acts_contrib.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest
+from acts_contrib.test_utils.tel.tel_test_utils import ensure_phones_idle
+from acts_contrib.test_utils.tel.tel_test_utils import ensure_wifi_connected
+from acts_contrib.test_utils.tel.tel_5g_utils import disable_apm_mode_both_devices
+from acts_contrib.test_utils.tel.tel_5g_utils import provision_device_for_5g
+from acts_contrib.test_utils.tel.tel_5g_utils import verify_5g_attach_for_both_devices
+from acts_contrib.test_utils.tel.tel_mms_utils import _mms_test_mo
+from acts_contrib.test_utils.tel.tel_mms_utils import _long_mms_test_mo
+
+
+class Sa5gMmsTest(TelephonyBaseTest):
+    def setup_class(self):
+        super().setup_class()
+        self.number_of_devices = 2
+
+    def setup_test(self):
+        TelephonyBaseTest.setup_test(self)
+
+    def teardown_test(self):
+        ensure_phones_idle(self.log, self.android_devices)
+
+
+    """ Tests Begin """
+
+
+    @test_tracker_info(uuid="74e2ae79-aee4-46e0-9326-fcd3b7f19128")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_5g_sa_mms_mo_mt(self):
+        """Test MMS between two phones in 5g SA
+
+        Provision devices in 5g SA
+        Send and Verify MMS from PhoneA to PhoneB
+        Verify both devices are still on 5g SA
+
+        Returns:
+            True if success.
+            False if failed.
+        """
+        ads = self.android_devices
+        if not provision_device_for_5g(self.log, ads, sa_5g=True):
+            return False
+
+        if not _mms_test_mo(self.log, ads):
+            return False
+
+        if not verify_5g_attach_for_both_devices(self.log, ads, True):
+            return False
+
+        self.log.info("PASS - mms test over 5g sa validated")
+        return True
+
+
+    @test_tracker_info(uuid="6cd173f5-bd1d-44bb-aac2-ac63f37b9a62")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_5g_sa_mms_long_message_mo_mt(self):
+        """Test MMS basic function between two phone. Phones in sa 5G network.
+
+        Airplane mode is off. Phone in 5G SA.
+        Send MMS from PhoneA to PhoneB.
+        Verify received message on PhoneB is correct.
+
+        Returns:
+            True if success.
+            False if failed.
+        """
+
+        ads = self.android_devices
+
+        if not disable_apm_mode_both_devices(self.log, ads):
+            return False
+
+        if not provision_device_for_5g(self.log, ads, sa_5g=True):
+            return False
+
+        return _long_mms_test_mo(self.log, ads)
+
+
+    @test_tracker_info(uuid="83d24fb5-1ebd-42e0-a3d1-b85b607234e2")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_5g_sa_mms_mo_mt_wifi(self):
+        """Test MMS basic function between two phone. Phones in sa 5g network.
+
+        Airplane mode is off. Phone in sa 5G.
+        Connect to Wifi.
+        Send MMS from PhoneA to PhoneB.
+        Verify received message on PhoneB is correct.
+
+        Returns:
+            True if success.
+            False if failed.
+        """
+
+        ads = self.android_devices
+
+        if not disable_apm_mode_both_devices(self.log, ads):
+            return False
+
+        if not provision_device_for_5g(self.log, ads, sa_5g=True):
+            return False
+
+        ensure_wifi_connected(self.log, ads[0], self.wifi_network_ssid,
+                              self.wifi_network_pass)
+
+        return _mms_test_mo(self.log, ads)
+
+
+    """ Tests End """
diff --git a/acts_tests/tests/google/nr/sa5g/Sa5gSmsTest.py b/acts_tests/tests/google/nr/sa5g/Sa5gSmsTest.py
new file mode 100755
index 0000000..61d427a
--- /dev/null
+++ b/acts_tests/tests/google/nr/sa5g/Sa5gSmsTest.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python3.4
+#
+#   Copyright 2021 - Google
+#
+#   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.
+"""
+    Test Script for 5G SA SMS scenarios
+"""
+
+import time
+from acts.test_decorators import test_tracker_info
+from acts_contrib.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest
+from acts_contrib.test_utils.tel.tel_test_utils import ensure_phones_idle
+from acts_contrib.test_utils.tel.tel_5g_utils import disable_apm_mode_both_devices
+from acts_contrib.test_utils.tel.tel_5g_utils import provision_device_for_5g
+from acts_contrib.test_utils.tel.tel_5g_utils import provision_both_devices_for_volte
+from acts_contrib.test_utils.tel.tel_5g_utils import verify_5g_attach_for_both_devices
+from acts_contrib.test_utils.tel.tel_sms_utils import _sms_test_mo
+from acts_contrib.test_utils.tel.tel_sms_utils import _long_sms_test_mo
+
+
+class Sa5gSmsTest(TelephonyBaseTest):
+    def setup_class(self):
+        super().setup_class()
+
+    def setup_test(self):
+        TelephonyBaseTest.setup_test(self)
+
+    def teardown_test(self):
+        ensure_phones_idle(self.log, self.android_devices)
+
+
+    """ Tests Begin """
+
+
+    @test_tracker_info(uuid="8949d1c7-1719-4960-b79c-041b467fb5ef")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_5g_sa_sms_mo_mt(self):
+        """Test SMS between two phones in 5g SA
+
+        Provision devices in 5g SA
+        Send and Verify SMS from PhoneA to PhoneB
+        Verify both devices are still on 5g SA
+
+        Returns:
+            True if success.
+            False if failed.
+        """
+        ads = self.android_devices
+        if not provision_device_for_5g(self.log, ads, sa_5g=True):
+            return False
+
+        if not _sms_test_mo(self.log, ads):
+            return False
+
+        if not verify_5g_attach_for_both_devices(self.log, ads, True):
+            return False
+
+        self.log.info("PASS - SMS test over 5G SA validated")
+        return True
+
+
+    @test_tracker_info(uuid="5c7a717b-1f98-44b7-95e7-0e83afb82a84")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_5g_sa_sms_long_message_mo_mt(self):
+        """Test SMS basic function between two phone.
+
+        Phones in sa 5G network.
+        Airplane mode is off.
+        Send SMS from PhoneA to PhoneB.
+        Verify received message on PhoneB is correct.
+
+        Returns:
+            True if success.
+            False if failed.
+        """
+
+        ads = self.android_devices
+
+        if not disable_apm_mode_both_devices(self.log, ads):
+            return False
+
+        if not provision_device_for_5g(self.log, ads, sa_5g=True):
+            return False
+
+        return _long_sms_test_mo(self.log, ads)
+
+    """ Tests End """