Merge "Fix tdls_supported testcase" into oc-dev
diff --git a/acts/framework/acts/test_utils/tel/tel_test_utils.py b/acts/framework/acts/test_utils/tel/tel_test_utils.py
index 8127ae1..5732351 100644
--- a/acts/framework/acts/test_utils/tel/tel_test_utils.py
+++ b/acts/framework/acts/test_utils/tel/tel_test_utils.py
@@ -1774,7 +1774,11 @@
     """Check file existance by file_path. If expected_file_size
        is provided, then also check if the file meet the file size requirement.
     """
-    out = ad.adb.shell('stat -c "%%s" %s' % file_path)
+    out = None
+    try:
+        out = ad.adb.shell('stat -c "%%s" %s' % file_path)
+    except AdbError:
+        pass
     # Handle some old version adb returns error message "No such" into std_out
     if out and "No such" not in out:
         if expected_file_size:
diff --git a/acts/framework/acts/test_utils/wifi/wifi_test_utils.py b/acts/framework/acts/test_utils/wifi/wifi_test_utils.py
index 2e121af..72bc4bd 100755
--- a/acts/framework/acts/test_utils/wifi/wifi_test_utils.py
+++ b/acts/framework/acts/test_utils/wifi/wifi_test_utils.py
@@ -36,13 +36,6 @@
 # change.
 SHORT_TIMEOUT = 30
 
-# The currently supported devices that existed before release
-#TODO: (navtejsingh) Need to clean up the below lists going forward
-K_DEVICES = ["hammerhead", "razor", "razorg"]
-L_DEVICES = ["shamu", "ryu"]
-L_TAP_DEVICES = ["volantis", "volantisg"]
-M_DEVICES = ["angler"]
-
 # Speed of light in m/s.
 SPEED_OF_LIGHT = 299792458
 
@@ -391,30 +384,10 @@
                         5320, 5520, 5560, 5700, 5745, 5805]
 
     def __init__(self, model=None):
