1#!/usr/bin/python3.4 2# 3# Copyright 2017 - 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 queue 18 19from acts import asserts 20from acts.test_decorators import test_tracker_info 21from acts.test_utils.wifi import wifi_test_utils as wutils 22from acts.test_utils.wifi.rtt import rtt_const as rconsts 23from acts.test_utils.wifi.rtt import rtt_test_utils as rutils 24from acts.test_utils.wifi.rtt.RttBaseTest import RttBaseTest 25 26 27class RangeApSupporting11McTest(RttBaseTest): 28 """Test class for RTT ranging to Access Points which support IEEE 802.11mc""" 29 30 # Number of RTT iterations 31 NUM_ITER = 10 32 33 # Time gap (in seconds) between iterations 34 TIME_BETWEEN_ITERATIONS = 0 35 36 def __init__(self, controllers): 37 RttBaseTest.__init__(self, controllers) 38 39 ############################################################################# 40 41 @test_tracker_info(uuid="6705270f-924b-4bef-b50a-0f0a7eb9ce52") 42 def test_rtt_80211mc_supporting_aps(self): 43 """Scan for APs and perform RTT only to those which support 802.11mc""" 44 dut = self.android_devices[0] 45 rtt_supporting_aps = rutils.select_best_scan_results( 46 rutils.scan_with_rtt_support_constraint(dut, True, repeat=10), 47 select_count=2) 48 dut.log.debug("RTT Supporting APs=%s", rtt_supporting_aps) 49 events = rutils.run_ranging(dut, rtt_supporting_aps, self.NUM_ITER, 50 self.TIME_BETWEEN_ITERATIONS) 51 stats = rutils.analyze_results(events, self.rtt_reference_distance_mm, 52 self.rtt_reference_distance_margin_mm, 53 self.rtt_min_expected_rssi_dbm, 54 self.lci_reference, self.lcr_reference) 55 dut.log.debug("Stats=%s", stats) 56 57 for bssid, stat in stats.items(): 58 asserts.assert_true(stat['num_no_results'] == 0, 59 "Missing (timed-out) results", extras=stats) 60 asserts.assert_false(stat['any_lci_mismatch'], 61 "LCI mismatch", extras=stats) 62 asserts.assert_false(stat['any_lcr_mismatch'], 63 "LCR mismatch", extras=stats) 64 asserts.assert_false(stat['invalid_num_attempted'], 65 "Invalid (0) number of attempts", extras=stats) 66 asserts.assert_false(stat['invalid_num_successful'], 67 "Invalid (0) number of successes", extras=stats) 68 asserts.assert_equal(stat['num_invalid_rssi'], 0, "Invalid RSSI", 69 extras=stats) 70 asserts.assert_true(stat['num_failures'] <= 71 self.rtt_max_failure_rate_two_sided_rtt_percentage 72 * stat['num_results'] / 100, 73 "Failure rate is too high", extras=stats) 74 asserts.assert_true(stat['num_range_out_of_margin'] <= 75 self.rtt_max_margin_exceeded_rate_two_sided_rtt_percentage 76 * stat['num_success_results'] / 100, 77 "Results exceeding error margin rate is too high", extras=stats) 78 asserts.explicit_pass("RTT test done", extras=stats) 79 80 ######################################################################### 81 # 82 # LEGACY API test code 83 # 84 ######################################################################### 85 86 @test_tracker_info(uuid="18be9737-2f03-4e35-9a23-f722dea7b82d") 87 def test_legacy_rtt_80211mc_supporting_aps(self): 88 """Scan for APs and perform RTT only to those which support 802.11mc - using 89 the LEGACY API!""" 90 dut = self.android_devices[0] 91 rtt_supporting_aps = rutils.select_best_scan_results( 92 rutils.scan_with_rtt_support_constraint(dut, True, repeat=10), 93 select_count=2) 94 dut.log.debug("RTT Supporting APs=%s", rtt_supporting_aps) 95 96 rtt_configs = [] 97 for ap in rtt_supporting_aps: 98 rtt_configs.append(self.rtt_config_from_scan_result(ap)) 99 dut.log.debug("RTT configs=%s", rtt_configs) 100 101 results = [] 102 num_missing = 0 103 num_failed_aborted = 0 104 for i in range(self.NUM_ITER): 105 idx = dut.droid.wifiRttStartRanging(rtt_configs) 106 event = None 107 try: 108 events = dut.ed.pop_events("WifiRttRanging%d" % idx, 30) 109 dut.log.debug("Event=%s", events) 110 for event in events: 111 if rconsts.EVENT_CB_RANGING_KEY_RESULTS in event["data"]: 112 results.append( 113 event["data"][rconsts.EVENT_CB_RANGING_KEY_RESULTS]) 114 else: 115 self.log.info("RTT failed/aborted - %s", event) 116 results.append([]) 117 num_failed_aborted = num_failed_aborted + 1 118 except queue.Empty: 119 self.log.debug("Waiting for RTT event timed out.") 120 results.append([]) 121 num_missing = num_missing + 1 122 123 # basic error checking: 124 # 1. no missing 125 # 2. no full failed/aborted (i.e. operation not even tried) 126 # 3. overall (all BSSIDs) success rate > threshold 127 asserts.assert_equal(num_missing, 0, 128 "Missing results (timeout waiting for event)", 129 extras={"data":results}) 130 asserts.assert_equal(num_failed_aborted, 0, 131 "Failed or aborted operations (not tried)", 132 extras={"data":results}) 133 134 num_results = 0 135 num_errors = 0 136 for result_group in results: 137 num_results = num_results + len(result_group) 138 for result in result_group: 139 if result["status"] != 0: 140 num_errors = num_errors + 1 141 142 extras = [results, {"num_results": num_results, "num_errors": num_errors}] 143 asserts.assert_true( 144 num_errors <= self.rtt_max_failure_rate_two_sided_rtt_percentage 145 * num_results / 100, 146 "Failure rate is too high", extras={"data":extras}) 147 asserts.explicit_pass("RTT test done", extras={"data": extras}) 148 149 def rtt_config_from_scan_result(self, scan_result): 150 """Creates an Rtt configuration based on the scan result of a network. 151 """ 152 WifiEnums = wutils.WifiEnums 153 ScanResult = WifiEnums.ScanResult 154 RttParam = WifiEnums.RttParam 155 RttBW = WifiEnums.RttBW 156 RttPreamble = WifiEnums.RttPreamble 157 RttType = WifiEnums.RttType 158 159 scan_result_channel_width_to_rtt = { 160 ScanResult.CHANNEL_WIDTH_20MHZ: RttBW.BW_20_SUPPORT, 161 ScanResult.CHANNEL_WIDTH_40MHZ: RttBW.BW_40_SUPPORT, 162 ScanResult.CHANNEL_WIDTH_80MHZ: RttBW.BW_80_SUPPORT, 163 ScanResult.CHANNEL_WIDTH_160MHZ: RttBW.BW_160_SUPPORT, 164 ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ: RttBW.BW_160_SUPPORT 165 } 166 p = {} 167 freq = scan_result[RttParam.frequency] 168 p[RttParam.frequency] = freq 169 p[RttParam.BSSID] = scan_result[WifiEnums.BSSID_KEY] 170 if freq > 5000: 171 p[RttParam.preamble] = RttPreamble.PREAMBLE_VHT 172 else: 173 p[RttParam.preamble] = RttPreamble.PREAMBLE_HT 174 cf0 = scan_result[RttParam.center_freq0] 175 if cf0 > 0: 176 p[RttParam.center_freq0] = cf0 177 cf1 = scan_result[RttParam.center_freq1] 178 if cf1 > 0: 179 p[RttParam.center_freq1] = cf1 180 cw = scan_result["channelWidth"] 181 p[RttParam.channel_width] = cw 182 p[RttParam.bandwidth] = scan_result_channel_width_to_rtt[cw] 183 if scan_result["is80211McRTTResponder"]: 184 p[RttParam.request_type] = RttType.TYPE_TWO_SIDED 185 else: 186 p[RttParam.request_type] = RttType.TYPE_ONE_SIDED 187 return p 188