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 18import time 19 20from acts import asserts 21from acts.test_utils.net import connectivity_const as cconsts 22from acts.test_utils.wifi.aware import aware_const as aconsts 23from acts.test_utils.wifi.aware import aware_test_utils as autils 24from acts.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest 25 26 27class LatencyTest(AwareBaseTest): 28 """Set of tests for Wi-Fi Aware to measure latency of Aware operations.""" 29 SERVICE_NAME = "GoogleTestServiceXY" 30 31 # number of second to 'reasonably' wait to make sure that devices synchronize 32 # with each other - useful for OOB test cases, where the OOB discovery would 33 # take some time 34 WAIT_FOR_CLUSTER = 5 35 36 def __init__(self, controllers): 37 AwareBaseTest.__init__(self, controllers) 38 39 def start_discovery_session(self, dut, session_id, is_publish, dtype): 40 """Start a discovery session 41 42 Args: 43 dut: Device under test 44 session_id: ID of the Aware session in which to start discovery 45 is_publish: True for a publish session, False for subscribe session 46 dtype: Type of the discovery session 47 48 Returns: 49 Discovery session started event. 50 """ 51 config = {} 52 config[aconsts.DISCOVERY_KEY_DISCOVERY_TYPE] = dtype 53 config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = "GoogleTestServiceXY" 54 55 if is_publish: 56 disc_id = dut.droid.wifiAwarePublish(session_id, config) 57 event_name = aconsts.SESSION_CB_ON_PUBLISH_STARTED 58 else: 59 disc_id = dut.droid.wifiAwareSubscribe(session_id, config) 60 event_name = aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED 61 62 event = autils.wait_for_event(dut, event_name) 63 return disc_id, event 64 65 def run_synchronization_latency(self, results, do_unsolicited_passive, 66 dw_24ghz, dw_5ghz, num_iterations, 67 startup_offset, timeout_period): 68 """Run the synchronization latency test with the specified DW intervals. 69 There is no direct measure of synchronization. Instead starts a discovery 70 session as soon as possible and measures both probability of discovery 71 within a timeout period and the actual discovery time (not necessarily 72 accurate). 73 74 Args: 75 results: Result array to be populated - will add results (not erase it) 76 do_unsolicited_passive: True for unsolicited/passive, False for 77 solicited/active. 78 dw_24ghz: DW interval in the 2.4GHz band. 79 dw_5ghz: DW interval in the 5GHz band. 80 startup_offset: The start-up gap (in seconds) between the two devices 81 timeout_period: Time period over which to measure synchronization 82 """ 83 key = "%s_dw24_%d_dw5_%d_offset_%d" % ( 84 "unsolicited_passive" if do_unsolicited_passive else "solicited_active", 85 dw_24ghz, dw_5ghz, startup_offset) 86 results[key] = {} 87 results[key]["num_iterations"] = num_iterations 88 89 p_dut = self.android_devices[0] 90 p_dut.pretty_name = "Publisher" 91 s_dut = self.android_devices[1] 92 s_dut.pretty_name = "Subscriber" 93 94 # override the default DW configuration 95 autils.config_power_settings(p_dut, dw_24ghz, dw_5ghz) 96 autils.config_power_settings(s_dut, dw_24ghz, dw_5ghz) 97 98 latencies = [] 99 failed_discoveries = 0 100 for i in range(num_iterations): 101 # Publisher+Subscriber: attach and wait for confirmation 102 p_id = p_dut.droid.wifiAwareAttach(False) 103 autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED) 104 time.sleep(startup_offset) 105 s_id = s_dut.droid.wifiAwareAttach(False) 106 autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED) 107 108 # start publish 109 p_disc_id, p_disc_event = self.start_discovery_session( 110 p_dut, p_id, True, aconsts.PUBLISH_TYPE_UNSOLICITED 111 if do_unsolicited_passive else aconsts.PUBLISH_TYPE_SOLICITED) 112 113 # start subscribe 114 s_disc_id, s_session_event = self.start_discovery_session( 115 s_dut, s_id, False, aconsts.SUBSCRIBE_TYPE_PASSIVE 116 if do_unsolicited_passive else aconsts.SUBSCRIBE_TYPE_ACTIVE) 117 118 # wait for discovery (allow for failures here since running lots of 119 # samples and would like to get the partial data even in the presence of 120 # errors) 121 try: 122 discovery_event = s_dut.ed.pop_event( 123 aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, timeout_period) 124 s_dut.log.info("[Subscriber] SESSION_CB_ON_SERVICE_DISCOVERED: %s", 125 discovery_event["data"]) 126 except queue.Empty: 127 s_dut.log.info("[Subscriber] Timed out while waiting for " 128 "SESSION_CB_ON_SERVICE_DISCOVERED") 129 failed_discoveries = failed_discoveries + 1 130 continue 131 finally: 132 # destroy sessions 133 p_dut.droid.wifiAwareDestroyDiscoverySession(p_disc_id) 134 s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id) 135 p_dut.droid.wifiAwareDestroy(p_id) 136 s_dut.droid.wifiAwareDestroy(s_id) 137 138 # collect latency information 139 latencies.append( 140 discovery_event["data"][aconsts.SESSION_CB_KEY_TIMESTAMP_MS] - 141 s_session_event["data"][aconsts.SESSION_CB_KEY_TIMESTAMP_MS]) 142 self.log.info("Latency #%d = %d" % (i, latencies[-1])) 143 144 autils.extract_stats( 145 s_dut, 146 data=latencies, 147 results=results[key], 148 key_prefix="", 149 log_prefix="Subscribe Session Sync/Discovery (%s, dw24=%d, dw5=%d)" % 150 ("Unsolicited/Passive" 151 if do_unsolicited_passive else "Solicited/Active", dw_24ghz, dw_5ghz)) 152 results[key]["num_failed_discovery"] = failed_discoveries 153 154 def run_discovery_latency(self, results, do_unsolicited_passive, dw_24ghz, 155 dw_5ghz, num_iterations): 156 """Run the service discovery latency test with the specified DW intervals. 157 158 Args: 159 results: Result array to be populated - will add results (not erase it) 160 do_unsolicited_passive: True for unsolicited/passive, False for 161 solicited/active. 162 dw_24ghz: DW interval in the 2.4GHz band. 163 dw_5ghz: DW interval in the 5GHz band. 164 """ 165 key = "%s_dw24_%d_dw5_%d" % ( 166 "unsolicited_passive" 167 if do_unsolicited_passive else "solicited_active", dw_24ghz, dw_5ghz) 168 results[key] = {} 169 results[key]["num_iterations"] = num_iterations 170 171 p_dut = self.android_devices[0] 172 p_dut.pretty_name = "Publisher" 173 s_dut = self.android_devices[1] 174 s_dut.pretty_name = "Subscriber" 175 176 # override the default DW configuration 177 autils.config_power_settings(p_dut, dw_24ghz, dw_5ghz) 178 autils.config_power_settings(s_dut, dw_24ghz, dw_5ghz) 179 180 # Publisher+Subscriber: attach and wait for confirmation 181 p_id = p_dut.droid.wifiAwareAttach(False) 182 autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED) 183 time.sleep(self.device_startup_offset) 184 s_id = s_dut.droid.wifiAwareAttach(False) 185 autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED) 186 187 # start publish 188 p_disc_event = self.start_discovery_session( 189 p_dut, p_id, True, aconsts.PUBLISH_TYPE_UNSOLICITED 190 if do_unsolicited_passive else aconsts.PUBLISH_TYPE_SOLICITED) 191 192 # wait for for devices to synchronize with each other - used so that first 193 # discovery isn't biased by synchronization. 194 time.sleep(self.WAIT_FOR_CLUSTER) 195 196 # loop, perform discovery, and collect latency information 197 latencies = [] 198 failed_discoveries = 0 199 for i in range(num_iterations): 200 # start subscribe 201 s_disc_id, s_session_event = self.start_discovery_session( 202 s_dut, s_id, False, aconsts.SUBSCRIBE_TYPE_PASSIVE 203 if do_unsolicited_passive else aconsts.SUBSCRIBE_TYPE_ACTIVE) 204 205 # wait for discovery (allow for failures here since running lots of 206 # samples and would like to get the partial data even in the presence of 207 # errors) 208 try: 209 discovery_event = s_dut.ed.pop_event( 210 aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, autils.EVENT_TIMEOUT) 211 except queue.Empty: 212 s_dut.log.info("[Subscriber] Timed out while waiting for " 213 "SESSION_CB_ON_SERVICE_DISCOVERED") 214 failed_discoveries = failed_discoveries + 1 215 continue 216 finally: 217 # destroy subscribe 218 s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id) 219 220 # collect latency information 221 latencies.append( 222 discovery_event["data"][aconsts.SESSION_CB_KEY_TIMESTAMP_MS] - 223 s_session_event["data"][aconsts.SESSION_CB_KEY_TIMESTAMP_MS]) 224 self.log.info("Latency #%d = %d" % (i, latencies[-1])) 225 226 autils.extract_stats( 227 s_dut, 228 data=latencies, 229 results=results[key], 230 key_prefix="", 231 log_prefix="Subscribe Session Discovery (%s, dw24=%d, dw5=%d)" % 232 ("Unsolicited/Passive" 233 if do_unsolicited_passive else "Solicited/Active", dw_24ghz, dw_5ghz)) 234 results[key]["num_failed_discovery"] = failed_discoveries 235 236 # clean up 237 p_dut.droid.wifiAwareDestroyAll() 238 s_dut.droid.wifiAwareDestroyAll() 239 240 def run_message_latency(self, results, dw_24ghz, dw_5ghz, num_iterations): 241 """Run the message tx latency test with the specified DW intervals. 242 243 Args: 244 results: Result array to be populated - will add results (not erase it) 245 dw_24ghz: DW interval in the 2.4GHz band. 246 dw_5ghz: DW interval in the 5GHz band. 247 """ 248 key = "dw24_%d_dw5_%d" % (dw_24ghz, dw_5ghz) 249 results[key] = {} 250 results[key]["num_iterations"] = num_iterations 251 252 p_dut = self.android_devices[0] 253 s_dut = self.android_devices[1] 254 255 # override the default DW configuration 256 autils.config_power_settings(p_dut, dw_24ghz, dw_5ghz) 257 autils.config_power_settings(s_dut, dw_24ghz, dw_5ghz) 258 259 # Start up a discovery session 260 (p_id, s_id, p_disc_id, s_disc_id, 261 peer_id_on_sub) = autils.create_discovery_pair( 262 p_dut, 263 s_dut, 264 p_config=autils.create_discovery_config( 265 self.SERVICE_NAME, aconsts.PUBLISH_TYPE_UNSOLICITED), 266 s_config=autils.create_discovery_config( 267 self.SERVICE_NAME, aconsts.SUBSCRIBE_TYPE_PASSIVE), 268 device_startup_offset=self.device_startup_offset) 269 270 latencies = [] 271 failed_tx = 0 272 messages_rx = 0 273 missing_rx = 0 274 corrupted_rx = 0 275 for i in range(num_iterations): 276 # send message 277 msg_s2p = "Message Subscriber -> Publisher #%d" % i 278 next_msg_id = self.get_next_msg_id() 279 s_dut.droid.wifiAwareSendMessage(s_disc_id, peer_id_on_sub, next_msg_id, 280 msg_s2p, 0) 281 282 # wait for Tx confirmation 283 try: 284 sub_tx_msg_event = s_dut.ed.pop_event( 285 aconsts.SESSION_CB_ON_MESSAGE_SENT, 2 * autils.EVENT_TIMEOUT) 286 latencies.append( 287 sub_tx_msg_event["data"][aconsts.SESSION_CB_KEY_LATENCY_MS]) 288 except queue.Empty: 289 s_dut.log.info("[Subscriber] Timed out while waiting for " 290 "SESSION_CB_ON_MESSAGE_SENT") 291 failed_tx = failed_tx + 1 292 continue 293 294 # wait for Rx confirmation (and validate contents) 295 try: 296 pub_rx_msg_event = p_dut.ed.pop_event( 297 aconsts.SESSION_CB_ON_MESSAGE_RECEIVED, 2 * autils.EVENT_TIMEOUT) 298 messages_rx = messages_rx + 1 299 if (pub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING] 300 != msg_s2p): 301 corrupted_rx = corrupted_rx + 1 302 except queue.Empty: 303 s_dut.log.info("[Publisher] Timed out while waiting for " 304 "SESSION_CB_ON_MESSAGE_RECEIVED") 305 missing_rx = missing_rx + 1 306 continue 307 308 autils.extract_stats( 309 s_dut, 310 data=latencies, 311 results=results[key], 312 key_prefix="", 313 log_prefix="Subscribe Session Discovery (dw24=%d, dw5=%d)" % 314 (dw_24ghz, dw_5ghz)) 315 results[key]["failed_tx"] = failed_tx 316 results[key]["messages_rx"] = messages_rx 317 results[key]["missing_rx"] = missing_rx 318 results[key]["corrupted_rx"] = corrupted_rx 319 320 # clean up 321 p_dut.droid.wifiAwareDestroyAll() 322 s_dut.droid.wifiAwareDestroyAll() 323 324 def run_ndp_oob_latency(self, results, dw_24ghz, dw_5ghz, num_iterations): 325 """Runs the NDP setup with OOB (out-of-band) discovery latency test. 326 327 Args: 328 results: Result array to be populated - will add results (not erase it) 329 dw_24ghz: DW interval in the 2.4GHz band. 330 dw_5ghz: DW interval in the 5GHz band. 331 """ 332 key_avail = "on_avail_dw24_%d_dw5_%d" % (dw_24ghz, dw_5ghz) 333 key_link_props = "link_props_dw24_%d_dw5_%d" % (dw_24ghz, dw_5ghz) 334 results[key_avail] = {} 335 results[key_link_props] = {} 336 results[key_avail]["num_iterations"] = num_iterations 337 338 init_dut = self.android_devices[0] 339 init_dut.pretty_name = 'Initiator' 340 resp_dut = self.android_devices[1] 341 resp_dut.pretty_name = 'Responder' 342 343 # override the default DW configuration 344 autils.config_power_settings(init_dut, dw_24ghz, dw_5ghz) 345 autils.config_power_settings(resp_dut, dw_24ghz, dw_5ghz) 346 347 # Initiator+Responder: attach and wait for confirmation & identity 348 init_id = init_dut.droid.wifiAwareAttach(True) 349 autils.wait_for_event(init_dut, aconsts.EVENT_CB_ON_ATTACHED) 350 init_ident_event = autils.wait_for_event(init_dut, 351 aconsts.EVENT_CB_ON_IDENTITY_CHANGED) 352 init_mac = init_ident_event['data']['mac'] 353 time.sleep(self.device_startup_offset) 354 resp_id = resp_dut.droid.wifiAwareAttach(True) 355 autils.wait_for_event(resp_dut, aconsts.EVENT_CB_ON_ATTACHED) 356 resp_ident_event = autils.wait_for_event(resp_dut, 357 aconsts.EVENT_CB_ON_IDENTITY_CHANGED) 358 resp_mac = resp_ident_event['data']['mac'] 359 360 # wait for for devices to synchronize with each other - there are no other 361 # mechanisms to make sure this happens for OOB discovery (except retrying 362 # to execute the data-path request) 363 time.sleep(autils.WAIT_FOR_CLUSTER) 364 365 on_available_latencies = [] 366 link_props_latencies = [] 367 ndp_setup_failures = 0 368 for i in range(num_iterations): 369 # Responder: request network 370 resp_req_key = autils.request_network( 371 resp_dut, 372 resp_dut.droid.wifiAwareCreateNetworkSpecifierOob( 373 resp_id, aconsts.DATA_PATH_RESPONDER, init_mac, None)) 374 375 # Initiator: request network 376 init_req_key = autils.request_network( 377 init_dut, 378 init_dut.droid.wifiAwareCreateNetworkSpecifierOob( 379 init_id, aconsts.DATA_PATH_INITIATOR, resp_mac, None)) 380 381 # Initiator & Responder: wait for network formation 382 got_on_available = False 383 got_on_link_props = False 384 while not got_on_available or not got_on_link_props: 385 try: 386 nc_event = init_dut.ed.pop_event(cconsts.EVENT_NETWORK_CALLBACK, 387 autils.EVENT_NDP_TIMEOUT) 388 if nc_event["data"][ 389 cconsts.NETWORK_CB_KEY_EVENT] == cconsts.NETWORK_CB_AVAILABLE: 390 got_on_available = True 391 on_available_latencies.append( 392 nc_event["data"][cconsts.NETWORK_CB_KEY_CURRENT_TS] - 393 nc_event["data"][cconsts.NETWORK_CB_KEY_CREATE_TS]) 394 elif (nc_event["data"][cconsts.NETWORK_CB_KEY_EVENT] == 395 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED): 396 got_on_link_props = True 397 link_props_latencies.append( 398 nc_event["data"][cconsts.NETWORK_CB_KEY_CURRENT_TS] - 399 nc_event["data"][cconsts.NETWORK_CB_KEY_CREATE_TS]) 400 except queue.Empty: 401 ndp_setup_failures = ndp_setup_failures + 1 402 init_dut.log.info("[Initiator] Timed out while waiting for " 403 "EVENT_NETWORK_CALLBACK") 404 break 405 406 # clean-up 407 init_dut.droid.connectivityUnregisterNetworkCallback(init_req_key) 408 resp_dut.droid.connectivityUnregisterNetworkCallback(resp_req_key) 409 410 # wait to make sure previous NDP terminated, otherwise its termination 411 # time will be counted in the setup latency! 412 time.sleep(2) 413 414 autils.extract_stats( 415 init_dut, 416 data=on_available_latencies, 417 results=results[key_avail], 418 key_prefix="", 419 log_prefix="NDP setup OnAvailable(dw24=%d, dw5=%d)" % (dw_24ghz, 420 dw_5ghz)) 421 autils.extract_stats( 422 init_dut, 423 data=link_props_latencies, 424 results=results[key_link_props], 425 key_prefix="", 426 log_prefix="NDP setup OnLinkProperties (dw24=%d, dw5=%d)" % (dw_24ghz, 427 dw_5ghz)) 428 results[key_avail]["ndp_setup_failures"] = ndp_setup_failures 429 430 def run_end_to_end_latency(self, results, dw_24ghz, dw_5ghz, num_iterations, 431 startup_offset, include_setup): 432 """Measure the latency for end-to-end communication link setup: 433 - Start Aware 434 - Discovery 435 - Message from Sub -> Pub 436 - Message from Pub -> Sub 437 - NDP setup 438 439 Args: 440 results: Result array to be populated - will add results (not erase it) 441 dw_24ghz: DW interval in the 2.4GHz band. 442 dw_5ghz: DW interval in the 5GHz band. 443 startup_offset: The start-up gap (in seconds) between the two devices 444 include_setup: True to include the cluster setup in the latency 445 measurements. 446 """ 447 key = "dw24_%d_dw5_%d" % (dw_24ghz, dw_5ghz) 448 results[key] = {} 449 results[key]["num_iterations"] = num_iterations 450 451 p_dut = self.android_devices[0] 452 p_dut.pretty_name = "Publisher" 453 s_dut = self.android_devices[1] 454 s_dut.pretty_name = "Subscriber" 455 456 # override the default DW configuration 457 autils.config_power_settings(p_dut, dw_24ghz, dw_5ghz) 458 autils.config_power_settings(s_dut, dw_24ghz, dw_5ghz) 459 460 latencies = [] 461 462 # allow for failures here since running lots of samples and would like to 463 # get the partial data even in the presence of errors 464 failures = 0 465 466 if not include_setup: 467 # Publisher+Subscriber: attach and wait for confirmation 468 p_id = p_dut.droid.wifiAwareAttach(False) 469 autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED) 470 time.sleep(startup_offset) 471 s_id = s_dut.droid.wifiAwareAttach(False) 472 autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED) 473 474 for i in range(num_iterations): 475 while (True): # for pseudo-goto/finalize 476 timestamp_start = time.perf_counter() 477 478 if include_setup: 479 # Publisher+Subscriber: attach and wait for confirmation 480 p_id = p_dut.droid.wifiAwareAttach(False) 481 autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED) 482 time.sleep(startup_offset) 483 s_id = s_dut.droid.wifiAwareAttach(False) 484 autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED) 485 486 # start publish 487 p_disc_id, p_disc_event = self.start_discovery_session( 488 p_dut, p_id, True, aconsts.PUBLISH_TYPE_UNSOLICITED) 489 490 # start subscribe 491 s_disc_id, s_session_event = self.start_discovery_session( 492 s_dut, s_id, False, aconsts.SUBSCRIBE_TYPE_PASSIVE) 493 494 # wait for discovery (allow for failures here since running lots of 495 # samples and would like to get the partial data even in the presence of 496 # errors) 497 try: 498 event = s_dut.ed.pop_event(aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, 499 autils.EVENT_TIMEOUT) 500 s_dut.log.info("[Subscriber] SESSION_CB_ON_SERVICE_DISCOVERED: %s", 501 event["data"]) 502 peer_id_on_sub = event['data'][aconsts.SESSION_CB_KEY_PEER_ID] 503 except queue.Empty: 504 s_dut.log.info("[Subscriber] Timed out while waiting for " 505 "SESSION_CB_ON_SERVICE_DISCOVERED") 506 failures = failures + 1 507 break 508 509 # message from Sub -> Pub 510 msg_s2p = "Message Subscriber -> Publisher #%d" % i 511 next_msg_id = self.get_next_msg_id() 512 s_dut.droid.wifiAwareSendMessage(s_disc_id, peer_id_on_sub, next_msg_id, 513 msg_s2p, 0) 514 515 # wait for Tx confirmation 516 try: 517 s_dut.ed.pop_event(aconsts.SESSION_CB_ON_MESSAGE_SENT, 518 autils.EVENT_TIMEOUT) 519 except queue.Empty: 520 s_dut.log.info("[Subscriber] Timed out while waiting for " 521 "SESSION_CB_ON_MESSAGE_SENT") 522 failures = failures + 1 523 break 524 525 # wait for Rx confirmation (and validate contents) 526 try: 527 event = p_dut.ed.pop_event(aconsts.SESSION_CB_ON_MESSAGE_RECEIVED, 528 autils.EVENT_TIMEOUT) 529 peer_id_on_pub = event['data'][aconsts.SESSION_CB_KEY_PEER_ID] 530 if (event["data"][ 531 aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING] != msg_s2p): 532 p_dut.log.info("[Publisher] Corrupted input message - %s", event) 533 failures = failures + 1 534 break 535 except queue.Empty: 536 p_dut.log.info("[Publisher] Timed out while waiting for " 537 "SESSION_CB_ON_MESSAGE_RECEIVED") 538 failures = failures + 1 539 break 540 541 # message from Pub -> Sub 542 msg_p2s = "Message Publisher -> Subscriber #%d" % i 543 next_msg_id = self.get_next_msg_id() 544 p_dut.droid.wifiAwareSendMessage(p_disc_id, peer_id_on_pub, next_msg_id, 545 msg_p2s, 0) 546 547 # wait for Tx confirmation 548 try: 549 p_dut.ed.pop_event(aconsts.SESSION_CB_ON_MESSAGE_SENT, 550 autils.EVENT_TIMEOUT) 551 except queue.Empty: 552 p_dut.log.info("[Publisher] Timed out while waiting for " 553 "SESSION_CB_ON_MESSAGE_SENT") 554 failures = failures + 1 555 break 556 557 # wait for Rx confirmation (and validate contents) 558 try: 559 event = s_dut.ed.pop_event(aconsts.SESSION_CB_ON_MESSAGE_RECEIVED, 560 autils.EVENT_TIMEOUT) 561 if (event["data"][ 562 aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING] != msg_p2s): 563 s_dut.log.info("[Subscriber] Corrupted input message - %s", event) 564 failures = failures + 1 565 break 566 except queue.Empty: 567 s_dut.log.info("[Subscriber] Timed out while waiting for " 568 "SESSION_CB_ON_MESSAGE_RECEIVED") 569 failures = failures + 1 570 break 571 572 # create NDP 573 574 # Publisher: request network 575 p_req_key = autils.request_network( 576 p_dut, 577 p_dut.droid.wifiAwareCreateNetworkSpecifier(p_disc_id, 578 peer_id_on_pub, None)) 579 580 # Subscriber: request network 581 s_req_key = autils.request_network( 582 s_dut, 583 s_dut.droid.wifiAwareCreateNetworkSpecifier(s_disc_id, 584 peer_id_on_sub, None)) 585 586 # Publisher & Subscriber: wait for network formation 587 try: 588 p_net_event = autils.wait_for_event_with_keys( 589 p_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_TIMEOUT, ( 590 cconsts.NETWORK_CB_KEY_EVENT, 591 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED), 592 (cconsts.NETWORK_CB_KEY_ID, p_req_key)) 593 s_net_event = autils.wait_for_event_with_keys( 594 s_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_TIMEOUT, ( 595 cconsts.NETWORK_CB_KEY_EVENT, 596 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED), 597 (cconsts.NETWORK_CB_KEY_ID, s_req_key)) 598 except: 599 failures = failures + 1 600 break 601 602 p_aware_if = p_net_event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME] 603 s_aware_if = s_net_event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME] 604 605 p_ipv6 = \ 606 p_dut.droid.connectivityGetLinkLocalIpv6Address(p_aware_if).split("%")[ 607 0] 608 s_ipv6 = \ 609 s_dut.droid.connectivityGetLinkLocalIpv6Address(s_aware_if).split("%")[ 610 0] 611 612 p_dut.log.info("[Publisher] IF=%s, IPv6=%s", p_aware_if, p_ipv6) 613 s_dut.log.info("[Subscriber] IF=%s, IPv6=%s", s_aware_if, s_ipv6) 614 615 latencies.append(time.perf_counter() - timestamp_start) 616 break 617 618 # destroy sessions 619 p_dut.droid.wifiAwareDestroyDiscoverySession(p_disc_id) 620 s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id) 621 if include_setup: 622 p_dut.droid.wifiAwareDestroy(p_id) 623 s_dut.droid.wifiAwareDestroy(s_id) 624 625 autils.extract_stats( 626 p_dut, 627 data=latencies, 628 results=results[key], 629 key_prefix="", 630 log_prefix="End-to-End(dw24=%d, dw5=%d)" % (dw_24ghz, dw_5ghz)) 631 results[key]["failures"] = failures 632 633 634 ######################################################################## 635 636 def test_synchronization_default_dws(self): 637 """Measure the device synchronization for default dws. Loop over values 638 from 0 to 4 seconds.""" 639 results = {} 640 for startup_offset in range(5): 641 self.run_synchronization_latency( 642 results=results, 643 do_unsolicited_passive=True, 644 dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE, 645 dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE, 646 num_iterations=10, 647 startup_offset=startup_offset, 648 timeout_period=20) 649 asserts.explicit_pass( 650 "test_synchronization_default_dws finished", extras=results) 651 652 def test_synchronization_non_interactive_dws(self): 653 """Measure the device synchronization for non-interactive dws. Loop over 654 values from 0 to 4 seconds.""" 655 results = {} 656 for startup_offset in range(5): 657 self.run_synchronization_latency( 658 results=results, 659 do_unsolicited_passive=True, 660 dw_24ghz=aconsts.POWER_DW_24_NON_INTERACTIVE, 661 dw_5ghz=aconsts.POWER_DW_5_NON_INTERACTIVE, 662 num_iterations=10, 663 startup_offset=startup_offset, 664 timeout_period=20) 665 asserts.explicit_pass( 666 "test_synchronization_non_interactive_dws finished", extras=results) 667 668 def test_discovery_latency_default_dws(self): 669 """Measure the service discovery latency with the default DW configuration. 670 """ 671 results = {} 672 self.run_discovery_latency( 673 results=results, 674 do_unsolicited_passive=True, 675 dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE, 676 dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE, 677 num_iterations=100) 678 asserts.explicit_pass( 679 "test_discovery_latency_default_parameters finished", extras=results) 680 681 def test_discovery_latency_non_interactive_dws(self): 682 """Measure the service discovery latency with the DW configuration for non 683 -interactive mode (lower power).""" 684 results = {} 685 self.run_discovery_latency( 686 results=results, 687 do_unsolicited_passive=True, 688 dw_24ghz=aconsts.POWER_DW_24_NON_INTERACTIVE, 689 dw_5ghz=aconsts.POWER_DW_5_NON_INTERACTIVE, 690 num_iterations=100) 691 asserts.explicit_pass( 692 "test_discovery_latency_non_interactive_dws finished", extras=results) 693 694 def test_discovery_latency_all_dws(self): 695 """Measure the service discovery latency with all DW combinations (low 696 iteration count)""" 697 results = {} 698 for dw24 in range(1, 6): # permitted values: 1-5 699 for dw5 in range(0, 6): # permitted values: 0, 1-5 700 self.run_discovery_latency( 701 results=results, 702 do_unsolicited_passive=True, 703 dw_24ghz=dw24, 704 dw_5ghz=dw5, 705 num_iterations=10) 706 asserts.explicit_pass( 707 "test_discovery_latency_all_dws finished", extras=results) 708 709 def test_message_latency_default_dws(self): 710 """Measure the send message latency with the default DW configuration. Test 711 performed on non-queued message transmission - i.e. waiting for confirmation 712 of reception (ACK) before sending the next message.""" 713 results = {} 714 self.run_message_latency( 715 results=results, 716 dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE, 717 dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE, 718 num_iterations=100) 719 asserts.explicit_pass( 720 "test_message_latency_default_dws finished", extras=results) 721 722 def test_message_latency_non_interactive_dws(self): 723 """Measure the send message latency with the DW configuration for 724 non-interactive mode. Test performed on non-queued message transmission - 725 i.e. waiting for confirmation of reception (ACK) before sending the next 726 message.""" 727 results = {} 728 self.run_message_latency( 729 results=results, 730 dw_24ghz=aconsts.POWER_DW_24_NON_INTERACTIVE, 731 dw_5ghz=aconsts.POWER_DW_5_NON_INTERACTIVE, 732 num_iterations=100) 733 asserts.explicit_pass( 734 "test_message_latency_non_interactive_dws finished", extras=results) 735 736 def test_oob_ndp_setup_latency_default_dws(self): 737 """Measure the NDP setup latency with the default DW configuration. The 738 NDP is setup with OOB (out-of-band) configuration.""" 739 results = {} 740 self.run_ndp_oob_latency( 741 results=results, 742 dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE, 743 dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE, 744 num_iterations=100) 745 asserts.explicit_pass( 746 "test_ndp_setup_latency_default_dws finished", extras=results) 747 748 def test_oob_ndp_setup_latency_non_interactive_dws(self): 749 """Measure the NDP setup latency with the DW configuration for 750 non-interactive mode. The NDP is setup with OOB (out-of-band) 751 configuration""" 752 results = {} 753 self.run_ndp_oob_latency( 754 results=results, 755 dw_24ghz=aconsts.POWER_DW_24_NON_INTERACTIVE, 756 dw_5ghz=aconsts.POWER_DW_5_NON_INTERACTIVE, 757 num_iterations=100) 758 asserts.explicit_pass( 759 "test_ndp_setup_latency_non_interactive_dws finished", extras=results) 760 761 def test_end_to_end_latency_default_dws(self): 762 """Measure the latency for end-to-end communication link setup: 763 - Start Aware 764 - Discovery 765 - Message from Sub -> Pub 766 - Message from Pub -> Sub 767 - NDP setup 768 """ 769 results = {} 770 self.run_end_to_end_latency( 771 results, 772 dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE, 773 dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE, 774 num_iterations=10, 775 startup_offset=0, 776 include_setup=True) 777 asserts.explicit_pass( 778 "test_end_to_end_latency_default_dws finished", extras=results) 779 780 def test_end_to_end_latency_post_attach_default_dws(self): 781 """Measure the latency for end-to-end communication link setup without 782 the initial synchronization: 783 - Start Aware & synchronize initially 784 - Loop: 785 - Discovery 786 - Message from Sub -> Pub 787 - Message from Pub -> Sub 788 - NDP setup 789 """ 790 results = {} 791 self.run_end_to_end_latency( 792 results, 793 dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE, 794 dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE, 795 num_iterations=10, 796 startup_offset=0, 797 include_setup=False) 798 asserts.explicit_pass( 799 "test_end_to_end_latency_post_attach_default_dws finished", 800 extras=results) 801