-        if model and utils.trim_model_name(model) in K_DEVICES:
-            self.DFS_5G_FREQUENCIES = []
-            self.ALL_5G_FREQUENCIES = self.NONE_DFS_5G_FREQUENCIES
-            self.MIX_CHANNEL_SCAN = [2412, 2437, 2462, 5180, 5200, 5240, 5745,
-                                     5765]
-        elif model and utils.trim_model_name(model) in L_DEVICES:
-            self.DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520,
-                                       5540, 5560, 5580, 5660, 5680, 5700]
-            self.ALL_5G_FREQUENCIES = self.DFS_5G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES
-        elif model and utils.trim_model_name(model) in L_TAP_DEVICES:
-            self.DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520,
-                                       5540, 5560, 5580, 5660, 5680, 5700,
-                                       5720]
-            self.ALL_5G_FREQUENCIES = self.DFS_5G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES
-        elif model and utils.trim_model_name(model) in M_DEVICES:
-            self.DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520,
-                                       5540, 5560, 5580, 5600, 5620, 5640,
-                                       5660, 5680, 5700]
-            self.ALL_5G_FREQUENCIES = self.DFS_5G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES
-        else:
-            self.DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520,
-                                       5540, 5560, 5580, 5600, 5620, 5640,
-                                       5660, 5680, 5700, 5720]
-            self.ALL_5G_FREQUENCIES = self.DFS_5G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES
+        self.DFS_5G_FREQUENCIES = [5260, 5280, 5300, 5320, 5500, 5520,
+                                   5540, 5560, 5580, 5600, 5620, 5640,
+                                   5660, 5680, 5700, 5720]
+        self.ALL_5G_FREQUENCIES = self.DFS_5G_FREQUENCIES + self.NONE_DFS_5G_FREQUENCIES
 
 class WifiReferenceNetworks:
     """ Class to parse and return networks of different band and
diff --git a/acts/tests/google/wifi/WifiScannerScanTest.py b/acts/tests/google/wifi/WifiScannerScanTest.py
index d19a620..8f89559 100755
--- a/acts/tests/google/wifi/WifiScannerScanTest.py
+++ b/acts/tests/google/wifi/WifiScannerScanTest.py
@@ -51,7 +51,12 @@
         # There are order dependencies among these tests so we'll have to leave
         # it here for now. :(
         self.tests = (
-            "test_available_channels_generated",
+            "test_available_channels_band_1",
+            "test_available_channels_band_2",
+            "test_available_channels_band_3",
+            "test_available_channels_band_4",
+            "test_available_channels_band_6",
+            "test_available_channels_band_7",
             "test_wifi_scanner_single_scan_channel_sanity",
             "test_wifi_scanner_with_wifi_off",
             "test_single_scan_report_each_scan_for_channels_with_enumerated_params",
@@ -550,22 +555,35 @@
     """ Helper Functions End """
     """ Tests Begin """
 
-    @test_tracker_info(uuid="7cca8142-529f-4951-ab6f-cd03b359b3cc")
-    def test_available_channels_generated(self):
-        """Test available channels for different bands.
+    # Test channels
+    """ Test available channels for different bands.
 
-         1. Get available channels for different bands.
-         2. Verify that channels match with supported channels for respective band.
-        """
-        bands = (1, 2, 3, 4, 6, 7)
-        name_func = lambda band: "test_get_channel_band_{}".format(band)
-        failed = self.run_generated_testcases(
-            self.check_get_available_channels_with_one_band,
-            bands,
-            name_func=name_func)
-        asserts.assert_true(
-            not failed,
-            "Number of test_get_channel_band failed {}".format(len(failed)))
+        1. Get available channels for different bands.
+        2. Verify that channels match with supported channels for respective band.
+    """
+    @test_tracker_info(uuid="7cca8142-529f-4951-ab6f-cd03b359b3cc")
+    def test_available_channels_band_1(self):
+        self.check_get_available_channels_with_one_band(1)
+
+    @test_tracker_info(uuid="612afda1-0d74-4d2f-bc37-72ef2b98310a")
+    def test_available_channels_band_2(self):
+        self.check_get_available_channels_with_one_band(2)
+
+    @test_tracker_info(uuid="a9275bb9-afa7-4dd4-b2e0-60296ffd33bb")
+    def test_available_channels_band_3(self):
+        self.check_get_available_channels_with_one_band(3)
+
+    @test_tracker_info(uuid="5413632e-ce72-4ecc-bf9b-33ac9e4bf3fc")
+    def test_available_channels_band_4(self):
+        self.check_get_available_channels_with_one_band(4)
+
+    @test_tracker_info(uuid="a8f40b4f-d79d-4d2f-bed8-3b139a082f6c")
+    def test_available_channels_band_6(self):
+        self.check_get_available_channels_with_one_band(6)
+
+    @test_tracker_info(uuid="84cdfc25-8e64-42c7-b7f9-0a04e45d78b6")
+    def test_available_channels_band_7(self):
+        self.check_get_available_channels_with_one_band(7)
 
     @test_tracker_info(uuid="95069244-b76c-4834-b3a6-96b0d8da98d8")
     def test_single_scan_report_each_scan_for_channels_with_enumerated_params(
@@ -581,21 +599,7 @@
             wutils.WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN)
         self.log.debug("Scan settings: %s\n%s", len(scan_settings),
                        scan_settings)
-
-        def name_func(scan_setting):
-            return (
-                "test_single_scan_report_each_scan_for_channels_%s"
-                "_numBssidsPerScan_%s_maxScansToCache_%s_period_%s") % (
-                    scan_setting["channels"], scan_setting["numBssidsPerScan"],
-                    scan_setting["maxScansToCache"],
-                    scan_setting["periodInMs"])
-
-        failed = self.run_generated_testcases(self.wifi_scanner_single_scan,
-                                              scan_settings,
-                                              name_func=name_func)
-        asserts.assert_false(
-            failed, ("Number of test_single_scan_report_each_scan_for_channels"
-                     " failed {}").format(len(failed)))
+        self.wifi_scanner_single_scan(scan_settings[0])
 
     @test_tracker_info(uuid="5595ebe5-6d91-4379-a606-be59967e5ec9")
     def test_single_scan_report_each_scan_for_band_with_enumerated_params(
@@ -611,20 +615,7 @@
             wutils.WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN)
         self.log.debug("Scan settings:%s\n%s", len(scan_settings),
                        scan_settings)
-
-        def scan_setting_name_gen(scan_setting):
-            return "test_single_scan_report_each_scan_for_band_%s_numBssidsPerScan_%s_maxScansToCache_%s_period_%s" % (
-                scan_setting["band"], scan_setting["numBssidsPerScan"],
-                scan_setting["maxScansToCache"], scan_setting["periodInMs"])
-
-        name_func = scan_setting_name_gen
-        failed = self.run_generated_testcases(self.wifi_scanner_single_scan,
-                                              scan_settings,
-                                              name_func=name_func)
-        asserts.assert_true(
-            not failed,
-            "Number of test_single_scan_report_each_scan_for_band failed %s" %
-            len(failed))
+        self.wifi_scanner_single_scan(scan_settings[0])
 
     @test_tracker_info(uuid="44989f93-e63b-4c2e-a90a-a483477303bb")
     def test_batch_scan_report_buffer_full_for_channels_with_enumerated_params(
@@ -641,16 +632,7 @@
             wutils.WifiEnums.REPORT_EVENT_AFTER_BUFFER_FULL)
         self.log.debug("Scan settings:%s\n%s", len(scan_settings),
                        scan_settings)
-        name_func = (
-            lambda scan_setting: ("test_batch_scan_report_buffer_full_for_channels_{}"
-                                  "_numBssidsPerScan_{}_maxScansToCache_{}_periodInMs_{}").format(scan_setting["channels"], scan_setting["numBssidsPerScan"], scan_setting["maxScansToCache"], scan_setting["periodInMs"])
-        )
-        failed = self.run_generated_testcases(self.wifi_scanner_batch_scan,
-                                              scan_settings,
-                                              name_func=name_func)
-        asserts.assert_false(failed, (
-            "Number of test_batch_scan_report_buffer_full_for_channels"
-            " failed {}").format(len(failed)))
+        self.wifi_scanner_batch_scan(scan_settings[0])
 
     @test_tracker_info(uuid="63538df6-388a-4c16-964f-e9c19b750e07")
     def test_batch_scan_report_buffer_full_for_band_with_enumerated_params(
@@ -667,16 +649,7 @@
             wutils.WifiEnums.REPORT_EVENT_AFTER_BUFFER_FULL)
         self.log.debug("Scan settings:{}\n{}".format(
             len(scan_settings), scan_settings))
-        name_func = (
-            lambda scan_setting: ("test_batch_scan_report_buffer_full_for_band_{}"
-                                  "_numBssidsPerScan_{}_maxScansToCache_{}_periodInMs_{}").format(scan_setting["band"], scan_setting["numBssidsPerScan"], scan_setting["maxScansToCache"], scan_setting["periodInMs"])
-        )
-        failed = self.run_generated_testcases(self.wifi_scanner_batch_scan,
-                                              scan_settings,
-                                              name_func=name_func)
-        asserts.assert_false(
-            failed, ("Number of test_batch_scan_report_buffer_full_for_band"
-                     " failed {}").format(len(failed)))
+        self.wifi_scanner_batch_scan(scan_settings[0])
 
     @test_tracker_info(uuid="bd4e8c53-16c8-4ed6-b680-55c1ba688ad8")
     def test_batch_scan_report_each_scan_for_channels_with_enumerated_params(
@@ -693,16 +666,7 @@
             wutils.WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN)
         self.log.debug("Scan settings:{}\n{}".format(
             len(scan_settings), scan_settings))
-        name_func = (
-            lambda scan_setting: ("test_batch_scan_report_each_scan_for_channels_{}"
-                                  "_numBssidsPerScan_{}_maxScansToCache_{}_periodInMs_{}").format(scan_setting["channels"], scan_setting["numBssidsPerScan"], scan_setting["maxScansToCache"], scan_setting["periodInMs"])
-        )
-        failed = self.run_generated_testcases(self.wifi_scanner_batch_scan,
-                                              scan_settings,
-                                              name_func=name_func)
-        asserts.assert_false(
-            failed, ("Number of test_batch_scan_report_each_scan_for_channels"
-                     " failed {}").format(len(failed)))
+        self.wifi_scanner_batch_scan(scan_settings[0])
 
     @test_tracker_info(uuid="d11e8c09-97d0-49c1-bf09-b9ec672c2fa6")
     def test_batch_scan_report_each_scan_for_band_with_enumerated_params(self):
@@ -718,16 +682,7 @@
             wutils.WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN)
         self.log.debug("Scan settings:{}\n{}".format(
             len(scan_settings), scan_settings))
-        name_func = (
-            lambda scan_setting: ("test_batch_scan_report_each_scan_for_band_{}"
-                                  "_numBssidsPerScan_{}_maxScansToCache_{}_periodInMs_{}").format(scan_setting["band"], scan_setting["numBssidsPerScan"], scan_setting["maxScansToCache"], scan_setting["periodInMs"])
-        )
-        failed = self.run_generated_testcases(self.wifi_scanner_batch_scan,
-                                              scan_settings,
-                                              name_func=name_func)
-        asserts.assert_true(
-            not failed, ("Number of test_batch_scan_report_each_scan_for_band"
-                         " failed {}").format(len(failed)))
+        self.wifi_scanner_batch_scan(scan_settings[0])
 
     @test_tracker_info(uuid="7f967b0e-82fe-403e-9d74-0dee7f09a21d")
     def test_single_scan_report_full_scan_for_channels_with_enumerated_params(
@@ -744,16 +699,7 @@
             wutils.WifiEnums.REPORT_EVENT_FULL_SCAN_RESULT)
         self.log.debug("Full Scan settings:{}\n{}".format(
             len(scan_settings), scan_settings))
-        name_func = (
-            lambda scan_setting: "test_single_scan_report_full_scan_for_channels_{}_periodInMs_{}".format(scan_setting["channels"], scan_setting["periodInMs"])
-        )
-        failed = self.run_generated_testcases(
-            self.wifi_scanner_single_scan_full,
-            scan_settings,
-            name_func=name_func)
-        asserts.assert_false(
-            failed, ("Number of test_single_scan_report_full_scan_for_channels"
-                     " failed {}").format(len(failed)))
+        self.wifi_scanner_single_scan_full(scan_settings[0])
 
     @test_tracker_info(uuid="34d09f60-31bf-4952-8fb3-03fc93ec98fa")
     def test_single_scan_report_full_scan_for_band_with_enumerated_params(
@@ -770,16 +716,7 @@
             wutils.WifiEnums.REPORT_EVENT_FULL_SCAN_RESULT)
         self.log.debug("Full Scan settings:{}\n{}".format(
             len(scan_settings), scan_settings))
-        name_func = (
-            lambda scan_setting: "test_single_scan_report_full_scan_for_band_{}_periodInMs_{}".format(scan_setting["band"], scan_setting["periodInMs"])
-        )
-        failed = self.run_generated_testcases(
-            self.wifi_scanner_single_scan_full,
-            scan_settings,
-            name_func=name_func)
-        asserts.assert_true(
-            not failed, ("Number of test_single_scan_report_full_scan_for_band"
-                         " failed {}").format(len(failed)))
+        self.wifi_scanner_single_scan_full(scan_settings[0])
 
     @test_tracker_info(uuid="0ddccf2e-b518-45a7-ae75-96924070b841")
     def test_batch_scan_report_full_scan_for_channels_with_enumerated_params(
@@ -796,17 +733,7 @@
             wutils.WifiEnums.REPORT_EVENT_FULL_SCAN_RESULT)
         self.log.debug("Full Scan settings:{}\n{}".format(
             len(scan_settings), scan_settings))
-        name_func = (
-            lambda scan_setting: ("test_batch_scan_report_full_scan_for_channels"
-                                  "_{}_periodInMs_{}").format(scan_setting["channels"], scan_setting["periodInMs"])
-        )
-        failed = self.run_generated_testcases(
-            self.wifi_scanner_batch_scan_full,
-            scan_settings,
-            name_func=name_func)
-        asserts.assert_false(
-            failed, ("Number of test_batch_scan_report_full_scan_for_channels"
-                     " failed {}").format(len(failed)))
+        self.wifi_scanner_batch_scan_full(scan_settings[0])
 
     @test_tracker_info(uuid="0685b667-8470-43a0-923d-dee71428f8ce")
     def test_batch_scan_report_full_scan_for_band_with_enumerated_params(self):
@@ -822,17 +749,7 @@
             wutils.WifiEnums.REPORT_EVENT_FULL_SCAN_RESULT)
         self.log.debug("Full Scan settings:{}\n{}".format(
             len(scan_settings), scan_settings))
-        name_func = (
-            lambda scan_setting: ("test_batch_scan_report_full_scan_for_band"
-                                  "_{}_periodInMs_{}").format(scan_setting["band"], scan_setting["periodInMs"])
-        )
-        failed = self.run_generated_testcases(
-            self.wifi_scanner_batch_scan_full,
-            scan_settings,
-            name_func=name_func)
-        asserts.assert_true(
-            not failed, ("Number of test_batch_scan_report_full_scan_for_band"
-                         " failed {}").format(len(failed)))
+        self.wifi_scanner_batch_scan_full(scan_settings[0])
 
     @test_tracker_info(uuid="740e1c18-911a-43d2-9317-3827ecf71d3b")
     def test_wifi_connection_while_single_scan(self):
diff --git a/acts/tests/google/wifi/WifiTetheringTest.py b/acts/tests/google/wifi/WifiTetheringTest.py
index c1e0b23..c33c964 100644
--- a/acts/tests/google/wifi/WifiTetheringTest.py
+++ b/acts/tests/google/wifi/WifiTetheringTest.py
@@ -14,17 +14,25 @@
 #   limitations under the License.
 
 import logging
-import time
+import random
 import socket
+import time
 
 from acts import asserts
 from acts import base_test
 from acts import test_runner
 from acts.controllers import adb
+from acts.test_decorators import test_tracker_info
 from acts.test_utils.tel import tel_data_utils
-from acts.test_utils.tel import tel_test_utils
 from acts.test_utils.tel import tel_defines
-from acts.test_utils.wifi import wifi_test_utils
+from acts.test_utils.tel.tel_data_utils import toggle_airplane_mode
+from acts.test_utils.tel.tel_data_utils import wait_for_cell_data_connection
+from acts.test_utils.tel.tel_test_utils import get_operator_name
+from acts.test_utils.tel.tel_test_utils import http_file_download_by_chrome
+from acts.test_utils.tel.tel_test_utils import verify_http_connection
+from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_2G
+from acts.test_utils.tel.tel_test_utils import WIFI_CONFIG_APBAND_5G
+from acts.test_utils.wifi import wifi_test_utils as wutils
 
 
 class WifiTetheringTest(base_test.BaseTestClass):
@@ -32,33 +40,40 @@
 
     def setup_class(self):
         """ Setup devices for tethering and unpack params """
-        self.hotspot_device, self.tethered_device = self.android_devices[:2]
-        req_params = ("ssid", "password", "url")
+
+        self.convert_byte_to_mb = 1024.0 * 1024.0
+        self.new_ssid = "wifi_tethering_test2"
+        self.data_usage_error = 0.3
+
+        self.hotspot_device = self.android_devices[0]
+        self.tethered_devices = self.android_devices[1:]
+        req_params = ("network", "url", "download_file", "file_size")
         self.unpack_userparams(req_params)
-        asserts.assert_true(
-            tel_data_utils.toggle_airplane_mode(self.log, self.hotspot_device, False),
-            "Could not disable airplane mode")
-        wifi_test_utils.wifi_toggle_state(self.hotspot_device, False)
+        self.file_size = int(self.file_size)
+
+        wutils.wifi_toggle_state(self.hotspot_device, False)
         self.hotspot_device.droid.telephonyToggleDataConnection(True)
-        tel_data_utils.wait_for_cell_data_connection(self.log, self.hotspot_device, True)
+        wait_for_cell_data_connection(self.log, self.hotspot_device, True)
         asserts.assert_true(
-            tel_data_utils.verify_http_connection(self.log, self.hotspot_device),
+            verify_http_connection(self.log, self.hotspot_device),
             "HTTP verification failed on cell data connection")
         asserts.assert_true(
             self.hotspot_device.droid.connectivityIsTetheringSupported(),
             "Tethering is not supported for the provider")
-        wifi_test_utils.wifi_test_device_init(self.tethered_device)
-        self.tethered_device.droid.telephonyToggleDataConnection(False)
+        for ad in self.tethered_devices:
+            wutils.wifi_test_device_init(ad)
 
     def teardown_class(self):
         """ Reset devices """
-        wifi_test_utils.wifi_toggle_state(self.hotspot_device, True)
-        self.hotspot_device.droid.telephonyToggleDataConnection(True)
-        self.tethered_device.droid.telephonyToggleDataConnection(True)
+        wutils.wifi_toggle_state(self.hotspot_device, True)
+
+    def on_fail(self, test_name, begin_time):
+        """ Collect bug report on failure """
+        self.hotspot_device.take_bug_report(test_name, begin_time)
 
     """ Helper functions """
 
-    def _is_ipaddress_ipv6(self,ip_address):
+    def _is_ipaddress_ipv6(self, ip_address):
         """ Verify if the given string is a valid IPv6 address
 
         Args:
