Merge "Integrate NR related functions."
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7a4a3ea
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
\ No newline at end of file
diff --git a/acts/framework/acts/controllers/access_point.py b/acts/framework/acts/controllers/access_point.py
index 21e26bb..a2f2840 100755
--- a/acts/framework/acts/controllers/access_point.py
+++ b/acts/framework/acts/controllers/access_point.py
@@ -185,15 +185,14 @@
         ssh_settings: The ssh settings being used by the ssh connection.
         dhcp_settings: The dhcp server settings being used.
     """
-
     def __init__(self, configs):
         """
         Args:
             configs: configs for the access point from config file.
         """
         self.ssh_settings = settings.from_config(configs['ssh_config'])
-        self.log = logger.create_logger(lambda msg: '[Access Point|%s] %s' % (
-            self.ssh_settings.hostname, msg))
+        self.log = logger.create_logger(lambda msg: '[Access Point|%s] %s' %
+                                        (self.ssh_settings.hostname, msg))
         self.device_pdu_config = configs.get('PduDevice', None)
         self.identifier = self.ssh_settings.hostname
 
@@ -429,11 +428,25 @@
     def get_dhcp_logs(self):
         """Get DHCP logs for this AP object.
 
-        This allows consumers of the access point objects validate DHCP
+        This allows consumers of the access point objects to validate DHCP
         behavior.
         """
         return self._dhcp.get_logs()
 
+    def get_hostapd_logs(self):
+        """Get hostapd logs for all interfaces on AP object.
+
+        This allows consumers of the access point objects to validate hostapd
+        behavior.
+
+        Returns: A dict with {interface: log} from hostapd instances.
+        """
+        hostapd_logs = dict()
+        for identifier in self._aps:
+            hostapd_logs[identifier] = self._aps.get(
+                identifier).hostapd.pull_logs()
+        return hostapd_logs
+
     def start_nat(self):
         """Start NAT on the AP.
 
diff --git a/acts/framework/acts/controllers/android_device.py b/acts/framework/acts/controllers/android_device.py
index 74fb2fe..793cb23 100755
--- a/acts/framework/acts/controllers/android_device.py
+++ b/acts/framework/acts/controllers/android_device.py
@@ -48,6 +48,10 @@
 ACTS_CONTROLLER_REFERENCE_NAME = "android_devices"
 
 ANDROID_DEVICE_PICK_ALL_TOKEN = "*"
+# Key name for SL4A extra params in config file
+ANDROID_DEVICE_SL4A_CLIENT_PORT_KEY = "sl4a_client_port"
+ANDROID_DEVICE_SL4A_FORWARDED_PORT_KEY = "sl4a_forwarded_port"
+ANDROID_DEVICE_SL4A_SERVER_PORT_KEY = "sl4a_server_port"
 # Key name for adb logcat extra params in config file.
 ANDROID_DEVICE_ADB_LOGCAT_PARAM_KEY = "adb_logcat_param"
 ANDROID_DEVICE_EMPTY_CONFIG_MSG = "Configuration is empty, abort!"
@@ -58,7 +62,7 @@
 CRASH_REPORT_SKIPS = ("RAMDUMP_RESERVED", "RAMDUMP_STATUS", "RAMDUMP_OUTPUT",
                       "bluetooth")
 ALWAYS_ON_LOG_PATH = "/data/vendor/radio/logs/always-on"
-DEFAULT_QXDM_LOG_PATH = "/data/vendor/radio/diag_logs/logs"
+DEFAULT_QXDM_LOG_PATH = "/data/vendor/radio/diag_logs"
 DEFAULT_SDM_LOG_PATH = "/data/vendor/slog/"
 DEFAULT_SCREENSHOT_PATH = "/sdcard/Pictures/screencap"
 BUG_REPORT_TIMEOUT = 1800
@@ -235,12 +239,41 @@
             raise errors.AndroidDeviceConfigError(
                 "Required value 'serial' is missing in AndroidDevice config %s."
                 % c)
+        client_port = 0
+        if ANDROID_DEVICE_SL4A_CLIENT_PORT_KEY in c:
+            try:
+                client_port = int(c.pop(ANDROID_DEVICE_SL4A_CLIENT_PORT_KEY))
+            except ValueError:
+                raise errors.AndroidDeviceConfigError(
+                    "'%s' is not a valid number for config %s" %
+                    (ANDROID_DEVICE_SL4A_CLIENT_PORT_KEY, c))
+        server_port = None
+        if ANDROID_DEVICE_SL4A_SERVER_PORT_KEY in c:
+            try:
+                server_port = int(c.pop(ANDROID_DEVICE_SL4A_SERVER_PORT_KEY))
+            except ValueError:
+                raise errors.AndroidDeviceConfigError(
+                    "'%s' is not a valid number for config %s" %
+                    (ANDROID_DEVICE_SL4A_SERVER_PORT_KEY, c))
+        forwarded_port = 0
+        if ANDROID_DEVICE_SL4A_FORWARDED_PORT_KEY in c:
+            try:
+                forwarded_port = int(
+                    c.pop(ANDROID_DEVICE_SL4A_FORWARDED_PORT_KEY))
+            except ValueError:
+                raise errors.AndroidDeviceConfigError(
+                    "'%s' is not a valid number for config %s" %
+                    (ANDROID_DEVICE_SL4A_FORWARDED_PORT_KEY, c))
         ssh_config = c.pop('ssh_config', None)
         ssh_connection = None
         if ssh_config is not None:
             ssh_settings = settings.from_config(ssh_config)
             ssh_connection = connection.SshConnection(ssh_settings)
-        ad = AndroidDevice(serial, ssh_connection=ssh_connection)
+        ad = AndroidDevice(serial,
+                           ssh_connection=ssh_connection,
+                           client_port=client_port,
+                           forwarded_port=forwarded_port,
+                           server_port=server_port)
         ad.load_config(c)
         results.append(ad)
     return results
@@ -360,14 +393,27 @@
         adb: An AdbProxy object used for interacting with the device via adb.
         fastboot: A FastbootProxy object used for interacting with the device
                   via fastboot.
+        client_port: Preferred client port number on the PC host side for SL4A
+        forwarded_port: Preferred server port number forwarded from Android
+                        to the host PC via adb for SL4A connections
+        server_port: Preferred server port used by SL4A on Android device
+
     """
 
-    def __init__(self, serial='', ssh_connection=None):
+    def __init__(self,
+                 serial='',
+                 ssh_connection=None,
+                 client_port=0,
+                 forwarded_port=0,
+                 server_port=None):
         self.serial = serial
         # logging.log_path only exists when this is used in an ACTS test run.
         log_path_base = getattr(logging, 'log_path', '/tmp/logs')
         self.log_dir = 'AndroidDevice%s' % serial
         self.log_path = os.path.join(log_path_base, self.log_dir)
+        self.client_port = client_port
+        self.forwarded_port = forwarded_port
+        self.server_port = server_port
         self.log = tracelogger.TraceLogger(
             AndroidDeviceLoggerAdapter(logging.getLogger(),
                                        {'serial': serial}))
@@ -377,8 +423,8 @@
         self.register_service(services.Sl4aService(self))
         self.adb_logcat_process = None
         self.adb = adb.AdbProxy(serial, ssh_connection=ssh_connection)
-        self.fastboot = fastboot.FastbootProxy(
-            serial, ssh_connection=ssh_connection)
+        self.fastboot = fastboot.FastbootProxy(serial,
+                                               ssh_connection=ssh_connection)
         if not self.is_bootloader:
             self.root_adb()
         self._ssh_connection = ssh_connection
@@ -402,6 +448,34 @@
         if self._ssh_connection:
             self._ssh_connection.close()
 
+    def recreate_services(self, serial):
+        """Clean up the AndroidDevice object and re-create adb/sl4a services.
+
+        Unregister the existing services and re-create adb and sl4a services,
+        call this method when the connection break after certain API call
+        (e.g., enable USB tethering by #startTethering)
+
+        Args:
+            serial: the serial number of the AndroidDevice
+        """
+        # Clean the old services
+        for service in self._services:
+            service.unregister()
+        self._services.clear()
+        if self._ssh_connection:
+            self._ssh_connection.close()
+        self._sl4a_manager.stop_service()
+
+        # Wait for old services to stop
+        time.sleep(5)
+
+        # Re-create the new adb and sl4a services
+        self.register_service(services.AdbLogcatService(self))
+        self.register_service(services.Sl4aService(self))
+        self.adb.wait_for_device()
+        self.terminate_all_sessions()
+        self.start_services()
+
     def register_service(self, service):
         """Registers the service on the device. """
         service.register()
@@ -428,8 +502,8 @@
 
         Stop adb logcat and terminate sl4a sessions if exist.
         """
-        event_bus.post(
-            android_events.AndroidStopServicesEvent(self), ignore_errors=True)
+        event_bus.post(android_events.AndroidStopServicesEvent(self),
+                       ignore_errors=True)
 
     def is_connected(self):
         out = self.adb.devices()
@@ -654,7 +728,13 @@
             >>> ad = AndroidDevice()
             >>> droid, ed = ad.get_droid()
         """
-        session = self._sl4a_manager.create_session()
+        self.log.debug(
+            "Creating RPC client_port={}, forwarded_port={}, server_port={}".
+            format(self.client_port, self.forwarded_port, self.server_port))
+        session = self._sl4a_manager.create_session(
+            client_port=self.client_port,
+            forwarded_port=self.forwarded_port,
+            server_port=self.server_port)
         droid = session.rpc_client
         if handle_event:
             ed = session.get_event_dispatcher()
@@ -674,9 +754,8 @@
         """
         for cmd in ("ps -A", "ps"):
             try:
-                out = self.adb.shell(
-                    '%s | grep "S %s"' % (cmd, package_name),
-                    ignore_status=True)
+                out = self.adb.shell('%s | grep "S %s"' % (cmd, package_name),
+                                     ignore_status=True)
                 if package_name not in out:
                     continue
                 try:
@@ -768,10 +847,10 @@
         return adb_excerpt_path
 
     def search_logcat(self,
-                    matching_string,
-                    begin_time=None,
-                    end_time=None,
-                    logcat_path=None):
+                      matching_string,
+                      begin_time=None,
+                      end_time=None,
+                      logcat_path=None):
         """Search logcat message with given string.
 
         Args:
@@ -801,13 +880,12 @@
         """
         if not logcat_path:
             logcat_path = os.path.join(self.device_log_path,
-                                    'adblog_%s_debug.txt' % self.serial)
+                                       'adblog_%s_debug.txt' % self.serial)
         if not os.path.exists(logcat_path):
             self.log.warning("Logcat file %s does not exist." % logcat_path)
             return
-        output = job.run(
-            "grep '%s' %s" % (matching_string, logcat_path),
-            ignore_status=True)
+        output = job.run("grep '%s' %s" % (matching_string, logcat_path),
+                         ignore_status=True)
         if not output.stdout or output.exit_status != 0:
             return []
         if begin_time:
@@ -815,13 +893,13 @@
                 log_begin_time = acts_logger.epoch_to_log_line_timestamp(
                     begin_time)
                 begin_time = datetime.strptime(log_begin_time,
-                                            "%Y-%m-%d %H:%M:%S.%f")
+                                               "%Y-%m-%d %H:%M:%S.%f")
         if end_time:
             if not isinstance(end_time, datetime):
                 log_end_time = acts_logger.epoch_to_log_line_timestamp(
                     end_time)
                 end_time = datetime.strptime(log_end_time,
-                                            "%Y-%m-%d %H:%M:%S.%f")
+                                             "%Y-%m-%d %H:%M:%S.%f")
         result = []
         logs = re.findall(r'(\S+\s\S+)(.*)', output.stdout)
         for log in logs:
@@ -893,8 +971,8 @@
         Returns:
         Linux UID for the apk.
         """
-        output = self.adb.shell(
-            "dumpsys package %s | grep userId=" % apk_name, ignore_status=True)
+        output = self.adb.shell("dumpsys package %s | grep userId=" % apk_name,
+                                ignore_status=True)
         result = re.search(r"userId=(\d+)", output)
         if result:
             return result.group(1)
@@ -960,9 +1038,8 @@
         """
         for cmd in ("ps -A", "ps"):
             try:
-                out = self.adb.shell(
-                    '%s | grep "S %s"' % (cmd, package_name),
-                    ignore_status=True)
+                out = self.adb.shell('%s | grep "S %s"' % (cmd, package_name),
+                                     ignore_status=True)
                 if package_name in out:
                     self.log.info("apk %s is running", package_name)
                     return True
@@ -987,8 +1064,8 @@
         True if package is installed. False otherwise.
         """
         try:
-            self.adb.shell(
-                'am force-stop %s' % package_name, ignore_status=True)
+            self.adb.shell('am force-stop %s' % package_name,
+                           ignore_status=True)
         except Exception as e:
             self.log.warning("Fail to stop package %s: %s", package_name, e)
 
@@ -1029,8 +1106,8 @@
             br_out_path = out.split(':')[1].strip().split()[0]
             self.adb.pull("%s %s" % (br_out_path, full_out_path))
         else:
-            self.adb.bugreport(
-                " > {}".format(full_out_path), timeout=BUG_REPORT_TIMEOUT)
+            self.adb.bugreport(" > {}".format(full_out_path),
+                               timeout=BUG_REPORT_TIMEOUT)
         self.log.info("Bugreport for %s taken at %s.", test_name,
                       full_out_path)
         self.adb.wait_for_device(timeout=WAIT_FOR_DEVICE_TIMEOUT)
@@ -1092,10 +1169,10 @@
         if not host_path:
             host_path = self.log_path
         for device_path in device_paths:
-            self.log.info(
-                'Pull from device: %s -> %s' % (device_path, host_path))
-            self.adb.pull(
-                "%s %s" % (device_path, host_path), timeout=PULL_TIMEOUT)
+            self.log.info('Pull from device: %s -> %s' %
+                          (device_path, host_path))
+            self.adb.pull("%s %s" % (device_path, host_path),
+                          timeout=PULL_TIMEOUT)
 
     def check_crash_report(self,
                            test_name=None,
@@ -1110,10 +1187,9 @@
             except Exception as e:
                 self.log.debug("received exception %s", e)
                 continue
-            crashes = self.get_file_names(
-                crash_path,
-                skip_files=CRASH_REPORT_SKIPS,
-                begin_time=begin_time)
+            crashes = self.get_file_names(crash_path,
+                                          skip_files=CRASH_REPORT_SKIPS,
+                                          begin_time=begin_time)
             if crash_path == "/data/tombstones/" and crashes:
                 tombstones = crashes[:]
                 for tombstone in tombstones:
@@ -1136,8 +1212,9 @@
         # Sleep 10 seconds for the buffered log to be written in qxdm log file
         time.sleep(10)
         log_path = getattr(self, "qxdm_log_path", DEFAULT_QXDM_LOG_PATH)
-        qxdm_logs = self.get_file_names(
-            log_path, begin_time=begin_time, match_string="*.qmdl")
+        qxdm_logs = self.get_file_names(log_path,
+                                        begin_time=begin_time,
+                                        match_string="*.qmdl")
         if qxdm_logs:
             qxdm_log_path = os.path.join(self.device_log_path,
                                          "QXDM_%s" % self.serial)
@@ -1146,10 +1223,9 @@
             self.log.info("Pull QXDM Log %s to %s", qxdm_logs, qxdm_log_path)
             self.pull_files(qxdm_logs, qxdm_log_path)
 
-            self.adb.pull(
-                "/firmware/image/qdsp6m.qdb %s" % qxdm_log_path,
-                timeout=PULL_TIMEOUT,
-                ignore_status=True)
+            self.adb.pull("/firmware/image/qdsp6m.qdb %s" % qxdm_log_path,
+                          timeout=PULL_TIMEOUT,
+                          ignore_status=True)
             # Zip Folder
             utils.zip_directory('%s.zip' % qxdm_log_path, qxdm_log_path)
             shutil.rmtree(qxdm_log_path)
@@ -1176,8 +1252,9 @@
         ]
         sdm_logs = []
         for path in log_paths:
-            sdm_logs += self.get_file_names(
-                path, begin_time=begin_time, match_string="*.sdm*")
+            sdm_logs += self.get_file_names(path,
+                                            begin_time=begin_time,
+                                            match_string="*.sdm*")
         if sdm_logs:
             sdm_log_path = os.path.join(self.device_log_path,
                                         "SDM_%s" % self.serial)
@@ -1185,7 +1262,7 @@
             self.log.info("Pull SDM Log %s to %s", sdm_logs, sdm_log_path)
             self.pull_files(sdm_logs, sdm_log_path)
         else:
-            self.log.error("Didn't find SDM logs in %s." % log_paths)
+            self.log.error("Didn't find SDM logs in %s." % log_path)
         if "Verizon" in self.adb.getprop("gsm.sim.operator.alpha"):
             omadm_log_path = os.path.join(self.device_log_path,
                                           "OMADM_%s" % self.serial)
@@ -1263,8 +1340,8 @@
             status: true if iperf client start successfully.
             results: results have data flow information
         """
-        out = self.adb.shell(
-            "iperf3 -c {} {}".format(server_host, extra_args), timeout=timeout)
+        out = self.adb.shell("iperf3 -c {} {}".format(server_host, extra_args),
+                             timeout=timeout)
         clean_out = out.split('\n')
         if "error" in clean_out[0].lower():
             return False, clean_out
@@ -1315,7 +1392,9 @@
             'Device %s booting process timed out.' % self.serial,
             serial=self.serial)
 
