1 #!/usr/bin/env python3.4 2 # 3 # Copyright 2016 - 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 17 import queue 18 import time 19 20 from acts import asserts 21 from acts import base_test 22 from acts import signals 23 from acts.test_decorators import test_tracker_info 24 from acts.test_utils.wifi import wifi_test_utils as wutils 25 from acts.test_utils.wifi.WifiBaseTest import WifiBaseTest 26 27 WifiChannelUS = wutils.WifiChannelUS 28 WifiEnums = wutils.WifiEnums 29 30 SCAN_EVENT_TAG = "WifiScannerScan" 31 32 33 class WifiScanResultEvents(): 34 """This class stores the setting of a scan, parameters generated 35 from starting the scan, and events reported later from the scan 36 for validation. 37 38 Attributes: 39 scan_setting: Setting used to perform the scan. 40 scan_channels: Channels used for scanning. 41 events: A list to store the scan result events. 42 """ 43 44 def __init__(self, scan_setting, scan_channels): 45 self.scan_setting = scan_setting 46 self.scan_channels = scan_channels 47 self.results_events = [] 48 49 def add_results_event(self, event): 50 self.results_events.append(event) 51 52 def check_interval(self, scan_result, scan_result_next): 53 """Verifies that the time gap between two consecutive results is within 54 expected range. 55 56 Right now it is hard coded to be 20 percent of the interval specified 57 by scan settings. This threshold can be imported from the configuration 58 file in the future if necessary later. 59 60 Note the scan result timestamps are in microseconds, but "periodInMs" 61 in scan settings is in milliseconds. 62 63 Args: 64 scan_result: A dictionary representing a scan result for a BSSID. 65 scan_result_next: A dictionary representing a scan result for a 66 BSSID, whose scan happened after scan_result. 67 """ 68 actual_interval = scan_result_next["timestamp"] - scan_result[ 69 "timestamp"] 70 expected_interval = self.scan_setting['periodInMs'] * 1000 71 delta = abs(actual_interval - expected_interval) 72 margin = expected_interval * 0.25 # 25% of the expected_interval 73 asserts.assert_true( 74 delta < margin, "The difference in time between scan %s and " 75 "%s is %dms, which is out of the expected range %sms" % ( 76 scan_result, scan_result_next, delta / 1000, 77 self.scan_setting['periodInMs'])) 78 79 def verify_one_scan_result(self, scan_result): 80 """Verifies the scan result of a single BSSID. 81 82 1. Verifies the frequency of the network is within the range requested 83 in the scan. 84 85 Args: 86 scan_result: A dictionary representing the scan result of a single 87 BSSID. 88 """ 89 freq = scan_result["frequency"] 90 asserts.assert_true( 91 freq in self.scan_channels, 92 "Frequency %d of result entry %s is out of the expected range %s." 93 % (freq, scan_result, self.scan_channels)) 94 # TODO(angli): add RSSI check. 95 96 def verify_one_scan_result_group(self, batch): 97 """Verifies a group of scan results obtained during one scan. 98 99 1. Verifies the number of BSSIDs in the batch is less than the 100 threshold set by scan settings. 101 2. Verifies each scan result for individual BSSID. 102 103 Args: 104 batch: A list of dictionaries, each dictionary represents a scan 105 result. 106 """ 107 scan_results = batch["ScanResults"] 108 actual_num_of_results = len(scan_results) 109 expected_num_of_results = self.scan_setting['numBssidsPerScan'] 110 asserts.assert_true(actual_num_of_results <= expected_num_of_results, 111 "Expected no more than %d BSSIDs, got %d." % 112 (expected_num_of_results, actual_num_of_results)) 113 for scan_result in scan_results: 114 self.verify_one_scan_result(scan_result) 115 116 def have_enough_events(self): 117 """Check if there are enough events to properly validate the scan""" 118 return len(self.results_events) >= 2 119 120 def check_scan_results(self): 121 """Validate the reported scan results against the scan settings. 122 Assert if any error detected in the results. 123 124 1. For each scan setting there should be no less than 2 events received. 125 2. For batch scan, the number of buffered results in each event should 126 be exactly what the scan setting specified. 127 3. Each scan result should contain no more BBSIDs than what scan 128 setting specified. 129 4. The frequency reported by each scan result should comply with its 130 scan setting. 131 5. The time gap between two consecutive scan results should be 132 approximately equal to the scan interval specified by the scan 133 setting. 134 A scan result looks like this: 135 { 136 'data': 137 { 138 'Type': 'onResults', 139 'ResultElapsedRealtime': 4280931, 140 'Index': 10, 141 'Results': [ 142 { 143 'Flags': 0, 144 'Id': 4, 145 'ScanResults':[ 146 { 147 'is80211McRTTResponder': False, 148 'channelWidth': 0, 149 'numUsage': 0, 150 'SSID': '"wh_ap1_2g"', 151 'timestamp': 4280078660, 152 'BSSID': '30:b5:c2:33:f9:05', 153 'frequency': 2412, 154 'distanceSdCm': 0, 155 'distanceCm': 0, 156 'centerFreq1': 0, 157 'centerFreq0': 0, 158 'venueName': '', 159 'seen': 0, 160 'operatorFriendlyName': '', 161 'level': -31, 162 'passpointNetwork': False, 163 'untrusted': False 164 } 165 ] 166 } 167 ] 168 }, 169 'time': 1491744576383, 170 'name': 'WifiScannerScan10onResults' 171 } 172 """ 173 num_of_events = len(self.results_events) 174 asserts.assert_true( 175 num_of_events >= 2, 176 "Expected more than one scan result events, got %d." % 177 num_of_events) 178 for event_idx in range(num_of_events): 179 batches = self.results_events[event_idx]["data"]["Results"] 180 actual_num_of_batches = len(batches) 181 if not actual_num_of_batches: 182 raise signals.TestFailure("Scan returned empty Results list %s " 183 "% batches") 184 # For batch scan results. 185 report_type = self.scan_setting['reportEvents'] 186 if not (report_type & WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN): 187 # Verifies that the number of buffered results matches the 188 # number defined in scan settings. 189 expected_num_of_batches = self.scan_setting['maxScansToCache'] 190 asserts.assert_true( 191 actual_num_of_batches <= expected_num_of_batches, 192 "Expected to get at most %d batches in event No.%d, got %d." 193 % (expected_num_of_batches, event_idx, 194 actual_num_of_batches)) 195 # Check the results within each event of batch scan 196 for batch_idx in range(actual_num_of_batches): 197 if not len(batches[batch_idx]["ScanResults"]): 198 raise signals.TestFailure("Scan event %d returned empty" 199 " scan results in batch %d" % (event_idx, batch_idx)) 200 # Start checking interval from the second batch. 201 if batch_idx >=1: 202 self.check_interval( 203 batches[batch_idx - 1]["ScanResults"][0], 204 batches[batch_idx]["ScanResults"][0]) 205 for batch in batches: 206 self.verify_one_scan_result_group(batch) 207 208 # Check the time gap between the first result of an event and 209 # the last result of its previous event 210 # Skip the very first event. 211 if event_idx >= 1: 212 previous_batches = self.results_events[event_idx - 1]["data"][ 213 "Results"] 214 self.check_interval(previous_batches[-1]["ScanResults"][0], 215 batches[0]["ScanResults"][0]) 216 217 218 class WifiScannerMultiScanTest(WifiBaseTest): 219 """This class is the WiFi Scanner Multi-Scan Test suite. 220 It collects a number of test cases, sets up and executes 221 the tests, and validates the scan results. 222 223 Attributes: 224 tests: A collection of tests to excute. 225 leeway: Scan interval drift time (in seconds). 226 stime_channels: Dwell time plus 2ms. 227 dut: Android device(s). 228 wifi_chs: WiFi channels according to the device model. 229 max_bugreports: Max number of bug reports allowed. 230 """ 231 232 def __init__(self, controllers): 233 WifiBaseTest.__init__(self, controllers) 234 235 def setup_class(self): 236 # If running in a setup with attenuators, set attenuation on all 237 # channels to zero. 238 if getattr(self, "attenuators", []): 239 for a in self.attenuators: 240 a.set_atten(0) 241 self.leeway = 5 # seconds, for event wait time computation 242 self.stime_channel = 47 #dwell time plus 2ms 243 self.dut = self.android_devices[0] 244 wutils.wifi_test_device_init(self.dut) 245 asserts.assert_true(self.dut.droid.wifiIsScannerSupported(), 246 "Device %s doesn't support WifiScanner, abort." % 247 self.dut.model) 248 """ Setup the required dependencies and fetch the user params from 249 config file. 250 """ 251 req_params = ("bssid_2g", "bssid_5g", "bssid_dfs", "max_bugreports") 252 opt_param = ["reference_networks"] 253 self.unpack_userparams( 254 req_param_names=req_params, opt_param_names=opt_param) 255 256 if "AccessPoint" in self.user_params: 257 self.legacy_configure_ap_and_start() 258 259 self.wifi_chs = WifiChannelUS(self.dut.model) 260 261 def on_fail(self, test_name, begin_time): 262 if self.max_bugreports > 0: 263 self.dut.take_bug_report(test_name, begin_time) 264 self.max_bugreports -= 1 265 self.dut.cat_adb_log(test_name, begin_time) 266 267 def teardown_class(self): 268 if "AccessPoint" in self.user_params: 269 del self.user_params["reference_networks"] 270 del self.user_params["open_network"] 271 272 """ Helper Functions Begin """ 273 274 def start_scan(self, scan_setting): 275 data = wutils.start_wifi_background_scan(self.dut, scan_setting) 276 idx = data["Index"] 277 # Calculate event wait time from scan setting plus leeway 278 scan_time, scan_channels = wutils.get_scan_time_and_channels( 279 self.wifi_chs, scan_setting, self.stime_channel) 280 scan_period = scan_setting['periodInMs'] 281 report_type = scan_setting['reportEvents'] 282 if report_type & WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN: 283 scan_time += scan_period 284 else: 285 max_scan = scan_setting['maxScansToCache'] 286 scan_time += max_scan * scan_period 287 wait_time = scan_time / 1000 + self.leeway 288 return idx, wait_time, scan_channels 289 290 def validate_scan_results(self, scan_results_dict): 291 # Sanity check to make sure the dict is not empty 292 asserts.assert_true(scan_results_dict, "Scan result dict is empty.") 293 for scan_result_obj in scan_results_dict.values(): 294 # Validate the results received for each scan setting 295 scan_result_obj.check_scan_results() 296 297 def wait_for_scan_events(self, wait_time_list, scan_results_dict): 298 """Poll for WifiScanner events and record them""" 299 300 # Compute the event wait time 301 event_wait_time = min(wait_time_list) 302 303 # Compute the maximum test time that guarantee that even the scan 304 # which requires the most wait time will receive at least two 305 # results. 306 max_wait_time = max(wait_time_list) 307 max_end_time = time.monotonic() + max_wait_time 308 self.log.debug("Event wait time %s seconds", event_wait_time) 309 310 try: 311 # Wait for scan results on all the caller specified bands 312 event_name = SCAN_EVENT_TAG 313 while True: 314 self.log.debug("Waiting for events '%s' for up to %s seconds", 315 event_name, event_wait_time) 316 events = self.dut.ed.pop_events(event_name, event_wait_time) 317 for event in events: 318 self.log.debug("Event received: %s", event) 319 # Event name is the key to the scan results dictionary 320 actual_event_name = event["name"] 321 asserts.assert_true( 322 actual_event_name in scan_results_dict, 323 "Expected one of these event names: %s, got '%s'." % 324 (scan_results_dict.keys(), actual_event_name)) 325 326 # TODO validate full result callbacks also 327 if event["name"].endswith("onResults"): 328 # Append the event 329 scan_results_dict[actual_event_name].add_results_event( 330 event) 331 332 # If we time out then stop waiting for events. 333 if time.monotonic() >= max_end_time: 334 break 335 # If enough scan results have been returned to validate the 336 # results then break early. 337 have_enough_events = True 338 for key in scan_results_dict: 339 if not scan_results_dict[key].have_enough_events(): 340 have_enough_events = False 341 if have_enough_events: 342 break 343 except queue.Empty: 344 asserts.fail("Event did not trigger for {} in {} seconds".format( 345 event_name, event_wait_time)) 346 347 def scan_and_validate_results(self, scan_settings): 348 """Perform WifiScanner scans and check the scan results 349 350 Procedures: 351 * Start scans for each caller specified setting 352 * Wait for at least two results for each scan 353 * Check the results received for each scan 354 """ 355 # Awlays get a clean start 356 self.dut.ed.clear_all_events() 357 358 # Start scanning with the caller specified settings and 359 # compute parameters for receiving events 360 idx_list = [] 361 wait_time_list = [] 362 scan_results_dict = {} 363 364 try: 365 for scan_setting in scan_settings: 366 self.log.debug( 367 "Scan setting: band %s, interval %s, reportEvents " 368 "%s, numBssidsPerScan %s", scan_setting["band"], 369 scan_setting["periodInMs"], scan_setting["reportEvents"], 370 scan_setting["numBssidsPerScan"]) 371 idx, wait_time, scan_chan = self.start_scan(scan_setting) 372 self.log.debug( 373 "Scan started for band %s: idx %s, wait_time %ss, scan_channels %s", 374 scan_setting["band"], idx, wait_time, scan_chan) 375 idx_list.append(idx) 376 wait_time_list.append(wait_time) 377 378 report_type = scan_setting['reportEvents'] 379 scan_results_events = WifiScanResultEvents(scan_setting, 380 scan_chan) 381 scan_results_dict["{}{}onResults".format( 382 SCAN_EVENT_TAG, idx)] = scan_results_events 383 if (scan_setting['reportEvents'] 384 & WifiEnums.REPORT_EVENT_FULL_SCAN_RESULT): 385 scan_results_dict["{}{}onFullResult".format( 386 SCAN_EVENT_TAG, idx)] = scan_results_events 387 388 self.wait_for_scan_events(wait_time_list, scan_results_dict) 389 390 # Validate the scan results 391 self.validate_scan_results(scan_results_dict) 392 393 finally: 394 # Tear down and clean up 395 for idx in idx_list: 396 self.dut.droid.wifiScannerStopBackgroundScan(idx) 397 self.dut.ed.clear_all_events() 398 399 """ Helper Functions End """ 400 """ Tests Begin """ 401 402 @test_tracker_info(uuid="d490b146-5fc3-4fc3-9958-78ba0ad63211") 403 def test_wifi_two_scans_at_same_interval(self): 404 """Perform two WifiScanner background scans, one at 2.4GHz and the other 405 at 5GHz, the same interval and number of BSSIDs per scan. 406 407 Initial Conditions: 408 * Set multiple APs broadcasting 2.4GHz and 5GHz. 409 410 Expected Results: 411 * DUT reports success for starting both scans 412 * Scan results for each callback contains only the results on the 413 frequency scanned 414 * Wait for at least two scan results and confirm that separation 415 between them approximately equals to the expected interval 416 * Number of BSSIDs doesn't exceed 417 """ 418 scan_settings = [{"band": WifiEnums.WIFI_BAND_24_GHZ, 419 "periodInMs": 10000, # ms 420 "reportEvents": 421 WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 422 "numBssidsPerScan": 24}, 423 {"band": WifiEnums.WIFI_BAND_5_GHZ, 424 "periodInMs": 10000, # ms 425 "reportEvents": 426 WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 427 "numBssidsPerScan": 24}] 428 429 self.scan_and_validate_results(scan_settings) 430 431 @test_tracker_info(uuid="0ec9a554-f942-41a9-8096-6b0b400f60b0") 432 def test_wifi_two_scans_at_different_interval(self): 433 """Perform two WifiScanner background scans, one at 2.4GHz and the other 434 at 5GHz, different interval and number of BSSIDs per scan. 435 436 Initial Conditions: 437 * Set multiple APs broadcasting 2.4GHz and 5GHz. 438 439 Expected Results: 440 * DUT reports success for starting both scans 441 * Scan results for each callback contains only the results on the 442 frequency scanned 443 * Wait for at least two scan results and confirm that separation 444 between them approximately equals to the expected interval 445 * Number of BSSIDs doesn't exceed 446 """ 447 scan_settings = [{"band": WifiEnums.WIFI_BAND_24_GHZ, 448 "periodInMs": 10000, # ms 449 "reportEvents": 450 WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 451 "numBssidsPerScan": 20}, 452 {"band": WifiEnums.WIFI_BAND_5_GHZ, 453 "periodInMs": 30000, # ms 454 "reportEvents": 455 WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 456 "numBssidsPerScan": 24}] 457 458 self.scan_and_validate_results(scan_settings) 459 460 @test_tracker_info(uuid="0d616591-0d32-4be6-8fd4-e4a5e9ccdce0") 461 def test_wifi_scans_24GHz_and_both(self): 462 """Perform two WifiScanner background scans, one at 2.4GHz and 463 the other at both 2.4GHz and 5GHz 464 465 Initial Conditions: 466 * Set multiple APs broadcasting 2.4GHz and 5GHz. 467 468 Expected Results: 469 * DUT reports success for starting both scans 470 * Scan results for each callback contains only the results on the 471 frequency scanned 472 * Wait for at least two scan results and confirm that separation 473 between them approximately equals to the expected interval 474 * Number of BSSIDs doesn't exceed 475 """ 476 scan_settings = [{"band": WifiEnums.WIFI_BAND_BOTH, 477 "periodInMs": 10000, # ms 478 "reportEvents": 479 WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 480 "numBssidsPerScan": 24}, 481 {"band": WifiEnums.WIFI_BAND_24_GHZ, 482 "periodInMs": 10000, # ms 483 "reportEvents": 484 WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 485 "numBssidsPerScan": 24}] 486 487 self.scan_and_validate_results(scan_settings) 488 489 @test_tracker_info(uuid="ddcf959e-512a-4e86-b3d3-18cebd0b22a0") 490 def test_wifi_scans_5GHz_and_both(self): 491 """Perform two WifiScanner scans, one at 5GHz and the other at both 492 2.4GHz and 5GHz 493 494 Initial Conditions: 495 * Set multiple APs broadcasting 2.4GHz and 5GHz. 496 497 Expected Results: 498 * DUT reports success for starting both scans 499 * Scan results for each callback contains only the results on the 500 frequency scanned 501 * Wait for at least two scan results and confirm that separation 502 between them approximately equals to the expected interval 503 * Number of BSSIDs doesn't exceed 504 """ 505 scan_settings = [{"band": WifiEnums.WIFI_BAND_BOTH, 506 "periodInMs": 10000, # ms 507 "reportEvents": 508 WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 509 "numBssidsPerScan": 24}, 510 {"band": WifiEnums.WIFI_BAND_5_GHZ, 511 "periodInMs": 10000, # ms 512 "reportEvents": 513 WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 514 "numBssidsPerScan": 24}] 515 516 self.scan_and_validate_results(scan_settings) 517 518 @test_tracker_info(uuid="060469f1-fc6b-4255-ab6e-b1d5b54db53d") 519 def test_wifi_scans_24GHz_5GHz_and_DFS(self): 520 """Perform three WifiScanner scans, one at 5GHz, one at 2.4GHz and the 521 other at just 5GHz DFS channels 522 523 Initial Conditions: 524 * Set multiple APs broadcasting 2.4GHz and 5GHz. 525 526 Expected Results: 527 * DUT reports success for starting both scans 528 * Scan results for each callback contains only the results on the 529 frequency scanned 530 * Wait for at least two scan results and confirm that separation 531 between them approximately equals to the expected interval 532 * Number of BSSIDs doesn't exceed 533 """ 534 scan_settings = [ 535 {"band": WifiEnums.WIFI_BAND_5_GHZ_DFS_ONLY, 536 "periodInMs": 10000, # ms 537 "reportEvents": WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 538 "numBssidsPerScan": 24}, 539 {"band": WifiEnums.WIFI_BAND_5_GHZ, 540 "periodInMs": 10000, # ms 541 "reportEvents": WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 542 "numBssidsPerScan": 24}, 543 {"band": WifiEnums.WIFI_BAND_24_GHZ, 544 "periodInMs": 30000, # ms 545 "reportEvents": WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 546 "numBssidsPerScan": 24} 547 ] 548 549 self.scan_and_validate_results(scan_settings) 550 551 @test_tracker_info(uuid="14104e98-27a0-43d5-9525-b36b65ac3957") 552 def test_wifi_scans_batch_and_24GHz(self): 553 """Perform two WifiScanner background scans, one in batch mode for both 554 bands and the other in periodic mode at 2.4GHz 555 556 Initial Conditions: 557 * Set multiple APs broadcasting 2.4GHz and 5GHz. 558 559 Expected Results: 560 * DUT reports success for starting both scans 561 * Scan results for each callback contains only the results on the 562 frequency scanned 563 * Wait for at least two scan results and confirm that separation 564 between them approximately equals to the expected interval 565 * Number of results in batch mode should match the setting 566 * Number of BSSIDs doesn't exceed 567 """ 568 scan_settings = [{"band": WifiEnums.WIFI_BAND_BOTH, 569 "periodInMs": 10000, # ms 570 "reportEvents": 571 WifiEnums.REPORT_EVENT_AFTER_BUFFER_FULL, 572 "numBssidsPerScan": 24, 573 "maxScansToCache": 2}, 574 {"band": WifiEnums.WIFI_BAND_24_GHZ, 575 "periodInMs": 10000, # ms 576 "reportEvents": 577 WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 578 "numBssidsPerScan": 24}] 579 580 self.scan_and_validate_results(scan_settings) 581 582 @test_tracker_info(uuid="cd6064b5-840b-4334-8cd4-8320a6cda52f") 583 def test_wifi_scans_batch_and_5GHz(self): 584 """Perform two WifiScanner background scans, one in batch mode for both 585 bands and the other in periodic mode at 5GHz 586 587 Initial Conditions: 588 * Set multiple APs broadcasting 2.4GHz and 5GHz. 589 590 Expected Results: 591 * DUT reports success for starting both scans 592 * Scan results for each callback contains only the results on the 593 frequency scanned 594 * Wait for at least two scan results and confirm that separation 595 between them approximately equals to the expected interval 596 * Number of results in batch mode should match the setting 597 * Number of BSSIDs doesn't exceed 598 """ 599 scan_settings = [{"band": WifiEnums.WIFI_BAND_BOTH, 600 "periodInMs": 10000, # ms 601 "reportEvents": 602 WifiEnums.REPORT_EVENT_AFTER_BUFFER_FULL, 603 "numBssidsPerScan": 24, 604 "maxScansToCache": 2}, 605 {"band": WifiEnums.WIFI_BAND_5_GHZ, 606 "periodInMs": 10000, # ms 607 "reportEvents": 608 WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 609 "numBssidsPerScan": 24}] 610 611 self.scan_and_validate_results(scan_settings) 612 613 @test_tracker_info(uuid="9f48cb0c-de87-4cd2-9e50-857579d44079") 614 def test_wifi_scans_24GHz_5GHz_full_result(self): 615 """Perform two WifiScanner background scans, one at 2.4GHz and 616 the other at 5GHz. Report full scan results. 617 618 Initial Conditions: 619 * Set multiple APs broadcasting 2.4GHz and 5GHz. 620 621 Expected Results: 622 * DUT reports success for starting both scans 623 * Scan results for each callback contains only the results on the 624 frequency scanned 625 * Wait for at least two scan results and confirm that separation 626 between them approximately equals to the expected interval 627 * Number of BSSIDs doesn't exceed 628 """ 629 scan_settings = [ 630 {"band": WifiEnums.WIFI_BAND_24_GHZ, 631 "periodInMs": 10000, # ms 632 "reportEvents": WifiEnums.REPORT_EVENT_FULL_SCAN_RESULT 633 | WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 634 "numBssidsPerScan": 24}, 635 {"band": WifiEnums.WIFI_BAND_5_GHZ, 636 "periodInMs": 10000, # ms 637 "reportEvents": WifiEnums.REPORT_EVENT_FULL_SCAN_RESULT 638 | WifiEnums.REPORT_EVENT_AFTER_EACH_SCAN, 639 "numBssidsPerScan": 24} 640 ] 641 642 self.scan_and_validate_results(scan_settings) 643 644 """ Tests End """ 645