@@ -84,9 +99,21 @@
         """
         # Currently only Verizon support IPv6 tethering
         carrier_supports_tethering = ["vzw"]
-        operator = tel_test_utils.get_operator_name(self.log, dut)
+        operator = get_operator_name(self.log, dut)
         return operator in carrier_supports_tethering
 
+    def _carrier_supports_ipv6(self,dut):
+        """ Verify if carrier supports ipv6
+            Currently, only verizon and t-mobile supports IPv6
+
+        Returns:
+            True: if carrier supports ipv6
+            False: if not
+        """
+        carrier_supports_ipv6 = ["vzw", "tmo"]
+        operator = get_operator_name(self.log, dut)
+        return operator in carrier_supports_ipv6
+
     def _find_ipv6_default_route(self, dut):
         """ Checks if IPv6 default route exists in the link properites
 
@@ -98,12 +125,13 @@
         link_properties = dut.droid.connectivityGetActiveLinkProperties()
         return link_properties and default_route_substr in link_properties
 
-    def _verify_ipv6_tethering(self,dut):
+    def _verify_ipv6_tethering(self, dut):
         """ Verify IPv6 tethering """
         http_response = dut.droid.httpRequestString(self.url)
         link_properties = dut.droid.connectivityGetActiveLinkProperties()
         self.log.info("IP address %s " % http_response)