-    def reboot(self, stop_at_lock_screen=False, timeout=180,
+    def reboot(self,
+               stop_at_lock_screen=False,
+               timeout=180,
                wait_after_reboot_complete=1):
         """Reboots the device.
 
@@ -1352,8 +1431,8 @@
                 # want the device to be missing to prove the device has kicked
                 # off the reboot.
                 break
-        self.wait_for_boot_completion(
-            timeout=(timeout - time.time() + timeout_start))
+        self.wait_for_boot_completion(timeout=(timeout - time.time() +
+                                               timeout_start))
 
         self.log.debug('Wait for a while after boot completion.')
         time.sleep(wait_after_reboot_complete)
@@ -1388,8 +1467,8 @@
                 break
             except adb.AdbError as e:
                 if timer + 1 == timeout:
-                    self.log.warning(
-                        'Unable to find IP address for %s.' % interface)
+                    self.log.warning('Unable to find IP address for %s.' %
+                                     interface)
                     return None
                 else:
                     time.sleep(1)
@@ -1454,7 +1533,7 @@
         for cmd in dumpsys_cmd:
             output = self.adb.shell(cmd, ignore_status=True)
             if not output or "not found" in output or "Can't find" in output or (
-                "mFocusedApp=null" in output):
+                    "mFocusedApp=null" in output):
                 result = ''
             else:
                 result = output.split(' ')[-2]
@@ -1603,11 +1682,11 @@
             return
         if not self.is_user_setup_complete() or self.is_setupwizard_on():
             # b/116709539 need this to prevent reboot after skip setup wizard
-            self.adb.shell(
-                "am start -a com.android.setupwizard.EXIT", ignore_status=True)
-            self.adb.shell(
-                "pm disable %s" % self.get_setupwizard_package_name(),
-                ignore_status=True)
+            self.adb.shell("am start -a com.android.setupwizard.EXIT",
+                           ignore_status=True)
+            self.adb.shell("pm disable %s" %
+                           self.get_setupwizard_package_name(),
+                           ignore_status=True)
         # Wait up to 5 seconds for user_setup_complete to be updated
         end_time = time.time() + 5
         while time.time() < end_time:
@@ -1657,8 +1736,8 @@
         try:
             self.ensure_verity_disabled()
             self.adb.remount()
-            out = self.adb.push(
-                '%s %s' % (src_file_path, dst_file_path), timeout=push_timeout)
+            out = self.adb.push('%s %s' % (src_file_path, dst_file_path),
+                                timeout=push_timeout)
             if 'error' in out:
                 self.log.error('Unable to push system file %s to %s due to %s',
                                src_file_path, dst_file_path, out)
diff --git a/acts/framework/acts/controllers/fuchsia_device.py b/acts/framework/acts/controllers/fuchsia_device.py
index efa34dd..59abec3 100644
--- a/acts/framework/acts/controllers/fuchsia_device.py
+++ b/acts/framework/acts/controllers/fuchsia_device.py
@@ -320,17 +320,17 @@
         self.start_services(skip_sl4f=self.skip_sl4f)
         # Init server
         self.init_server_connection()
-        self.init_ffx_connection()
 
         self.setup_commands = fd_conf_data.get('setup_commands', [])
         self.teardown_commands = fd_conf_data.get('teardown_commands', [])
 
         try:
+            self.init_ffx_connection()
             self.run_commands_from_config(self.setup_commands)
-        except FuchsiaDeviceError:
+        except Exception as e:
             # Prevent a threading error, since controller isn't fully up yet.
             self.clean_up()
-            raise FuchsiaDeviceError('Failed to run setup commands.')
+            raise e
 
     def _set_control_path_config(self, old_config, new_config):
         """Given an input ssh_config, write to a new config with proper
diff --git a/acts/framework/acts/controllers/fuchsia_lib/lib_controllers/wlan_controller.py b/acts/framework/acts/controllers/fuchsia_lib/lib_controllers/wlan_controller.py
index 1d202c6..d50f726 100644
--- a/acts/framework/acts/controllers/fuchsia_lib/lib_controllers/wlan_controller.py
+++ b/acts/framework/acts/controllers/fuchsia_lib/lib_controllers/wlan_controller.py
@@ -111,7 +111,12 @@
         net_ifaces = self.device.netstack_controller.list_interfaces()
         wlan_ifaces_by_role = {'client': {}, 'ap': {}}
         for iface in net_ifaces:
-            iface_mac = utils.mac_address_list_to_str(iface['mac'])
+            try:
+                # Some interfaces might not have a MAC
+                iface_mac = utils.mac_address_list_to_str(iface['mac'])
+            except Exception as e:
+                self.log.debug(f'Error {e} getting MAC for iface {iface}')
+                continue
             if iface_mac in wlan_ifaces_by_mac:
                 wlan_ifaces_by_mac[iface_mac]['netstack_id'] = iface['id']
 
diff --git a/acts/framework/acts/controllers/fuchsia_lib/session_manager_lib.py b/acts/framework/acts/controllers/fuchsia_lib/session_manager_lib.py
index 8c4bb55..2593dde 100644
--- a/acts/framework/acts/controllers/fuchsia_lib/session_manager_lib.py
+++ b/acts/framework/acts/controllers/fuchsia_lib/session_manager_lib.py
@@ -33,7 +33,7 @@
         """
         try:
             self.device.ffx_command(
-                "component bind /core/session-manager/session:session")
+                "component start /core/session-manager/session:session")
             return {'error': None, 'result': 'Success'}
         except Exception as e:
             return {'error': e, 'result': None}
diff --git a/acts/framework/acts/controllers/openwrt_lib/network_const.py b/acts/framework/acts/controllers/openwrt_lib/network_const.py
index 0a3fb42..3aba0de 100644
--- a/acts/framework/acts/controllers/openwrt_lib/network_const.py
+++ b/acts/framework/acts/controllers/openwrt_lib/network_const.py
@@ -1,3 +1,5 @@
+LOCALHOST = "192.168.1.1"
+
 # params for ipsec.conf
 IPSEC_CONF = {
     "config setup": {
@@ -15,7 +17,7 @@
     "conn L2TP_PSK": {
         "keyexchange": "ikev1",
         "type": "transport",
-        "left": "192.168.1.1",
+        "left": LOCALHOST,
         "leftprotoport": "17/1701",
         "leftauth": "psk",
         "right": "%any",
@@ -30,7 +32,7 @@
     "conn L2TP_RSA": {
         "keyexchange": "ikev1",
         "type": "transport",
-        "left": "192.168.1.1",
+        "left": LOCALHOST,
         "leftprotoport": "17/1701",
         "leftauth": "pubkey",
         "leftcert": "serverCert.der",
@@ -45,7 +47,7 @@
 IPSEC_HYBRID_RSA = {
     "conn HYBRID_RSA": {
         "keyexchange": "ikev1",
-        "left": "192.168.1.1",
+        "left": LOCALHOST,
         "leftsubnet": "0.0.0.0/0",
         "leftauth": "pubkey",
         "leftcert": "serverCert.der",
@@ -62,7 +64,7 @@
 IPSEC_XAUTH_PSK = {
     "conn XAUTH_PSK": {
         "keyexchange": "ikev1",
-        "left": "192.168.1.1",
+        "left": LOCALHOST,
         "leftsubnet": "0.0.0.0/0",
         "leftauth": "psk",
         "right": "%any",
@@ -76,7 +78,7 @@
 IPSEC_XAUTH_RSA = {
     "conn XAUTH_RSA": {
         "keyexchange": "ikev1",
-        "left": "192.168.1.1",
+        "left": LOCALHOST,
         "leftsubnet": "0.0.0.0/0",
         "leftcert": "serverCert.der",
         "leftsendcert": "always",
@@ -88,6 +90,100 @@
     }
 }
 
+IPSEC_IKEV2_MSCHAPV2 = {
+    "conn IKEV2_MSCHAPV2": {
+        "keyexchange": "ikev2",
+        "left": LOCALHOST,
+        "leftid": LOCALHOST,
+        "leftcert": "serverCert.der",
+        "leftsubnet": "0.0.0.0/0",
+        "leftauth": "pubkey",
+        "leftsendcert": "always",
+        "right": "%any",
+        "rightid": "vpntest",
+        "rightauth": "eap-mschapv2",
+        "auto": "add"
+    }
+}
+
+IPSEC_IKEV2_PSK = {
+    "conn IKEV2_PSK": {
+        "keyexchange": "ikev2",
+        "left": LOCALHOST,
+        "leftid": LOCALHOST,
+        "leftauth": "psk",
+        "leftsubnet": "0.0.0.0/0",
+        "right": "%any",
+        "rightid": "vpntest",
+        "rightauth": "psk",
+        "auto": "add"
+    }
+}
+
+IPSEC_IKEV2_RSA = {
+    "conn IKEV2_RSA": {
+        "keyexchange": "ikev2",
+        "left": LOCALHOST,
+        "leftid": LOCALHOST,
+        "leftcert": "serverCert.der",
+        "leftsubnet": "0.0.0.0/0",
+        "leftauth": "pubkey",
+        "leftsendcert": "always",
+        "right": "%any",
+        "rightid": "vpntest@%s" % LOCALHOST,
+        "rightauth": "pubkey",
+        "rightcert": "clientCert.pem",
+        "auto": "add"
+    }
+}
+
+IPSEC_IKEV2_MSCHAPV2_HOSTNAME = {
+    "conn IKEV2_MSCHAPV2_HOSTNAME": {
+        "keyexchange": "ikev2",
+        "left": LOCALHOST,
+        "leftid": "strongswan-vpn-server.android-iperf.com",
+        "leftcert": "serverCert.der",
+        "leftsubnet": "0.0.0.0/0",
+        "leftauth": "pubkey",
+        "leftsendcert": "always",
+        "right": "%any",
+        "rightid": "vpntest",
+        "rightauth": "eap-mschapv2",
+        "auto": "add"
+    }
+}
+
+IPSEC_IKEV2_PSK_HOSTNAME = {
+    "conn IKEV2_PSK_HOSTNAME": {
+        "keyexchange": "ikev2",
+        "left": LOCALHOST,
+        "leftid": "strongswan-vpn-server.android-iperf.com",
+        "leftauth": "psk",
+        "leftsubnet": "0.0.0.0/0",
+        "right": "%any",
+        "rightid": "vpntest",
+        "rightauth": "psk",
+        "auto": "add"
+    }
+}
+
+IPSEC_IKEV2_RSA_HOSTNAME = {
+    "conn IKEV2_RSA_HOSTNAME": {
+        "keyexchange": "ikev2",
+        "left": LOCALHOST,
+        "leftid": "strongswan-vpn-server.android-iperf.com",
+        "leftcert": "serverCert.der",
+        "leftsubnet": "0.0.0.0/0",
+        "leftauth": "pubkey",
+        "leftsendcert": "always",
+        "right": "%any",
+        "rightid": "vpntest@strongswan-vpn-server.android-iperf.com",
+        "rightauth": "pubkey",
+        "rightcert": "clientCert.pem",
+        "auto": "add"
+    }
+}
+
 # parmas for lx2tpd
 
 XL2TPD_CONF_GLOBAL = (
@@ -149,7 +245,6 @@
     "iptables -I FORWARD  -m policy --dir out --pol ipsec --proto esp -j ACCEPT",
     "iptables -I OUTPUT   -m policy --dir out --pol ipsec --proto esp -j ACCEPT",
     "iptables -t nat -I POSTROUTING -m policy --pol ipsec --dir out -j ACCEPT",
-    "iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT",
     "iptables -A INPUT -p esp -j ACCEPT",
     "iptables -A INPUT -i eth0.2 -p udp --dport 500 -j ACCEPT",
     "iptables -A INPUT -i eth0.2 -p tcp --dport 500 -j ACCEPT",
diff --git a/acts/framework/acts/controllers/openwrt_lib/network_settings.py b/acts/framework/acts/controllers/openwrt_lib/network_settings.py
index f632d57..b3c1e4e 100644
--- a/acts/framework/acts/controllers/openwrt_lib/network_settings.py
+++ b/acts/framework/acts/controllers/openwrt_lib/network_settings.py
@@ -42,6 +42,7 @@
 XL2TPD_OPTION_CONFIG_PATH = "/etc/ppp/options.xl2tpd"
 FIREWALL_CUSTOM_OPTION_PATH = "/etc/firewall.user"
 PPP_CHAP_SECRET_PATH = "/etc/ppp/chap-secrets"
+IKEV2_VPN_CERT_KEYS_PATH = "/var/ikev2_cert.sh"
 TCPDUMP_DIR = "/tmp/tcpdump/"
 LOCALHOST = "192.168.1.1"
 DEFAULT_PACKAGE_INSTALL_TIMEOUT = 200
@@ -463,7 +464,11 @@
         # setup vpn server local ip
         self.setup_vpn_local_ip()
         # generate cert and key for rsa
-        self.generate_vpn_cert_keys(country, org)
+        if self.l2tp.name == "ikev2-server":
+            self.generate_ikev2_vpn_cert_keys(country, org)
+            self.add_resource_record(self.l2tp.hostname, LOCALHOST)
+        else:
+            self.generate_vpn_cert_keys(country, org)
         # restart service
         self.service_manager.need_restart(SERVICE_IPSEC)
         self.service_manager.need_restart(SERVICE_XL2TPD)
@@ -475,6 +480,8 @@
         self.config.discard("setup_vpn_l2tp_server")
         self.restore_firewall_rules_for_l2tp()
         self.remove_vpn_local_ip()
+        if self.l2tp.name == "ikev2-server":
+            self.clear_resource_record()
         self.service_manager.need_restart(SERVICE_IPSEC)
         self.service_manager.need_restart(SERVICE_XL2TPD)
         self.service_manager.need_restart(SERVICE_FIREWALL)
@@ -508,6 +515,12 @@
                 config.append("")
 
         config = []
+        load_ipsec_config(network_const.IPSEC_IKEV2_MSCHAPV2, True)
+        load_ipsec_config(network_const.IPSEC_IKEV2_PSK, True)
+        load_ipsec_config(network_const.IPSEC_IKEV2_RSA, True)
+        load_ipsec_config(network_const.IPSEC_IKEV2_MSCHAPV2_HOSTNAME, True)
+        load_ipsec_config(network_const.IPSEC_IKEV2_PSK_HOSTNAME, True)
+        load_ipsec_config(network_const.IPSEC_IKEV2_RSA_HOSTNAME, True)
         load_ipsec_config(network_const.IPSEC_CONF)
         load_ipsec_config(network_const.IPSEC_L2TP_PSK)
         load_ipsec_config(network_const.IPSEC_L2TP_RSA)
@@ -601,6 +614,54 @@
         self.ssh.run("mv clientPkcs.p12 /www/downloads/")
         self.ssh.run("chmod 664 /www/downloads/clientPkcs.p12")
 
+    def generate_ikev2_vpn_cert_keys(self, country, org):
+        rsa = "--type rsa"
+        lifetime = "--lifetime 365"
+        size = "--size 4096"
+
+        if not self.path_exists("/www/downloads/"):
+            self.ssh.run("mkdir /www/downloads/")
+
+        ikev2_vpn_cert_keys = [
+            "ipsec pki --gen %s %s --outform der > caKey.der" % (rsa, size),
+            "ipsec pki --self --ca %s --in caKey.der %s --dn "
+            "\"C=%s, O=%s, CN=%s\" --outform der > caCert.der" %
+            (lifetime, rsa, country, org, self.l2tp.hostname),
+            "ipsec pki --gen %s %s --outform der > serverKey.der" % (size, rsa),
+            "ipsec pki --pub --in serverKey.der %s | ipsec pki --issue %s "
+            r"--cacert caCert.der --cakey caKey.der --dn \"C=%s, O=%s, CN=%s\" "
+            "--san %s --san %s --flag serverAuth --flag ikeIntermediate "
+            "--outform der > serverCert.der" % (rsa, lifetime, country, org,
+                                                self.l2tp.hostname, LOCALHOST,
+                                                self.l2tp.hostname),
+            "ipsec pki --gen %s %s --outform der > clientKey.der" % (size, rsa),
+            "ipsec pki --pub --in clientKey.der %s | ipsec pki --issue %s "
+            r"--cacert caCert.der --cakey caKey.der --dn \"C=%s, O=%s, CN=%s@%s\" "
+            r"--san \"%s\" --san \"%s@%s\" --san \"%s@%s\" --outform der "
+            "> clientCert.der" % (rsa, lifetime, country, org, self.l2tp.username,
+                                  self.l2tp.hostname, self.l2tp.username,
+                                  self.l2tp.username, LOCALHOST,
+                                  self.l2tp.username, self.l2tp.hostname),
+            "openssl rsa -inform DER -in clientKey.der "
+            "-out clientKey.pem -outform PEM",
+            "openssl x509 -inform DER -in clientCert.der "
+            "-out clientCert.pem -outform PEM",
+            "openssl x509 -inform DER -in caCert.der "
+            "-out caCert.pem -outform PEM",
+            "openssl pkcs12 -in clientCert.pem -inkey  clientKey.pem "
+            "-certfile caCert.pem -export -out clientPkcs.p12 -passout pass:",
+            "mv caCert.pem /etc/ipsec.d/cacerts/",
+            "mv *Cert* /etc/ipsec.d/certs/",
+            "mv *Key* /etc/ipsec.d/private/",
+            "mv clientPkcs.p12 /www/downloads/",
+            "chmod 664 /www/downloads/clientPkcs.p12",
+        ]
+        file_string = "\n".join(ikev2_vpn_cert_keys)
+        self.create_config_file(file_string, IKEV2_VPN_CERT_KEYS_PATH)
+
+        self.ssh.run("chmod +x %s" % IKEV2_VPN_CERT_KEYS_PATH)
+        self.ssh.run("%s" % IKEV2_VPN_CERT_KEYS_PATH)
+
     def update_firewall_rules_list(self):
         """Update rule list in /etc/config/firewall."""
         new_rules_list = []
@@ -919,9 +980,11 @@
         return tcpdump_remote_path if pull_dir else None
 
     def clear_tcpdump(self):
-        self.ssh.run("killall tpcdump", ignore_status=True)
-        if self.ssh.run("pgrep tpcdump", ignore_status=True).stdout:
+        self.ssh.run("killall tcpdump", ignore_status=True)
+        if self.ssh.run("pgrep tcpdump", ignore_status=True).stdout:
             raise signals.TestFailure("Failed to clean up tcpdump process.")
+        if self.path_exists(TCPDUMP_DIR):
+            self.ssh.run("rm -f  %s/*" % TCPDUMP_DIR)
 
     def _get_tcpdump_pid(self, tcpdump_file_name):
         """Check tcpdump process on OpenWrt."""
diff --git a/acts/framework/acts/controllers/sl4a_lib/sl4a_manager.py b/acts/framework/acts/controllers/sl4a_lib/sl4a_manager.py
index dbc59e7..959274d 100644
--- a/acts/framework/acts/controllers/sl4a_lib/sl4a_manager.py
+++ b/acts/framework/acts/controllers/sl4a_lib/sl4a_manager.py
@@ -111,12 +111,12 @@
         self._listen_for_port_lock = threading.Lock()
         self._sl4a_ports = set()
         self.adb = adb
-        self.log = logger.create_logger(
-            lambda msg: '[SL4A Manager|%s] %s' % (adb.serial, msg))
+        self.log = logger.create_logger(lambda msg: '[SL4A Manager|%s] %s' % (
+            adb.serial, msg))
         self.sessions = {}
         self._started = False
-        self.error_reporter = error_reporter.ErrorReporter(
-            'SL4A %s' % adb.serial)
+        self.error_reporter = error_reporter.ErrorReporter('SL4A %s' %
+                                                           adb.serial)
 
     @property
     def sl4a_ports_in_use(self):
@@ -163,8 +163,8 @@
 
         raise rpc_client.Sl4aConnectionError(
             'Unable to find a valid open port for a new server connection. '
-            'Expected port: %s. Open ports: %s' % (device_port,
-                                                   self._sl4a_ports))
+            'Expected port: %s. Open ports: %s' %
+            (device_port, self._sl4a_ports))
 
     def _get_all_ports_command(self):
         """Returns the list of all ports from the command to get ports."""
@@ -242,6 +242,7 @@
     def create_session(self,
                        max_connections=None,
                        client_port=0,
+                       forwarded_port=0,
                        server_port=None):
         """Creates an SL4A server with the given ports if possible.
 
@@ -250,7 +251,9 @@
         be randomized.
 
         Args:
-            client_port: The port on the host machine
+            client_port: The client port on the host machine
+            forwarded_port: The server port on the host machine forwarded
+                            by adb from the Android device
             server_port: The port on the Android device.
             max_connections: The max number of client connections for the
                 session.
@@ -266,22 +269,25 @@
             # Otherwise, open a new server on a random port.
             else:
                 server_port = 0
+        self.log.debug(
+            "Creating SL4A session client_port={}, forwarded_port={}, server_port={}"
+            .format(client_port, forwarded_port, server_port))
         self.start_sl4a_service()
-        session = sl4a_session.Sl4aSession(
-            self.adb,
-            client_port,
-            server_port,
-            self.obtain_sl4a_server,
-            self.diagnose_failure,
-            max_connections=max_connections)
+        session = sl4a_session.Sl4aSession(self.adb,
+                                           client_port,
+                                           server_port,
+                                           self.obtain_sl4a_server,
+                                           self.diagnose_failure,
+                                           forwarded_port,
+                                           max_connections=max_connections)
         self.sessions[session.uid] = session
         return session
 
     def stop_service(self):
         """Stops The SL4A Service. Force-stops the SL4A apk."""
         try:
-            self.adb.shell(
-                'am force-stop %s' % SL4A_PKG_NAME, ignore_status=True)
+            self.adb.shell('am force-stop %s' % SL4A_PKG_NAME,
+                           ignore_status=True)
         except Exception as e:
             self.log.warning("Fail to stop package %s: %s", SL4A_PKG_NAME, e)
         self._started = False
diff --git a/acts/framework/acts/controllers/sl4a_lib/sl4a_session.py b/acts/framework/acts/controllers/sl4a_lib/sl4a_session.py
index c0a4e1d..04fd787 100644
--- a/acts/framework/acts/controllers/sl4a_lib/sl4a_session.py
+++ b/acts/framework/acts/controllers/sl4a_lib/sl4a_session.py
@@ -55,6 +55,7 @@
                  device_port,
                  get_server_port_func,
                  on_error_callback,
+                 forwarded_port=0,
                  max_connections=None):
         """Creates an SL4A Session.
 
@@ -67,6 +68,8 @@
                 server for its first connection.
             device_port: The SL4A server port to be used as a hint for which
                 SL4A server to connect to.
+            forwarded_port: The server port on host machine forwarded by adb
+                            from Android device to accept SL4A connection
         """
         self._event_dispatcher = None
         self._terminate_lock = threading.Lock()
@@ -79,24 +82,24 @@
 
         self.log = logger.create_logger(_log_formatter)
 
+        self.forwarded_port = forwarded_port
         self.server_port = device_port
         self.uid = UNKNOWN_UID
         self.obtain_server_port = get_server_port_func
         self._on_error_callback = on_error_callback
 
         connection_creator = self._rpc_connection_creator(host_port)
-        self.rpc_client = rpc_client.RpcClient(
-            self.uid,
-            self.adb.serial,
-            self.diagnose_failure,
-            connection_creator,
-            max_connections=max_connections)
+        self.rpc_client = rpc_client.RpcClient(self.uid,
+                                               self.adb.serial,
+                                               self.diagnose_failure,
+                                               connection_creator,
+                                               max_connections=max_connections)
 
     def _rpc_connection_creator(self, host_port):
         def create_client(uid):
-            return self._create_rpc_connection(
-                ports=sl4a_ports.Sl4aPorts(host_port, 0, self.server_port),
-                uid=uid)
+            return self._create_rpc_connection(ports=sl4a_ports.Sl4aPorts(
+                host_port, self.forwarded_port, self.server_port),
+                                               uid=uid)
 
         return create_client
 
@@ -156,10 +159,14 @@
         ports.server_port = self.obtain_server_port(ports.server_port)
         self.server_port = ports.server_port
         # Forward the device port to the host.
-        ports.forwarded_port = self._create_forwarded_port(ports.server_port)
+        ports.forwarded_port = self._create_forwarded_port(
+            ports.server_port, hinted_port=ports.forwarded_port)
         client_socket, fd = self._create_client_side_connection(ports)
-        client = rpc_connection.RpcConnection(
-            self.adb, ports, client_socket, fd, uid=uid)
+        client = rpc_connection.RpcConnection(self.adb,
+                                              ports,
+                                              client_socket,
+                                              fd,
+                                              uid=uid)
         client.open()
         if uid == UNKNOWN_UID:
             self.uid = client.uid
@@ -195,9 +202,9 @@
             except OSError as e:
                 # If the port is in use, log and ask for any open port.
                 if e.errno == errno.EADDRINUSE:
-                    self.log.warning(
-                        'Port %s is already in use on the host. '
-                        'Generating a random port.' % ports.client_port)
+                    self.log.warning('Port %s is already in use on the host. '
+                                     'Generating a random port.' %
+                                     ports.client_port)
                     ports.client_port = 0
                     return self._create_client_side_connection(ports)
                 raise
diff --git a/acts/framework/tests/acts_utils_test.py b/acts/framework/tests/acts_utils_test.py
index 2c7c8ab..e662db8 100755
--- a/acts/framework/tests/acts_utils_test.py
+++ b/acts/framework/tests/acts_utils_test.py
@@ -72,74 +72,68 @@
 FUCHSIA_INTERFACES = {
     'id':
     '1',
-    'result': [{
-        'features':
-        4,
-        'filepath':
-        '[none]',
-        'id':
-        1,
-        'ipv4_addresses': [[127, 0, 0, 1]],
-        'ipv6_addresses': [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]],
-        'is_administrative_status_enabled':
-        True,
-        'is_physical_status_up':
-        True,
-        'mac': [0, 0, 0, 0, 0, 0],
-        'mtu':
-        65536,
-        'name':
-        'lo',
-        'topopath':
-        'loopback'
-    }, {
-        'features':
-        0,
-        'filepath':
-        '/dev/class/ethernet/000',
-        'id':
-        2,
-        'ipv4_addresses': [[100, 127, 110, 79]],
-        'ipv6_addresses':
-        [[254, 128, 0, 0, 0, 0, 0, 0, 198, 109, 60, 117, 44, 236, 29, 114],
-         [36, 1, 250, 0, 4, 128, 122, 0, 141, 79, 133, 255, 204, 92, 120, 126],
-         [36, 1, 250, 0, 4, 128, 122, 0, 4, 89, 185, 147, 252, 191, 20, 25]],
-        'is_administrative_status_enabled':
-        True,
-        'is_physical_status_up':
-        True,
-        'mac': [0, 224, 76, 5, 76, 229],
-        'mtu':
-        1514,
-        'name':
-        'eno1',
-        'topopath':
-        '@/dev/xhci/xhci/usb-bus/001/001/ifc-000/usb-cdc-ecm/ethernet'
-    }, {
-        'features':
-        1,
-        'filepath':
-        '/dev/class/ethernet/001',
-        'id':
-        3,
-        'ipv4_addresses': [],
-        'ipv6_addresses':
-        [[254, 128, 0, 0, 0, 0, 0, 0, 96, 255, 93, 96, 52, 253, 253, 243],
-         [254, 128, 0, 0, 0, 0, 0, 0, 70, 7, 11, 255, 254, 118, 126, 192]],
-        'is_administrative_status_enabled':
-        False,
-        'is_physical_status_up':
-        False,
-        'mac': [68, 7, 11, 118, 126, 192],
-        'mtu':
-        1500,
-        'name':
-        'wlanxc0',
-        'topopath':
-        '@/dev/wifi/wlanphy/wlanif-client/wlan-ethernet/ethernet'
-    }],
+    'result': [
+        {
+            'id': 1,
+            'name': 'lo',
+            'ipv4_addresses': [
+                [127, 0, 0, 1],
+            ],
+            'ipv6_addresses': [
+                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
+            ],
+            'online': True,
+            'mac': [0, 0, 0, 0, 0, 0],
+        },
+        {
+            'id':
+            2,
+            'name':
+            'eno1',
+            'ipv4_addresses': [
+                [100, 127, 110, 79],
+            ],
+            'ipv6_addresses': [
+                [
+                    254, 128, 0, 0, 0, 0, 0, 0, 198, 109, 60, 117, 44, 236, 29,
+                    114
+                ],
+                [
+                    36, 1, 250, 0, 4, 128, 122, 0, 141, 79, 133, 255, 204, 92,
+                    120, 126
+                ],
+                [
+                    36, 1, 250, 0, 4, 128, 122, 0, 4, 89, 185, 147, 252, 191,
+                    20, 25
+                ],
+            ],
+            'online':
+            True,
+            'mac': [0, 224, 76, 5, 76, 229],
+        },
+        {
+            'id':
+            3,
+            'name':
+            'wlanxc0',
+            'ipv4_addresses': [],
+            'ipv6_addresses': [
+                [
+                    254, 128, 0, 0, 0, 0, 0, 0, 96, 255, 93, 96, 52, 253, 253,
+                    243
+                ],
+                [
+                    254, 128, 0, 0, 0, 0, 0, 0, 70, 7, 11, 255, 254, 118, 126,
+                    192
+                ],
+            ],
+            'online':
+            False,
+            'mac': [68, 7, 11, 118, 126, 192],
+        },
+    ],
     'error':
