• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3.4
2#
3#   Copyright 2018 - The Android Open Source Project
4#
5#   Licensed under the Apache License, Version 2.0 (the "License");
6#   you may not use this file except in compliance with the License.
7#   You may obtain a copy of the License at
8#
9#       http://www.apache.org/licenses/LICENSE-2.0
10#
11#   Unless required by applicable law or agreed to in writing, software
12#   distributed under the License is distributed on an "AS IS" BASIS,
13#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14#   See the License for the specific language governing permissions and
15#   limitations under the License.
16
17import logging
18import queue
19import threading
20import time
21
22import acts.base_test
23import acts_contrib.test_utils.wifi.wifi_test_utils as wutils
24import acts_contrib.test_utils.tel.tel_test_utils as tutils
25
26from acts import asserts
27from acts import signals
28from acts import utils
29from acts.controllers.iperf_server import IPerfServer
30from acts.test_decorators import test_tracker_info
31from acts_contrib.test_utils.bt.bt_test_utils import enable_bluetooth
32from acts_contrib.test_utils.bt.bt_test_utils import disable_bluetooth
33from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest
34
35WifiEnums = wutils.WifiEnums
36
37WAIT_FOR_AUTO_CONNECT = 40
38WAIT_WIFI_DISCONNECT_SEC = 60
39WAIT_BEFORE_CONNECTION = 30
40DEFAULT_TIMEOUT = 10
41PING_ADDR = 'www.google.com'
42BAND_2GHZ = 0
43BAND_5GHZ = 1
44MIN_ATTN = 0
45MAX_ATTN = 95
46
47
48class WifiStressTest(WifiBaseTest):
49    """WiFi Stress test class.
50
51    Test Bed Requirement:
52    * Two Android device
53    * Several Wi-Fi networks visible to the device, including an open Wi-Fi
54      network.
55    """
56
57    def __init__(self, configs):
58        super().__init__(configs)
59        self.enable_packet_log = True
60
61    def setup_class(self):
62        super().setup_class()
63
64        self.dut = self.android_devices[0]
65        # Note that test_stress_softAP_startup_and_stop_5g will always fail
66        # when testing with a single device.
67        if len(self.android_devices) > 1:
68            self.dut_client = self.android_devices[1]
69        else:
70            self.dut_client = None
71        wutils.wifi_test_device_init(self.dut)
72        req_params = []
73        opt_param = [
74            "open_network", "reference_networks",
75            "stress_count", "stress_hours", "attn_vals", "pno_interval",
76        ]
77        self.unpack_userparams(req_param_names=req_params,
78                               opt_param_names=opt_param)
79
80        if "AccessPoint" in self.user_params:
81            self.legacy_configure_ap_and_start(ap_count=2)
82        elif "OpenWrtAP" in self.user_params:
83            self.configure_openwrt_ap_and_start(open_network=True,
84                                                wpa_network=True,
85                                                ap_count=2)
86        asserts.assert_true(
87            len(self.reference_networks) > 0,
88            "Need at least one reference network with psk.")
89        self.wpa_2g = self.reference_networks[0]["2g"]
90        self.wpa_5g = self.reference_networks[0]["5g"]
91        self.open_2g = self.open_network[0]["2g"]
92        self.open_5g = self.open_network[0]["5g"]
93        self.networks = [self.wpa_2g, self.wpa_5g, self.open_2g, self.open_5g]
94
95        self.iperf_server_port = wutils.get_iperf_server_port()
96        try:
97          self.iperf_server = IPerfServer(self.iperf_server_port)
98          self.iperf_server.start()
99          logging.info(f"IPerf server started on {self.iperf_server_port}")
100        except Exception as e:
101          raise signals.TestFailure("Failed to start iperf3 server: %s" % e)
102
103    def setup_test(self):
104        super().setup_test()
105        self.dut.droid.wakeLockAcquireBright()
106        self.dut.droid.wakeUpNow()
107
108    def teardown_test(self):
109        super().teardown_test()
110        if self.dut.droid.wifiIsApEnabled():
111            wutils.stop_wifi_tethering(self.dut)
112        self.dut.droid.wakeLockRelease()
113        self.dut.droid.goToSleepNow()
114        wutils.reset_wifi(self.dut)
115        self.log.debug("Toggling Airplane mode OFF")
116        asserts.assert_true(
117            acts.utils.force_airplane_mode(self.dut, False),
118            "Can not turn airplane mode off: %s" % self.dut.serial)
119
120    def teardown_class(self):
121        wutils.reset_wifi(self.dut)
122        self.iperf_server.stop()
123        if "AccessPoint" in self.user_params:
124            del self.user_params["reference_networks"]
125            del self.user_params["open_network"]
126
127    """Helper Functions"""
128
129    def scan_and_connect_by_ssid(self, ad, network):
130        """Scan for network and connect using network information.
131
132        Args:
133            network: A dictionary representing the network to connect to.
134
135        """
136        ssid = network[WifiEnums.SSID_KEY]
137        wutils.start_wifi_connection_scan_and_ensure_network_found(ad, ssid)
138        wutils.wifi_connect(ad, network, num_of_tries=3)
139
140    def scan_and_connect_by_id(self, network, net_id):
141        """Scan for network and connect using network id.
142
143        Args:
144            net_id: Integer specifying the network id of the network.
145
146        """
147        ssid = network[WifiEnums.SSID_KEY]
148        wutils.start_wifi_connection_scan_and_ensure_network_found(
149            self.dut, ssid)
150        wutils.wifi_connect_by_id(self.dut, net_id)
151
152    def run_ping(self, sec):
153        """Run ping for given number of seconds.
154
155        Args:
156            sec: Time in seconds to run teh ping traffic.
157
158        """
159        self.log.info("Running ping for %d seconds" % sec)
160        result = self.dut.adb.shell("ping -w %d %s" % (sec, PING_ADDR),
161                                    timeout=sec + 1)
162        self.log.debug("Ping Result = %s" % result)
163        if "100% packet loss" in result:
164            raise signals.TestFailure("100% packet loss during ping")
165
166    def start_youtube_video(self, url=None, secs=60):
167        """Start a youtube video and check if it's playing.
168
169        Args:
170            url: The URL of the youtube video to play.
171            secs: Time to play video in seconds.
172
173        """
174        ad = self.dut
175        ad.log.info("Start a youtube video")
176        ad.ensure_screen_on()
177        video_played = False
178        for count in range(2):
179            ad.unlock_screen()
180            ad.adb.shell('am start -a android.intent.action.VIEW -d "%s"' %
181                         url)
182            if tutils.wait_for_state(ad.droid.audioIsMusicActive, True, 15, 1):
183                ad.log.info("Started a video in youtube.")
184                # Play video for given seconds.
185                time.sleep(secs)
186                video_played = True
187                break
188        if not video_played:
189            raise signals.TestFailure(
190                "Youtube video did not start. Current WiFi "
191                "state is %d" % self.dut.droid.wifiCheckState())
192
193    def add_networks(self, ad, networks):
194        """Add Wi-Fi networks to an Android device and verify the networks were
195        added correctly.
196
197        Args:
198            ad: the AndroidDevice object to add networks to.
199            networks: a list of dicts, each dict represents a Wi-Fi network.
200        """
201        for network in networks:
202            ret = ad.droid.wifiAddNetwork(network)
203            asserts.assert_true(ret != -1,
204                                "Failed to add network %s" % network)
205            ad.droid.wifiEnableNetwork(ret, 0)
206        configured_networks = ad.droid.wifiGetConfiguredNetworks()
207        self.log.debug("Configured networks: %s", configured_networks)
208
209    def connect_and_verify_connected_ssid(self, expected_con, is_pno=False):
210        """Start a scan to get the DUT connected to an AP and verify the DUT
211        is connected to the correct SSID.
212
213        Args:
214            expected_con: The expected info of the network to we expect the DUT
215                to roam to.
216        """
217        if is_pno:
218            self.dut.log.info("Wait %ss for PNO to trigger.", self.pno_interval)
219            self.dut.log.info("Move the DUT in range of %s", self.wpa_2g[WifiEnums.SSID_KEY])
220            self.attenuators[0].set_atten(MIN_ATTN)
221            time.sleep(self.pno_interval)
222            wutils.wait_for_connect(self.dut, self.wpa_2g[WifiEnums.SSID_KEY])
223            connection_info = self.dut.droid.wifiGetConnectionInfo()
224            self.log.info("Triggering network selection from %s to %s",
225                      connection_info[WifiEnums.SSID_KEY],
226                      expected_con[WifiEnums.SSID_KEY])
227        else:
228            logging.info("Move the DUT in WiFi range.")
229            self.attenuators[0].set_atten(MIN_ATTN)
230            # force start a single scan so we don't have to wait for the scheduled scan.
231            wutils.start_wifi_connection_scan_and_return_status(self.dut)
232            self.log.info("Wait 60s for network selection.")
233            time.sleep(60)
234        try:
235            self.log.info("Connecting to %s network after network selection" %
236                          self.dut.droid.wifiGetConnectionInfo())
237            expected_ssid = expected_con[WifiEnums.SSID_KEY]
238            verify_con = {WifiEnums.SSID_KEY: expected_ssid}
239            wutils.verify_wifi_connection_info(self.dut, verify_con)
240            self.log.info(
241                "Connected to %s successfully after network selection",
242                expected_ssid)
243        finally:
244            pass
245
246    def run_long_traffic(self, sec, args, q):
247        try:
248            # Use local host as iperf server.
249            self.iperf_server_address = wutils.get_host_iperf_ipv4_address(self.dut)
250            asserts.assert_true(self.iperf_server_address, "The host has no "
251                                "available IPv4 address for iperf client to "
252                                "connect to.")
253            # Start IPerf traffic
254            self.log.info("Running iperf client {}".format(args))
255            result, data = self.dut.run_iperf_client(self.iperf_server_address,
256                                                     args,
257                                                     timeout=sec + 1)
258            if not result:
259                self.log.debug("Error occurred in iPerf traffic.")
260                self.run_ping(sec)
261            q.put(True)
262        except:
263            q.put(False)
264
265    """Tests"""
266
267    @test_tracker_info(uuid="cd0016c6-58cf-4361-b551-821c0b8d2554")
268    def test_stress_toggle_wifi_state(self):
269        """Toggle WiFi state ON and OFF for N times."""
270        for count in range(self.stress_count):
271            """Test toggling wifi"""
272            try:
273                self.log.debug("Going from on to off.")
274                wutils.wifi_toggle_state(self.dut, False)
275                self.log.debug("Going from off to on.")
276                startTime = time.time()
277                wutils.wifi_toggle_state(self.dut, True)
278                startup_time = time.time() - startTime
279                self.log.debug("WiFi was enabled on the device in %s s." %
280                               startup_time)
281            except:
282                signals.TestFailure(details="",
283                                    extras={
284                                        "Iterations": "%d" % self.stress_count,
285                                        "Pass": "%d" % count
286                                    })
287        raise signals.TestPass(details="",
288                               extras={
289                                   "Iterations": "%d" % self.stress_count,
290                                   "Pass": "%d" % (count + 1)
291                               })
292
293    @test_tracker_info(uuid="4e591cec-9251-4d52-bc6e-6621507524dc")
294    def test_stress_toggle_wifi_state_bluetooth_on(self):
295        """Toggle WiFi state ON and OFF for N times when bluetooth ON."""
296        enable_bluetooth(self.dut.droid, self.dut.ed)
297        for count in range(self.stress_count):
298            """Test toggling wifi"""
299            try:
300                self.log.debug("Going from on to off.")
301                wutils.wifi_toggle_state(self.dut, False)
302                self.log.debug("Going from off to on.")
303                startTime = time.time()
304                wutils.wifi_toggle_state(self.dut, True)
305                startup_time = time.time() - startTime
306                self.log.debug("WiFi was enabled on the device in %s s." %
307                               startup_time)
308            except:
309                signals.TestFailure(details="",
310                                    extras={
311                                        "Iterations": "%d" % self.stress_count,
312                                        "Pass": "%d" % count
313                                    })
314        disable_bluetooth(self.dut.droid)
315        raise signals.TestPass(details="",
316                               extras={
317                                   "Iterations": "%d" % self.stress_count,
318                                   "Pass": "%d" % (count + 1)
319                               })
320
321    @test_tracker_info(uuid="49e3916a-9580-4bf7-a60d-a0f2545dcdde")
322    def test_stress_connect_traffic_disconnect_5g(self):
323        """Test to connect and disconnect from a network for N times.
324
325           Steps:
326               1. Scan and connect to a network.
327               2. Run IPerf to upload data for few seconds.
328               3. Disconnect.
329               4. Repeat 1-3.
330
331        """
332        for count in range(self.stress_count):
333            try:
334                net_id = self.dut.droid.wifiAddNetwork(self.wpa_5g)
335                asserts.assert_true(net_id != -1,
336                                    "Add network %r failed" % self.wpa_5g)
337                self.scan_and_connect_by_id(self.wpa_5g, net_id)
338                # Use local host as iperf server.
339                self.iperf_server_address = wutils.get_host_iperf_ipv4_address(self.dut)
340                asserts.assert_true(self.iperf_server_address, "The host has no "
341                                "available IPv4 address for iperf client to "
342                                "connect to.")
343                # Start IPerf traffic from phone to server.
344                # Upload data for 10s.
345                args = "-p {} -t {}".format(self.iperf_server_port, 10)
346                self.log.info("Running iperf client {}".format(args))
347                result, data = self.dut.run_iperf_client(
348                    self.iperf_server_address, args)
349                if not result:
350                    self.log.debug("Error occurred in iPerf traffic.")
351                    self.run_ping(10)
352                wutils.wifi_forget_network(self.dut,
353                                           self.wpa_5g[WifiEnums.SSID_KEY])
354                time.sleep(WAIT_BEFORE_CONNECTION)
355            except:
356                raise signals.TestFailure(
357                    "Network connect-disconnect failed."
358                    "Look at logs",
359                    extras={
360                        "Iterations": "%d" % self.stress_count,
361                        "Pass": "%d" % count
362                    })
363        raise signals.TestPass(details="",
364                               extras={
365                                   "Iterations": "%d" % self.stress_count,
366                                   "Pass": "%d" % (count + 1)
367                               })
368
369    @test_tracker_info(uuid="e9827dff-0755-43ec-8b50-1f9756958460")
370    def test_stress_connect_long_traffic_5g(self):
371        """Test to connect to network and hold connection for few hours.
372
373           Steps:
374               1. Scan and connect to a network.
375               2. Run IPerf to download data for few hours.
376               3. Run IPerf to upload data for few hours.
377               4. Verify no WiFi disconnects/data interruption.
378
379        """
380        self.scan_and_connect_by_ssid(self.dut, self.wpa_5g)
381        self.scan_and_connect_by_ssid(self.dut_client, self.wpa_5g)
382
383        q = queue.Queue()
384        sec = self.stress_hours * 60 * 60
385        start_time = time.time()
386
387        dl_args = "-p {} -t {} -b1M -R".format(self.iperf_server_port, sec)
388        dl = threading.Thread(target=self.run_long_traffic,
389                              args=(sec, dl_args, q))
390        dl.start()
391        dl.join()
392
393        total_time = time.time() - start_time
394        self.log.debug("WiFi state = %d" % self.dut.droid.wifiCheckState())
395        while (q.qsize() > 0):
396            if not q.get():
397                raise signals.TestFailure("Network long-connect failed.",
398                                          extras={
399                                              "Total Hours":
400                                              "%d" % self.stress_hours,
401                                              "Seconds Run": "%d" % total_time
402                                          })
403        raise signals.TestPass(details="",
404                               extras={
405                                   "Total Hours": "%d" % self.stress_hours,
406                                   "Seconds Run": "%d" % total_time
407                               })
408
409    @test_tracker_info(uuid="591d257d-9477-4a89-a220-5715c93a76a7")
410    def test_stress_youtube_5g(self):
411        """Test to connect to network and play various youtube videos.
412
413           Steps:
414               1. Scan and connect to a network.
415               2. Loop through and play a list of youtube videos.
416               3. Verify no WiFi disconnects/data interruption.
417
418        """
419        # List of Youtube 4K videos.
420        videos = [
421            "https://www.youtube.com/watch?v=TKmGU77INaM",
422            "https://www.youtube.com/watch?v=WNCl-69POro",
423            "https://www.youtube.com/watch?v=dVkK36KOcqs",
424            "https://www.youtube.com/watch?v=0wCC3aLXdOw",
425            "https://www.youtube.com/watch?v=rN6nlNC9WQA",
426            "https://www.youtube.com/watch?v=RK1K2bCg4J8"
427        ]
428        try:
429            self.scan_and_connect_by_ssid(self.dut, self.wpa_5g)
430            start_time = time.time()
431            for video in videos:
432                self.start_youtube_video(url=video, secs=10 * 60)
433        except:
434            total_time = time.time() - start_time
435            raise signals.TestFailure("The youtube stress test has failed."
436                                      "WiFi State = %d" %
437                                      self.dut.droid.wifiCheckState(),
438                                      extras={
439                                          "Total Hours": "1",
440                                          "Seconds Run": "%d" % total_time
441                                      })
442        total_time = time.time() - start_time
443        self.log.debug("WiFi state = %d" % self.dut.droid.wifiCheckState())
444        raise signals.TestPass(details="",
445                               extras={
446                                   "Total Hours": "1",
447                                   "Seconds Run": "%d" % total_time
448                               })
449
450    @test_tracker_info(uuid="d367c83e-5b00-4028-9ed8-f7b875997d13")
451    def test_stress_wifi_failover(self):
452        """This test does aggressive failover to several networks in list.
453
454           Steps:
455               1. Add and enable few networks.
456               2. Let device auto-connect.
457               3. Remove the connected network.
458               4. Repeat 2-3.
459               5. Device should connect to a network until all networks are
460                  exhausted.
461
462        """
463        for count in range(int(self.stress_count / 4)):
464            wutils.reset_wifi(self.dut)
465            ssids = list()
466            for network in self.networks:
467                ssids.append(network[WifiEnums.SSID_KEY])
468                ret = self.dut.droid.wifiAddNetwork(network)
469                asserts.assert_true(ret != -1,
470                                    "Add network %r failed" % network)
471                self.dut.droid.wifiEnableNetwork(ret, 0)
472            self.dut.droid.wifiStartScan()
473            time.sleep(WAIT_FOR_AUTO_CONNECT)
474            cur_network = self.dut.droid.wifiGetConnectionInfo()
475            cur_ssid = cur_network[WifiEnums.SSID_KEY]
476            self.log.info("Cur_ssid = %s" % cur_ssid)
477            for i in range(0, len(self.networks)):
478                self.log.debug("Forget network %s" % cur_ssid)
479                wutils.wifi_forget_network(self.dut, cur_ssid)
480                time.sleep(WAIT_FOR_AUTO_CONNECT)
481                cur_network = self.dut.droid.wifiGetConnectionInfo()
482                cur_ssid = cur_network[WifiEnums.SSID_KEY]
483                self.log.info("Cur_ssid = %s" % cur_ssid)
484                if i == len(self.networks) - 1:
485                    break
486                if cur_ssid not in ssids:
487                    raise signals.TestFailure("Device did not failover to the "
488                                              "expected network. SSID = %s" %
489                                              cur_ssid)
490            network_config = self.dut.droid.wifiGetConfiguredNetworks()
491            self.log.info("Network Config = %s" % network_config)
492            if len(network_config):
493                raise signals.TestFailure(
494                    "All the network configurations were not "
495                    "removed. Configured networks = %s" % network_config,
496                    extras={
497                        "Iterations": "%d" % self.stress_count,
498                        "Pass": "%d" % (count * 4)
499                    })
500        raise signals.TestPass(details="",
501                               extras={
502                                   "Iterations": "%d" % self.stress_count,
503                                   "Pass": "%d" % ((count + 1) * 4)
504                               })
505
506    @test_tracker_info(uuid="2c19e8d1-ac16-4d7e-b309-795144e6b956")
507    def test_stress_softAP_startup_and_stop_5g(self):
508        """Test to bring up softAP and down for N times.
509
510        Steps:
511            1. Bring up softAP on 5G.
512            2. Check for softAP on teh client device.
513            3. Turn ON WiFi.
514            4. Verify softAP is turned down and WiFi is up.
515
516        """
517        ap_ssid = "softap_" + utils.rand_ascii_str(8)
518        ap_password = utils.rand_ascii_str(8)
519        self.dut.log.info("softap setup: %s %s", ap_ssid, ap_password)
520        config = {wutils.WifiEnums.SSID_KEY: ap_ssid}
521        config[wutils.WifiEnums.PWD_KEY] = ap_password
522        # Set country code explicitly to "US".
523        wutils.set_wifi_country_code(self.dut, wutils.WifiEnums.CountryCode.US)
524        wutils.set_wifi_country_code(self.dut_client,
525                                     wutils.WifiEnums.CountryCode.US)
526        for count in range(self.stress_count):
527            initial_wifi_state = self.dut.droid.wifiCheckState()
528            wutils.start_wifi_tethering(self.dut, ap_ssid, ap_password,
529                                        WifiEnums.WIFI_CONFIG_APBAND_5G)
530            wutils.start_wifi_connection_scan_and_ensure_network_found(
531                self.dut_client, ap_ssid)
532            wutils.stop_wifi_tethering(self.dut)
533            asserts.assert_false(self.dut.droid.wifiIsApEnabled(),
534                                 "SoftAp failed to shutdown!")
535            # Give some time for WiFi to come back to previous state.
536            time.sleep(2)
537            cur_wifi_state = self.dut.droid.wifiCheckState()
538            if initial_wifi_state != cur_wifi_state:
539                raise signals.TestFailure(
540                    "Wifi state was %d before softAP and %d now!" %
541                    (initial_wifi_state, cur_wifi_state),
542                    extras={
543                        "Iterations": "%d" % self.stress_count,
544                        "Pass": "%d" % count
545                    })
546        raise signals.TestPass(details="",
547                               extras={
548                                   "Iterations": "%d" % self.stress_count,
549                                   "Pass": "%d" % (count + 1)
550                               })
551
552    @test_tracker_info(uuid="eb22e26b-95d1-4580-8c76-85dfe6a42a0f")
553    def test_stress_wifi_roaming(self):
554        AP1_network = self.reference_networks[0]["5g"]
555        AP2_network = self.reference_networks[1]["5g"]
556        wutils.set_attns(self.attenuators, "AP1_on_AP2_off")
557        self.scan_and_connect_by_ssid(self.dut, AP1_network)
558        # Reduce iteration to half because each iteration does two roams.
559        for count in range(int(self.stress_count / 2)):
560            self.log.info("Roaming iteration %d, from %s to %s", count,
561                          AP1_network, AP2_network)
562            try:
563                wutils.trigger_roaming_and_validate(self.dut, self.attenuators,
564                                                    "AP1_off_AP2_on",
565                                                    AP2_network)
566                self.log.info("Roaming iteration %d, from %s to %s", count,
567                              AP2_network, AP1_network)
568                wutils.trigger_roaming_and_validate(self.dut, self.attenuators,
569                                                    "AP1_on_AP2_off",
570                                                    AP1_network)
571            except:
572                raise signals.TestFailure("Roaming failed. Look at logs",
573                                          extras={
574                                              "Iterations":
575                                              "%d" % self.stress_count,
576                                              "Pass": "%d" % (count * 2)
577                                          })
578        raise signals.TestPass(details="",
579                               extras={
580                                   "Iterations": "%d" % self.stress_count,
581                                   "Pass": "%d" % ((count + 1) * 2)
582                               })
583
584    @test_tracker_info(uuid="e8ae8cd2-c315-4c08-9eb3-83db65b78a58")
585    def test_stress_network_selector_2G_connection(self):
586        """
587            1. Add one saved 2G network to DUT.
588            2. Move the DUT in range.
589            3. Verify the DUT is connected to the network.
590            4. Move the DUT out of range
591            5. Repeat step 2-4
592        """
593        for attenuator in self.attenuators:
594            attenuator.set_atten(95)
595        # add a saved network to DUT
596        networks = [self.reference_networks[0]['2g']]
597        self.add_networks(self.dut, networks)
598        for count in range(self.stress_count):
599            self.connect_and_verify_connected_ssid(
600                self.reference_networks[0]['2g'])
601            logging.info("Move the DUT out of WiFi range and wait 10 seconds.")
602            self.attenuators[0].set_atten(95)
603            time.sleep(10)
604        wutils.set_attns(self.attenuators, "default")
605        raise signals.TestPass(details="",
606                               extras={
607                                   "Iterations": "%d" % self.stress_count,
608                                   "Pass": "%d" % (count + 1)
609                               })
610
611    @test_tracker_info(uuid="5d5d14cb-3cd1-4b3d-8c04-0d6f4b764b6b")
612    def test_stress_pno_connection_to_2g(self):
613        """Test PNO triggered autoconnect to a network for N times
614
615        Steps:
616        1. DUT Connects to a 2GHz network.
617        2. Screen off DUT.
618        3. Attenuate 2GHz network and wait for triggering PNO.
619        4. Move the DUT in range of 2GHz network.
620        5. Check the device connected to 2GHz network automatically.
621        6. Repeat step 3-5.
622        """
623        self.scan_and_connect_by_ssid(self.dut, self.wpa_2g)
624        for attenuator in self.attenuators:
625            attenuator.set_atten(MAX_ATTN)
626        self.dut.droid.wakeLockRelease()
627        self.dut.droid.goToSleepNow()
628        self.dut.log.info("DUT screen off")
629        for count in range(self.stress_count):
630            self.connect_and_verify_connected_ssid(
631                self.reference_networks[0]['2g'], is_pno=True)
632            logging.info("Move the DUT out of range by fully attenuate %s",
633                         self.wpa_2g[WifiEnums.SSID_KEY])
634            self.attenuators[0].set_atten(MAX_ATTN)
635            logging.info("Wait for DUT to disconnect from %s",
636                         self.wpa_2g[WifiEnums.SSID_KEY])
637            wutils.wait_for_disconnect(self.dut,
638                                       timeout=WAIT_WIFI_DISCONNECT_SEC)
639            self.dut.log.info("DUT disconnected from from %s",
640                              self.wpa_2g[WifiEnums.SSID_KEY])
641        wutils.set_attns(self.attenuators, "default")
642        raise signals.TestPass(details="",
643                               extras={
644                                   "Iterations": "%d" % self.stress_count,
645                                   "Pass": "%d" % (count + 1)
646                               })
647
648    @test_tracker_info(uuid="c880e742-8d20-4134-b717-5b6d45f6c337")
649    def test_2g_sta_wifi_on_off_under_airplane_mode(self):
650        """Toggle WiFi state ON and OFF for N times when airplane mode ON."""
651        self.scan_and_connect_by_ssid(self.dut, self.wpa_2g)
652        self.log.debug("Toggling Airplane mode ON")
653        asserts.assert_true(
654            acts.utils.force_airplane_mode(self.dut, True),
655            "Can not turn on airplane mode on: %s" % self.dut.serial)
656        time.sleep(DEFAULT_TIMEOUT)
657        for count in range(self.stress_count):
658            """Test toggling wifi"""
659            try:
660                self.log.debug("Going from on to off.")
661                wutils.wifi_toggle_state(self.dut, False)
662                self.log.debug("Going from off to on.")
663                startTime = time.time()
664                wutils.wifi_toggle_state(self.dut, True)
665                startup_time = time.time() - startTime
666                self.log.debug("WiFi was enabled on the device in %s s." %
667                               startup_time)
668                time.sleep(DEFAULT_TIMEOUT)
669                # Use local host as iperf server.
670                self.iperf_server_address = wutils.get_host_iperf_ipv4_address(self.dut)
671                asserts.assert_true(self.iperf_server_address, "The host has no "
672                                "available IPv4 address for iperf client to "
673                                "connect to.")
674                # Start IPerf traffic from phone to server.
675                # Upload data for 10s.
676                args = "-p {} -t {}".format(self.iperf_server_port, 10)
677                self.log.info("Running iperf client {}".format(args))
678                result, data = self.dut.run_iperf_client(
679                    self.iperf_server_address, args)
680                if not result:
681                    self.log.debug("Error occurred in iPerf traffic.")
682                    self.run_ping(10)
683            except:
684                signals.TestFailure(details="",
685                                    extras={
686                                        "Iterations": "%d" % self.stress_count,
687                                        "Pass": "%d" % count
688                                    })
689        raise signals.TestPass(details="",
690                               extras={
691                                   "Iterations": "%d" % self.stress_count,
692                                   "Pass": "%d" % (count + 1)
693                               })
694