-        if dut==self.hotspot_device or self._supports_ipv6_tethering(self.hotspot_device):
+        if dut==self.hotspot_device and self._carrier_supports_ipv6(dut)\
+            or self._supports_ipv6_tethering(self.hotspot_device):
             asserts.assert_true(self._is_ipaddress_ipv6(http_response),
                                 "The http response did not return IPv6 address")
             asserts.assert_true(link_properties and http_response in link_properties,
@@ -114,42 +142,132 @@
             asserts.assert_true(not self._find_ipv6_default_route(dut),
                                 "Found IPv6 default route in link properties")
 
+    def _start_wifi_tethering(self, wifi_band=WIFI_CONFIG_APBAND_2G):
+        """ Start wifi tethering on hotspot device
+
+        Args:
+            1. wifi_band: specifies the wifi band to start the hotspot
+               on. The current options are 2G and 5G
+        """
+        wutils.start_wifi_tethering(self.hotspot_device,
+                                    self.network[wutils.WifiEnums.SSID_KEY],
+                                    self.network[wutils.WifiEnums.PWD_KEY],
+                                    wifi_band)
+
+    def _connect_disconnect_devices(self):
+        """ Randomly connect and disconnect devices from the
+            self.tethered_devices list to hotspot device
+        """
+        device_connected = [ False ] * len(self.tethered_devices)
+        for _ in range(50):
+            dut_id = random.randint(0, len(self.tethered_devices)-1)
+            dut = self.tethered_devices[dut_id]
+            if device_connected[dut_id]:
+                wutils.wifi_forget_network(dut, self.network["SSID"])
+            else:
+                wutils.wifi_connect(dut, self.network)
+            device_connected[dut_id] = not device_connected[dut_id]
+
+    def _verify_ping(self, dut, ip):
+        """ Verify ping works from the dut to IP/hostname
+
+        Args:
+            1. dut - ad object to check ping from
+            2. ip - ip/hostname to ping (IPv4 and IPv6)
+
+        Returns:
+            True - if ping is successful
+            False - if not
+        """
+        self.log.info("Pinging %s from dut %s" % (ip, dut.serial))
+        if self._is_ipaddress_ipv6(ip):
+            return dut.droid.pingHost(ip, 5, "ping6")
+        return dut.droid.pingHost(ip)
+
+    def _return_ip_for_interface(self, dut, iface_name):
+        """ Return list of IP addresses for an interface
+
+        Args:
+            1. dut - ad object
+            2. iface_name - interface name
+
+        Returns:
+            List of IPv4 and IPv6 addresses
+        """
+        return dut.droid.connectivityGetIPv4Addresses(iface_name) + \
+            dut.droid.connectivityGetIPv6Addresses(iface_name)
+
+    def _test_traffic_between_two_tethered_devices(self, dut1, dut2):
+        """ Verify pinging interfaces of one DUT from another
+
+        Args:
+            1. dut1 - tethered device 1
+            2. dut2 - tethered device 2
+        """
+        wutils.wifi_connect(dut1, self.network)
+        wutils.wifi_connect(dut2, self.network)
+
+        dut1_ipaddrs = dut1.droid.connectivityGetIPv4Addresses("wlan0") + \
+            dut1.droid.connectivityGetIPv6Addresses("wlan0")
+        dut2_ipaddrs = dut2.droid.connectivityGetIPv4Addresses("wlan0") + \
+            dut2.droid.connectivityGetIPv6Addresses("wlan0")
+
+        for ip in dut1_ipaddrs:
+            asserts.assert_true(self._verify_ping(dut2, ip), "%s " % ip)
+        for ip in dut2_ipaddrs:
+            asserts.assert_true(self._verify_ping(dut1, ip), "%s " % ip)
+
+    def _ping_hotspot_interfaces_from_tethered_device(self, dut):
+        """ Ping hotspot interfaces from tethered device
+
+        Args:
+            1. dut - tethered device
+
+        Returns:
+            True - if all IP addresses are pingable
+            False - if not
+        """
+        ifaces = self.hotspot_device.droid.connectivityGetNetworkInterfaces()
+        return_result = True
+        for interface in ifaces:
+            iface_name = interface.split()[0].split(':')[1]
+            if iface_name == "lo":
+                continue
+            ip_list = self._return_ip_for_interface(
+                self.hotspot_device, iface_name)
+            for ip in ip_list:
+                ping_result = self._verify_ping(dut, ip)
+                self.log.info("Ping result: %s %s %s" %
+                              (iface_name, ip, ping_result))
+                return_result = return_result and ping_result
+
+        return return_result
 
     """ Test Cases """
 
+    @test_tracker_info(uuid="36d03295-bea3-446e-8342-b9f8f1962a32")
     def test_ipv6_tethering(self):
         """ IPv6 tethering test
 
         Steps:
-            1. Start wifi tethering on provider
-            2. Client connects to wifi tethering SSID
-            3. Verify IPv6 address on the client's link properties
-            4. Verify ping on client using ping6 which should pass
-            5. Disable mobile data on provider and verify that link properties
+            1. Start wifi tethering on hotspot device
+            2. Verify IPv6 address on hotspot device
+            3. Connect tethered device to hotspot device
+            4. Verify IPv6 address on the client's link properties
+            5. Verify ping on client using ping6 which should pass
+            6. Disable mobile data on provider and verify that link properties
                does not have IPv6 address and default route
         """
         # Start wifi tethering on the hotspot device
-        self.log.info("Start tethering on provider: {}"
-                      .format(self.hotspot_device.serial))
-        wifi_test_utils.start_wifi_tethering(self.hotspot_device,
-                                             self.ssid,
-                                             self.password)
-        time.sleep(tel_defines.WAIT_TIME_ANDROID_STATE_SETTLING)
-        asserts.assert_true(
-            tel_data_utils.verify_http_connection(self.log,self.hotspot_device),
-            "Could not verify http connection on the provider")
+        wutils.toggle_wifi_off_and_on(self.hotspot_device)
+        self._start_wifi_tethering()
 
         # Verify link properties on hotspot device
         self.log.info("Check IPv6 properties on the hotspot device")
         self._verify_ipv6_tethering(self.hotspot_device)
 
         # Connect the client to the SSID
-        asserts.assert_true(
-            tel_test_utils.WifiUtils.wifi_connect(self.log,
-                                                  self.tethered_device,
-                                                  self.ssid,
-                                                  self.password),
-            "Unable to connect to the hotspot SSID")
+        wutils.wifi_connect(self.tethered_devices[0], self.network)
 
         # Need to wait atleast 2 seconds for IPv6 address to
         # show up in the link properties
@@ -157,12 +275,11 @@
 
         # Verify link properties on tethered device
         self.log.info("Check IPv6 properties on the tethered device")
-        self._verify_ipv6_tethering(self.tethered_device)
+        self._verify_ipv6_tethering(self.tethered_devices[0])
 
         # Verify ping6 on tethered device
-        ping_result = self.tethered_device.droid.pingHost("www.google.com",
-                                                          5,
-                                                          "ping6")
+        ping_result = self._verify_ping(self.tethered_devices[0],
+                                        "www.google.com")
         if self._supports_ipv6_tethering(self.hotspot_device):
             asserts.assert_true(ping_result, "Ping6 failed on the client")
         else:
@@ -170,11 +287,253 @@
 
         # Disable mobile data on hotspot device
         # and verify the link properties on tethered device
-        self.log.info("Disabling mobile data on hotspot device")
+        self.log.info("Disabling mobile data to verify ipv6 default route")
         self.hotspot_device.droid.telephonyToggleDataConnection(False)
-        asserts.assert_equal(self.hotspot_device.droid.telephonyGetDataConnectionState(),
-                             tel_defines.DATA_STATE_CONNECTED,
-                             "Could not disable cell data")
+        asserts.assert_equal(
+            self.hotspot_device.droid.telephonyGetDataConnectionState(),
+            tel_defines.DATA_STATE_CONNECTED,
+            "Could not disable cell data")
+
         time.sleep(2) # wait until the IPv6 is removed from link properties
-        asserts.assert_true(not self._find_ipv6_default_route(self.tethered_device),
-                            "Found IPv6 default route in link properties - Data off")
+
+        result = self._find_ipv6_default_route(self.tethered_devices[0])
+        self.hotspot_device.droid.telephonyToggleDataConnection(True)
+        if not result:
+            asserts.fail("Found IPv6 default route in link properties:Data off")
+
+        # Disable wifi tethering
+        wutils.stop_wifi_tethering(self.hotspot_device)
+
+    @test_tracker_info(uuid="110b61d1-8af2-4589-8413-11beac7a3025")
+    def test_wifi_tethering_2ghz_traffic_between_2tethered_devices(self):
+        """ Steps:
+
+            1. Start wifi hotspot with 2G band
+            2. Connect 2 tethered devices to the hotspot device
+            3. Ping interfaces between the tethered devices
+        """
+        wutils.toggle_wifi_off_and_on(self.hotspot_device)
+        self._start_wifi_tethering(WIFI_CONFIG_APBAND_2G)
+        self._test_traffic_between_two_tethered_devices(self.tethered_devices[0],
+                                                        self.tethered_devices[1])
+        wutils.stop_wifi_tethering(self.hotspot_device)
+
+    @test_tracker_info(uuid="953f6e2e-27bd-4b73-85a6-d2eaa4e755d5")
+    def test_wifi_tethering_5ghz_traffic_between_2tethered_devices(self):
+        """ Steps:
+
+            1. Start wifi hotspot with 5ghz band
+            2. Connect 2 tethered devices to the hotspot device
+            3. Send traffic between the tethered devices
+        """
+        wutils.toggle_wifi_off_and_on(self.hotspot_device)
+        self._start_wifi_tethering(WIFI_CONFIG_APBAND_5G)
+        self._test_traffic_between_two_tethered_devices(self.tethered_devices[0],
+                                                        self.tethered_devices[1])
+        wutils.stop_wifi_tethering(self.hotspot_device)
+
+    @test_tracker_info(uuid="d7d5aa51-682d-4882-a334-61966d93b68c")
+    def test_wifi_tethering_2ghz_connect_disconnect_devices(self):
+        """ Steps:
+
+            1. Start wifi hotspot with 2ghz band
+            2. Connect and disconnect multiple devices randomly
+            3. Verify the correct functionality
+        """
+        wutils.toggle_wifi_off_and_on(self.hotspot_device)
+        self._start_wifi_tethering(WIFI_CONFIG_APBAND_2G)
+        self._connect_disconnect_devices()
+        wutils.stop_wifi_tethering(self.hotspot_device)
+
+    @test_tracker_info(uuid="34abd6c9-c7f1-4d89-aa2b-a66aeabed9aa")
+    def test_wifi_tethering_5ghz_connect_disconnect_devices(self):
+        """ Steps:
+
+            1. Start wifi hotspot with 5ghz band
+            2. Connect and disconnect multiple devices randomly
+            3. Verify the correct functionality
+        """
+        wutils.toggle_wifi_off_and_on(self.hotspot_device)
+        self._start_wifi_tethering(WIFI_CONFIG_APBAND_5G)
+        self._connect_disconnect_devices()
+        wutils.stop_wifi_tethering(self.hotspot_device)
+
+    @test_tracker_info(uuid="7edfb220-37f8-42ea-8d7c-39712fbe9be5")
+    def test_wifi_tethering_2ghz_ping_hotspot_interfaces(self):
+        """ Steps:
+
+            1. Start wifi hotspot with 2ghz band
+            2. Connect tethered device to hotspot device
+            3. Ping 'wlan0' and 'rmnet_data' interface's IPv4
+               and IPv6 interfaces on hotspot device from tethered device
+        """
+        wutils.toggle_wifi_off_and_on(self.hotspot_device)
+        self._start_wifi_tethering(WIFI_CONFIG_APBAND_2G)
+        wutils.wifi_connect(self.tethered_devices[0], self.network)
+        result = self._ping_hotspot_interfaces_from_tethered_device(
+            self.tethered_devices[0])
+        wutils.stop_wifi_tethering(self.hotspot_device)
+        return result
+
+    @test_tracker_info(uuid="17e450f4-795f-4e67-adab-984940dffedc")
+    def test_wifi_tethering_5ghz_ping_hotspot_interfaces(self):
+        """ Steps:
+
+            1. Start wifi hotspot with 5ghz band
+            2. Connect tethered device to hotspot device
+            3. Ping 'wlan0' and 'rmnet_data' interface's IPv4
+               and IPv6 interfaces on hotspot device from tethered device
+        """
+        wutils.toggle_wifi_off_and_on(self.hotspot_device)
+        self._start_wifi_tethering(WIFI_CONFIG_APBAND_5G)
+        wutils.wifi_connect(self.tethered_devices[0], self.network)
+        result = self._ping_hotspot_interfaces_from_tethered_device(
+            self.tethered_devices[0])
+        wutils.stop_wifi_tethering(self.hotspot_device)
+        return result
+
+    @test_tracker_info(uuid="d4e18031-0af0-4b29-a574-8707cd4029b7")
+    def test_wifi_tethering_verify_received_bytes(self):
+        """ Steps:
+
+            1. Start wifi hotspot and connect tethered device to it
+            2. Get the data usage on hotspot device
+            3. Download data on tethered device
+            4. Get the new data usage on hotspot device
+            5. Verify that hotspot device's data usage
+               increased by downloaded file size
+        """
+        wutils.toggle_wifi_off_and_on(self.hotspot_device)
+        dut = self.hotspot_device
+        self._start_wifi_tethering()
+        wutils.wifi_connect(self.tethered_devices[0], self.network)
+        subscriber_id = dut.droid.telephonyGetSubscriberId()
+
+        # get data usage limit
+        end_time = int(time.time() * 1000)
+        bytes_before_download = dut.droid.connectivityGetRxBytesForDevice(
+            subscriber_id, 0, end_time)
+        self.log.info("Bytes before download %s" % bytes_before_download)
+
+        # download file
+        http_file_download_by_chrome(self.tethered_devices[0],
+                                     self.download_file)
+
+        # get data usage limit after download
+        end_time = int(time.time() * 1000)
+        bytes_after_download = dut.droid.connectivityGetRxBytesForDevice(
+            subscriber_id, 0, end_time)
+        self.log.info("Bytes after download %s" % bytes_after_download)
+
+        bytes_diff = bytes_after_download - bytes_before_download
+        wutils.stop_wifi_tethering(self.hotspot_device)
+
+        # verify data usage update is correct
+        bytes_used = bytes_diff/self.convert_byte_to_mb
+        return bytes_used > self.file_size \
+            and bytes_used < self.file_size + self.data_usage_error
+
+    @test_tracker_info(uuid="07a00c96-4770-44a1-a9db-b3d02d6a12b6")
+    def test_wifi_tethering_data_usage_limit(self):
+        """ Steps:
+
+            1. Set the data usage limit to current data usage + 2MB
+            2. Start wifi tethering and connect a dut to the SSID
+            3. Download 5MB data on tethered device
+               a. file download should stop
+               b. tethered device will lose internet connectivity
+               c. data usage limit reached message should be displayed
+                  on the hotspot device
+            4. Verify data usage limit
+        """
+        wutils.toggle_wifi_off_and_on(self.hotspot_device)
+        dut = self.hotspot_device
+        data_usage_2mb = 2 * self.convert_byte_to_mb
+        subscriber_id = dut.droid.telephonyGetSubscriberId()
+
+        self._start_wifi_tethering()
+        wutils.wifi_connect(self.tethered_devices[0], self.network)
+
+        # get current data usage
+        end_time = int(time.time() * 1000)
+        old_data_usage = dut.droid.connectivityQuerySummaryForDevice(
+            subscriber_id, 0, end_time)
+
+        # set data usage limit to current usage limit + 2MB
+        dut.droid.connectivitySetDataUsageLimit(
+            subscriber_id, str(int(old_data_usage + data_usage_2mb)))
+
+        # download file - size 5MB
+        http_file_download_by_chrome(self.tethered_devices[0],
+                                     self.download_file,
+                                     timeout=120)
+        end_time = int(time.time() * 1000)
+        new_data_usage = dut.droid.connectivityQuerySummaryForDevice(
+            subscriber_id, 0, end_time)
+
+        # test network connectivity on tethered device
+        asserts.assert_true(
+            not wutils.validate_connection(self.tethered_devices[0]),
+            "Tethered device has internet connectivity after data usage"
+            "limit is reached on hotspot device")
+        dut.droid.connectivityFactoryResetNetworkPolicies(subscriber_id)
+        wutils.stop_wifi_tethering(self.hotspot_device)
+
+        old_data_usage = (old_data_usage+data_usage_2mb)/self.convert_byte_to_mb
+        new_data_usage = new_data_usage/self.convert_byte_to_mb
+
+        return (new_data_usage-old_data_usage) < self.data_usage_error
+
+    @test_tracker_info(uuid="2bc344cb-0277-4f06-b6cc-65b3972086ed")
+    def test_change_wifi_hotspot_ssid_when_hotspot_enabled(self):
+        """ Steps:
+
+            1. Start wifi tethering
+            2. Verify wifi Ap configuration
+            3. Change the SSID of the wifi hotspot while hotspot is on
+            4. Verify the new SSID in wifi ap configuration
+            5. Restart tethering and verify that the tethered device is able
+               to connect to the new SSID
+        """
+        wutils.toggle_wifi_off_and_on(self.hotspot_device)
+        dut = self.hotspot_device
+
+        # start tethering and verify the wifi ap configuration settings
+        self._start_wifi_tethering()
+        wifi_ap = dut.droid.wifiGetApConfiguration()
+        asserts.assert_true(
+            wifi_ap[wutils.WifiEnums.SSID_KEY] == \
+                self.network[wutils.WifiEnums.SSID_KEY],
+            "Configured wifi hotspot SSID did not match with the expected SSID")
+        wutils.wifi_connect(self.tethered_devices[0], self.network)
+
+        # update the wifi ap configuration with new ssid
+        config = {wutils.WifiEnums.SSID_KEY: self.new_ssid}
+        config[wutils.WifiEnums.PWD_KEY] = self.network[wutils.WifiEnums.PWD_KEY]
+        config[wutils.WifiEnums.APBAND_KEY] = WIFI_CONFIG_APBAND_2G
+        asserts.assert_true(
+            dut.droid.wifiSetWifiApConfiguration(config),
+            "Failed to update WifiAp Configuration")
+        wifi_ap = dut.droid.wifiGetApConfiguration()
+        asserts.assert_true(
+            wifi_ap[wutils.WifiEnums.SSID_KEY] == self.new_ssid,
+            "Configured wifi hotspot SSID does not match with the expected SSID")
+
+        # start wifi tethering with new wifi ap configuration
+        wutils.stop_wifi_tethering(dut)
+        dut.droid.wifiStartTrackingTetherStateChange()
+        dut.droid.connectivityStartTethering(tel_defines.TETHERING_WIFI, False)
+        try:
+            dut.ed.pop_event("ConnectivityManagerOnTetheringStarted")
+            dut.ed.wait_for_event("TetherStateChanged",
+                                  lambda x: x["data"]["ACTIVE_TETHER"], 30)
+        except:
+            asserts.fail("Didn't receive wifi tethering starting confirmation")
+        dut.droid.wifiStopTrackingTetherStateChange()
+
+        # verify dut can connect to new wifi ap configuration
+        new_network = {wutils.WifiEnums.SSID_KEY: self.new_ssid,
+                       wutils.WifiEnums.PWD_KEY: \
+                       self.network[wutils.WifiEnums.PWD_KEY]}
+        wutils.wifi_connect(self.tethered_devices[0], new_network)
+        wutils.stop_wifi_tethering(self.hotspot_device)