-    None
+    None,
 }
 
 CORRECT_FULL_IP_LIST = {
diff --git a/acts_tests/acts_contrib/test_utils/abstract_devices/wlan_device_lib/AbstractDeviceWlanDeviceBaseTest.py b/acts_tests/acts_contrib/test_utils/abstract_devices/wlan_device_lib/AbstractDeviceWlanDeviceBaseTest.py
index a39eeed..ba05a53 100644
--- a/acts_tests/acts_contrib/test_utils/abstract_devices/wlan_device_lib/AbstractDeviceWlanDeviceBaseTest.py
+++ b/acts_tests/acts_contrib/test_utils/abstract_devices/wlan_device_lib/AbstractDeviceWlanDeviceBaseTest.py
@@ -13,6 +13,9 @@
 #   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.
+import os
+
+from acts import context
 from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
 
 from mobly import utils
@@ -54,3 +57,24 @@
 
         if device.hard_reboot_on_fail:
             device.reboot(reboot_type='hard', testbed_pdus=self.pdu_devices)
+
+    def download_ap_logs(self):
+        """Downloads the DHCP and hostapad logs from the access_point.
+
+        Using the current TestClassContext and TestCaseContext this method pulls
+        the DHCP and hostapd logs and outputs them to the correct path.
+        """
+        current_path = context.get_current_context().get_full_output_path()
+        dhcp_full_out_path = os.path.join(current_path, "dhcp_log.txt")
+
+        dhcp_log_file = open(dhcp_full_out_path, 'w')
+        dhcp_log_file.write(self.access_point.get_dhcp_logs())
+        dhcp_log_file.close()
+
+        hostapd_logs = self.access_point.get_hostapd_logs()
+        for interface in hostapd_logs:
+            out_name = interface + "_hostapd_log.txt"
+            hostapd_full_out_path = os.path.join(current_path, out_name)
+            hostapd_log_file = open(hostapd_full_out_path, 'w')
+            hostapd_log_file.write(hostapd_logs[interface])
+            hostapd_log_file.close()
diff --git a/acts_tests/acts_contrib/test_utils/net/net_test_utils.py b/acts_tests/acts_contrib/test_utils/net/net_test_utils.py
index c2e4de4..81416c8 100644
--- a/acts_tests/acts_contrib/test_utils/net/net_test_utils.py
+++ b/acts_tests/acts_contrib/test_utils/net/net_test_utils.py
@@ -16,7 +16,6 @@
 import logging
 import os
 import re
-import subprocess
 import time
 import urllib.request
 
@@ -33,6 +32,7 @@
 from acts_contrib.test_utils.tel.tel_data_utils import wait_for_cell_data_connection
 from acts_contrib.test_utils.tel.tel_test_utils import get_operator_name
 from acts_contrib.test_utils.tel.tel_test_utils import verify_http_connection
+
 from acts_contrib.test_utils.wifi import wifi_test_utils as wutils
 from scapy.config import conf
 from scapy.compat import plain_str
@@ -43,7 +43,6 @@
 TCPDUMP_PATH = "/data/local/tmp/"
 USB_CHARGE_MODE = "svc usb setFunctions"
 USB_TETHERING_MODE = "svc usb setFunctions rndis"
-USB_TETHERING_MODE_NCM = "svc usb setFunctions ncm"
 DEVICE_IP_ADDRESS = "ip address"
 LOCALHOST = "192.168.1.1"
 
@@ -510,59 +509,15 @@
 
 
 def start_usb_tethering(ad):
-    """Start USB tethering.
+    """Start USB tethering using #startTethering API.
 
-    Note: Start USB tethering with svc command will skip the entitlement check
-    flow, which is supported by carrier ATT, VZW, and SoftBank, and lead tests
-    to failed.
-    Since we're still using svc command to enable the USB tethering, make sure
-    your carrier doesn't support the entitlement.
+    Enable USB tethering by #startTethering API will break the RPC session,
+    Make sure you call #ad.recreate_services after call this API - b/149116235
 
     Args:
-        ad: android device object
+        ad: AndroidDevice object
     """
-    # TODO: test USB tethering by #startTethering API - b/149116235
-    if is_carrier_supports_entitlement(ad):
-        raise signals.TestFailure(
-            "Carrier supports entitlement, fail to enable the USB tethering.")
-    if not start_usb_tethering_rndis(ad) and not start_usb_tethering_ncm(ad):
-        raise signals.TestFailure("Unable to enable USB tethering.")
-
-
-def start_usb_tethering_rndis(ad):
-    """Start USB tethering using RNDIS.
-
-    Args:
-        ad: Android device object
-    Return:
-        true if USB tethering enabled
-    """
-    ad.log.info("Starting USB Tethering RNDIS")
-    ad.stop_services()
-    ad.adb.shell(USB_TETHERING_MODE, ignore_status=True)
-    ad.adb.wait_for_device()
-    ad.start_services()
-    if "rndis" not in ad.adb.shell(DEVICE_IP_ADDRESS):
-        return False
-    return True
-
-
-def start_usb_tethering_ncm(ad):
-    """Start USB tethering using NCM.
-
-    Args:
-        ad: Android device object
-    Return:
-        true if USB tethering enabled.
-    """
-    ad.log.info("Starting USB Tethering NCM")
-    ad.stop_services()
-    ad.adb.shell(USB_TETHERING_MODE_NCM, ignore_status=True)
-    ad.adb.wait_for_device()
-    ad.start_services()
-    if "ncm" not in ad.adb.shell(DEVICE_IP_ADDRESS):
-        return False
-    return True
+    ad.droid.connectivityStartTethering(tel_defines.TETHERING_USB, False)
 
 
 def stop_usb_tethering(ad):
diff --git a/acts_tests/acts_contrib/test_utils/tel/GFTInOutBaseTest.py b/acts_tests/acts_contrib/test_utils/tel/GFTInOutBaseTest.py
index 4ee6b16..9ff86be 100644
--- a/acts_tests/acts_contrib/test_utils/tel/GFTInOutBaseTest.py
+++ b/acts_tests/acts_contrib/test_utils/tel/GFTInOutBaseTest.py
@@ -126,7 +126,7 @@
                 adjust_gradually = self.user_params.get('adjust_gradually')
             if adjust_gradually:
                 self.log.info("adjust wifi signal set mini-circuits to %s" %(power))
-                self.adjust_atten_slowly(10, NO_SERVICE_AREA)
+                self.adjust_atten_slowly(10, NO_WIFI_AREA)
             else:
                 self.log.info("adjust wifi signal and set mini-circuits to %s" %(power))
                 self.attenuators[WIFI_PORT].set_atten(power)
@@ -175,7 +175,7 @@
         """adjust attenuator slowly
         Args:
             adjust_level: adjust power level for each cycle
-            move_to: no service area, in service area, wifi area
+            move_to: NO_SERVICE_AREA, IN_SERVICE_AREA , WIFI_AREA, NO_WIFI_AREA
             step: adjust attenuator how many time
             step_time: wait for how many sec for each loop
         Returns:
@@ -225,7 +225,7 @@
         return True
 
     def verify_device_status(self, ad, call_type=None, end_call=True,
-        talk_time=30, verify_data=True, verify_voice=True, retry=True, data_retries=2):
+        talk_time=30, verify_data=True, verify_voice=True, data_retries=2, voice_retries=2):
         """verfiy device status includes network service, data connection and voice call
         Args:
             ad: android device
@@ -234,37 +234,39 @@
             talk_time: in call duration in sec
             verify_data: flag to check data connection
             verify_voice: flag to check voice
+            data_retries: retry times for data verification
+            voice_retris:retry times for voice call
         Returns:
             return True if pass
         """
-        test_result = True
         tasks = [(check_network_service, (ad, )) for ad in self.android_devices]
         if not multithread_func(self.log, tasks):
             log_screen_shot(ad, "check_network_service_fail")
-            ad.log.info("check_network_service_fail")
-            test_result = False
-        if retry:
-            if call_type:
-                tasks = [(mo_voice_call, (self.log, ad, call_type, end_call, talk_time, 3))
-                    for ad in self.android_devices]
-                test_result = multithread_func(self.log, tasks)
-        elif verify_data and test_result:
+            ad.log.info("check_network_service fail")
+            return False
+        else:
+            self.log.info("check_network_service pass")
+        if verify_data:
             tasks = [(verify_data_connection, (ad, data_retries ))
                 for ad in self.android_devices]
             if not multithread_func(self.log, tasks):
                 log_screen_shot(ad, "verify_data_connection_fail")
                 ad.log.info("verify_data_connection_fail")
-                test_result = False
-        elif verify_voice and test_result:
+                return False
+            else:
+                self.log.info("verify_data_connection pass")
+        if verify_voice:
             if call_type:
-                tasks = [(mo_voice_call, (self.log, ad, call_type, end_call, talk_time))
-                    for ad in self.android_devices]
+                tasks = [(mo_voice_call, (self.log, ad, call_type, end_call, talk_time,
+                    voice_retries)) for ad in self.android_devices]
             if not multithread_func(self.log, tasks):
                 log_screen_shot(ad, "verify_voice_call_fail")
                 ad.log.info("verify_voice_call_fail")
-                test_result = False
-        return test_result
-
+                return False
+            else:
+                self.log.info("verify_voice_call pass")
+                return True
+        return True
 
     def _on_failure(self, error_msg="", assert_on_fail=True, test_result=False):
         """ operation on fail
@@ -279,3 +281,4 @@
         for ad in self.android_devices:
             log_screen_shot(ad, error_msg)
         self.log.info(error_msg)
+
diff --git a/acts_tests/acts_contrib/test_utils/tel/TelephonyBaseTest.py b/acts_tests/acts_contrib/test_utils/tel/TelephonyBaseTest.py
index 60941ce..45edc1f 100644
--- a/acts_tests/acts_contrib/test_utils/tel/TelephonyBaseTest.py
+++ b/acts_tests/acts_contrib/test_utils/tel/TelephonyBaseTest.py
@@ -503,6 +503,8 @@
         stop_tcpdumps(self.android_devices)
 
     def on_fail(self, test_name, begin_time):
+        for ad in self.android_devices:
+            ad.screenshot(f"{ad.serial}_last_screen")
         self._take_bug_report(test_name, begin_time)
 
     def on_pass(self, test_name, begin_time):
diff --git a/acts_tests/acts_contrib/test_utils/tel/gft_inout_utils.py b/acts_tests/acts_contrib/test_utils/tel/gft_inout_utils.py
index 87f0e68..2e4cfd4 100644
--- a/acts_tests/acts_contrib/test_utils/tel/gft_inout_utils.py
+++ b/acts_tests/acts_contrib/test_utils/tel/gft_inout_utils.py
@@ -15,7 +15,6 @@
 #   limitations under the License.
 
 import time
-
 from acts_contrib.test_utils.tel.gft_inout_defines import VOLTE_CALL
 from acts_contrib.test_utils.tel.gft_inout_defines import CSFB_CALL
 from acts_contrib.test_utils.tel.gft_inout_defines import WFC_CALL
@@ -61,6 +60,7 @@
         %(timeout, service_state))
     return False
 
+
 def check_back_to_service_time(ad, timeout=120):
     """ check device is back to service or not
 
@@ -90,6 +90,7 @@
         %(timeout, service_state))
     return False
 
+
 def check_network_service(ad):
     """ check network service
 
@@ -231,7 +232,8 @@
         ad.log.error("device is not in call")
     return "UNKNOWN"
 
-def verify_data_connection(ad, retries=1, retry_time=30):
+
+def verify_data_connection(ad, retries=3, retry_time=30):
     """ verify data connection
 
         Args:
@@ -247,19 +249,18 @@
         wifi_info = ad.droid.wifiGetConnectionInfo()
         if wifi_info["supplicant_state"] == "completed":
             ad.log.info("Wifi is connected=%s" %(wifi_info["SSID"]))
