1#!/usr/bin/env python3
2#
3#   Copyright 2019 - 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 time
18
19from acts import asserts
20from acts.test_decorators import test_tracker_info
21from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest
22import acts.test_utils.wifi.wifi_test_utils as wutils
23
24WifiEnums = wutils.WifiEnums
25NUM_LINK_PROBES = 8
26PROBE_DELAY_SEC = 3
27ATTENUATION = 40
28
29
30class WifiLinkProbeTest(WifiBaseTest):
31    """
32    Tests sending 802.11 Probe Request frames to the currently connected AP to
33    determine if the uplink to the AP is working.
34
35    Test Bed Requirements:
36    * One Android Device
37    * One Wi-Fi network visible to the device, with an attenuator
38    """
39
40    def setup_class(self):
41        super().setup_class()
42
43        self.dut = self.android_devices[0]
44        wutils.wifi_test_device_init(self.dut)
45        self.unpack_userparams(req_param_names=[],
46                               opt_param_names=["reference_networks"])
47
48        if "AccessPoint" in self.user_params:
49            self.legacy_configure_ap_and_start()
50        self.configure_packet_capture()
51
52        asserts.assert_true(len(self.reference_networks) > 0,
53                            "Need at least one reference network with psk.")
54        self.attenuators = wutils.group_attenuators(self.attenuators)
55
56    def setup_test(self):
57        self.dut.droid.wakeLockAcquireBright()
58        self.dut.droid.wakeUpNow()
59        wutils.wifi_toggle_state(self.dut, True)
60        self.attenuators[0].set_atten(0)
61        self.attenuators[1].set_atten(0)
62        self.pcap_procs = wutils.start_pcap(
63            self.packet_capture, 'dual', self.test_name)
64
65    def teardown_test(self):
66        self.dut.droid.wakeLockRelease()
67        self.dut.droid.goToSleepNow()
68        wutils.reset_wifi(self.dut)
69
70    def on_pass(self, test_name, begin_time):
71        wutils.stop_pcap(self.packet_capture, self.pcap_procs, True)
72
73    def on_fail(self, test_name, begin_time):
74        wutils.stop_pcap(self.packet_capture, self.pcap_procs, False)
75        self.dut.take_bug_report(test_name, begin_time)
76        self.dut.cat_adb_log(test_name, begin_time)
77
78    def teardown_class(self):
79        if "AccessPoint" in self.user_params:
80            del self.user_params["reference_networks"]
81
82    # HELPER METHODS
83
84    def _test_link_probe_does_not_crash_device(self, network):
85        """
86        Connect to a network, send link probes, and verify that the device did
87        not crash. Also verify that at least one link probe succeeded.
88
89        Steps:
90        1. Connect to a network.
91        2. Send a few link probes.
92        3. Verify that at least one link probe succeeded.
93        4. Ensure that the device did not crash (by checking that it is
94           connected to the expected network).
95        """
96        wutils.wifi_connect(self.dut, network, num_of_tries=3)
97
98        results = wutils.send_link_probes(
99            self.dut, NUM_LINK_PROBES, PROBE_DELAY_SEC)
100
101        asserts.assert_true(any(result.is_success for result in results),
102                            "Expect at least 1 probe success: " + str(results))
103
104        wifi_info = self.dut.droid.wifiGetConnectionInfo()
105        expected = network[WifiEnums.SSID_KEY]
106        actual = wifi_info[WifiEnums.SSID_KEY]
107        asserts.assert_equal(
108            expected, actual,
109            "Device did not remain connected after sending link probes!")
110
111    def _test_link_probe_ap_attenuated(self, network):
112        """
113        Connect to a network, significantly attenuate the signal, and verify
114        that the device did not crash.
115
116        Steps:
117        1. Connect to a network.
118        2. Attenuate the signal.
119        3. Send a few link probes.
120        4. Stop attenuating the signal.
121        5. Ensure that the device did not crash (by checking that it is
122           connected to the expected network).
123        """
124        wutils.wifi_connect(self.dut, network, num_of_tries=3)
125        self.attenuators[0].set_atten(ATTENUATION)
126
127        wutils.send_link_probes(self.dut, NUM_LINK_PROBES, PROBE_DELAY_SEC)
128
129        # we cannot assert for failed link probe when attenuated, this would
130        # depend too much on the attenuator setup => too flaky
131
132        self.attenuators[0].set_atten(0)
133        time.sleep(PROBE_DELAY_SEC * 3)
134        wifi_info = self.dut.droid.wifiGetConnectionInfo()
135        expected = network[WifiEnums.SSID_KEY]
136        actual = wifi_info[WifiEnums.SSID_KEY]
137        asserts.assert_equal(
138            expected, actual,
139            "Device did not remain connected after sending link probes!")
140
141    # TEST METHODS
142
143    @test_tracker_info(uuid='2afd309b-6bf3-4de4-9d8a-e4d35354a2cb')
144    def test_link_probe_does_not_crash_device_2g(self):
145        network = self.reference_networks[0]["2g"]
146        self._test_link_probe_does_not_crash_device(network)
147
148    @test_tracker_info(uuid='69417a6d-7090-4dd0-81ad-55fa3f12b7b1')
149    def test_link_probe_does_not_crash_device_5g(self):
150        network = self.reference_networks[0]["5g"]
151        self._test_link_probe_does_not_crash_device(network)
152
153    @test_tracker_info(uuid='54b8ffaa-c305-4772-928d-03342c51122d')
154    def test_link_probe_ap_attenuated_2g(self):
155        network = self.reference_networks[0]["2g"]
156        self._test_link_probe_ap_attenuated(network)
157
158    @test_tracker_info(uuid='54e29fa4-ff44-4aad-8999-676b361cacf4')
159    def test_link_probe_ap_attenuated_5g(self):
160        network = self.reference_networks[0]["5g"]
161        self._test_link_probe_ap_attenuated(network)
162
163