-        else:
-            ad.log.info("verify_data_connection attempt %d", i + 1)
-            if not verify_internet_connection(ad.log, ad, retries=3):
-                data_state = ad.droid.telephonyGetDataConnectionState()
-                network_type_data = ad.droid.telephonyGetCurrentDataNetworkType()
-                ad.log.error("verify_internet fail. data_state=%s, network_type_data=%s"
+        ad.log.info("verify_data_connection attempt %d", i + 1)
+        if not verify_internet_connection(ad.log, ad, retries=3):
+            data_state = ad.droid.telephonyGetDataConnectionState()
+            network_type_data = ad.droid.telephonyGetCurrentDataNetworkType()
+            ad.log.error("verify_internet fail. data_state=%s, network_type_data=%s"
                 %(data_state, network_type_data))
-                ad.log.info("verify_data_connection fail attempt %d", i + 1)
-                log_screen_shot(ad, "verify_internet")
-                time.sleep(retry_time)
-            else:
-                ad.log.info("verify_data_connection pass")
-                return True
+            ad.log.info("verify_data_connection fail attempt %d", i + 1)
+            log_screen_shot(ad, "verify_internet")
+            time.sleep(retry_time)
+        else:
+            ad.log.info("verify_data_connection pass")
+            return True
     return False
 
 
@@ -282,6 +283,7 @@
     ad.log.info("telephonyIsVolteAvailable=%s" %(r4))
     return r1
 
+
 def browsing_test_ping_retry(ad):
     """ If browse test fails, use ping to test data connection
 
@@ -300,8 +302,4 @@
             ad.log.info("Ping fail!")
             return False
     else:
-        ad.log.info("Successful to browse websites!")
-
-
-
-
+        ad.log.info("Successful to browse websites!")
\ No newline at end of file
diff --git a/acts_tests/acts_contrib/test_utils/tel/tel_bt_utils.py b/acts_tests/acts_contrib/test_utils/tel/tel_bt_utils.py
index 6f49178..8f754ed 100644
--- a/acts_tests/acts_contrib/test_utils/tel/tel_bt_utils.py
+++ b/acts_tests/acts_contrib/test_utils/tel/tel_bt_utils.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#   Copyright 2021 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -21,9 +21,9 @@
 from acts_contrib.test_utils.bt.bt_test_utils import pair_pri_to_sec
 from acts_contrib.test_utils.tel.tel_defines import NETWORK_SERVICE_DATA
 from acts_contrib.test_utils.tel.tel_data_utils import test_internet_connection
-from acts_contrib.test_utils.tel.tel_data_utils import verify_internet_connection
 from acts_contrib.test_utils.tel.tel_data_utils import wait_for_cell_data_connection
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_network_generation
+from acts_contrib.test_utils.tel.tel_test_utils import verify_internet_connection
 from acts_contrib.test_utils.tel.tel_test_utils import wait_for_state
 from acts_contrib.test_utils.tel.tel_voice_utils import call_setup_teardown
 from acts_contrib.test_utils.tel.tel_voice_utils import hangup_call
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 2c9a4a7..05808f9 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
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#   Copyright 2021 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -16,10 +16,12 @@
 
 
 import logging
+import os
 import time
 import random
 from queue import Empty
 
+from acts.controllers.android_device import SL4A_APK_NAME
 from acts.utils import adb_shell_ping
 from acts.utils import rand_ascii_str
 from acts.utils import disable_doze
@@ -49,11 +51,15 @@
 from acts_contrib.test_utils.tel.tel_defines import NETWORK_SERVICE_VOICE
 from acts_contrib.test_utils.tel.tel_defines import RAT_5G
 from acts_contrib.test_utils.tel.tel_defines import TETHERING_MODE_WIFI
+from acts_contrib.test_utils.tel.tel_defines import TYPE_MOBILE
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_AFTER_REBOOT
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_ANDROID_STATE_SETTLING
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_BETWEEN_REG_AND_CALL
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_BETWEEN_STATE_CHECK
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_DATA_STATUS_CHANGE_DURING_WIFI_TETHERING
+from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_FOR_DATA_STALL
+from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_FOR_NW_VALID_FAIL
+from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_FOR_DATA_STALL_RECOVERY
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_IN_CALL_FOR_IMS
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_TETHERING_AFTER_REBOOT
 from acts_contrib.test_utils.tel.tel_defines import DataConnectionStateContainer
@@ -73,22 +79,21 @@
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_iwlan
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_voice_general
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import wait_for_voice_attach_for_subscription
+from acts_contrib.test_utils.tel.tel_test_utils import _check_file_existence
+from acts_contrib.test_utils.tel.tel_test_utils import _generate_file_directory_and_file_name
 from acts_contrib.test_utils.tel.tel_test_utils import _wait_for_droid_in_state
 from acts_contrib.test_utils.tel.tel_test_utils import get_internet_connection_type
-from acts_contrib.test_utils.tel.tel_test_utils import get_mobile_data_usage
 from acts_contrib.test_utils.tel.tel_test_utils import get_network_rat_for_subscription
 from acts_contrib.test_utils.tel.tel_test_utils import get_service_state_by_adb
 from acts_contrib.test_utils.tel.tel_test_utils import is_droid_in_network_generation_for_subscription
 from acts_contrib.test_utils.tel.tel_test_utils import is_event_match
 from acts_contrib.test_utils.tel.tel_test_utils import rat_generation_from_rat
-from acts_contrib.test_utils.tel.tel_test_utils import start_youtube_video
 from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode
 from acts_contrib.test_utils.tel.tel_test_utils import verify_http_connection
 from acts_contrib.test_utils.tel.tel_test_utils import verify_incall_state
 from acts_contrib.test_utils.tel.tel_test_utils import verify_internet_connection
 from acts_contrib.test_utils.tel.tel_test_utils import wait_for_data_attach_for_subscription
 from acts_contrib.test_utils.tel.tel_test_utils import wait_for_state
-from acts_contrib.test_utils.tel.tel_test_utils import active_file_download_task
 from acts_contrib.test_utils.tel.tel_voice_utils import call_setup_teardown
 from acts_contrib.test_utils.tel.tel_voice_utils import hangup_call
 from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call_active
@@ -2364,4 +2369,500 @@
         ad.log.error("Exception error %s", str(e))
         return False
     finally:
-        ad.droid.connectivityStopTrackingConnectivityStateChange()
\ No newline at end of file
+        ad.droid.connectivityStopTrackingConnectivityStateChange()
+
+
+def check_curl_availability(ad):
+    if not hasattr(ad, "curl_capable"):
+        try:
+            out = ad.adb.shell("/data/curl --version")
+            if not out or "not found" in out:
+                setattr(ad, "curl_capable", False)
+                ad.log.info("curl is unavailable, use chrome to download file")
+            else:
+                setattr(ad, "curl_capable", True)
+        except Exception:
+            setattr(ad, "curl_capable", False)
+            ad.log.info("curl is unavailable, use chrome to download file")
+    return ad.curl_capable
+
+
+def start_youtube_video(ad, url="vnd.youtube:watch?v=pSJoP0LR8CQ"):
+    ad.log.info("Open an youtube video")
+    for _ in range(3):
+        ad.ensure_screen_on()
+        ad.adb.shell('am start -a android.intent.action.VIEW -d "%s"' % url)
+        if wait_for_state(ad.droid.audioIsMusicActive, True, 15, 1):
+            ad.log.info("Started a video in youtube, audio is in MUSIC state")
+            return True
+        ad.log.info("Audio is not in MUSIC state. Quit Youtube.")
+        for _ in range(3):
+            ad.send_keycode("BACK")
+            time.sleep(1)
+        time.sleep(3)
+    return False
+
+
+def http_file_download_by_sl4a(ad,
+                               url,
+                               out_path=None,
+                               expected_file_size=None,
+                               remove_file_after_check=True,
+                               timeout=300):
+    """Download http file by sl4a RPC call.
+
+    Args:
+        ad: Android Device Object.
+        url: The url that file to be downloaded from".
+        out_path: Optional. Where to download file to.
+                  out_path is /sdcard/Download/ by default.
+        expected_file_size: Optional. Provided if checking the download file meet
+                            expected file size in unit of byte.
+        remove_file_after_check: Whether to remove the downloaded file after
+                                 check.
+        timeout: timeout for file download to complete.
+    """
+    file_folder, file_name = _generate_file_directory_and_file_name(
+        url, out_path)
+    file_path = os.path.join(file_folder, file_name)
+    ad.adb.shell("rm -f %s" % file_path)
+    accounting_apk = SL4A_APK_NAME
+    result = True
+    try:
+        if not getattr(ad, "data_droid", None):
+            ad.data_droid, ad.data_ed = ad.get_droid()
+            ad.data_ed.start()
+        else:
+            try:
+                if not ad.data_droid.is_live:
+                    ad.data_droid, ad.data_ed = ad.get_droid()
+                    ad.data_ed.start()
+            except Exception:
+                ad.log.info("Start new sl4a session for file download")
+                ad.data_droid, ad.data_ed = ad.get_droid()
+                ad.data_ed.start()
+        data_accounting = {
+            "mobile_rx_bytes":
+            ad.droid.getMobileRxBytes(),
+            "subscriber_mobile_data_usage":
+            get_mobile_data_usage(ad, None, None),
+            "sl4a_mobile_data_usage":
+            get_mobile_data_usage(ad, None, accounting_apk)
+        }
+        ad.log.debug("Before downloading: %s", data_accounting)
+        ad.log.info("Download file from %s to %s by sl4a RPC call", url,
+                    file_path)
+        try:
+            ad.data_droid.httpDownloadFile(url, file_path, timeout=timeout)
+        except Exception as e:
+            ad.log.warning("SL4A file download error: %s", e)
+            ad.data_droid.terminate()
+            return False
+        if _check_file_existence(ad, file_path, expected_file_size):
+            ad.log.info("%s is downloaded successfully", url)
+            new_data_accounting = {
+                "mobile_rx_bytes":
+                ad.droid.getMobileRxBytes(),
+                "subscriber_mobile_data_usage":
+                get_mobile_data_usage(ad, None, None),
+                "sl4a_mobile_data_usage":
+                get_mobile_data_usage(ad, None, accounting_apk)
+            }
+            ad.log.debug("After downloading: %s", new_data_accounting)
+            accounting_diff = {
+                key: value - data_accounting[key]
+                for key, value in new_data_accounting.items()
+            }
+            ad.log.debug("Data accounting difference: %s", accounting_diff)
+            if getattr(ad, "on_mobile_data", False):
+                for key, value in accounting_diff.items():
+                    if value < expected_file_size:
+                        ad.log.debug("%s diff is %s less than %s", key,
+                                       value, expected_file_size)
+                        ad.data_accounting["%s_failure"] += 1
+            else:
+                for key, value in accounting_diff.items():
+                    if value >= expected_file_size:
+                        ad.log.error("%s diff is %s. File download is "
+                                     "consuming mobile data", key, value)
+                        result = False
+            return result
+        else:
+            ad.log.warning("Fail to download %s", url)
+            return False
+    except Exception as e:
+        ad.log.error("Download %s failed with exception %s", url, e)
+        raise
+    finally:
+        if remove_file_after_check:
+            ad.log.info("Remove the downloaded file %s", file_path)
+            ad.adb.shell("rm %s" % file_path, ignore_status=True)
+
+
+def http_file_download_by_curl(ad,
+                               url,
+                               out_path=None,
+                               expected_file_size=None,
+                               remove_file_after_check=True,
+                               timeout=3600,
+                               limit_rate=None,
+                               retry=3):
+    """Download http file by adb curl.
+
+    Args:
+        ad: Android Device Object.
+        url: The url that file to be downloaded from".
+        out_path: Optional. Where to download file to.
+                  out_path is /sdcard/Download/ by default.
+        expected_file_size: Optional. Provided if checking the download file meet
+                            expected file size in unit of byte.
+        remove_file_after_check: Whether to remove the downloaded file after
+                                 check.
+        timeout: timeout for file download to complete.
+        limit_rate: download rate in bps. None, if do not apply rate limit.
+        retry: the retry request times provided in curl command.
+    """
+    file_directory, file_name = _generate_file_directory_and_file_name(
+        url, out_path)
+    file_path = os.path.join(file_directory, file_name)
+    curl_cmd = "/data/curl"
+    if limit_rate:
+        curl_cmd += " --limit-rate %s" % limit_rate
+    if retry:
+        curl_cmd += " --retry %s" % retry
+    curl_cmd += " --url %s > %s" % (url, file_path)
+    try:
+        ad.log.info("Download %s to %s by adb shell command %s", url,
+                    file_path, curl_cmd)
+
+        ad.adb.shell(curl_cmd, timeout=timeout)
+        if _check_file_existence(ad, file_path, expected_file_size):
+            ad.log.info("%s is downloaded to %s successfully", url, file_path)
+            return True
+        else:
+            ad.log.warning("Fail to download %s", url)
+            return False
+    except Exception as e:
+        ad.log.warning("Download %s failed with exception %s", url, e)
+        return False
+    finally:
+        if remove_file_after_check:
+            ad.log.info("Remove the downloaded file %s", file_path)
+            ad.adb.shell("rm %s" % file_path, ignore_status=True)
+
+
+def open_url_by_adb(ad, url):
+    ad.adb.shell('am start -a android.intent.action.VIEW -d "%s"' % url)
+
+
+def http_file_download_by_chrome(ad,
+                                 url,
+                                 expected_file_size=None,
+                                 remove_file_after_check=True,
+                                 timeout=3600):
+    """Download http file by chrome.
+
+    Args:
+        ad: Android Device Object.
+        url: The url that file to be downloaded from".
+        expected_file_size: Optional. Provided if checking the download file meet
+                            expected file size in unit of byte.
+        remove_file_after_check: Whether to remove the downloaded file after
+                                 check.
+        timeout: timeout for file download to complete.
+    """
+    chrome_apk = "com.android.chrome"
+    file_directory, file_name = _generate_file_directory_and_file_name(
+        url, "/sdcard/Download/")
+    file_path = os.path.join(file_directory, file_name)
+    # Remove pre-existing file
+    ad.force_stop_apk(chrome_apk)
+    file_to_be_delete = os.path.join(file_directory, "*%s*" % file_name)
+    ad.adb.shell("rm -f %s" % file_to_be_delete)
+    ad.adb.shell("rm -rf /sdcard/Download/.*")
+    ad.adb.shell("rm -f /sdcard/Download/.*")
+    data_accounting = {
+        "total_rx_bytes": ad.droid.getTotalRxBytes(),
+        "mobile_rx_bytes": ad.droid.getMobileRxBytes(),
+        "subscriber_mobile_data_usage": get_mobile_data_usage(ad, None, None),
+        "chrome_mobile_data_usage": get_mobile_data_usage(
+            ad, None, chrome_apk)
+    }
+    ad.log.debug("Before downloading: %s", data_accounting)
+    ad.log.info("Download %s with timeout %s", url, timeout)
+    ad.ensure_screen_on()
+    open_url_by_adb(ad, url)
+    elapse_time = 0
+    result = True
+    while elapse_time < timeout:
+        time.sleep(30)
+        if _check_file_existence(ad, file_path, expected_file_size):
+            ad.log.info("%s is downloaded successfully", url)
+            if remove_file_after_check:
+                ad.log.info("Remove the downloaded file %s", file_path)
+                ad.adb.shell("rm -f %s" % file_to_be_delete)
+                ad.adb.shell("rm -rf /sdcard/Download/.*")
+                ad.adb.shell("rm -f /sdcard/Download/.*")
+            #time.sleep(30)
+            new_data_accounting = {
+                "mobile_rx_bytes":
+                ad.droid.getMobileRxBytes(),
+                "subscriber_mobile_data_usage":
+                get_mobile_data_usage(ad, None, None),
+                "chrome_mobile_data_usage":
+                get_mobile_data_usage(ad, None, chrome_apk)
+            }
+            ad.log.info("After downloading: %s", new_data_accounting)
+            accounting_diff = {
+                key: value - data_accounting[key]
+                for key, value in new_data_accounting.items()
+            }
+            ad.log.debug("Data accounting difference: %s", accounting_diff)
+            if getattr(ad, "on_mobile_data", False):
+                for key, value in accounting_diff.items():
+                    if value < expected_file_size:
+                        ad.log.warning("%s diff is %s less than %s", key,
+                                       value, expected_file_size)
+                        ad.data_accounting["%s_failure" % key] += 1
+            else:
+                for key, value in accounting_diff.items():
+                    if value >= expected_file_size:
+                        ad.log.error("%s diff is %s. File download is "
+                                     "consuming mobile data", key, value)
+                        result = False
+            return result
+        elif _check_file_existence(ad, "%s.crdownload" % file_path):
+            ad.log.info("Chrome is downloading %s", url)
+        elif elapse_time < 60:
+            # download not started, retry download wit chrome again
+            open_url_by_adb(ad, url)
+        else:
+            ad.log.error("Unable to download file from %s", url)
+            break
+        elapse_time += 30
+    ad.log.warning("Fail to download file from %s", url)
+    ad.force_stop_apk("com.android.chrome")
+    ad.adb.shell("rm -f %s" % file_to_be_delete)
+    ad.adb.shell("rm -rf /sdcard/Download/.*")
+    ad.adb.shell("rm -f /sdcard/Download/.*")
+    return False
+
+
+def get_mobile_data_usage(ad, sid=None, apk=None):
+    if not sid:
+        sid = ad.droid.subscriptionGetDefaultDataSubId()
+    current_time = int(time.time() * 1000)
+    begin_time = current_time - 10 * 24 * 60 * 60 * 1000
+    end_time = current_time + 10 * 24 * 60 * 60 * 1000
+
+    if apk:
+        uid = ad.get_apk_uid(apk)
+        ad.log.debug("apk %s uid = %s", apk, uid)
+        try:
+            usage_info = ad.droid.getMobileDataUsageInfoForUid(uid, sid)
+            ad.log.debug("Mobile data usage info for uid %s = %s", uid,
+                        usage_info)
+            return usage_info["UsageLevel"]
+        except:
+            try:
+                return ad.droid.connectivityQueryDetailsForUid(
+                    TYPE_MOBILE,
+                    ad.droid.telephonyGetSubscriberIdForSubscription(sid),
+                    begin_time, end_time, uid)
+            except:
+                return ad.droid.connectivityQueryDetailsForUid(
+                    ad.droid.telephonyGetSubscriberIdForSubscription(sid),
+                    begin_time, end_time, uid)
+    else:
+        try:
+            usage_info = ad.droid.getMobileDataUsageInfo(sid)
+            ad.log.debug("Mobile data usage info = %s", usage_info)
+            return usage_info["UsageLevel"]
+        except:
+            try:
+                return ad.droid.connectivityQuerySummaryForDevice(
+                    TYPE_MOBILE,
+                    ad.droid.telephonyGetSubscriberIdForSubscription(sid),
+                    begin_time, end_time)
+            except:
+                return ad.droid.connectivityQuerySummaryForDevice(
+                    ad.droid.telephonyGetSubscriberIdForSubscription(sid),
+                    begin_time, end_time)
+
+
+def set_mobile_data_usage_limit(ad, limit, subscriber_id=None):
+    if not subscriber_id:
+        subscriber_id = ad.droid.telephonyGetSubscriberId()
+    ad.log.debug("Set subscriber mobile data usage limit to %s", limit)
+    ad.droid.logV("Setting subscriber mobile data usage limit to %s" % limit)
+    try:
+        ad.droid.connectivitySetDataUsageLimit(subscriber_id, str(limit))
+    except:
+        ad.droid.connectivitySetDataUsageLimit(subscriber_id, limit)
+
+
+def remove_mobile_data_usage_limit(ad, subscriber_id=None):
+    if not subscriber_id:
+        subscriber_id = ad.droid.telephonyGetSubscriberId()
+    ad.log.debug("Remove subscriber mobile data usage limit")
+    ad.droid.logV(
+        "Setting subscriber mobile data usage limit to -1, unlimited")
+    try:
+        ad.droid.connectivitySetDataUsageLimit(subscriber_id, "-1")
+    except:
+        ad.droid.connectivitySetDataUsageLimit(subscriber_id, -1)
+
+
+def active_file_download_task(log, ad, file_name="5MB", method="curl"):
+    # files available for download on the same website:
+    # 1GB.zip, 512MB.zip, 200MB.zip, 50MB.zip, 20MB.zip, 10MB.zip, 5MB.zip
+    # download file by adb command, as phone call will use sl4a
+    file_size_map = {
+        '1MB': 1000000,
+        '5MB': 5000000,
+        '10MB': 10000000,
+        '20MB': 20000000,
+        '50MB': 50000000,
+        '100MB': 100000000,
+        '200MB': 200000000,
+        '512MB': 512000000
+    }
+    url_map = {
+        "1MB": [
+            "http://146.148.91.8/download/1MB.zip",
+            "http://ipv4.download.thinkbroadband.com/1MB.zip"
+        ],
+        "5MB": [
+            "http://146.148.91.8/download/5MB.zip",
+            "http://212.183.159.230/5MB.zip",
+            "http://ipv4.download.thinkbroadband.com/5MB.zip"
+        ],
+        "10MB": [
+            "http://146.148.91.8/download/10MB.zip",
+            "http://212.183.159.230/10MB.zip",
+            "http://ipv4.download.thinkbroadband.com/10MB.zip",
+            "http://lax.futurehosting.com/test.zip",
+            "http://ovh.net/files/10Mio.dat"
+        ],
+        "20MB": [
+            "http://146.148.91.8/download/20MB.zip",
+            "http://212.183.159.230/20MB.zip",
+            "http://ipv4.download.thinkbroadband.com/20MB.zip"
+        ],
+        "50MB": [
+            "http://146.148.91.8/download/50MB.zip",
+            "http://212.183.159.230/50MB.zip",
+            "http://ipv4.download.thinkbroadband.com/50MB.zip"
+        ],
+        "100MB": [
+            "http://146.148.91.8/download/100MB.zip",
+            "http://212.183.159.230/100MB.zip",
+            "http://ipv4.download.thinkbroadband.com/100MB.zip",
+            "http://speedtest-ca.turnkeyinternet.net/100mb.bin",
+            "http://ovh.net/files/100Mio.dat",
+            "http://lax.futurehosting.com/test100.zip"
+        ],
+        "200MB": [
+            "http://146.148.91.8/download/200MB.zip",
+            "http://212.183.159.230/200MB.zip",
+            "http://ipv4.download.thinkbroadband.com/200MB.zip"
+        ],
+        "512MB": [
+            "http://146.148.91.8/download/512MB.zip",
+            "http://212.183.159.230/512MB.zip",
+            "http://ipv4.download.thinkbroadband.com/512MB.zip"
+        ]
+    }
+
+    file_size = file_size_map.get(file_name)
+    file_urls = url_map.get(file_name)
+    file_url = None
+    for url in file_urls:
+        url_splits = url.split("/")
+        if verify_http_connection(log, ad, url=url, retry=1):
+            output_path = "/sdcard/Download/%s" % url_splits[-1]
+            file_url = url
+            break
+    if not file_url:
+        ad.log.error("No url is available to download %s", file_name)
+        return False
+    timeout = min(max(file_size / 100000, 600), 3600)
+    if method == "sl4a":
+        return (http_file_download_by_sl4a, (ad, file_url, output_path,
+                                             file_size, True, timeout))
+    if method == "curl" and check_curl_availability(ad):
+        return (http_file_download_by_curl, (ad, file_url, output_path,
+                                             file_size, True, timeout))
+    elif method == "sl4a" or method == "curl":
+        return (http_file_download_by_sl4a, (ad, file_url, output_path,
+                                             file_size, True, timeout))
+    else:
+        return (http_file_download_by_chrome, (ad, file_url, file_size, True,
+                                               timeout))
+
+
+def active_file_download_test(log, ad, file_name="5MB", method="sl4a"):
+    task = active_file_download_task(log, ad, file_name, method=method)
+    if not task:
+        return False
+    return task[0](*task[1])
+
+
+def check_data_stall_detection(ad, wait_time=WAIT_TIME_FOR_DATA_STALL):
+    data_stall_detected = False
+    time_var = 1
+    try:
+        while (time_var < wait_time):
+            out = ad.adb.shell("dumpsys network_stack " \
+                              "| grep \"Suspecting data stall\"",
+                            ignore_status=True)
+            ad.log.debug("Output is %s", out)
+            if out:
+                ad.log.info("NetworkMonitor detected - %s", out)
+                data_stall_detected = True
+                break
+            time.sleep(30)
+            time_var += 30
+    except Exception as e:
+        ad.log.error(e)
+    return data_stall_detected
+
+
+def check_network_validation_fail(ad, begin_time=None,
+                                  wait_time=WAIT_TIME_FOR_NW_VALID_FAIL):
+    network_validation_fail = False
+    time_var = 1
+    try:
+        while (time_var < wait_time):
+            time_var += 30
+            nw_valid = ad.search_logcat("validation failed",
+                                         begin_time)
+            if nw_valid:
+                ad.log.info("Validation Failed received here - %s",
+                            nw_valid[0]["log_message"])
+                network_validation_fail = True
+                break
+            time.sleep(30)
+    except Exception as e:
+        ad.log.error(e)
+    return network_validation_fail
+
+
+def check_data_stall_recovery(ad, begin_time=None,
+                              wait_time=WAIT_TIME_FOR_DATA_STALL_RECOVERY):
+    data_stall_recovery = False
+    time_var = 1
+    try:
+        while (time_var < wait_time):
+            time_var += 30
+            recovery = ad.search_logcat("doRecovery() cleanup all connections",
+                                         begin_time)
+            if recovery:
+                ad.log.info("Recovery Performed here - %s",
+                            recovery[-1]["log_message"])
+                data_stall_recovery = True
+                break
+            time.sleep(30)
+    except Exception as e:
+        ad.log.error(e)
+    return data_stall_recovery
\ No newline at end of file
diff --git a/acts_tests/acts_contrib/test_utils/tel/tel_dsds_utils.py b/acts_tests/acts_contrib/test_utils/tel/tel_dsds_utils.py
index 4d91839..0a93e8f 100644
--- a/acts_tests/acts_contrib/test_utils/tel/tel_dsds_utils.py
+++ b/acts_tests/acts_contrib/test_utils/tel/tel_dsds_utils.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#   Copyright 2021 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -27,6 +27,8 @@
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_ANDROID_STATE_SETTLING
 from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_CELLULAR_PREFERRED
 from acts_contrib.test_utils.tel.tel_defines import YOUTUBE_PACKAGE_NAME
+from acts_contrib.test_utils.tel.tel_data_utils import active_file_download_test
+from acts_contrib.test_utils.tel.tel_data_utils import start_youtube_video
 from acts_contrib.test_utils.tel.tel_message_utils import log_messaging_screen_shot
 from acts_contrib.test_utils.tel.tel_message_utils import mms_send_receive_verify
 from acts_contrib.test_utils.tel.tel_message_utils import sms_send_receive_verify_for_subscription
@@ -51,12 +53,10 @@
 from acts_contrib.test_utils.tel.tel_subscription_utils import set_message_subid
 from acts_contrib.test_utils.tel.tel_subscription_utils import set_subid_for_data
 from acts_contrib.test_utils.tel.tel_subscription_utils import set_voice_sub_id
-from acts_contrib.test_utils.tel.tel_test_utils import active_file_download_test
 from acts_contrib.test_utils.tel.tel_test_utils import get_operator_name
 from acts_contrib.test_utils.tel.tel_test_utils import num_active_calls
 from acts_contrib.test_utils.tel.tel_test_utils import power_off_sim
 from acts_contrib.test_utils.tel.tel_test_utils import power_on_sim
-from acts_contrib.test_utils.tel.tel_test_utils import start_youtube_video
 from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode
 from acts_contrib.test_utils.tel.tel_test_utils import verify_incall_state
 from acts_contrib.test_utils.tel.tel_test_utils import verify_http_connection
diff --git a/acts_tests/acts_contrib/test_utils/tel/tel_logging_utils.py b/acts_tests/acts_contrib/test_utils/tel/tel_logging_utils.py
index fdfda44..1cb6bb5 100644
--- a/acts_tests/acts_contrib/test_utils/tel/tel_logging_utils.py
+++ b/acts_tests/acts_contrib/test_utils/tel/tel_logging_utils.py
@@ -118,6 +118,7 @@
 
 def stop_sdm_logger(ad):
     """Stop SDM logger."""
+    ad.sdm_log_path = DEFAULT_SDM_LOG_PATH
     cycle = 1
 
     ad.log.debug("stop sdm logging")
diff --git a/acts_tests/acts_contrib/test_utils/tel/tel_test_utils.py b/acts_tests/acts_contrib/test_utils/tel/tel_test_utils.py
index f861ce1..3d7e935 100644
--- a/acts_tests/acts_contrib/test_utils/tel/tel_test_utils.py
+++ b/acts_tests/acts_contrib/test_utils/tel/tel_test_utils.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#   Copyright 2021 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -33,7 +33,6 @@
 from acts.controllers.android_device import list_adb_devices
 from acts.controllers.android_device import list_fastboot_devices
 
-from acts.controllers.android_device import SL4A_APK_NAME
 from acts.libs.proc.job import TimeoutError
 from acts_contrib.test_utils.tel.loggers.protos.telephony_metric_pb2 import TelephonyVoiceTestResult
 from acts_contrib.test_utils.tel.tel_defines import CarrierConfigs
@@ -60,9 +59,6 @@
 from acts_contrib.test_utils.tel.tel_defines import MAX_SCREEN_ON_TIME
 from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_AIRPLANEMODE_EVENT
 from acts_contrib.test_utils.tel.tel_defines import MESSAGE_PACKAGE_NAME
-from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_FOR_DATA_STALL
-from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_FOR_NW_VALID_FAIL
-from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_FOR_DATA_STALL_RECOVERY
 from acts_contrib.test_utils.tel.tel_defines import NETWORK_SERVICE_DATA
 from acts_contrib.test_utils.tel.tel_defines import NETWORK_SERVICE_VOICE
 from acts_contrib.test_utils.tel.tel_defines import PHONE_NUMBER_STRING_FORMAT_7_DIGIT
@@ -88,7 +84,6 @@
 from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_CELLULAR_PREFERRED
 from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_WIFI_ONLY
 from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_WIFI_PREFERRED
-from acts_contrib.test_utils.tel.tel_defines import TYPE_MOBILE
 from acts_contrib.test_utils.tel.tel_defines import EventActiveDataSubIdChanged
 from acts_contrib.test_utils.tel.tel_defines import EventDisplayInfoChanged
 from acts_contrib.test_utils.tel.tel_defines import EventServiceStateChanged
@@ -551,66 +546,6 @@
     return None
 
 
-def check_data_stall_detection(ad, wait_time=WAIT_TIME_FOR_DATA_STALL):
-    data_stall_detected = False
-    time_var = 1
-    try:
-        while (time_var < wait_time):
-            out = ad.adb.shell("dumpsys network_stack " \
-                              "| grep \"Suspecting data stall\"",
-                            ignore_status=True)
-            ad.log.debug("Output is %s", out)
-            if out:
-                ad.log.info("NetworkMonitor detected - %s", out)
-                data_stall_detected = True
-                break
-            time.sleep(30)
-            time_var += 30
-    except Exception as e:
-        ad.log.error(e)
-    return data_stall_detected
-
-
-def check_network_validation_fail(ad, begin_time=None,
-                                  wait_time=WAIT_TIME_FOR_NW_VALID_FAIL):
-    network_validation_fail = False
-    time_var = 1
-    try:
-        while (time_var < wait_time):
-            time_var += 30
-            nw_valid = ad.search_logcat("validation failed",
-                                         begin_time)
-            if nw_valid:
-                ad.log.info("Validation Failed received here - %s",
-                            nw_valid[0]["log_message"])
-                network_validation_fail = True
-                break
-            time.sleep(30)
-    except Exception as e:
-        ad.log.error(e)
-    return network_validation_fail
-
-
-def check_data_stall_recovery(ad, begin_time=None,
-                              wait_time=WAIT_TIME_FOR_DATA_STALL_RECOVERY):
-    data_stall_recovery = False
-    time_var = 1
-    try:
-        while (time_var < wait_time):
-            time_var += 30
-            recovery = ad.search_logcat("doRecovery() cleanup all connections",
-                                         begin_time)
-            if recovery:
-                ad.log.info("Recovery Performed here - %s",
-                            recovery[-1]["log_message"])
-                data_stall_recovery = True
-                break
-            time.sleep(30)
-    except Exception as e:
-        ad.log.error(e)
-    return data_stall_recovery
-
-
 def break_internet_except_sl4a_port(ad, sl4a_port):
     ad.log.info("Breaking internet using iptables rules")
     ad.adb.shell("iptables -I INPUT 1 -p tcp --dport %s -j ACCEPT" % sl4a_port,
@@ -1401,7 +1336,7 @@
     return file_directory, file_name
 
 
-def _check_file_existance(ad, file_path, expected_file_size=None):
+def _check_file_existence(ad, file_path, expected_file_size=None):
     """Check file existance by file_path. If expected_file_size
        is provided, then also check if the file meet the file size requirement.
     """
@@ -1429,132 +1364,6 @@
         return False
 
 
-def check_curl_availability(ad):
-    if not hasattr(ad, "curl_capable"):
-        try:
-            out = ad.adb.shell("/data/curl --version")
-            if not out or "not found" in out:
-                setattr(ad, "curl_capable", False)
-                ad.log.info("curl is unavailable, use chrome to download file")
-            else:
-                setattr(ad, "curl_capable", True)
-        except Exception:
-            setattr(ad, "curl_capable", False)
-            ad.log.info("curl is unavailable, use chrome to download file")
-    return ad.curl_capable
-
-
-def start_youtube_video(ad, url="vnd.youtube:watch?v=pSJoP0LR8CQ"):
-    ad.log.info("Open an youtube video")
-    for _ in range(3):
-        ad.ensure_screen_on()
-        ad.adb.shell('am start -a android.intent.action.VIEW -d "%s"' % url)
-        if wait_for_state(ad.droid.audioIsMusicActive, True, 15, 1):
-            ad.log.info("Started a video in youtube, audio is in MUSIC state")
-            return True
-        ad.log.info("Audio is not in MUSIC state. Quit Youtube.")
-        for _ in range(3):
-            ad.send_keycode("BACK")
-            time.sleep(1)
-        time.sleep(3)
-    return False
-
-
-def active_file_download_task(log, ad, file_name="5MB", method="curl"):
-    # files available for download on the same website:
-    # 1GB.zip, 512MB.zip, 200MB.zip, 50MB.zip, 20MB.zip, 10MB.zip, 5MB.zip
-    # download file by adb command, as phone call will use sl4a
-    file_size_map = {
-        '1MB': 1000000,
-        '5MB': 5000000,
-        '10MB': 10000000,
-        '20MB': 20000000,
-        '50MB': 50000000,
-        '100MB': 100000000,
-        '200MB': 200000000,
-        '512MB': 512000000
-    }
-    url_map = {
-        "1MB": [
-            "http://146.148.91.8/download/1MB.zip",
-            "http://ipv4.download.thinkbroadband.com/1MB.zip"
-        ],
-        "5MB": [
-            "http://146.148.91.8/download/5MB.zip",
-            "http://212.183.159.230/5MB.zip",
-            "http://ipv4.download.thinkbroadband.com/5MB.zip"
-        ],
-        "10MB": [
-            "http://146.148.91.8/download/10MB.zip",
-            "http://212.183.159.230/10MB.zip",
-            "http://ipv4.download.thinkbroadband.com/10MB.zip",
-            "http://lax.futurehosting.com/test.zip",
-            "http://ovh.net/files/10Mio.dat"
-        ],
-        "20MB": [
-            "http://146.148.91.8/download/20MB.zip",
-            "http://212.183.159.230/20MB.zip",
-            "http://ipv4.download.thinkbroadband.com/20MB.zip"
-        ],
-        "50MB": [
-            "http://146.148.91.8/download/50MB.zip",
-            "http://212.183.159.230/50MB.zip",
-            "http://ipv4.download.thinkbroadband.com/50MB.zip"
-        ],
-        "100MB": [
-            "http://146.148.91.8/download/100MB.zip",
-            "http://212.183.159.230/100MB.zip",
-            "http://ipv4.download.thinkbroadband.com/100MB.zip",
-            "http://speedtest-ca.turnkeyinternet.net/100mb.bin",
-            "http://ovh.net/files/100Mio.dat",
-            "http://lax.futurehosting.com/test100.zip"
-        ],
-        "200MB": [
-            "http://146.148.91.8/download/200MB.zip",
-            "http://212.183.159.230/200MB.zip",
-            "http://ipv4.download.thinkbroadband.com/200MB.zip"
-        ],
-        "512MB": [
-            "http://146.148.91.8/download/512MB.zip",
-            "http://212.183.159.230/512MB.zip",
-            "http://ipv4.download.thinkbroadband.com/512MB.zip"
-        ]
-    }
-
-    file_size = file_size_map.get(file_name)
-    file_urls = url_map.get(file_name)
-    file_url = None
-    for url in file_urls:
-        url_splits = url.split("/")
-        if verify_http_connection(log, ad, url=url, retry=1):
-            output_path = "/sdcard/Download/%s" % url_splits[-1]
-            file_url = url
-            break
-    if not file_url:
-        ad.log.error("No url is available to download %s", file_name)
-        return False
-    timeout = min(max(file_size / 100000, 600), 3600)
-    if method == "sl4a":
-        return (http_file_download_by_sl4a, (ad, file_url, output_path,
-                                             file_size, True, timeout))
-    if method == "curl" and check_curl_availability(ad):
-        return (http_file_download_by_curl, (ad, file_url, output_path,
-                                             file_size, True, timeout))
-    elif method == "sl4a" or method == "curl":
-        return (http_file_download_by_sl4a, (ad, file_url, output_path,
-                                             file_size, True, timeout))
-    else:
-        return (http_file_download_by_chrome, (ad, file_url, file_size, True,
-                                               timeout))
-
-
-def active_file_download_test(log, ad, file_name="5MB", method="sl4a"):
-    task = active_file_download_task(log, ad, file_name, method=method)
-    if not task:
-        return False
-    return task[0](*task[1])
-
-
 def verify_internet_connection_by_ping(log,
                                        ad,
                                        retries=1,
@@ -1808,316 +1617,6 @@
             return False
 
 
-def http_file_download_by_curl(ad,
-                               url,
-                               out_path=None,
-                               expected_file_size=None,
-                               remove_file_after_check=True,
-                               timeout=3600,
-                               limit_rate=None,
-                               retry=3):
-    """Download http file by adb curl.
-
-    Args:
-        ad: Android Device Object.
-        url: The url that file to be downloaded from".
-        out_path: Optional. Where to download file to.
-                  out_path is /sdcard/Download/ by default.
-        expected_file_size: Optional. Provided if checking the download file meet
-                            expected file size in unit of byte.
-        remove_file_after_check: Whether to remove the downloaded file after
-                                 check.
-        timeout: timeout for file download to complete.
-        limit_rate: download rate in bps. None, if do not apply rate limit.
-        retry: the retry request times provided in curl command.
-    """
-    file_directory, file_name = _generate_file_directory_and_file_name(
-        url, out_path)
-    file_path = os.path.join(file_directory, file_name)
-    curl_cmd = "/data/curl"
-    if limit_rate:
-        curl_cmd += " --limit-rate %s" % limit_rate
-    if retry:
-        curl_cmd += " --retry %s" % retry
-    curl_cmd += " --url %s > %s" % (url, file_path)
-    try:
-        ad.log.info("Download %s to %s by adb shell command %s", url,
-                    file_path, curl_cmd)
-
-        ad.adb.shell(curl_cmd, timeout=timeout)
-        if _check_file_existance(ad, file_path, expected_file_size):
-            ad.log.info("%s is downloaded to %s successfully", url, file_path)
-            return True
-        else:
-            ad.log.warning("Fail to download %s", url)
-            return False
-    except Exception as e:
-        ad.log.warning("Download %s failed with exception %s", url, e)
-        return False
-    finally:
-        if remove_file_after_check:
-            ad.log.info("Remove the downloaded file %s", file_path)
-            ad.adb.shell("rm %s" % file_path, ignore_status=True)
-
-
-def open_url_by_adb(ad, url):
-    ad.adb.shell('am start -a android.intent.action.VIEW -d "%s"' % url)
-
-
-def http_file_download_by_chrome(ad,
-                                 url,
-                                 expected_file_size=None,
-                                 remove_file_after_check=True,
-                                 timeout=3600):
-    """Download http file by chrome.
-
-    Args:
-        ad: Android Device Object.
-        url: The url that file to be downloaded from".
-        expected_file_size: Optional. Provided if checking the download file meet
-                            expected file size in unit of byte.
-        remove_file_after_check: Whether to remove the downloaded file after
-                                 check.
-        timeout: timeout for file download to complete.
-    """
-    chrome_apk = "com.android.chrome"
-    file_directory, file_name = _generate_file_directory_and_file_name(
-        url, "/sdcard/Download/")
-    file_path = os.path.join(file_directory, file_name)
-    # Remove pre-existing file
-    ad.force_stop_apk(chrome_apk)
-    file_to_be_delete = os.path.join(file_directory, "*%s*" % file_name)
-    ad.adb.shell("rm -f %s" % file_to_be_delete)
-    ad.adb.shell("rm -rf /sdcard/Download/.*")
-    ad.adb.shell("rm -f /sdcard/Download/.*")
-    data_accounting = {
-        "total_rx_bytes": ad.droid.getTotalRxBytes(),
-        "mobile_rx_bytes": ad.droid.getMobileRxBytes(),
-        "subscriber_mobile_data_usage": get_mobile_data_usage(ad, None, None),
-        "chrome_mobile_data_usage": get_mobile_data_usage(
-            ad, None, chrome_apk)
-    }
-    ad.log.debug("Before downloading: %s", data_accounting)
-    ad.log.info("Download %s with timeout %s", url, timeout)
-    ad.ensure_screen_on()
-    open_url_by_adb(ad, url)
-    elapse_time = 0
-    result = True
-    while elapse_time < timeout:
-        time.sleep(30)
-        if _check_file_existance(ad, file_path, expected_file_size):
-            ad.log.info("%s is downloaded successfully", url)
-            if remove_file_after_check:
-                ad.log.info("Remove the downloaded file %s", file_path)
-                ad.adb.shell("rm -f %s" % file_to_be_delete)
-                ad.adb.shell("rm -rf /sdcard/Download/.*")
-                ad.adb.shell("rm -f /sdcard/Download/.*")
-            #time.sleep(30)
-            new_data_accounting = {
-                "mobile_rx_bytes":
-                ad.droid.getMobileRxBytes(),
-                "subscriber_mobile_data_usage":
-                get_mobile_data_usage(ad, None, None),
-                "chrome_mobile_data_usage":
-                get_mobile_data_usage(ad, None, chrome_apk)
-            }
-            ad.log.info("After downloading: %s", new_data_accounting)
-            accounting_diff = {
-                key: value - data_accounting[key]
-                for key, value in new_data_accounting.items()
-            }
-            ad.log.debug("Data accounting difference: %s", accounting_diff)
-            if getattr(ad, "on_mobile_data", False):
-                for key, value in accounting_diff.items():
-                    if value < expected_file_size:
-                        ad.log.warning("%s diff is %s less than %s", key,
-                                       value, expected_file_size)
-                        ad.data_accounting["%s_failure" % key] += 1
-            else:
-                for key, value in accounting_diff.items():
-                    if value >= expected_file_size:
-                        ad.log.error("%s diff is %s. File download is "
-                                     "consuming mobile data", key, value)
-                        result = False
-            return result
-        elif _check_file_existance(ad, "%s.crdownload" % file_path):
-            ad.log.info("Chrome is downloading %s", url)
-        elif elapse_time < 60:
-            # download not started, retry download wit chrome again
-            open_url_by_adb(ad, url)
-        else:
-            ad.log.error("Unable to download file from %s", url)
-            break
-        elapse_time += 30
-    ad.log.warning("Fail to download file from %s", url)
-    ad.force_stop_apk("com.android.chrome")
-    ad.adb.shell("rm -f %s" % file_to_be_delete)
-    ad.adb.shell("rm -rf /sdcard/Download/.*")
-    ad.adb.shell("rm -f /sdcard/Download/.*")
-    return False
-
-
-def http_file_download_by_sl4a(ad,
-                               url,
-                               out_path=None,
-                               expected_file_size=None,
-                               remove_file_after_check=True,
-                               timeout=300):
-    """Download http file by sl4a RPC call.
-
-    Args:
-        ad: Android Device Object.
-        url: The url that file to be downloaded from".
-        out_path: Optional. Where to download file to.
-                  out_path is /sdcard/Download/ by default.
-        expected_file_size: Optional. Provided if checking the download file meet
-                            expected file size in unit of byte.
-        remove_file_after_check: Whether to remove the downloaded file after
-                                 check.
-        timeout: timeout for file download to complete.
-    """
-    file_folder, file_name = _generate_file_directory_and_file_name(
-        url, out_path)
-    file_path = os.path.join(file_folder, file_name)
-    ad.adb.shell("rm -f %s" % file_path)
-    accounting_apk = SL4A_APK_NAME
-    result = True
-    try:
-        if not getattr(ad, "data_droid", None):
-            ad.data_droid, ad.data_ed = ad.get_droid()
-            ad.data_ed.start()
-        else:
-            try:
-                if not ad.data_droid.is_live:
-                    ad.data_droid, ad.data_ed = ad.get_droid()
-                    ad.data_ed.start()
-            except Exception:
-                ad.log.info("Start new sl4a session for file download")
-                ad.data_droid, ad.data_ed = ad.get_droid()
-                ad.data_ed.start()
-        data_accounting = {
-            "mobile_rx_bytes":
-            ad.droid.getMobileRxBytes(),
-            "subscriber_mobile_data_usage":
-            get_mobile_data_usage(ad, None, None),
-            "sl4a_mobile_data_usage":
-            get_mobile_data_usage(ad, None, accounting_apk)
-        }
-        ad.log.debug("Before downloading: %s", data_accounting)
-        ad.log.info("Download file from %s to %s by sl4a RPC call", url,
-                    file_path)
-        try:
-            ad.data_droid.httpDownloadFile(url, file_path, timeout=timeout)
-        except Exception as e:
-            ad.log.warning("SL4A file download error: %s", e)
-            ad.data_droid.terminate()
-            return False
-        if _check_file_existance(ad, file_path, expected_file_size):
-            ad.log.info("%s is downloaded successfully", url)
-            new_data_accounting = {
-                "mobile_rx_bytes":
-                ad.droid.getMobileRxBytes(),
-                "subscriber_mobile_data_usage":
-                get_mobile_data_usage(ad, None, None),
-                "sl4a_mobile_data_usage":
-                get_mobile_data_usage(ad, None, accounting_apk)
-            }
-            ad.log.debug("After downloading: %s", new_data_accounting)
-            accounting_diff = {
-                key: value - data_accounting[key]
-                for key, value in new_data_accounting.items()
-            }
-            ad.log.debug("Data accounting difference: %s", accounting_diff)
-            if getattr(ad, "on_mobile_data", False):
-                for key, value in accounting_diff.items():
-                    if value < expected_file_size:
-                        ad.log.debug("%s diff is %s less than %s", key,
-                                       value, expected_file_size)
-                        ad.data_accounting["%s_failure"] += 1
-            else:
-                for key, value in accounting_diff.items():
-                    if value >= expected_file_size:
-                        ad.log.error("%s diff is %s. File download is "
-                                     "consuming mobile data", key, value)
-                        result = False
-            return result
-        else:
-            ad.log.warning("Fail to download %s", url)
-            return False
-    except Exception as e:
-        ad.log.error("Download %s failed with exception %s", url, e)
-        raise
-    finally:
-        if remove_file_after_check:
-            ad.log.info("Remove the downloaded file %s", file_path)
-            ad.adb.shell("rm %s" % file_path, ignore_status=True)
-
-
-def get_mobile_data_usage(ad, sid=None, apk=None):
-    if not sid:
-        sid = ad.droid.subscriptionGetDefaultDataSubId()
-    current_time = int(time.time() * 1000)
-    begin_time = current_time - 10 * 24 * 60 * 60 * 1000
-    end_time = current_time + 10 * 24 * 60 * 60 * 1000
-
-    if apk:
-        uid = ad.get_apk_uid(apk)
-        ad.log.debug("apk %s uid = %s", apk, uid)
-        try:
-            usage_info = ad.droid.getMobileDataUsageInfoForUid(uid, sid)
-            ad.log.debug("Mobile data usage info for uid %s = %s", uid,
-                        usage_info)
-            return usage_info["UsageLevel"]
-        except:
-            try:
-                return ad.droid.connectivityQueryDetailsForUid(
-                    TYPE_MOBILE,
-                    ad.droid.telephonyGetSubscriberIdForSubscription(sid),
-                    begin_time, end_time, uid)
-            except:
-                return ad.droid.connectivityQueryDetailsForUid(
-                    ad.droid.telephonyGetSubscriberIdForSubscription(sid),
-                    begin_time, end_time, uid)
-    else:
-        try:
-            usage_info = ad.droid.getMobileDataUsageInfo(sid)
-            ad.log.debug("Mobile data usage info = %s", usage_info)
-            return usage_info["UsageLevel"]
-        except:
-            try:
-                return ad.droid.connectivityQuerySummaryForDevice(
-                    TYPE_MOBILE,
-                    ad.droid.telephonyGetSubscriberIdForSubscription(sid),
-                    begin_time, end_time)
-            except:
-                return ad.droid.connectivityQuerySummaryForDevice(
-                    ad.droid.telephonyGetSubscriberIdForSubscription(sid),
-                    begin_time, end_time)
-
-
-def set_mobile_data_usage_limit(ad, limit, subscriber_id=None):
-    if not subscriber_id:
-        subscriber_id = ad.droid.telephonyGetSubscriberId()
-    ad.log.debug("Set subscriber mobile data usage limit to %s", limit)
-    ad.droid.logV("Setting subscriber mobile data usage limit to %s" % limit)
-    try:
-        ad.droid.connectivitySetDataUsageLimit(subscriber_id, str(limit))
-    except:
-        ad.droid.connectivitySetDataUsageLimit(subscriber_id, limit)
-
-
-def remove_mobile_data_usage_limit(ad, subscriber_id=None):
-    if not subscriber_id:
-        subscriber_id = ad.droid.telephonyGetSubscriberId()
-    ad.log.debug("Remove subscriber mobile data usage limit")
-    ad.droid.logV(
-        "Setting subscriber mobile data usage limit to -1, unlimited")
-    try:
-        ad.droid.connectivitySetDataUsageLimit(subscriber_id, "-1")
-    except:
-        ad.droid.connectivitySetDataUsageLimit(subscriber_id, -1)
-
-
 def trigger_modem_crash(ad, timeout=120):
     cmd = "echo restart > /sys/kernel/debug/msm_subsys/modem"
     ad.log.info("Triggering Modem Crash from kernel using adb command %s", cmd)
diff --git a/acts_tests/acts_contrib/test_utils/tel/tel_voice_utils.py b/acts_tests/acts_contrib/test_utils/tel/tel_voice_utils.py
index b1b1626..ac6f1f9 100644
--- a/acts_tests/acts_contrib/test_utils/tel/tel_voice_utils.py
+++ b/acts_tests/acts_contrib/test_utils/tel/tel_voice_utils.py
@@ -64,7 +64,6 @@
 from acts_contrib.test_utils.tel.tel_defines import EventMessageWaitingIndicatorChanged
 from acts_contrib.test_utils.tel.tel_defines import CallStateContainer
 from acts_contrib.test_utils.tel.tel_defines import MessageWaitingIndicatorContainer
-from acts_contrib.test_utils.tel.tel_5g_utils import is_current_network_5g
 from acts_contrib.test_utils.tel.tel_ims_utils import is_wfc_enabled
 from acts_contrib.test_utils.tel.tel_ims_utils import toggle_volte
 from acts_contrib.test_utils.tel.tel_ims_utils import toggle_wfc
@@ -351,15 +350,8 @@
                   ad,
                   callee_number,
                   emergency=False,
-                  timeout=MAX_WAIT_TIME_CALL_INITIATION,
-                  checking_interval=5,
                   incall_ui_display=INCALL_UI_DISPLAY_FOREGROUND,
-                  video=False,
-                  voice_type_init=None,
-                  call_stats_check=False,
-                  result_info=result_dict,
-                  nw_gen_5g=False,
-                  nr_type= None):
+                  video=False):
     """Make phone call from caller to callee.
 
     Args:
@@ -400,10 +392,6 @@
             ad.adb.shell("i2cset -fy 3 65 6 1 b", ignore_status=True)
         ad.droid.telephonyStopTrackingCallStateChangeForSubscription(sub_id)
 
-        if nw_gen_5g:
-            if not is_current_network_5g(ad, nr_type= nr_type):
-                ad.log.error("Phone is not attached on 5G")
-
         if incall_ui_display == INCALL_UI_DISPLAY_FOREGROUND:
             ad.droid.telecomShowInCallScreen()
         elif incall_ui_display == INCALL_UI_DISPLAY_BACKGROUND:
@@ -738,9 +726,7 @@
                         slot_id_callee=None,
                         voice_type_init=None,
                         call_stats_check=False,
-                        result_info=result_dict,
-                        nsa_5g_for_stress=False,
-                        nr_type= None):
+                        result_info=result_dict):
     """ Call process, including make a phone call from caller,
     accept from callee, and hang up. The call is on default voice subscription
 
@@ -779,8 +765,7 @@
         log, ad_caller, ad_callee, subid_caller, subid_callee, ad_hangup,
         verify_caller_func, verify_callee_func, wait_time_in_call,
         incall_ui_display, dialing_number_length, video_state,
-        voice_type_init, call_stats_check, result_info, nsa_5g_for_stress,
-        nr_type)
+        voice_type_init, call_stats_check, result_info)
 
 
 def call_setup_teardown_for_subscription(
@@ -798,9 +783,7 @@
         video_state=None,
         voice_type_init=None,
         call_stats_check=False,
-        result_info=result_dict,
-        nsa_5g_for_stress=False,
-        nr_type= None):
+        result_info=result_dict):
     """ Call process, including make a phone call from caller,
     accept from callee, and hang up. The call is on specified subscription
 
@@ -992,11 +975,6 @@
                 except Exception as e:
                     log.error(str(e))
 
-        if nsa_5g_for_stress:
-            for ad in (ad_caller, ad_callee):
-                if not is_current_network_5g(ad, nr_type):
-                    ad.log.error("Phone not attached on 5G")
-
         if ad_hangup or not tel_result_wrapper:
             for ad in (ad_caller, ad_callee):
                 if not wait_for_call_id_clearing(
diff --git a/acts_tests/acts_contrib/test_utils_tests/audio_analysis_integrationtest.py b/acts_tests/acts_contrib/test_utils_tests/audio_analysis_integrationtest.py
index a00a431..eb56f20 100644
--- a/acts_tests/acts_contrib/test_utils_tests/audio_analysis_integrationtest.py
+++ b/acts_tests/acts_contrib/test_utils_tests/audio_analysis_integrationtest.py
@@ -21,11 +21,6 @@
 import os
 import unittest
 
-# TODO(markdr): Remove this after soundfile is added to setup.py
-import sys
-import mock
-sys.modules['soundfile'] = mock.Mock()
-
 import acts_contrib.test_utils.audio_analysis_lib.audio_analysis as audio_analysis
 import acts_contrib.test_utils.audio_analysis_lib.audio_data as audio_data
 
diff --git a/acts_tests/acts_contrib/test_utils_tests/audio_quality_measurement_integrationtest.py b/acts_tests/acts_contrib/test_utils_tests/audio_quality_measurement_integrationtest.py
index 396e5b8..c8b4f25 100644
--- a/acts_tests/acts_contrib/test_utils_tests/audio_quality_measurement_integrationtest.py
+++ b/acts_tests/acts_contrib/test_utils_tests/audio_quality_measurement_integrationtest.py
@@ -22,11 +22,6 @@
 import numpy
 import unittest
 
-# TODO(markdr): Remove this after soundfile is added to setup.py
-import sys
-import mock
-sys.modules['soundfile'] = mock.Mock()
-
 import acts_contrib.test_utils.audio_analysis_lib.audio_quality_measurement as audio_quality_measurement
 
 
diff --git a/acts_tests/setup.py b/acts_tests/setup.py
index 2269fcd..9f77e9e 100755
--- a/acts_tests/setup.py
+++ b/acts_tests/setup.py
@@ -30,7 +30,7 @@
 
 acts_tests_dir = os.path.abspath(os.path.dirname(__file__))
 
-install_requires = []
+install_requires = ['soundfile']
 
 
 
diff --git a/acts_tests/tests/google/fuchsia/wlan/compliance/VapeInteropTest.py b/acts_tests/tests/google/fuchsia/wlan/compliance/VapeInteropTest.py
index 65f1c9a..962c1bf 100644
--- a/acts_tests/tests/google/fuchsia/wlan/compliance/VapeInteropTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/compliance/VapeInteropTest.py
@@ -75,6 +75,7 @@
         self.dut.turn_location_off_and_scan_toggle_off()
         self.dut.disconnect()
         self.dut.reset_wifi()
+        self.download_ap_logs()
         self.access_point.stop_all_aps()
 
     def on_fail(self, test_name, begin_time):
diff --git a/acts_tests/tests/google/fuchsia/wlan/compliance/WlanPhyCompliance11ACTest.py b/acts_tests/tests/google/fuchsia/wlan/compliance/WlanPhyCompliance11ACTest.py
index fa4e13a..04adfab 100644
--- a/acts_tests/tests/google/fuchsia/wlan/compliance/WlanPhyCompliance11ACTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/compliance/WlanPhyCompliance11ACTest.py
@@ -159,6 +159,7 @@
         self.dut.turn_location_off_and_scan_toggle_off()
         self.dut.disconnect()
         self.dut.reset_wifi()
+        self.download_ap_logs()
         self.access_point.stop_all_aps()
 
     def on_fail(self, test_name, begin_time):
diff --git a/acts_tests/tests/google/fuchsia/wlan/compliance/WlanPhyCompliance11NTest.py b/acts_tests/tests/google/fuchsia/wlan/compliance/WlanPhyCompliance11NTest.py
index 08b2cc6..ad0800f 100644
--- a/acts_tests/tests/google/fuchsia/wlan/compliance/WlanPhyCompliance11NTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/compliance/WlanPhyCompliance11NTest.py
@@ -122,6 +122,7 @@
         self.dut.turn_location_off_and_scan_toggle_off()
         self.dut.disconnect()
         self.dut.reset_wifi()
+        self.download_ap_logs()
         self.access_point.stop_all_aps()
 
     def on_fail(self, test_name, begin_time):
diff --git a/acts_tests/tests/google/fuchsia/wlan/compliance/WlanPhyComplianceABGTest.py b/acts_tests/tests/google/fuchsia/wlan/compliance/WlanPhyComplianceABGTest.py
index 3dac3f9..2d17f4b 100644
--- a/acts_tests/tests/google/fuchsia/wlan/compliance/WlanPhyComplianceABGTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/compliance/WlanPhyComplianceABGTest.py
@@ -123,6 +123,7 @@
         self.dut.turn_location_off_and_scan_toggle_off()
         self.dut.disconnect()
         self.dut.reset_wifi()
+        self.download_ap_logs()
         self.access_point.stop_all_aps()
 
     def on_fail(self, test_name, begin_time):
diff --git a/acts_tests/tests/google/fuchsia/wlan/compliance/WlanSecurityComplianceABGTest.py b/acts_tests/tests/google/fuchsia/wlan/compliance/WlanSecurityComplianceABGTest.py
index 22bcfdc..a32c7c4 100644
--- a/acts_tests/tests/google/fuchsia/wlan/compliance/WlanSecurityComplianceABGTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/compliance/WlanSecurityComplianceABGTest.py
@@ -201,6 +201,7 @@
         self.dut.turn_location_off_and_scan_toggle_off()
         self.dut.disconnect()
         self.dut.reset_wifi()
+        self.download_ap_logs()
         self.access_point.stop_all_aps()
 
     def on_fail(self, test_name, begin_time):
diff --git a/acts_tests/tests/google/fuchsia/wlan/functional/BeaconLossTest.py b/acts_tests/tests/google/fuchsia/wlan/functional/BeaconLossTest.py
index f99e610..a2a763b 100644
--- a/acts_tests/tests/google/fuchsia/wlan/functional/BeaconLossTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/functional/BeaconLossTest.py
@@ -70,7 +70,7 @@
         else:
             # Default is an android device, just like the other tests
             self.dut = create_wlan_device(self.android_devices[0])
-        self.ap = self.access_points[0]
+        self.access_point = self.access_points[0]
         self.num_of_iterations = int(
             self.user_params.get("beacon_loss_test_iterations",
                                  self.num_of_iterations))
@@ -80,23 +80,25 @@
         self.dut.disconnect()
         self.dut.reset_wifi()
         # ensure radio is on, in case the test failed while the radio was off
-        self.ap.iwconfig.ap_iwconfig(self.in_use_interface, "txpower on")
-        self.ap.stop_all_aps()
+        self.access_point.iwconfig.ap_iwconfig(self.in_use_interface,
+                                               "txpower on")
+        self.download_ap_logs()
+        self.access_point.stop_all_aps()
 
     def on_fail(self, test_name, begin_time):
         super().on_fail(test_name, begin_time)
-        self.ap.stop_all_aps()
+        self.access_point.stop_all_aps()
 
     def beacon_loss(self, channel):
-        setup_ap(access_point=self.ap,
+        setup_ap(access_point=self.access_point,
                  profile_name='whirlwind',
                  channel=channel,
                  ssid=self.ssid)
         time.sleep(self.wait_ap_startup_s)
         if channel > 14:
-            self.in_use_interface = self.ap.wlan_5g
+            self.in_use_interface = self.access_point.wlan_5g
         else:
-            self.in_use_interface = self.ap.wlan_2g
+            self.in_use_interface = self.access_point.wlan_2g
 
         # TODO(b/144505723): [ACTS] update BeaconLossTest.py to handle client
         # roaming, saved networks, etc.
@@ -110,7 +112,8 @@
         for _ in range(0, self.num_of_iterations):
             # Turn off AP radio
             self.log.info("turning off radio")
-            self.ap.iwconfig.ap_iwconfig(self.in_use_interface, "txpower off")
+            self.access_point.iwconfig.ap_iwconfig(self.in_use_interface,
+                                                   "txpower off")
             time.sleep(self.wait_after_ap_txoff_s)
 
             # Did we disconnect from AP?
@@ -119,7 +122,8 @@
 
             # Turn on AP radio
             self.log.info("turning on radio")
-            self.ap.iwconfig.ap_iwconfig(self.in_use_interface, "txpower on")
+            self.access_point.iwconfig.ap_iwconfig(self.in_use_interface,
+                                                   "txpower on")
             time.sleep(self.wait_to_connect_after_ap_txon_s)
 
             # Tell the client to connect
diff --git a/acts_tests/tests/google/fuchsia/wlan/functional/ChannelSwitchTest.py b/acts_tests/tests/google/fuchsia/wlan/functional/ChannelSwitchTest.py
index ccaa37a..be8e3ca 100644
--- a/acts_tests/tests/google/fuchsia/wlan/functional/ChannelSwitchTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/functional/ChannelSwitchTest.py
@@ -57,14 +57,15 @@
         else:
             # Default is an android device, just like the other tests
             self.dut = create_wlan_device(self.android_devices[0])
-        self.ap = self.access_points[0]
+        self.access_point = self.access_points[0]
         self._stop_all_soft_aps()
         self.in_use_interface = None
 
     def teardown_test(self) -> None:
         self.dut.disconnect()
         self.dut.reset_wifi()
-        self.ap.stop_all_aps()
+        self.download_ap_logs()
+        self.access_point.stop_all_aps()
 
     # TODO(fxbug.dev/85738): Change band type to an enum.
     def channel_switch(self,
@@ -98,15 +99,15 @@
 
         self.current_channel_num = starting_channel
         if band == hostapd_constants.BAND_5G:
-            self.in_use_interface = self.ap.wlan_5g
+            self.in_use_interface = self.access_point.wlan_5g
         elif band == hostapd_constants.BAND_2G:
-            self.in_use_interface = self.ap.wlan_2g
+            self.in_use_interface = self.access_point.wlan_2g
         asserts.assert_true(
             self._channels_valid_for_band([self.current_channel_num], band),
             'starting channel {} not a valid channel for band {}'.format(
                 self.current_channel_num, band))
 
-        setup_ap(access_point=self.ap,
+        setup_ap(access_point=self.access_point,
                  profile_name='whirlwind',
                  channel=self.current_channel_num,
                  ssid=self.ssid)
@@ -128,8 +129,9 @@
                 continue
             self.log.info('channel switch: {} -> {}'.format(
                 self.current_channel_num, channel_num))
-            self.ap.channel_switch(self.in_use_interface, channel_num)
-            channel_num_after_switch = self.ap.get_current_channel(
+            self.access_point.channel_switch(self.in_use_interface,
+                                             channel_num)
+            channel_num_after_switch = self.access_point.get_current_channel(
                 self.in_use_interface)
             asserts.assert_true(channel_num_after_switch == channel_num,
                                 'AP failed to channel switch')
diff --git a/acts_tests/tests/google/fuchsia/wlan/functional/ConnectionStressTest.py b/acts_tests/tests/google/fuchsia/wlan/functional/ConnectionStressTest.py
index 640792a..64fc144 100644
--- a/acts_tests/tests/google/fuchsia/wlan/functional/ConnectionStressTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/functional/ConnectionStressTest.py
@@ -46,7 +46,7 @@
         self.ssid = rand_ascii_str(10)
         self.fd = self.fuchsia_devices[0]
         self.dut = create_wlan_device(self.fd)
-        self.ap = self.access_points[0]
+        self.access_point = self.access_points[0]
         self.num_of_iterations = int(
             self.user_params.get("connection_stress_test_iterations",
                                  self.num_of_iterations))
@@ -54,11 +54,12 @@
 
     def teardown_test(self):
         self.dut.reset_wifi()
-        self.ap.stop_all_aps()
+        self.download_ap_logs()
+        self.access_point.stop_all_aps()
 
     def on_fail(self, test_name, begin_time):
         super().on_fail(test_name, begin_time)
-        self.ap.stop_all_aps()
+        self.access_point.stop_all_aps()
 
     def start_ap(self, profile, channel, security=None):
         """Starts an Access Point
@@ -68,7 +69,7 @@
             channel: Channel to operate on
         """
         self.log.info('Profile: %s, Channel: %d' % (profile, channel))
-        setup_ap(access_point=self.ap,
+        setup_ap(access_point=self.access_point,
                  profile_name=profile,
                  channel=channel,
                  ssid=self.ssid,
@@ -131,7 +132,7 @@
             time.sleep(1)
 
         # Stop AP
-        self.ap.stop_all_aps()
+        self.access_point.stop_all_aps()
         if failed:
             raise signals.TestFailure(
                 'One or more association attempt failed.')
diff --git a/acts_tests/tests/google/fuchsia/wlan/functional/DownloadStressTest.py b/acts_tests/tests/google/fuchsia/wlan/functional/DownloadStressTest.py
index 5027ddf..5ec6290 100644
--- a/acts_tests/tests/google/fuchsia/wlan/functional/DownloadStressTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/functional/DownloadStressTest.py
@@ -56,12 +56,12 @@
         super().setup_class()
         self.ssid = rand_ascii_str(10)
         self.dut = create_wlan_device(self.fuchsia_devices[0])
-        self.ap = self.access_points[0]
+        self.access_point = self.access_points[0]
         self.num_of_iterations = int(
             self.user_params.get("download_stress_test_iterations",
                                  self.num_of_iterations))
 
-        setup_ap(access_point=self.ap,
+        setup_ap(access_point=self.access_point,
                  profile_name='whirlwind',
                  channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G,
                  ssid=self.ssid)
@@ -71,7 +71,8 @@
         self.download_threads_result.clear()
         self.dut.disconnect()
         self.dut.reset_wifi()
-        self.ap.stop_all_aps()
+        self.download_ap_logs()
+        self.access_point.stop_all_aps()
 
     def test_download_small(self):
         self.log.info("Downloading small file")
diff --git a/acts_tests/tests/google/fuchsia/wlan/functional/PingStressTest.py b/acts_tests/tests/google/fuchsia/wlan/functional/PingStressTest.py
index e7facd0..5f8addc 100644
--- a/acts_tests/tests/google/fuchsia/wlan/functional/PingStressTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/functional/PingStressTest.py
@@ -48,8 +48,8 @@
 
         self.ssid = rand_ascii_str(10)
         self.dut = create_wlan_device(self.fuchsia_devices[0])
-        self.ap = self.access_points[0]
-        setup_ap(access_point=self.ap,
+        self.access_point = self.access_points[0]
+        setup_ap(access_point=self.access_point,
                  profile_name='whirlwind',
                  channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G,
                  ssid=self.ssid,
@@ -59,7 +59,8 @@
     def teardown_class(self):
         self.dut.disconnect()
         self.dut.reset_wifi()
-        self.ap.stop_all_aps()
+        self.download_ap_logs()
+        self.access_point.stop_all_aps()
 
     def send_ping(self,
                   dest_ip,
@@ -97,7 +98,7 @@
         return self.send_ping('127.0.0.1')
 
     def test_ping_AP(self):
-        return self.send_ping(self.ap.ssh_settings.hostname)
+        return self.send_ping(self.access_point.ssh_settings.hostname)
 
     def test_ping_with_params(self):
         return self.send_ping(self.google_dns_1,
diff --git a/acts_tests/tests/google/fuchsia/wlan/functional/SoftApTest.py b/acts_tests/tests/google/fuchsia/wlan/functional/SoftApTest.py
index 2a05579..ec74992 100644
--- a/acts_tests/tests/google/fuchsia/wlan/functional/SoftApTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/functional/SoftApTest.py
@@ -208,6 +208,7 @@
             ad.droid.goToSleepNow()
         self.stop_all_soft_aps()
         if self.access_point:
+            self.download_ap_logs()
             self.access_point.stop_all_aps()
         self.dut.disconnect()
 
diff --git a/acts_tests/tests/google/fuchsia/wlan/functional/WlanRebootTest.py b/acts_tests/tests/google/fuchsia/wlan/functional/WlanRebootTest.py
index 7ffb5ef..8d365a7 100644
--- a/acts_tests/tests/google/fuchsia/wlan/functional/WlanRebootTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/functional/WlanRebootTest.py
@@ -168,8 +168,14 @@
         self.ssid = utils.rand_ascii_str(hostapd_constants.AP_SSID_LENGTH_2G)
 
     def teardown_test(self):
+        self.download_ap_logs()
         self.access_point.stop_all_aps()
         if self.router_adv_daemon:
+            output_path = context.get_current_context().get_base_output_path()
+            full_output_path = os.path.join(output_path, "radvd_log.txt")
+            radvd_log_file = open(full_output_path, 'w')
+            radvd_log_file.write(self.router_adv_daemon.pull_logs())
+            radvd_log_file.close()
             self.router_adv_daemon.stop()
             self.router_adv_daemon = None
         self.dut.disconnect()
diff --git a/acts_tests/tests/google/fuchsia/wlan/functional/WlanScanTest.py b/acts_tests/tests/google/fuchsia/wlan/functional/WlanScanTest.py
index 3a2e7f2..6133f0b 100644
--- a/acts_tests/tests/google/fuchsia/wlan/functional/WlanScanTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/functional/WlanScanTest.py
@@ -45,6 +45,7 @@
     def setup_class(self):
         super().setup_class()
 
+        self.access_point = self.access_points[0]
         self.start_access_point = False
         for fd in self.fuchsia_devices:
             fd.configure_wlan(association_mechanism='drivers')
@@ -84,14 +85,14 @@
                         security_mode=self.wpa2_network_5g["security"],
                         password=self.wpa2_network_5g["password"])))
             self.ap_2g = hostapd_ap_preset.create_ap_preset(
-                iface_wlan_2g=self.access_points[0].wlan_2g,
-                iface_wlan_5g=self.access_points[0].wlan_5g,
+                iface_wlan_2g=self.access_point.wlan_2g,
+                iface_wlan_5g=self.access_point.wlan_5g,
                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G,
                 ssid=self.open_network_2g['SSID'],
                 bss_settings=bss_settings_2g)
             self.ap_5g = hostapd_ap_preset.create_ap_preset(
-                iface_wlan_2g=self.access_points[0].wlan_2g,
-                iface_wlan_5g=self.access_points[0].wlan_5g,
+                iface_wlan_2g=self.access_point.wlan_2g,
+                iface_wlan_5g=self.access_point.wlan_5g,
                 channel=hostapd_constants.AP_DEFAULT_CHANNEL_5G,
                 ssid=self.open_network_5g['SSID'],
                 bss_settings=bss_settings_5g)
@@ -133,10 +134,10 @@
         # previously saved ssid on the device.
         if self.start_access_point_2g:
             self.start_access_point = True
-            self.access_points[0].start_ap(hostapd_config=self.ap_2g)
+            self.access_point.start_ap(hostapd_config=self.ap_2g)
         if self.start_access_point_5g:
             self.start_access_point = True
-            self.access_points[0].start_ap(hostapd_config=self.ap_5g)
+            self.access_point.start_ap(hostapd_config=self.ap_5g)
 
     def setup_test(self):
         for fd in self.fuchsia_devices:
@@ -149,7 +150,8 @@
 
     def teardown_class(self):
         if self.start_access_point:
-            self.access_points[0].stop_all_aps()
+            self.download_ap_logs()
+            self.access_point.stop_all_aps()
 
     def on_fail(self, test_name, begin_time):
         for fd in self.fuchsia_devices:
diff --git a/acts_tests/tests/google/fuchsia/wlan/functional/WlanTargetSecurityTest.py b/acts_tests/tests/google/fuchsia/wlan/functional/WlanTargetSecurityTest.py
index 0512b87..2debf65 100644
--- a/acts_tests/tests/google/fuchsia/wlan/functional/WlanTargetSecurityTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/functional/WlanTargetSecurityTest.py
@@ -49,8 +49,9 @@
         self.dut.disconnect()
         self.access_point.stop_all_aps()
 
-    def setup_test(self):
+    def teardown_test(self):
         self.dut.disconnect()
+        self.download_ap_logs()
         self.access_point.stop_all_aps()
 
     def on_fail(self, test_name, begin_time):
diff --git a/acts_tests/tests/google/fuchsia/wlan/misc/WlanMiscScenarioTest.py b/acts_tests/tests/google/fuchsia/wlan/misc/WlanMiscScenarioTest.py
index 842fa48..950015d 100644
--- a/acts_tests/tests/google/fuchsia/wlan/misc/WlanMiscScenarioTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/misc/WlanMiscScenarioTest.py
@@ -50,8 +50,9 @@
         self.dut.disconnect()
         self.access_point.stop_all_aps()
 
-    def setup_test(self):
+    def teardown_test(self):
         self.dut.disconnect()
+        self.download_ap_logs()
         self.access_point.stop_all_aps()
 
     def on_fail(self, test_name, begin_time):
diff --git a/acts_tests/tests/google/fuchsia/wlan/performance/ChannelSweepTest.py b/acts_tests/tests/google/fuchsia/wlan/performance/ChannelSweepTest.py
index b687022..8ea7891 100644
--- a/acts_tests/tests/google/fuchsia/wlan/performance/ChannelSweepTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/performance/ChannelSweepTest.py
@@ -175,6 +175,7 @@
             ad.droid.goToSleepNow()
         self.dut.turn_location_off_and_scan_toggle_off()
         self.dut.disconnect()
+        self.download_ap_logs()
         self.access_point.stop_all_aps()
 
     def set_dut_country_code(self, country_code):
diff --git a/acts_tests/tests/google/fuchsia/wlan/performance/WlanRvrTest.py b/acts_tests/tests/google/fuchsia/wlan/performance/WlanRvrTest.py
index e640238..545bbc5 100644
--- a/acts_tests/tests/google/fuchsia/wlan/performance/WlanRvrTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/performance/WlanRvrTest.py
@@ -13,6 +13,7 @@
 #   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.
+import os
 import time
 
 from acts import asserts
@@ -226,6 +227,11 @@
         """
 
         if self.router_adv_daemon:
+            output_path = context.get_current_context().get_base_output_path()
+            full_output_path = os.path.join(output_path, "radvd_log.txt")
+            radvd_log_file = open(full_output_path, 'w')
+            radvd_log_file.write(self.router_adv_daemon.pull_logs())
+            radvd_log_file.close()
             self.router_adv_daemon.stop()
         if hasattr(self, "android_devices"):
             for ad in self.android_devices:
@@ -236,6 +242,7 @@
         self.dut.turn_location_off_and_scan_toggle_off()
         self.dut.disconnect()
         self.dut.reset_wifi()
+        self.download_ap_logs()
         self.access_point.stop_all_aps()
 
     def _wait_for_ipv4_addrs(self):
diff --git a/acts_tests/tests/google/fuchsia/wlan/performance/WlanWmmTest.py b/acts_tests/tests/google/fuchsia/wlan/performance/WlanWmmTest.py
index 3a3cd13..adbb5f6 100644
--- a/acts_tests/tests/google/fuchsia/wlan/performance/WlanWmmTest.py
+++ b/acts_tests/tests/google/fuchsia/wlan/performance/WlanWmmTest.py
@@ -190,6 +190,7 @@
                 tc.wlan_device.disconnect()
                 tc.wlan_device.reset_wifi()
             if tc.access_point:
+                self.download_ap_logs()
                 tc.access_point.stop_all_aps()
 
     def teardown_class(self):
diff --git a/acts_tests/tests/google/net/ApfCountersTest.py b/acts_tests/tests/google/net/ApfCountersTest.py
index fc0d603..d2eeff3 100755
--- a/acts_tests/tests/google/net/ApfCountersTest.py
+++ b/acts_tests/tests/google/net/ApfCountersTest.py
@@ -52,10 +52,11 @@
                       "test_IPv6_RA_with_RTT", )
 
     def setup_class(self):
+        super().setup_class()
         self.dut = self.android_devices[0]
         wutils.wifi_test_device_init(self.dut)
         req_params = []
-        opt_param = ["reference_networks", ]
+        opt_param = ["reference_networks", "scapy"]
 
         self.unpack_userparams(
             req_param_names=req_params, opt_param_names=opt_param)
@@ -75,6 +76,8 @@
         current_dir = os.path.dirname(os.path.realpath(__file__))
         send_ra = os.path.join(current_dir, RA_SCRIPT)
         send_scapy = os.path.join(current_dir, SCAPY)
+        if hasattr(self, "scapy"):
+            send_scapy = self.scapy[0]
         self.access_points[0].install_scapy(send_scapy, send_ra)
         self.tcpdump_pid = None
 
diff --git a/acts_tests/tests/google/net/DataCostTest.py b/acts_tests/tests/google/net/DataCostTest.py
index 6174009..c8089d9 100644
--- a/acts_tests/tests/google/net/DataCostTest.py
+++ b/acts_tests/tests/google/net/DataCostTest.py
@@ -1,5 +1,5 @@
 #
-#   Copyright 2018 - The Android Open Source Project
+#   Copyright 2022 - 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.
@@ -28,7 +28,7 @@
 from acts.controllers import adb
 from acts.test_decorators import test_tracker_info
 from acts_contrib.test_utils.net import net_test_utils as nutils
-from acts_contrib.test_utils.tel.tel_test_utils import _check_file_existance
+from acts_contrib.test_utils.tel.tel_test_utils import _check_file_existence
 from acts_contrib.test_utils.tel.tel_test_utils import _generate_file_directory_and_file_name
 from acts_contrib.test_utils.wifi import wifi_test_utils as wutils
 from acts_contrib.test_utils.net.connectivity_const import MULTIPATH_PREFERENCE_NONE as NONE
@@ -252,7 +252,7 @@
             self.download_file, DOWNLOAD_PATH)
         file_path = os.path.join(file_folder, file_name)
         self.log.info("File path: %s" % file_path)
-        if _check_file_existance(ad, file_path):
+        if _check_file_existence(ad, file_path):
             self.log.info("File exists. Removing file %s" % file_name)
             ad.adb.shell("rm -rf %s%s" % (DOWNLOAD_PATH, file_name))
 
diff --git a/acts_tests/tests/google/net/DataUsageTest.py b/acts_tests/tests/google/net/DataUsageTest.py
index 1582886..e6b3fca 100644
--- a/acts_tests/tests/google/net/DataUsageTest.py
+++ b/acts_tests/tests/google/net/DataUsageTest.py
@@ -1,5 +1,5 @@
 #
-#   Copyright 2018 - The Android Open Source Project
+#   Copyright 2022 - 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.
@@ -30,7 +30,7 @@
 from acts_contrib.test_utils.net.net_test_utils import stop_tcpdump
 from acts_contrib.test_utils.tel import tel_test_utils as ttutils
 from acts_contrib.test_utils.tel.tel_test_utils import get_operator_name
-from acts_contrib.test_utils.tel.tel_test_utils import http_file_download_by_chrome
+from acts_contrib.test_utils.tel.tel_data_utils import http_file_download_by_chrome
 from acts_contrib.test_utils.wifi import wifi_test_utils as wutils
 import queue
 from queue import Empty
@@ -143,7 +143,7 @@
         download_status = False
         end_time = time.time() + TIMEOUT
         while time.time() < end_time:
-            download_status = ttutils._check_file_existance(
+            download_status = ttutils._check_file_existence(
                 ad, self.file_path, self.file_size * BYTE_TO_MB)
             if download_status:
                 self.log.info("Delete file: %s", self.file_path)
diff --git a/acts_tests/tests/google/net/DhcpTest.py b/acts_tests/tests/google/net/DhcpTest.py
index a06b8fe..08aa983 100644
--- a/acts_tests/tests/google/net/DhcpTest.py
+++ b/acts_tests/tests/google/net/DhcpTest.py
@@ -50,11 +50,12 @@
                             "OpenWrt Wifi interface is not ready.")
 
     def teardown_class(self):
-        """Reset wifi to make sure VPN tears down cleanly."""
+        """Reset wifi and stop tcpdump cleanly."""
         wutils.reset_wifi(self.dut)
+        self.openwrt.network_setting.clear_tcpdump()
 
     def teardown_test(self):
-        """Reset wifi to make sure VPN tears down cleanly."""
+        """Reset wifi to make sure DUT tears down cleanly."""
         wutils.reset_wifi(self.dut)
 
     def _verify_ping(self, option="", dest=PING_ADDR):
diff --git a/acts_tests/tests/google/net/IKEv2VpnOverWifiTest.py b/acts_tests/tests/google/net/IKEv2VpnOverWifiTest.py
index 6196f61..22fa780 100644
--- a/acts_tests/tests/google/net/IKEv2VpnOverWifiTest.py
+++ b/acts_tests/tests/google/net/IKEv2VpnOverWifiTest.py
@@ -13,39 +13,69 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 
+import time
 
-from acts import base_test
+from acts.controllers.openwrt_ap import MOBLY_CONTROLLER_CONFIG_NAME as OPENWRT
 from acts.test_decorators import test_tracker_info
 from acts_contrib.test_utils.net import connectivity_const
 from acts_contrib.test_utils.net import net_test_utils as nutils
 from acts_contrib.test_utils.wifi import wifi_test_utils as wutils
+from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
+
 
 VPN_CONST = connectivity_const.VpnProfile
 VPN_TYPE = connectivity_const.VpnProfileType
 VPN_PARAMS = connectivity_const.VpnReqParams
 
 
-class IKEv2VpnOverWifiTest(base_test.BaseTestClass):
+class IKEv2VpnOverWifiTest(WifiBaseTest):
   """IKEv2 VPN tests."""
 
   def setup_class(self):
+    """Setup wi-fi connection and unpack params."""
     self.dut = self.android_devices[0]
-
-    required_params = dir(VPN_PARAMS)
-    required_params = [x for x in required_params if not x.startswith("__")]
-    self.unpack_userparams(req_param_names=required_params)
-    self.vpn_params = {
-        "vpn_username": self.vpn_username,
-        "vpn_password": self.vpn_password,
-        "psk_secret": self.psk_secret,
-        "client_pkcs_file_name": self.client_pkcs_file_name,
-        "cert_path_vpnserver": self.cert_path_vpnserver,
-        "cert_password": self.cert_password,
-        "vpn_identity": self.vpn_identity,
-    }
+    req_params = dir(VPN_PARAMS)
+    req_params = [
+      x for x in req_params if not x.startswith("__")
+    ]
+    opt_params = ["wifi_network", "vpn_cert_country",
+            "vpn_cert_org", "configure_OpenWrt"]
+    self.unpack_userparams(req_param_names=req_params,
+                 opt_param_names=opt_params)
 
     wutils.wifi_test_device_init(self.dut)
-    wutils.connect_to_wifi_network(self.dut, self.wifi_network)
+    wutils.wifi_toggle_state(self.dut, True)
+    if OPENWRT in self.user_params:
+      self.openwrt = self.access_points[0]
+      if hasattr(self, "configure_OpenWrt") and self.configure_OpenWrt == "skip":
+        self.dut.log.info("Skip configure Wifi interface due to config setup.")
+      else:
+        self.configure_openwrt_ap_and_start(wpa_network=True)
+        self.wifi_network = self.openwrt.get_wifi_network()
+      # Wait for OpenWrt statement update
+      time.sleep(10)
+      self.openwrt.network_setting.setup_vpn_l2tp_server(
+        self.vpn_server_hostname,
+        self.vpn_verify_addresses["IKEV2_IPSEC_RSA"][0],
+        self.vpn_username,
+        self.vpn_password,
+        self.vpn_identity,
+        "ikev2-server",
+        self.vpn_cert_country,
+        self.vpn_cert_org
+      )
+    wutils.start_wifi_connection_scan_and_ensure_network_found(
+      self.dut, self.wifi_network["SSID"])
+    wutils.wifi_connect(self.dut, self.wifi_network)
+    time.sleep(3)
+
+    self.vpn_params = {"vpn_username": self.vpn_username,
+               "vpn_password": self.vpn_password,
+               "psk_secret": self.psk_secret,
+               "client_pkcs_file_name": self.client_pkcs_file_name,
+               "cert_path_vpnserver": self.cert_path_vpnserver,
+               "cert_password": self.cert_password,
+               "vpn_identity": self.vpn_identity}
 
   def teardown_class(self):
     wutils.reset_wifi(self.dut)
@@ -54,6 +84,7 @@
     self.dut.take_bug_report(test_name, begin_time)
 
   ### Helper methods ###
+
   def _test_ikev2_vpn(self, vpn, hostname=None):
     """Verify IKEv2 VPN connection.
 
@@ -86,7 +117,8 @@
 
   @test_tracker_info(uuid="bdd8a967-8dac-4e48-87b7-2ce9f7d32158")
   def test_ikev2_psk_vpn_wifi_with_hostname(self):
-    self._test_ikev2_vpn(VPN_TYPE.IKEV2_IPSEC_PSK, self.vpn_server_hostname)
+    self._test_ikev2_vpn(VPN_TYPE.IKEV2_IPSEC_PSK,
+                         self.vpn_server_hostname)
 
   @test_tracker_info(uuid="19692520-c123-4b42-8549-08dda9c4873e")
   def test_ikev2_mschapv2_vpn_wifi_with_hostname(self):
@@ -95,4 +127,5 @@
 
   @test_tracker_info(uuid="bdaaf6e3-6671-4533-baba-2951009c7d69")
   def test_ikev2_rsa_vpn_wifi_with_hostname(self):
-    self._test_ikev2_vpn(VPN_TYPE.IKEV2_IPSEC_RSA, self.vpn_server_hostname)
+    self._test_ikev2_vpn(VPN_TYPE.IKEV2_IPSEC_RSA,
+                         self.vpn_server_hostname)
diff --git a/acts_tests/tests/google/net/UsbTetheringTest.py b/acts_tests/tests/google/net/UsbTetheringTest.py
index 3b2b5dc..1f1d4cf 100644
--- a/acts_tests/tests/google/net/UsbTetheringTest.py
+++ b/acts_tests/tests/google/net/UsbTetheringTest.py
@@ -38,7 +38,9 @@
     self.unpack_userparams(req_params)
     # Enable USB tethering and get the USB network interface
     iflist_before = nutils.get_if_list()
+    serial = self.dut.device_info['serial']
     nutils.start_usb_tethering(self.dut)
+    self.dut.recreate_services(serial)
     self.iface = nutils.wait_for_new_iface(iflist_before)
     if not self.check_upstream_ready():
       raise asserts.fail("Upstream interface is not active.")
diff --git a/acts_tests/tests/google/nr/cbr/CellBroadcastInitializationTest.py b/acts_tests/tests/google/nr/cbr/CellBroadcastInitializationTest.py
new file mode 100644
index 0000000..ed3ea6a
--- /dev/null
+++ b/acts_tests/tests/google/nr/cbr/CellBroadcastInitializationTest.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python3.4
+#
+#   Copyright 2022 - 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 CellBroadcast initialization Test
+"""
+
+import time
+import os
+
+
+from acts.logger import epoch_to_log_line_timestamp
+from acts.keys import Config
+from acts.base_test import BaseTestClass
+from acts.test_decorators import test_tracker_info
+from acts.utils import load_config
+from acts_contrib.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest
+from acts_contrib.test_utils.tel.tel_test_utils import reboot_device
+from acts_contrib.test_utils.tel.tel_test_utils import get_device_epoch_time
+
+
+class CellBroadcastInitializationTest(BaseTestClass):
+    def setup_test(self):
+        super().setup_class()
+        self.number_of_devices = 1
+        self.cbr_init_iteration = self.user_params.get("cbr_init_iteration", 50)
+
+    def teardown_class(self):
+        super().teardown_class(self)
+
+    def _get_current_time_in_secs(self, ad):
+        try:
+            c_time = get_device_epoch_time(ad)
+            c_time = epoch_to_log_line_timestamp(c_time).split()[1].split('.')[0]
+            return self._convert_formatted_time_to_secs(c_time)
+        except Exception as e:
+            ad.log.error(e)
+
+    def _convert_formatted_time_to_secs(self, formatted_time):
+        try:
+            time_list = formatted_time.split(":")
+            return int(time_list[0]) * 3600 + int(time_list[1]) * 60 + int(time_list[2])
+        except Exception as e:
+            self.log.error(e)
+
+    def _verify_channel_config_4400(self, ad):
+        #TODO add all channel checks as constants in tel_defines
+        channel_4400__log = 'SmsBroadcastConfigInfo: Id \\[4400'
+        return ad.search_logcat(channel_4400__log)
+
+    @test_tracker_info(uuid="30f30fa4-f57a-40bd-a37a-141a8efb5a04")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_reboot_stress(self):
+        """ Verifies channel 4400 is set correctly after device boot up
+        only applicable to US carriers
+        after every boot up, search logcat to verify channel 4400 is set
+        default iterations is 50
+        config param : cbr_init_iteration
+
+        """
+        ad = self.android_devices[0]
+
+        current_cbr_version = ad.get_apk_version('com.google.android.cellbroadcast')
+        ad.log.info("Current cbr apk version is %s.", current_cbr_version)
+
+        failure_count = 0
+        begin_time = self._get_current_time_in_secs(ad)
+        for iteration in range(1, self.cbr_init_iteration + 1):
+            msg = "Stress CBR reboot initialization test Iteration: <%s>/<%s>" % (iteration, self.cbr_init_iteration)
+            self.log.info(msg)
+            ad.reboot()
+            ad.wait_for_boot_completion()
+            self.log.info("Rebooted")
+            #TODO make sleep time a constant in tel_defines WAIT_TIME_CBR_INIT_AFTER_REBOOT
+            time.sleep(40)
+            if not self._verify_channel_config_4400(ad):
+                failure_count += 1
+                self.log.error('Iteration failed at %d ' % iteration)
+        end_time = self._get_current_time_in_secs(ad)
+        self.log.debug('Test completed from %s to %s' % (begin_time, end_time))
+        result = True
+        if failure_count > 0:
+            result = False
+            self.log.error('CBR reboot init stress test: <%s> failures in %s iterations',
+                           failure_count, self.cbr_init_iteration)
+        return result
+
diff --git a/acts_tests/tests/google/nr/nsa5g/Nsa5gDataTest.py b/acts_tests/tests/google/nr/nsa5g/Nsa5gDataTest.py
index e75af47..1a6be2a 100755
--- a/acts_tests/tests/google/nr/nsa5g/Nsa5gDataTest.py
+++ b/acts_tests/tests/google/nr/nsa5g/Nsa5gDataTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3.4
 #
-#   Copyright 2020 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -27,6 +27,9 @@
 from acts_contrib.test_utils.tel.tel_defines import NetworkCallbackCapabilitiesChanged
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_ANDROID_STATE_SETTLING
 from acts_contrib.test_utils.tel.tel_data_utils import browsing_test
+from acts_contrib.test_utils.tel.tel_data_utils import check_data_stall_detection
+from acts_contrib.test_utils.tel.tel_data_utils import check_data_stall_recovery
+from acts_contrib.test_utils.tel.tel_data_utils import check_network_validation_fail
 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_data_connectivity_multi_bearer
 from acts_contrib.test_utils.tel.tel_data_utils import test_wifi_connect_disconnect
@@ -38,9 +41,6 @@
 from acts_contrib.test_utils.tel.tel_5g_test_utils import provision_device_for_5g
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_volte
 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 iperf_test_by_adb
diff --git a/acts_tests/tests/google/nr/nsa5g/Nsa5gMmsTest.py b/acts_tests/tests/google/nr/nsa5g/Nsa5gMmsTest.py
index a2a5b3a..e7bcb5a 100755
--- a/acts_tests/tests/google/nr/nsa5g/Nsa5gMmsTest.py
+++ b/acts_tests/tests/google/nr/nsa5g/Nsa5gMmsTest.py
@@ -25,8 +25,13 @@
 from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_CELLULAR_PREFERRED
 from acts_contrib.test_utils.tel.tel_message_utils import message_test
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phones_idle
+from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_volte
+from acts_contrib.test_utils.tel.tel_data_utils import active_file_download_task
 from acts_contrib.test_utils.tel.tel_test_utils import install_message_apk
 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_5g_test_utils import provision_device_for_5g
+from acts.libs.utils.multithread import run_multithread_func
 
 
 class Nsa5gMmsTest(TelephonyBaseTest):
@@ -761,4 +766,105 @@
             wifi_ssid=self.wifi_network_ssid,
             wifi_pwd=self.wifi_network_pass)
 
+    @test_tracker_info(uuid="536c8e25-2d72-46a6-89e1-03f70c5a28a3")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_5g_nsa_mms_multiple_pdns_mo(self):
+        """Test 5G NSA for multiple pdns
+
+        Steps:
+            (1) UE supports EN-DC option 3.
+            (2) SIM with 5G service.
+            (3) UE is provisioned for 5G service and powered off.
+            (4) NR cell (Cell 2) that is within the coverage of LTE cell (Cell 1).
+            (5) UE is in near cell coverage for LTE (Cell 1) and NR (Cell 2).
+            (6) Power on the UE.
+            (7) Initiate data transfer while UE is in idle mode.
+            (8) During data transferring, send a MO MMS.
+            (9) End the data transfer
+
+        Returns:
+            True if pass; False if fail.
+        """
+        cell_1 = self.android_devices[0]
+        cell_2 = self.android_devices[1]
+        if not phone_setup_volte(self.log, cell_1):
+            cell_1.log.error("Failed to setup on VoLTE")
+            return False
+
+        if not verify_internet_connection(self.log, cell_1):
+            return False
+        if not provision_device_for_5g(self.log, cell_2, nr_type='nsa'):
+            cell_2.log.error("Failed to setup on 5G NSA")
+            return False
+        if not verify_internet_connection(self.log, cell_2):
+            return False
+        if not active_file_download_task(self.log, cell_2):
+            return False
+        download_task = active_file_download_task(self.log, cell_2, "10MB")
+        message_task = (message_test, (self.log, cell_2, cell_1,
+                                        '5g', 'volte', 'mms'))
+        results = run_multithread_func(self.log, [download_task, message_task])
+
+        if ((results[0]) & (results[1])):
+            self.log.info("PASS - MO MMS test validated over active data transfer")
+        elif ((results[0] == False) & (results[1] == True)):
+            self.log.error("FAIL - Data Transfer failed")
+        elif ((results[0] == True) & (results[1] == False)):
+            self.log.error("FAIL - Sending MMS failed")
+        else:
+            self.log.error("FAILED - MO MMS test over active data transfer")
+
+        return results
+
+    @test_tracker_info(uuid="10212ab7-a03f-4e11-889e-236b8d1d8afc")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_5g_nsa_mms_multiple_pdns_mt(self):
+        """Test 5G NSA for multiple pdns
+
+        Steps:
+            (1) UE supports EN-DC option 3.
+            (2) SIM with 5G service.
+            (3) UE is provisioned for 5G service and powered off.
+            (4) NR cell (Cell 2) that is within the coverage of LTE cell (Cell 1).
+            (5) UE is in near cell coverage for LTE (Cell 1) and NR (Cell 2).
+            (6) Power on the UE.
+            (7) Initiate data transfer while UE is in idle mode.
+            (8) During data transferring, send a MT MMS.
+            (9) End the data transfer.
+
+        Returns:
+            True if pass; False if fail.
+        """
+        cell_1 = self.android_devices[0]
+        cell_2 = self.android_devices[1]
+
+        if not phone_setup_volte(self.log, cell_1):
+            cell_1.log.error("Failed to setup on VoLTE")
+            return False
+        if not verify_internet_connection(self.log, cell_1):
+            return False
+        if not provision_device_for_5g(self.log, cell_2, nr_type='nsa'):
+            cell_2.log.error("Failed to setup on 5G NSA")
+            return False
+        if not verify_internet_connection(self.log, cell_2):
+            return False
+        if not active_file_download_task(self.log, cell_2):
+            return False
+
+        download_task = active_file_download_task(self.log, cell_2, "10MB")
+        message_task = (message_test, (self.log, cell_1, cell_2,
+                                        'volte', '5g', 'mms'))
+        results = run_multithread_func(self.log, [download_task, message_task])
+
+        if ((results[0]) & (results[1])):
+            self.log.info("PASS - MT MMS test validated over active data transfer")
+        elif ((results[0] == False) & (results[1] == True)):
+            self.log.error("FAIL - Data Transfer failed")
+        elif ((results[0] == True) & (results[1] == False)):
+            self.log.error("FAIL - Sending MMS failed")
+        else:
+            self.log.error("FAILED - MT MMS test over active data transfer")
+
+        return results
+
     """ Tests End """
diff --git a/acts_tests/tests/google/nr/nsa5g/Nsa5gSmsTest.py b/acts_tests/tests/google/nr/nsa5g/Nsa5gSmsTest.py
index 3381d9f..f1df4f4 100755
--- a/acts_tests/tests/google/nr/nsa5g/Nsa5gSmsTest.py
+++ b/acts_tests/tests/google/nr/nsa5g/Nsa5gSmsTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3.4
 #
-#   Copyright 2021 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -24,10 +24,10 @@
 from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_WIFI_PREFERRED
 from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_CELLULAR_PREFERRED
 from acts_contrib.test_utils.tel.tel_5g_test_utils import provision_device_for_5g
+from acts_contrib.test_utils.tel.tel_data_utils import active_file_download_task
 from acts_contrib.test_utils.tel.tel_message_utils import message_test
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phones_idle
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_volte
-from acts_contrib.test_utils.tel.tel_test_utils import active_file_download_task
 from acts_contrib.test_utils.tel.tel_test_utils import install_message_apk
 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
diff --git a/acts_tests/tests/google/nr/nsa5g/Nsa5gVoiceTest.py b/acts_tests/tests/google/nr/nsa5g/Nsa5gVoiceTest.py
index 5140dec..ebeca77 100644
--- a/acts_tests/tests/google/nr/nsa5g/Nsa5gVoiceTest.py
+++ b/acts_tests/tests/google/nr/nsa5g/Nsa5gVoiceTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3.4
 #
-#   Copyright 2020 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -35,6 +35,9 @@
 from acts_contrib.test_utils.tel.tel_5g_test_utils import provision_device_for_5g
 from acts_contrib.test_utils.tel.tel_5g_test_utils import verify_5g_attach_for_both_devices
 from acts_contrib.test_utils.tel.tel_data_utils import call_epdg_to_epdg_wfc
+from acts_contrib.test_utils.tel.tel_data_utils import get_mobile_data_usage
+from acts_contrib.test_utils.tel.tel_data_utils import remove_mobile_data_usage_limit
+from acts_contrib.test_utils.tel.tel_data_utils import set_mobile_data_usage_limit
 from acts_contrib.test_utils.tel.tel_data_utils import test_call_setup_in_active_data_transfer
 from acts_contrib.test_utils.tel.tel_data_utils import test_call_setup_in_active_youtube_video
 from acts_contrib.test_utils.tel.tel_data_utils import wifi_cell_switching
@@ -50,10 +53,7 @@
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_voice_general
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_volte
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phones_idle
-from acts_contrib.test_utils.tel.tel_test_utils import get_mobile_data_usage
 from acts_contrib.test_utils.tel.tel_test_utils import install_dialer_apk
-from acts_contrib.test_utils.tel.tel_test_utils import remove_mobile_data_usage_limit
-from acts_contrib.test_utils.tel.tel_test_utils import set_mobile_data_usage_limit
 from acts_contrib.test_utils.tel.tel_voice_utils import _test_call_long_duration
 from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call_2g
 from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call_3g
diff --git a/acts_tests/tests/google/nr/nsa5gmmw/Nsa5gMmwDataTest.py b/acts_tests/tests/google/nr/nsa5gmmw/Nsa5gMmwDataTest.py
index adfe5c3..19618f7 100755
--- a/acts_tests/tests/google/nr/nsa5gmmw/Nsa5gMmwDataTest.py
+++ b/acts_tests/tests/google/nr/nsa5gmmw/Nsa5gMmwDataTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3.4
 #
-#   Copyright 2021 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -26,10 +26,19 @@
 from acts_contrib.test_utils.tel.tel_defines import NETWORK_MODE_NR_LTE_GSM_WCDMA
 from acts_contrib.test_utils.tel.tel_defines import NetworkCallbackCapabilitiesChanged
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_ANDROID_STATE_SETTLING
+from acts_contrib.test_utils.tel.tel_5g_test_utils import provision_device_for_5g
+from acts_contrib.test_utils.tel.tel_5g_test_utils import set_preferred_mode_for_5g
+from acts_contrib.test_utils.tel.tel_5g_utils import is_current_network_5g
+from acts_contrib.test_utils.tel.tel_data_utils import airplane_mode_test
+from acts_contrib.test_utils.tel.tel_data_utils import browsing_test
+from acts_contrib.test_utils.tel.tel_data_utils import check_data_stall_detection
+from acts_contrib.test_utils.tel.tel_data_utils import check_data_stall_recovery
+from acts_contrib.test_utils.tel.tel_data_utils import check_network_validation_fail
+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 verify_for_network_callback
+from acts_contrib.test_utils.tel.tel_data_utils import wifi_cell_switching
 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
@@ -37,15 +46,6 @@
 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_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 verify_for_network_callback
-from acts_contrib.test_utils.tel.tel_data_utils import wifi_cell_switching
-from acts_contrib.test_utils.tel.tel_data_utils import airplane_mode_test
-from acts_contrib.test_utils.tel.tel_5g_utils import is_current_network_5g
-from acts_contrib.test_utils.tel.tel_5g_test_utils import provision_device_for_5g
-from acts_contrib.test_utils.tel.tel_5g_test_utils import set_preferred_mode_for_5g
 from acts_contrib.test_utils.tel.tel_wifi_utils import ensure_wifi_connected
 from acts_contrib.test_utils.tel.tel_wifi_utils import wifi_reset
 from acts_contrib.test_utils.tel.tel_wifi_utils import wifi_toggle_state
diff --git a/acts_tests/tests/google/nr/sa5g/Sa5gDataTest.py b/acts_tests/tests/google/nr/sa5g/Sa5gDataTest.py
index 339969a..05d6535 100755
--- a/acts_tests/tests/google/nr/sa5g/Sa5gDataTest.py
+++ b/acts_tests/tests/google/nr/sa5g/Sa5gDataTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3.4
 #
-#   Copyright 2021 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -28,10 +28,14 @@
 from acts_contrib.test_utils.tel.tel_5g_test_utils import provision_device_for_5g
 from acts_contrib.test_utils.tel.tel_5g_utils import is_current_network_5g
 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_data_utils import browsing_test
+from acts_contrib.test_utils.tel.tel_data_utils import check_data_stall_detection
+from acts_contrib.test_utils.tel.tel_data_utils import check_data_stall_recovery
+from acts_contrib.test_utils.tel.tel_data_utils import check_network_validation_fail
+from acts_contrib.test_utils.tel.tel_data_utils import data_connectivity_single_bearer
 from acts_contrib.test_utils.tel.tel_test_utils import get_current_override_network_type
+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_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
@@ -39,10 +43,6 @@
 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_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_wifi_utils import wifi_reset
 from acts_contrib.test_utils.tel.tel_wifi_utils import wifi_toggle_state
 
diff --git a/acts_tests/tests/google/tel/lab/TelLabDataTest.py b/acts_tests/tests/google/tel/lab/TelLabDataTest.py
index 33c393d..7481799 100644
--- a/acts_tests/tests/google/tel/lab/TelLabDataTest.py
+++ b/acts_tests/tests/google/tel/lab/TelLabDataTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#   Copyright 2016 - The Android Open Source Project
+#   Copyright 2022 - 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.
@@ -43,15 +43,15 @@
 from acts_contrib.test_utils.tel.tel_defines import RAT_FAMILY_UMTS
 from acts_contrib.test_utils.tel.tel_defines import POWER_LEVEL_OUT_OF_SERVICE
 from acts_contrib.test_utils.tel.tel_defines import POWER_LEVEL_FULL_SERVICE
+from acts_contrib.test_utils.tel.tel_data_utils import check_data_stall_detection
+from acts_contrib.test_utils.tel.tel_data_utils import check_network_validation_fail
+from acts_contrib.test_utils.tel.tel_data_utils import check_data_stall_recovery
 from acts_contrib.test_utils.tel.tel_logging_utils import start_qxdm_loggers
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_network_rat
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phones_idle
 from acts_contrib.test_utils.tel.tel_test_utils import get_host_ip_address
 from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode
 from acts_contrib.test_utils.tel.tel_test_utils import iperf_test_by_adb
-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_network_validation_fail
-from acts_contrib.test_utils.tel.tel_test_utils import check_data_stall_recovery
 from acts_contrib.test_utils.tel.tel_test_utils import get_device_epoch_time
 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 resume_internet_with_sl4a_port
diff --git a/acts_tests/tests/google/tel/lab/TelLabGFTAirplaneModeTest.py b/acts_tests/tests/google/tel/lab/TelLabGFTAirplaneModeTest.py
index bbe9b14..b385d80 100644
--- a/acts_tests/tests/google/tel/lab/TelLabGFTAirplaneModeTest.py
+++ b/acts_tests/tests/google/tel/lab/TelLabGFTAirplaneModeTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#   Copyright 2021 - The Android Open Source Project
+#   Copyright 2022 - 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.
@@ -35,11 +35,11 @@
 from acts_contrib.test_utils.tel.tel_defines import GEN_4G
 from acts_contrib.test_utils.tel.tel_defines import GEN_5G
 from acts_contrib.test_utils.tel.tel_defines import YOUTUBE_PACKAGE_NAME
+from acts_contrib.test_utils.tel.tel_data_utils import start_youtube_video
 from acts_contrib.test_utils.tel.tel_data_utils import wait_for_cell_data_connection
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_network_generation
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phone_default_state
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phones_idle
-from acts_contrib.test_utils.tel.tel_test_utils import start_youtube_video
 from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode
 from acts_contrib.test_utils.tel.tel_test_utils import set_preferred_network_mode_pref
 
diff --git a/acts_tests/tests/google/tel/lab/TelLabGFTDSDSInOutServiceTest.py b/acts_tests/tests/google/tel/lab/TelLabGFTDSDSInOutServiceTest.py
index 9a56a42..8f254fb 100644
--- a/acts_tests/tests/google/tel/lab/TelLabGFTDSDSInOutServiceTest.py
+++ b/acts_tests/tests/google/tel/lab/TelLabGFTDSDSInOutServiceTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#   Copyright 2021 - The Android Open Source Project
+#   Copyright 2022 - 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.
@@ -23,7 +23,7 @@
 from acts_contrib.test_utils.tel.GFTInOutBaseTest import GFTInOutBaseTest
 from acts_contrib.test_utils.tel.gft_inout_utils import mo_voice_call
 from acts_contrib.test_utils.tel.tel_test_utils import wait_for_ims_registered
-from acts_contrib.test_utils.tel.tel_test_utils import active_file_download_test
+from acts_contrib.test_utils.tel.tel_data_utils import active_file_download_test
 from acts_contrib.test_utils.tel.tel_test_utils import ensure_phones_idle
 from acts_contrib.test_utils.tel.tel_data_utils import wait_for_cell_data_connection
 
diff --git a/acts_tests/tests/google/tel/lab/TelLabGFTDSDS.py b/acts_tests/tests/google/tel/lab/TelLabGFTDSDSTest.py
similarity index 98%
rename from acts_tests/tests/google/tel/lab/TelLabGFTDSDS.py
rename to acts_tests/tests/google/tel/lab/TelLabGFTDSDSTest.py
index 67833b2..4453d15 100644
--- a/acts_tests/tests/google/tel/lab/TelLabGFTDSDS.py
+++ b/acts_tests/tests/google/tel/lab/TelLabGFTDSDSTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#   Copyright 2021 - The Android Open Source Project
+#   Copyright 2022 - 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.
@@ -25,10 +25,10 @@
 from acts_contrib.test_utils.tel.gft_inout_defines import NO_SERVICE_POWER_LEVEL
 from acts_contrib.test_utils.tel.gft_inout_defines import IN_SERVICE_POWER_LEVEL
 from acts_contrib.test_utils.tel.tel_defines import INVALID_SUB_ID
+from acts_contrib.test_utils.tel.tel_data_utils import start_youtube_video
 from acts_contrib.test_utils.tel.tel_subscription_utils import set_dds_on_slot
 from acts_contrib.test_utils.tel.tel_subscription_utils import set_dds_on_slot_0
 from acts_contrib.test_utils.tel.tel_subscription_utils import set_dds_on_slot_1
-from acts_contrib.test_utils.tel.tel_test_utils import start_youtube_video
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phones_idle
 from acts_contrib.test_utils.tel.tel_dsds_utils import dsds_voice_call_test
 from acts_contrib.test_utils.tel.tel_subscription_utils import set_dds_on_slot_0
diff --git a/acts_tests/tests/google/tel/lab/TelLabGFTInOutServiceTest.py b/acts_tests/tests/google/tel/lab/TelLabGFTInOutServiceTest.py
index ba314d0..9694749 100644
--- a/acts_tests/tests/google/tel/lab/TelLabGFTInOutServiceTest.py
+++ b/acts_tests/tests/google/tel/lab/TelLabGFTInOutServiceTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#   Copyright 2021 - The Android Open Source Project
+#   Copyright 2022 - 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.
@@ -31,7 +31,7 @@
 from acts_contrib.test_utils.tel.tel_defines import SERVICE_STATE_IN_SERVICE
 from acts_contrib.test_utils.tel.tel_data_utils import wait_for_cell_data_connection
 from acts_contrib.test_utils.tel.tel_ims_utils import toggle_volte
-from acts_contrib.test_utils.tel.tel_test_utils import active_file_download_test
+from acts_contrib.test_utils.tel.tel_data_utils import active_file_download_test
 from acts_contrib.test_utils.tel.tel_test_utils import get_service_state_by_adb
 from acts_contrib.test_utils.tel.tel_voice_utils import hangup_call
 
diff --git a/acts_tests/tests/google/tel/live/TelLiveDSDSVoiceTest.py b/acts_tests/tests/google/tel/live/TelLiveDSDSVoiceTest.py
index 24a784c..78bd320 100644
--- a/acts_tests/tests/google/tel/live/TelLiveDSDSVoiceTest.py
+++ b/acts_tests/tests/google/tel/live/TelLiveDSDSVoiceTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3.4
 #
-#   Copyright 2019 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@
 from acts_contrib.test_utils.tel.tel_defines import DIRECTION_MOBILE_TERMINATED
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_BETWEEN_REG_AND_CALL
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_IN_CALL
+from acts_contrib.test_utils.tel.tel_data_utils import active_file_download_test
 from acts_contrib.test_utils.tel.tel_logging_utils import start_qxdm_loggers
 from acts_contrib.test_utils.tel.tel_logging_utils import start_qxdm_logger
 from acts_contrib.test_utils.tel.tel_message_utils import sms_send_receive_verify
@@ -55,7 +56,6 @@
 from acts_contrib.test_utils.tel.tel_test_utils import get_operator_name
 from acts_contrib.test_utils.tel.tel_test_utils import get_phone_number
 from acts_contrib.test_utils.tel.tel_test_utils import get_phone_number_for_subscription
-from acts_contrib.test_utils.tel.tel_test_utils import active_file_download_test
 from acts_contrib.test_utils.tel.tel_test_utils import verify_internet_connection
 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 test_data_browsing_failure_using_sl4a
diff --git a/acts_tests/tests/google/tel/live/TelLiveDataTest.py b/acts_tests/tests/google/tel/live/TelLiveDataTest.py
index 1f3e3c0..aae9fc0 100755
--- a/acts_tests/tests/google/tel/live/TelLiveDataTest.py
+++ b/acts_tests/tests/google/tel/live/TelLiveDataTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3.4
 #
-#   Copyright 2016 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -49,11 +49,18 @@
 from acts_contrib.test_utils.tel.tel_defines import TETHERING_SPECIAL_SSID_LIST
 from acts_contrib.test_utils.tel.tel_defines import TETHERING_SPECIAL_PASSWORD_LIST
 from acts_contrib.test_utils.tel.tel_bt_utils import verify_bluetooth_tethering_connection
+from acts_contrib.test_utils.tel.tel_data_utils import active_file_download_test
 from acts_contrib.test_utils.tel.tel_data_utils import airplane_mode_test
 from acts_contrib.test_utils.tel.tel_data_utils import browsing_test
+from acts_contrib.test_utils.tel.tel_data_utils import get_mobile_data_usage
 from acts_contrib.test_utils.tel.tel_data_utils import reboot_test
 from acts_contrib.test_utils.tel.tel_data_utils import change_data_sim_and_verify_data
+from acts_contrib.test_utils.tel.tel_data_utils import check_data_stall_detection
+from acts_contrib.test_utils.tel.tel_data_utils import check_data_stall_recovery
+from acts_contrib.test_utils.tel.tel_data_utils import check_network_validation_fail
 from acts_contrib.test_utils.tel.tel_data_utils import data_connectivity_single_bearer
+from acts_contrib.test_utils.tel.tel_data_utils import remove_mobile_data_usage_limit
+from acts_contrib.test_utils.tel.tel_data_utils import set_mobile_data_usage_limit
 from acts_contrib.test_utils.tel.tel_data_utils import tethering_check_internet_connection
 from acts_contrib.test_utils.tel.tel_data_utils import test_data_connectivity_multi_bearer
 from acts_contrib.test_utils.tel.tel_data_utils import test_setup_tethering
@@ -85,19 +92,12 @@
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phones_default_state
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_network_generation
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_network_generation_for_subscription
-from acts_contrib.test_utils.tel.tel_test_utils import active_file_download_test
-from acts_contrib.test_utils.tel.tel_test_utils import get_mobile_data_usage
-from acts_contrib.test_utils.tel.tel_test_utils import remove_mobile_data_usage_limit
-from acts_contrib.test_utils.tel.tel_test_utils import set_mobile_data_usage_limit
 from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode_by_adb
 from acts_contrib.test_utils.tel.tel_test_utils import verify_internet_connection
 from acts_contrib.test_utils.tel.tel_test_utils import wait_for_data_attach_for_subscription
-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_network_validation_fail
 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 resume_internet_with_sl4a_port
 from acts_contrib.test_utils.tel.tel_test_utils import get_device_epoch_time
-from acts_contrib.test_utils.tel.tel_test_utils import check_data_stall_recovery
 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 test_data_browsing_failure_using_sl4a
 from acts_contrib.test_utils.tel.tel_test_utils import set_time_sync_from_network
diff --git a/acts_tests/tests/google/tel/live/TelLiveGFTDSDSDDSSwitchTest.py b/acts_tests/tests/google/tel/live/TelLiveGFTDSDSDDSSwitchTest.py
index 92d01ec..b762af0 100644
--- a/acts_tests/tests/google/tel/live/TelLiveGFTDSDSDDSSwitchTest.py
+++ b/acts_tests/tests/google/tel/live/TelLiveGFTDSDSDDSSwitchTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#   Copyright 2020 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -27,6 +27,8 @@
 from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_CELLULAR_PREFERRED
 from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_WIFI_PREFERRED
 from acts_contrib.test_utils.tel.tel_data_utils import reboot_test
+from acts_contrib.test_utils.tel.tel_data_utils import start_youtube_video
+from acts_contrib.test_utils.tel.tel_data_utils import wait_for_cell_data_connection_for_subscription
 from acts_contrib.test_utils.tel.tel_ims_utils import is_volte_enabled
 from acts_contrib.test_utils.tel.tel_ims_utils import set_wfc_mode_for_subscription
 from acts_contrib.test_utils.tel.tel_ims_utils import toggle_volte_for_subscription
@@ -48,8 +50,6 @@
 from acts_contrib.test_utils.tel.tel_subscription_utils import set_dds_on_slot_0
 from acts_contrib.test_utils.tel.tel_subscription_utils import set_dds_on_slot_1
 from acts_contrib.test_utils.tel.tel_subscription_utils import get_subid_on_same_network_of_host_ad
-from acts_contrib.test_utils.tel.tel_test_utils import start_youtube_video
-from acts_contrib.test_utils.tel.tel_data_utils import wait_for_cell_data_connection_for_subscription
 from acts_contrib.test_utils.tel.tel_test_utils import verify_http_connection
 from acts_contrib.test_utils.tel.tel_test_utils import verify_internet_connection
 from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode
diff --git a/acts_tests/tests/google/tel/live/TelLiveMobilityStressTest.py b/acts_tests/tests/google/tel/live/TelLiveMobilityStressTest.py
index 824f0c8..b608584 100644
--- a/acts_tests/tests/google/tel/live/TelLiveMobilityStressTest.py
+++ b/acts_tests/tests/google/tel/live/TelLiveMobilityStressTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3.4
 #
-#   Copyright 2017 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -35,7 +35,7 @@
 from acts_contrib.test_utils.tel.tel_logging_utils import start_qxdm_loggers
 from acts_contrib.test_utils.tel.tel_message_utils import sms_send_receive_verify
 from acts_contrib.test_utils.tel.tel_message_utils import mms_send_receive_verify
-from acts_contrib.test_utils.tel.tel_test_utils import active_file_download_test
+from acts_contrib.test_utils.tel.tel_data_utils import active_file_download_test
 from acts_contrib.test_utils.tel.tel_voice_utils import call_setup_teardown
 from acts_contrib.test_utils.tel.tel_voice_utils import get_current_voice_rat
 from acts.utils import get_current_epoch_time
diff --git a/acts_tests/tests/google/tel/live/TelLiveRilDataKpiTest.py b/acts_tests/tests/google/tel/live/TelLiveRilDataKpiTest.py
index 44b3125..ce6e6fa 100644
--- a/acts_tests/tests/google/tel/live/TelLiveRilDataKpiTest.py
+++ b/acts_tests/tests/google/tel/live/TelLiveRilDataKpiTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 #
-#   Copyright 2021 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_ANDROID_STATE_SETTLING
 from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_WIFI_PREFERRED
 from acts_contrib.test_utils.tel.tel_data_utils import activate_and_verify_cellular_data
+from acts_contrib.test_utils.tel.tel_data_utils import active_file_download_test
 from acts_contrib.test_utils.tel.tel_data_utils import deactivate_and_verify_cellular_data
 from acts_contrib.test_utils.tel.tel_ims_utils import toggle_wfc
 from acts_contrib.test_utils.tel.tel_ims_utils import wait_for_wfc_enabled
@@ -38,7 +39,6 @@
 from acts_contrib.test_utils.tel.tel_subscription_utils import set_dds_on_slot_0
 from acts_contrib.test_utils.tel.tel_subscription_utils import set_dds_on_slot_1
 from acts_contrib.test_utils.tel.tel_subscription_utils import get_slot_index_from_data_sub_id
-from acts_contrib.test_utils.tel.tel_test_utils import active_file_download_test
 from acts.utils import get_current_epoch_time
 from acts.libs.utils.multithread import multithread_func
 
diff --git a/acts_tests/tests/google/tel/live/TelLiveSmsTest.py b/acts_tests/tests/google/tel/live/TelLiveSmsTest.py
index dc3af48..d03d42a 100644
--- a/acts_tests/tests/google/tel/live/TelLiveSmsTest.py
+++ b/acts_tests/tests/google/tel/live/TelLiveSmsTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3.4
 #
-#   Copyright 2021 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -26,16 +26,16 @@
 from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_DISABLED
 from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_WIFI_PREFERRED
 from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_CELLULAR_PREFERRED
+from acts_contrib.test_utils.tel.tel_data_utils import get_mobile_data_usage
+from acts_contrib.test_utils.tel.tel_data_utils import remove_mobile_data_usage_limit
+from acts_contrib.test_utils.tel.tel_data_utils import set_mobile_data_usage_limit
 from acts_contrib.test_utils.tel.tel_message_utils import sms_in_collision_send_receive_verify
 from acts_contrib.test_utils.tel.tel_message_utils import sms_rx_power_off_multiple_send_receive_verify
 from acts_contrib.test_utils.tel.tel_message_utils import message_test
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phone_default_state
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phones_idle
-from acts_contrib.test_utils.tel.tel_test_utils import get_mobile_data_usage
 from acts_contrib.test_utils.tel.tel_test_utils import get_operator_name
 from acts_contrib.test_utils.tel.tel_test_utils import install_message_apk
-from acts_contrib.test_utils.tel.tel_test_utils import remove_mobile_data_usage_limit
-from acts_contrib.test_utils.tel.tel_test_utils import set_mobile_data_usage_limit
 from acts.utils import rand_ascii_str
 from acts.libs.utils.multithread import multithread_func
 
diff --git a/acts_tests/tests/google/tel/live/TelLiveStressFdrTest.py b/acts_tests/tests/google/tel/live/TelLiveStressFdrTest.py
index da8d9b1..91e1332 100644
--- a/acts_tests/tests/google/tel/live/TelLiveStressFdrTest.py
+++ b/acts_tests/tests/google/tel/live/TelLiveStressFdrTest.py
@@ -57,6 +57,7 @@
     def setup_class(self):
         TelephonyBaseTest.setup_class(self)
 
+        self.user_params["telephony_auto_rerun"] = 0
         self.stress_test_number = int(
             self.user_params.get("stress_test_number", 100))
         self.skip_reset_between_cases = False
diff --git a/acts_tests/tests/google/tel/live/TelLiveStressTest.py b/acts_tests/tests/google/tel/live/TelLiveStressTest.py
index 6f3e0f7..e04ba6a 100644
--- a/acts_tests/tests/google/tel/live/TelLiveStressTest.py
+++ b/acts_tests/tests/google/tel/live/TelLiveStressTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3.4
 #
-#   Copyright 2017 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -47,6 +47,8 @@
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_CHANGE_MESSAGE_SUB_ID
 from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_CHANGE_VOICE_SUB_ID
 from acts_contrib.test_utils.tel.tel_5g_test_utils import provision_device_for_5g
+from acts_contrib.test_utils.tel.tel_5g_utils import is_current_network_5g
+from acts_contrib.test_utils.tel.tel_data_utils import active_file_download_test
 from acts_contrib.test_utils.tel.tel_ims_utils import set_wfc_mode
 from acts_contrib.test_utils.tel.tel_logging_utils import extract_test_log
 from acts_contrib.test_utils.tel.tel_logging_utils import start_qxdm_loggers
@@ -72,7 +74,6 @@
 from acts_contrib.test_utils.tel.tel_subscription_utils import set_subid_for_outgoing_call
 from acts_contrib.test_utils.tel.tel_subscription_utils import set_always_allow_mms_data
 from acts_contrib.test_utils.tel.tel_test_utils import STORY_LINE
-from acts_contrib.test_utils.tel.tel_test_utils import active_file_download_test
 from acts_contrib.test_utils.tel.tel_test_utils import force_connectivity_metrics_upload
 from acts_contrib.test_utils.tel.tel_test_utils import get_device_epoch_time
 from acts_contrib.test_utils.tel.tel_test_utils import get_telephony_signal_strength
@@ -477,9 +478,7 @@
                 incall_ui_display=INCALL_UI_DISPLAY_BACKGROUND,
                 call_stats_check=self.call_stats_check,
                 voice_type_init=voice_type_init,
-                result_info = self.result_info,
-                nw_gen_5g=self.nsa_5g_for_stress,
-                nr_type= self.nr_type
+                result_info = self.result_info
             ) and wait_for_in_call_active(self.dut, 60, 3)
         else:
             call_setup_result = call_setup_teardown(
@@ -494,9 +493,7 @@
                 slot_id_callee=slot_id_callee,
                 call_stats_check=self.call_stats_check,
                 voice_type_init=voice_type_init,
-                result_info = self.result_info,
-                nsa_5g_for_stress=self.nsa_5g_for_stress,
-                nr_type= self.nr_type)
+                result_info = self.result_info)
             self.result_collection[RESULTS_LIST[call_setup_result.result_value]] += 1
 
         if not call_setup_result:
@@ -563,6 +560,11 @@
         if not hangup_call(self.log, ads[0]):
             failure_reasons.add("Teardown")
             result = False
+        else:
+            if self.nsa_5g_for_stress:
+                for ad in (ads[0], ads[1]):
+                    if not is_current_network_5g(ad, self.nr_type):
+                        ad.log.error("Phone not attached on 5G")
         for ad in ads:
             if not wait_for_call_id_clearing(ad,
                                              []) or ad.droid.telecomIsInCall():
diff --git a/acts_tests/tests/google/tel/live/TelLiveVoiceTest.py b/acts_tests/tests/google/tel/live/TelLiveVoiceTest.py
index 344e1e9..b105660 100644
--- a/acts_tests/tests/google/tel/live/TelLiveVoiceTest.py
+++ b/acts_tests/tests/google/tel/live/TelLiveVoiceTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3.4
 #
-#   Copyright 2016 - Google
+#   Copyright 2022 - Google
 #
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
@@ -24,6 +24,9 @@
 from acts_contrib.test_utils.tel.loggers.protos.telephony_metric_pb2 import TelephonyVoiceTestResult
 from acts_contrib.test_utils.tel.loggers.telephony_metric_logger import TelephonyMetricLogger
 from acts_contrib.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest
+from acts_contrib.test_utils.tel.tel_data_utils import get_mobile_data_usage
+from acts_contrib.test_utils.tel.tel_data_utils import remove_mobile_data_usage_limit
+from acts_contrib.test_utils.tel.tel_data_utils import set_mobile_data_usage_limit
 from acts_contrib.test_utils.tel.tel_data_utils import test_call_setup_in_active_data_transfer
 from acts_contrib.test_utils.tel.tel_data_utils import test_call_setup_in_active_youtube_video
 from acts_contrib.test_utils.tel.tel_data_utils import call_epdg_to_epdg_wfc
@@ -57,11 +60,8 @@
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_volte
 from acts_contrib.test_utils.tel.tel_subscription_utils import get_incoming_voice_sub_id
 from acts_contrib.test_utils.tel.tel_subscription_utils import get_outgoing_voice_sub_id
-from acts_contrib.test_utils.tel.tel_test_utils import get_mobile_data_usage
 from acts_contrib.test_utils.tel.tel_test_utils import install_dialer_apk
 from acts_contrib.test_utils.tel.tel_test_utils import num_active_calls
-from acts_contrib.test_utils.tel.tel_test_utils import remove_mobile_data_usage_limit
-from acts_contrib.test_utils.tel.tel_test_utils import set_mobile_data_usage_limit
 from acts_contrib.test_utils.tel.tel_test_utils import STORY_LINE
 from acts_contrib.test_utils.tel.tel_voice_utils import hangup_call
 from acts_contrib.test_utils.tel.tel_voice_utils import hold_unhold_test
diff --git a/acts_tests/tests/google/tel/live/TelWifiDataTest.py b/acts_tests/tests/google/tel/live/TelWifiDataTest.py
index 2938c08..9582405 100644
--- a/acts_tests/tests/google/tel/live/TelWifiDataTest.py
+++ b/acts_tests/tests/google/tel/live/TelWifiDataTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3.4
 #
-# Copyright 2016 - The Android Open Source Project
+# Copyright 2022 - 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.
@@ -24,12 +24,12 @@
 from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_NW_SELECTION
 from acts_contrib.test_utils.tel.tel_defines import NETWORK_SERVICE_DATA
 from acts_contrib.test_utils.tel.tel_defines import GEN_4G
+from acts_contrib.test_utils.tel.tel_data_utils import active_file_download_test
+from acts_contrib.test_utils.tel.tel_data_utils import wait_for_cell_data_connection
 from acts_contrib.test_utils.tel.tel_data_utils import wait_for_wifi_data_connection
 from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_network_generation
 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_data_utils import wait_for_cell_data_connection
-from acts_contrib.test_utils.tel.tel_test_utils import active_file_download_test
 from acts_contrib.test_utils.tel.tel_test_utils import get_telephony_signal_strength
 from acts_contrib.test_utils.tel.tel_test_utils import reboot_device
 from acts_contrib.test_utils.tel.tel_wifi_utils import ensure_wifi_connected
diff --git a/acts_tests/tests/google/wifi/WifiTetheringPowerTest.py b/acts_tests/tests/google/wifi/WifiTetheringPowerTest.py
index e11eaa5..84fc6aa 100644
--- a/acts_tests/tests/google/wifi/WifiTetheringPowerTest.py
+++ b/acts_tests/tests/google/wifi/WifiTetheringPowerTest.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python3.4
 #
-#   Copyright 2017 - The Android Open Source Project
+#   Copyright 2022 - 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.
@@ -27,7 +27,7 @@
 from acts_contrib.test_utils.tel import tel_data_utils as tel_utils
 from acts_contrib.test_utils.tel.tel_wifi_utils import WIFI_CONFIG_APBAND_2G
 from acts_contrib.test_utils.tel.tel_wifi_utils import WIFI_CONFIG_APBAND_5G
-from acts_contrib.test_utils.tel.tel_test_utils import http_file_download_by_chrome
+from acts_contrib.test_utils.tel.tel_data_utils import http_file_download_by_chrome
 from acts.utils import force_airplane_mode
 from acts.utils import set_adaptive_brightness
 from acts.utils import set_ambient_display