blob: db5d416c4180b84eaecbf71e7e0e81616232dc6f [file] [log] [blame]
Etan Cohen2b1b03b2017-06-08 11:27:50 -07001#!/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
Etan Cohen8e9104f2017-06-13 08:33:52 -070021from acts.test_utils.net import connectivity_const as cconsts
Etan Cohen2b1b03b2017-06-08 11:27:50 -070022from 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):
Jaineel7e67a3f2019-08-28 15:58:49 -070028 """Set of tests for Wi-Fi Aware to measure latency of Aware operations."""
29 SERVICE_NAME = "GoogleTestServiceXY"
Etan Cohen2b1b03b2017-06-08 11:27:50 -070030
Jaineel7e67a3f2019-08-28 15:58:49 -070031 # 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
Etan Cohen2b1b03b2017-06-08 11:27:50 -070035
Jaineel7e67a3f2019-08-28 15:58:49 -070036 def __init__(self, controllers):
37 AwareBaseTest.__init__(self, controllers)
Etan Cohen2b1b03b2017-06-08 11:27:50 -070038
Jaineel7e67a3f2019-08-28 15:58:49 -070039 def start_discovery_session(self, dut, session_id, is_publish, dtype):
40 """Start a discovery session
Etan Cohen2b1b03b2017-06-08 11:27:50 -070041
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 """
Jaineel7e67a3f2019-08-28 15:58:49 -070051 config = {}
52 config[aconsts.DISCOVERY_KEY_DISCOVERY_TYPE] = dtype
53 config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = "GoogleTestServiceXY"
Etan Cohen2b1b03b2017-06-08 11:27:50 -070054
Jaineel7e67a3f2019-08-28 15:58:49 -070055 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
Etan Cohen2b1b03b2017-06-08 11:27:50 -070061
Jaineel7e67a3f2019-08-28 15:58:49 -070062 event = autils.wait_for_event(dut, event_name)
63 return disc_id, event
Etan Cohen2b1b03b2017-06-08 11:27:50 -070064
Jaineel7e67a3f2019-08-28 15:58:49 -070065 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.
Etan Cohen04b89522017-06-19 17:07:47 -070069 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 """
Jaineel7e67a3f2019-08-28 15:58:49 -070083 key = "%s_dw24_%d_dw5_%d_offset_%d" % ("unsolicited_passive"
84 if do_unsolicited_passive else
85 "solicited_active", dw_24ghz,
86 dw_5ghz, startup_offset)
87 results[key] = {}
88 results[key]["num_iterations"] = num_iterations
Etan Cohen04b89522017-06-19 17:07:47 -070089
Jaineel7e67a3f2019-08-28 15:58:49 -070090 p_dut = self.android_devices[0]
91 p_dut.pretty_name = "Publisher"
92 s_dut = self.android_devices[1]
93 s_dut.pretty_name = "Subscriber"
Etan Cohen04b89522017-06-19 17:07:47 -070094
Jaineel7e67a3f2019-08-28 15:58:49 -070095 # override the default DW configuration
96 autils.config_power_settings(p_dut, dw_24ghz, dw_5ghz)
97 autils.config_power_settings(s_dut, dw_24ghz, dw_5ghz)
Etan Cohen04b89522017-06-19 17:07:47 -070098
Jaineel7e67a3f2019-08-28 15:58:49 -070099 latencies = []
100 failed_discoveries = 0
101 for i in range(num_iterations):
102 # Publisher+Subscriber: attach and wait for confirmation
103 p_id = p_dut.droid.wifiAwareAttach(False)
104 autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED)
105 time.sleep(startup_offset)
106 s_id = s_dut.droid.wifiAwareAttach(False)
107 autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED)
Etan Cohen04b89522017-06-19 17:07:47 -0700108
Jaineel7e67a3f2019-08-28 15:58:49 -0700109 # start publish
110 p_disc_id, p_disc_event = self.start_discovery_session(
111 p_dut, p_id, True, aconsts.PUBLISH_TYPE_UNSOLICITED
112 if do_unsolicited_passive else aconsts.PUBLISH_TYPE_SOLICITED)
Etan Cohen04b89522017-06-19 17:07:47 -0700113
Jaineel7e67a3f2019-08-28 15:58:49 -0700114 # start subscribe
115 s_disc_id, s_session_event = self.start_discovery_session(
116 s_dut, s_id, False, aconsts.SUBSCRIBE_TYPE_PASSIVE
117 if do_unsolicited_passive else aconsts.SUBSCRIBE_TYPE_ACTIVE)
Etan Cohen04b89522017-06-19 17:07:47 -0700118
Jaineel7e67a3f2019-08-28 15:58:49 -0700119 # wait for discovery (allow for failures here since running lots of
120 # samples and would like to get the partial data even in the presence of
121 # errors)
122 try:
123 discovery_event = s_dut.ed.pop_event(
124 aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, timeout_period)
125 s_dut.log.info(
126 "[Subscriber] SESSION_CB_ON_SERVICE_DISCOVERED: %s",
127 discovery_event["data"])
128 except queue.Empty:
129 s_dut.log.info("[Subscriber] Timed out while waiting for "
130 "SESSION_CB_ON_SERVICE_DISCOVERED")
131 failed_discoveries = failed_discoveries + 1
132 continue
133 finally:
134 # destroy sessions
135 p_dut.droid.wifiAwareDestroyDiscoverySession(p_disc_id)
136 s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id)
137 p_dut.droid.wifiAwareDestroy(p_id)
138 s_dut.droid.wifiAwareDestroy(s_id)
Etan Cohen04b89522017-06-19 17:07:47 -0700139
Jaineel7e67a3f2019-08-28 15:58:49 -0700140 # collect latency information
141 latencies.append(
142 discovery_event["data"][aconsts.SESSION_CB_KEY_TIMESTAMP_MS] -
143 s_session_event["data"][aconsts.SESSION_CB_KEY_TIMESTAMP_MS])
144 self.log.info("Latency #%d = %d" % (i, latencies[-1]))
Etan Cohen04b89522017-06-19 17:07:47 -0700145
Jaineel7e67a3f2019-08-28 15:58:49 -0700146 autils.extract_stats(
147 s_dut,
148 data=latencies,
149 results=results[key],
150 key_prefix="",
151 log_prefix="Subscribe Session Sync/Discovery (%s, dw24=%d, dw5=%d)"
152 % ("Unsolicited/Passive" if do_unsolicited_passive else
153 "Solicited/Active", dw_24ghz, dw_5ghz))
154 results[key]["num_failed_discovery"] = failed_discoveries
Etan Cohen04b89522017-06-19 17:07:47 -0700155
Jaineel7e67a3f2019-08-28 15:58:49 -0700156 def run_discovery_latency(self, results, do_unsolicited_passive, dw_24ghz,
157 dw_5ghz, num_iterations):
158 """Run the service discovery latency test with the specified DW intervals.
Etan Cohen2b1b03b2017-06-08 11:27:50 -0700159
160 Args:
161 results: Result array to be populated - will add results (not erase it)
162 do_unsolicited_passive: True for unsolicited/passive, False for
163 solicited/active.
164 dw_24ghz: DW interval in the 2.4GHz band.
165 dw_5ghz: DW interval in the 5GHz band.
166 """
Jaineel7e67a3f2019-08-28 15:58:49 -0700167 key = "%s_dw24_%d_dw5_%d" % ("unsolicited_passive"
168 if do_unsolicited_passive else
169 "solicited_active", dw_24ghz, dw_5ghz)
170 results[key] = {}
171 results[key]["num_iterations"] = num_iterations
Etan Cohen2b1b03b2017-06-08 11:27:50 -0700172
Jaineel7e67a3f2019-08-28 15:58:49 -0700173 p_dut = self.android_devices[0]
174 p_dut.pretty_name = "Publisher"
175 s_dut = self.android_devices[1]
176 s_dut.pretty_name = "Subscriber"
Etan Cohen2b1b03b2017-06-08 11:27:50 -0700177
Jaineel7e67a3f2019-08-28 15:58:49 -0700178 # override the default DW configuration
179 autils.config_power_settings(p_dut, dw_24ghz, dw_5ghz)
180 autils.config_power_settings(s_dut, dw_24ghz, dw_5ghz)
Etan Cohen9b11b182017-06-12 09:51:12 -0700181
Jaineel7e67a3f2019-08-28 15:58:49 -0700182 # Publisher+Subscriber: attach and wait for confirmation
183 p_id = p_dut.droid.wifiAwareAttach(False)
184 autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED)
185 time.sleep(self.device_startup_offset)
186 s_id = s_dut.droid.wifiAwareAttach(False)
187 autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED)
Etan Cohen2b1b03b2017-06-08 11:27:50 -0700188
Jaineel7e67a3f2019-08-28 15:58:49 -0700189 # start publish
190 p_disc_event = self.start_discovery_session(
191 p_dut, p_id, True, aconsts.PUBLISH_TYPE_UNSOLICITED
192 if do_unsolicited_passive else aconsts.PUBLISH_TYPE_SOLICITED)
Etan Cohen2b1b03b2017-06-08 11:27:50 -0700193
Jaineel7e67a3f2019-08-28 15:58:49 -0700194 # wait for for devices to synchronize with each other - used so that first
195 # discovery isn't biased by synchronization.
196 time.sleep(self.WAIT_FOR_CLUSTER)
Etan Cohen2b1b03b2017-06-08 11:27:50 -0700197
Jaineel7e67a3f2019-08-28 15:58:49 -0700198 # loop, perform discovery, and collect latency information
199 latencies = []
200 failed_discoveries = 0
201 for i in range(num_iterations):
202 # start subscribe
203 s_disc_id, s_session_event = self.start_discovery_session(
204 s_dut, s_id, False, aconsts.SUBSCRIBE_TYPE_PASSIVE
205 if do_unsolicited_passive else aconsts.SUBSCRIBE_TYPE_ACTIVE)
Etan Cohen2b1b03b2017-06-08 11:27:50 -0700206
Jaineel7e67a3f2019-08-28 15:58:49 -0700207 # wait for discovery (allow for failures here since running lots of
208 # samples and would like to get the partial data even in the presence of
209 # errors)
210 try:
211 discovery_event = s_dut.ed.pop_event(
212 aconsts.SESSION_CB_ON_SERVICE_DISCOVERED,
213 autils.EVENT_TIMEOUT)
214 except queue.Empty:
215 s_dut.log.info("[Subscriber] Timed out while waiting for "
216 "SESSION_CB_ON_SERVICE_DISCOVERED")
217 failed_discoveries = failed_discoveries + 1
218 continue
219 finally:
220 # destroy subscribe
221 s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id)
Etan Cohen2b1b03b2017-06-08 11:27:50 -0700222
Jaineel7e67a3f2019-08-28 15:58:49 -0700223 # collect latency information
224 latencies.append(
225 discovery_event["data"][aconsts.SESSION_CB_KEY_TIMESTAMP_MS] -
226 s_session_event["data"][aconsts.SESSION_CB_KEY_TIMESTAMP_MS])
227 self.log.info("Latency #%d = %d" % (i, latencies[-1]))
Etan Cohen2b1b03b2017-06-08 11:27:50 -0700228
Jaineel7e67a3f2019-08-28 15:58:49 -0700229 autils.extract_stats(
230 s_dut,
231 data=latencies,
232 results=results[key],
233 key_prefix="",
234 log_prefix="Subscribe Session Discovery (%s, dw24=%d, dw5=%d)" %
235 ("Unsolicited/Passive" if do_unsolicited_passive else
236 "Solicited/Active", dw_24ghz, dw_5ghz))
237 results[key]["num_failed_discovery"] = failed_discoveries
Etan Cohen2b1b03b2017-06-08 11:27:50 -0700238
Jaineel7e67a3f2019-08-28 15:58:49 -0700239 # clean up
240 p_dut.droid.wifiAwareDestroyAll()
241 s_dut.droid.wifiAwareDestroyAll()
Etan Cohen9b11b182017-06-12 09:51:12 -0700242
Jaineel7e67a3f2019-08-28 15:58:49 -0700243 def run_message_latency(self, results, dw_24ghz, dw_5ghz, num_iterations):
244 """Run the message tx latency test with the specified DW intervals.
Etan Cohen7185c482017-06-12 14:30:59 -0700245
246 Args:
247 results: Result array to be populated - will add results (not erase it)
248 dw_24ghz: DW interval in the 2.4GHz band.
249 dw_5ghz: DW interval in the 5GHz band.
250 """
Jaineel7e67a3f2019-08-28 15:58:49 -0700251 key = "dw24_%d_dw5_%d" % (dw_24ghz, dw_5ghz)
252 results[key] = {}
253 results[key]["num_iterations"] = num_iterations
Etan Cohen7185c482017-06-12 14:30:59 -0700254
Jaineel7e67a3f2019-08-28 15:58:49 -0700255 p_dut = self.android_devices[0]
256 s_dut = self.android_devices[1]
Etan Cohen7185c482017-06-12 14:30:59 -0700257
Jaineel7e67a3f2019-08-28 15:58:49 -0700258 # override the default DW configuration
259 autils.config_power_settings(p_dut, dw_24ghz, dw_5ghz)
260 autils.config_power_settings(s_dut, dw_24ghz, dw_5ghz)
Etan Cohen7185c482017-06-12 14:30:59 -0700261
Jaineel7e67a3f2019-08-28 15:58:49 -0700262 # Start up a discovery session
263 (p_id, s_id, p_disc_id, s_disc_id,
264 peer_id_on_sub) = autils.create_discovery_pair(
265 p_dut,
266 s_dut,
267 p_config=autils.create_discovery_config(
268 self.SERVICE_NAME, aconsts.PUBLISH_TYPE_UNSOLICITED),
269 s_config=autils.create_discovery_config(
270 self.SERVICE_NAME, aconsts.SUBSCRIBE_TYPE_PASSIVE),
271 device_startup_offset=self.device_startup_offset)
Etan Cohen7185c482017-06-12 14:30:59 -0700272
Jaineel7e67a3f2019-08-28 15:58:49 -0700273 latencies = []
274 failed_tx = 0
275 messages_rx = 0
276 missing_rx = 0
277 corrupted_rx = 0
278 for i in range(num_iterations):
279 # send message
280 msg_s2p = "Message Subscriber -> Publisher #%d" % i
281 next_msg_id = self.get_next_msg_id()
282 s_dut.droid.wifiAwareSendMessage(s_disc_id, peer_id_on_sub,
283 next_msg_id, msg_s2p, 0)
Etan Cohen7185c482017-06-12 14:30:59 -0700284
Jaineel7e67a3f2019-08-28 15:58:49 -0700285 # wait for Tx confirmation
286 try:
287 sub_tx_msg_event = s_dut.ed.pop_event(
288 aconsts.SESSION_CB_ON_MESSAGE_SENT,
289 2 * autils.EVENT_TIMEOUT)
290 latencies.append(sub_tx_msg_event["data"][
291 aconsts.SESSION_CB_KEY_LATENCY_MS])
292 except queue.Empty:
293 s_dut.log.info("[Subscriber] Timed out while waiting for "
294 "SESSION_CB_ON_MESSAGE_SENT")
295 failed_tx = failed_tx + 1
296 continue
Etan Cohen7185c482017-06-12 14:30:59 -0700297
Jaineel7e67a3f2019-08-28 15:58:49 -0700298 # wait for Rx confirmation (and validate contents)
299 try:
300 pub_rx_msg_event = p_dut.ed.pop_event(
301 aconsts.SESSION_CB_ON_MESSAGE_RECEIVED,
302 2 * autils.EVENT_TIMEOUT)
303 messages_rx = messages_rx + 1
304 if (pub_rx_msg_event["data"]
305 [aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING] != msg_s2p):
306 corrupted_rx = corrupted_rx + 1
307 except queue.Empty:
308 s_dut.log.info("[Publisher] Timed out while waiting for "
309 "SESSION_CB_ON_MESSAGE_RECEIVED")
310 missing_rx = missing_rx + 1
311 continue
Etan Cohen7185c482017-06-12 14:30:59 -0700312
Jaineel7e67a3f2019-08-28 15:58:49 -0700313 autils.extract_stats(
314 s_dut,
315 data=latencies,
316 results=results[key],
317 key_prefix="",
318 log_prefix="Subscribe Session Discovery (dw24=%d, dw5=%d)" %
319 (dw_24ghz, dw_5ghz))
320 results[key]["failed_tx"] = failed_tx
321 results[key]["messages_rx"] = messages_rx
322 results[key]["missing_rx"] = missing_rx
323 results[key]["corrupted_rx"] = corrupted_rx
Etan Cohen7185c482017-06-12 14:30:59 -0700324
Jaineel7e67a3f2019-08-28 15:58:49 -0700325 # clean up
326 p_dut.droid.wifiAwareDestroyAll()
327 s_dut.droid.wifiAwareDestroyAll()
Etan Cohen7185c482017-06-12 14:30:59 -0700328
Jaineel7e67a3f2019-08-28 15:58:49 -0700329 def run_ndp_oob_latency(self, results, dw_24ghz, dw_5ghz, num_iterations):
330 """Runs the NDP setup with OOB (out-of-band) discovery latency test.
Etan Cohen8e9104f2017-06-13 08:33:52 -0700331
332 Args:
333 results: Result array to be populated - will add results (not erase it)
334 dw_24ghz: DW interval in the 2.4GHz band.
335 dw_5ghz: DW interval in the 5GHz band.
336 """
Jaineel7e67a3f2019-08-28 15:58:49 -0700337 key_avail = "on_avail_dw24_%d_dw5_%d" % (dw_24ghz, dw_5ghz)
338 key_link_props = "link_props_dw24_%d_dw5_%d" % (dw_24ghz, dw_5ghz)
339 results[key_avail] = {}
340 results[key_link_props] = {}
341 results[key_avail]["num_iterations"] = num_iterations
Etan Cohen8e9104f2017-06-13 08:33:52 -0700342
Jaineel7e67a3f2019-08-28 15:58:49 -0700343 init_dut = self.android_devices[0]
344 init_dut.pretty_name = 'Initiator'
345 resp_dut = self.android_devices[1]
346 resp_dut.pretty_name = 'Responder'
Etan Cohen8e9104f2017-06-13 08:33:52 -0700347
Jaineel7e67a3f2019-08-28 15:58:49 -0700348 # override the default DW configuration
349 autils.config_power_settings(init_dut, dw_24ghz, dw_5ghz)
350 autils.config_power_settings(resp_dut, dw_24ghz, dw_5ghz)
Etan Cohen8e9104f2017-06-13 08:33:52 -0700351
Jaineel7e67a3f2019-08-28 15:58:49 -0700352 # Initiator+Responder: attach and wait for confirmation & identity
353 init_id = init_dut.droid.wifiAwareAttach(True)
354 autils.wait_for_event(init_dut, aconsts.EVENT_CB_ON_ATTACHED)
355 init_ident_event = autils.wait_for_event(
356 init_dut, aconsts.EVENT_CB_ON_IDENTITY_CHANGED)
357 init_mac = init_ident_event['data']['mac']
358 time.sleep(self.device_startup_offset)
359 resp_id = resp_dut.droid.wifiAwareAttach(True)
360 autils.wait_for_event(resp_dut, aconsts.EVENT_CB_ON_ATTACHED)
361 resp_ident_event = autils.wait_for_event(
362 resp_dut, aconsts.EVENT_CB_ON_IDENTITY_CHANGED)
363 resp_mac = resp_ident_event['data']['mac']
Etan Cohen8e9104f2017-06-13 08:33:52 -0700364
Jaineel7e67a3f2019-08-28 15:58:49 -0700365 # wait for for devices to synchronize with each other - there are no other
366 # mechanisms to make sure this happens for OOB discovery (except retrying
367 # to execute the data-path request)
368 time.sleep(autils.WAIT_FOR_CLUSTER)
Etan Cohen8e9104f2017-06-13 08:33:52 -0700369
Jaineel7e67a3f2019-08-28 15:58:49 -0700370 on_available_latencies = []
371 link_props_latencies = []
372 ndp_setup_failures = 0
373 for i in range(num_iterations):
374 # Responder: request network
375 resp_req_key = autils.request_network(
376 resp_dut,
377 resp_dut.droid.wifiAwareCreateNetworkSpecifierOob(
378 resp_id, aconsts.DATA_PATH_RESPONDER, init_mac, None))
Etan Cohen8e9104f2017-06-13 08:33:52 -0700379
Jaineel7e67a3f2019-08-28 15:58:49 -0700380 # Initiator: request network
381 init_req_key = autils.request_network(
382 init_dut,
383 init_dut.droid.wifiAwareCreateNetworkSpecifierOob(
384 init_id, aconsts.DATA_PATH_INITIATOR, resp_mac, None))
Etan Cohen8e9104f2017-06-13 08:33:52 -0700385
Jaineel7e67a3f2019-08-28 15:58:49 -0700386 # Initiator & Responder: wait for network formation
387 got_on_available = False
388 got_on_link_props = False
389 while not got_on_available or not got_on_link_props:
390 try:
391 nc_event = init_dut.ed.pop_event(
392 cconsts.EVENT_NETWORK_CALLBACK,
393 autils.EVENT_NDP_TIMEOUT)
394 if nc_event["data"][
395 cconsts.
396 NETWORK_CB_KEY_EVENT] == cconsts.NETWORK_CB_AVAILABLE:
397 got_on_available = True
398 on_available_latencies.append(
399 nc_event["data"][cconsts.NETWORK_CB_KEY_CURRENT_TS]
400 -
401 nc_event["data"][cconsts.NETWORK_CB_KEY_CREATE_TS])
402 elif (nc_event["data"][cconsts.NETWORK_CB_KEY_EVENT] ==
403 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED):
404 got_on_link_props = True
405 link_props_latencies.append(
406 nc_event["data"][cconsts.NETWORK_CB_KEY_CURRENT_TS]
407 -
408 nc_event["data"][cconsts.NETWORK_CB_KEY_CREATE_TS])
409 except queue.Empty:
410 ndp_setup_failures = ndp_setup_failures + 1
411 init_dut.log.info(
412 "[Initiator] Timed out while waiting for "
413 "EVENT_NETWORK_CALLBACK")
414 break
Etan Cohen8e9104f2017-06-13 08:33:52 -0700415
Jaineel7e67a3f2019-08-28 15:58:49 -0700416 # clean-up
417 init_dut.droid.connectivityUnregisterNetworkCallback(init_req_key)
418 resp_dut.droid.connectivityUnregisterNetworkCallback(resp_req_key)
Etan Cohen8e9104f2017-06-13 08:33:52 -0700419
Jaineel7e67a3f2019-08-28 15:58:49 -0700420 # wait to make sure previous NDP terminated, otherwise its termination
421 # time will be counted in the setup latency!
422 time.sleep(2)
Etan Cohen1ff5c8e2017-07-10 18:04:38 -0700423
Jaineel7e67a3f2019-08-28 15:58:49 -0700424 autils.extract_stats(
425 init_dut,
426 data=on_available_latencies,
427 results=results[key_avail],
428 key_prefix="",
429 log_prefix="NDP setup OnAvailable(dw24=%d, dw5=%d)" % (dw_24ghz,
430 dw_5ghz))
431 autils.extract_stats(
432 init_dut,
433 data=link_props_latencies,
434 results=results[key_link_props],
435 key_prefix="",
436 log_prefix="NDP setup OnLinkProperties (dw24=%d, dw5=%d)" %
437 (dw_24ghz, dw_5ghz))
438 results[key_avail]["ndp_setup_failures"] = ndp_setup_failures
Etan Cohen8e9104f2017-06-13 08:33:52 -0700439
Jaineel7e67a3f2019-08-28 15:58:49 -0700440 def run_end_to_end_latency(self, results, dw_24ghz, dw_5ghz,
441 num_iterations, startup_offset, include_setup):
442 """Measure the latency for end-to-end communication link setup:
Etan Cohen3704c262018-05-01 14:38:23 -0700443 - Start Aware
444 - Discovery
445 - Message from Sub -> Pub
446 - Message from Pub -> Sub
447 - NDP setup
448
449 Args:
450 results: Result array to be populated - will add results (not erase it)
451 dw_24ghz: DW interval in the 2.4GHz band.
452 dw_5ghz: DW interval in the 5GHz band.
453 startup_offset: The start-up gap (in seconds) between the two devices
454 include_setup: True to include the cluster setup in the latency
455 measurements.
456 """
Jaineel7e67a3f2019-08-28 15:58:49 -0700457 key = "dw24_%d_dw5_%d" % (dw_24ghz, dw_5ghz)
458 results[key] = {}
459 results[key]["num_iterations"] = num_iterations
Etan Cohen3704c262018-05-01 14:38:23 -0700460
Jaineel7e67a3f2019-08-28 15:58:49 -0700461 p_dut = self.android_devices[0]
462 p_dut.pretty_name = "Publisher"
463 s_dut = self.android_devices[1]
464 s_dut.pretty_name = "Subscriber"
Etan Cohen3704c262018-05-01 14:38:23 -0700465
Jaineel7e67a3f2019-08-28 15:58:49 -0700466 # override the default DW configuration
467 autils.config_power_settings(p_dut, dw_24ghz, dw_5ghz)
468 autils.config_power_settings(s_dut, dw_24ghz, dw_5ghz)
Etan Cohen3704c262018-05-01 14:38:23 -0700469
Jaineel7e67a3f2019-08-28 15:58:49 -0700470 latencies = []
Etan Cohen3704c262018-05-01 14:38:23 -0700471
Jaineel7e67a3f2019-08-28 15:58:49 -0700472 # allow for failures here since running lots of samples and would like to
473 # get the partial data even in the presence of errors
474 failures = 0
Etan Cohen3704c262018-05-01 14:38:23 -0700475
Jaineel7e67a3f2019-08-28 15:58:49 -0700476 if not include_setup:
477 # Publisher+Subscriber: attach and wait for confirmation
478 p_id = p_dut.droid.wifiAwareAttach(False)
479 autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED)
480 time.sleep(startup_offset)
481 s_id = s_dut.droid.wifiAwareAttach(False)
482 autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED)
Etan Cohen3704c262018-05-01 14:38:23 -0700483
Jaineel7e67a3f2019-08-28 15:58:49 -0700484 for i in range(num_iterations):
485 while (True): # for pseudo-goto/finalize
486 timestamp_start = time.perf_counter()
Etan Cohen3704c262018-05-01 14:38:23 -0700487
Jaineel7e67a3f2019-08-28 15:58:49 -0700488 if include_setup:
489 # Publisher+Subscriber: attach and wait for confirmation
490 p_id = p_dut.droid.wifiAwareAttach(False)
491 autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED)
492 time.sleep(startup_offset)
493 s_id = s_dut.droid.wifiAwareAttach(False)
494 autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED)
Etan Cohen3704c262018-05-01 14:38:23 -0700495
Jaineel7e67a3f2019-08-28 15:58:49 -0700496 # start publish
497 p_disc_id, p_disc_event = self.start_discovery_session(
498 p_dut, p_id, True, aconsts.PUBLISH_TYPE_UNSOLICITED)
Etan Cohen3704c262018-05-01 14:38:23 -0700499
Jaineel7e67a3f2019-08-28 15:58:49 -0700500 # start subscribe
501 s_disc_id, s_session_event = self.start_discovery_session(
502 s_dut, s_id, False, aconsts.SUBSCRIBE_TYPE_PASSIVE)
Etan Cohen3704c262018-05-01 14:38:23 -0700503
Jaineel7e67a3f2019-08-28 15:58:49 -0700504 # wait for discovery (allow for failures here since running lots of
505 # samples and would like to get the partial data even in the presence of
506 # errors)
507 try:
508 event = s_dut.ed.pop_event(
509 aconsts.SESSION_CB_ON_SERVICE_DISCOVERED,
510 autils.EVENT_TIMEOUT)
511 s_dut.log.info(
512 "[Subscriber] SESSION_CB_ON_SERVICE_DISCOVERED: %s",
513 event["data"])
514 peer_id_on_sub = event['data'][
515 aconsts.SESSION_CB_KEY_PEER_ID]
516 except queue.Empty:
517 s_dut.log.info("[Subscriber] Timed out while waiting for "
518 "SESSION_CB_ON_SERVICE_DISCOVERED")
519 failures = failures + 1
520 break
Etan Cohen3704c262018-05-01 14:38:23 -0700521
Jaineel7e67a3f2019-08-28 15:58:49 -0700522 # message from Sub -> Pub
523 msg_s2p = "Message Subscriber -> Publisher #%d" % i
524 next_msg_id = self.get_next_msg_id()
525 s_dut.droid.wifiAwareSendMessage(s_disc_id, peer_id_on_sub,
526 next_msg_id, msg_s2p, 0)
Etan Cohen3704c262018-05-01 14:38:23 -0700527
Jaineel7e67a3f2019-08-28 15:58:49 -0700528 # wait for Tx confirmation
529 try:
530 s_dut.ed.pop_event(aconsts.SESSION_CB_ON_MESSAGE_SENT,
531 autils.EVENT_TIMEOUT)
532 except queue.Empty:
533 s_dut.log.info("[Subscriber] Timed out while waiting for "
534 "SESSION_CB_ON_MESSAGE_SENT")
535 failures = failures + 1
536 break
Etan Cohen3704c262018-05-01 14:38:23 -0700537
Jaineel7e67a3f2019-08-28 15:58:49 -0700538 # wait for Rx confirmation (and validate contents)
539 try:
540 event = p_dut.ed.pop_event(
541 aconsts.SESSION_CB_ON_MESSAGE_RECEIVED,
542 autils.EVENT_TIMEOUT)
543 peer_id_on_pub = event['data'][
544 aconsts.SESSION_CB_KEY_PEER_ID]
545 if (event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING]
546 != msg_s2p):
547 p_dut.log.info(
548 "[Publisher] Corrupted input message - %s", event)
549 failures = failures + 1
550 break
551 except queue.Empty:
552 p_dut.log.info("[Publisher] Timed out while waiting for "
553 "SESSION_CB_ON_MESSAGE_RECEIVED")
554 failures = failures + 1
555 break
Etan Cohen3704c262018-05-01 14:38:23 -0700556
Jaineel7e67a3f2019-08-28 15:58:49 -0700557 # message from Pub -> Sub
558 msg_p2s = "Message Publisher -> Subscriber #%d" % i
559 next_msg_id = self.get_next_msg_id()
560 p_dut.droid.wifiAwareSendMessage(p_disc_id, peer_id_on_pub,
561 next_msg_id, msg_p2s, 0)
Etan Cohen3704c262018-05-01 14:38:23 -0700562
Jaineel7e67a3f2019-08-28 15:58:49 -0700563 # wait for Tx confirmation
564 try:
565 p_dut.ed.pop_event(aconsts.SESSION_CB_ON_MESSAGE_SENT,
566 autils.EVENT_TIMEOUT)
567 except queue.Empty:
568 p_dut.log.info("[Publisher] Timed out while waiting for "
569 "SESSION_CB_ON_MESSAGE_SENT")
570 failures = failures + 1
571 break
Etan Cohen3704c262018-05-01 14:38:23 -0700572
Jaineel7e67a3f2019-08-28 15:58:49 -0700573 # wait for Rx confirmation (and validate contents)
574 try:
575 event = s_dut.ed.pop_event(
576 aconsts.SESSION_CB_ON_MESSAGE_RECEIVED,
577 autils.EVENT_TIMEOUT)
578 if (event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING]
579 != msg_p2s):
580 s_dut.log.info(
581 "[Subscriber] Corrupted input message - %s", event)
582 failures = failures + 1
583 break
584 except queue.Empty:
585 s_dut.log.info("[Subscriber] Timed out while waiting for "
586 "SESSION_CB_ON_MESSAGE_RECEIVED")
587 failures = failures + 1
588 break
Etan Cohen3704c262018-05-01 14:38:23 -0700589
Jaineel7e67a3f2019-08-28 15:58:49 -0700590 # create NDP
Etan Cohen3704c262018-05-01 14:38:23 -0700591
Jaineel7e67a3f2019-08-28 15:58:49 -0700592 # Publisher: request network
593 p_req_key = autils.request_network(
594 p_dut,
595 p_dut.droid.wifiAwareCreateNetworkSpecifier(
596 p_disc_id, peer_id_on_pub, None))
597
598 # Subscriber: request network
599 s_req_key = autils.request_network(
600 s_dut,
601 s_dut.droid.wifiAwareCreateNetworkSpecifier(
602 s_disc_id, peer_id_on_sub, None))
603
604 # Publisher & Subscriber: wait for network formation
605 try:
606 p_net_event = autils.wait_for_event_with_keys(
607 p_dut, cconsts.EVENT_NETWORK_CALLBACK,
608 autils.EVENT_TIMEOUT,
609 (cconsts.NETWORK_CB_KEY_EVENT,
610 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
611 (cconsts.NETWORK_CB_KEY_ID, p_req_key))
612 s_net_event = autils.wait_for_event_with_keys(
613 s_dut, cconsts.EVENT_NETWORK_CALLBACK,
614 autils.EVENT_TIMEOUT,
615 (cconsts.NETWORK_CB_KEY_EVENT,
616 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
617 (cconsts.NETWORK_CB_KEY_ID, s_req_key))
618 except:
619 failures = failures + 1
620 break
621
622 p_aware_if = p_net_event["data"][
623 cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
624 s_aware_if = s_net_event["data"][
625 cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
626
627 p_ipv6 = \
628 p_dut.droid.connectivityGetLinkLocalIpv6Address(p_aware_if).split("%")[
629 0]
630 s_ipv6 = \
631 s_dut.droid.connectivityGetLinkLocalIpv6Address(s_aware_if).split("%")[
632 0]
633
634 p_dut.log.info("[Publisher] IF=%s, IPv6=%s", p_aware_if,
635 p_ipv6)
636 s_dut.log.info("[Subscriber] IF=%s, IPv6=%s", s_aware_if,
637 s_ipv6)
638
639 latencies.append(time.perf_counter() - timestamp_start)
640 break
641
642 # destroy sessions
643 p_dut.droid.wifiAwareDestroyDiscoverySession(p_disc_id)
644 s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id)
645 if include_setup:
646 p_dut.droid.wifiAwareDestroy(p_id)
647 s_dut.droid.wifiAwareDestroy(s_id)
648
649 autils.extract_stats(
Etan Cohen3704c262018-05-01 14:38:23 -0700650 p_dut,
Jaineel7e67a3f2019-08-28 15:58:49 -0700651 data=latencies,
652 results=results[key],
653 key_prefix="",
654 log_prefix="End-to-End(dw24=%d, dw5=%d)" % (dw_24ghz, dw_5ghz))
655 results[key]["failures"] = failures
Etan Cohen3704c262018-05-01 14:38:23 -0700656
Jaineel7e67a3f2019-08-28 15:58:49 -0700657 ########################################################################
Etan Cohen3704c262018-05-01 14:38:23 -0700658
Jaineel7e67a3f2019-08-28 15:58:49 -0700659 def test_synchronization_default_dws(self):
660 """Measure the device synchronization for default dws. Loop over values
Etan Cohen04b89522017-06-19 17:07:47 -0700661 from 0 to 4 seconds."""
Jaineel7e67a3f2019-08-28 15:58:49 -0700662 results = {}
663 for startup_offset in range(5):
664 self.run_synchronization_latency(
665 results=results,
666 do_unsolicited_passive=True,
667 dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE,
668 dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE,
669 num_iterations=10,
670 startup_offset=startup_offset,
671 timeout_period=20)
672 asserts.explicit_pass(
673 "test_synchronization_default_dws finished", extras=results)
Etan Cohen04b89522017-06-19 17:07:47 -0700674
Jaineel7e67a3f2019-08-28 15:58:49 -0700675 def test_synchronization_non_interactive_dws(self):
676 """Measure the device synchronization for non-interactive dws. Loop over
Etan Cohen04b89522017-06-19 17:07:47 -0700677 values from 0 to 4 seconds."""
Jaineel7e67a3f2019-08-28 15:58:49 -0700678 results = {}
679 for startup_offset in range(5):
680 self.run_synchronization_latency(
681 results=results,
682 do_unsolicited_passive=True,
683 dw_24ghz=aconsts.POWER_DW_24_NON_INTERACTIVE,
684 dw_5ghz=aconsts.POWER_DW_5_NON_INTERACTIVE,
685 num_iterations=10,
686 startup_offset=startup_offset,
687 timeout_period=20)
688 asserts.explicit_pass(
689 "test_synchronization_non_interactive_dws finished",
690 extras=results)
Etan Cohen04b89522017-06-19 17:07:47 -0700691
Jaineel7e67a3f2019-08-28 15:58:49 -0700692 def test_discovery_latency_default_dws(self):
693 """Measure the service discovery latency with the default DW configuration.
Etan Cohen2b1b03b2017-06-08 11:27:50 -0700694 """
Jaineel7e67a3f2019-08-28 15:58:49 -0700695 results = {}
Etan Cohen9b11b182017-06-12 09:51:12 -0700696 self.run_discovery_latency(
697 results=results,
698 do_unsolicited_passive=True,
Jaineel7e67a3f2019-08-28 15:58:49 -0700699 dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE,
700 dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE,
701 num_iterations=100)
702 asserts.explicit_pass(
703 "test_discovery_latency_default_parameters finished",
704 extras=results)
Etan Cohen7185c482017-06-12 14:30:59 -0700705
Jaineel7e67a3f2019-08-28 15:58:49 -0700706 def test_discovery_latency_non_interactive_dws(self):
707 """Measure the service discovery latency with the DW configuration for non
708 -interactive mode (lower power)."""
709 results = {}
710 self.run_discovery_latency(
711 results=results,
712 do_unsolicited_passive=True,
713 dw_24ghz=aconsts.POWER_DW_24_NON_INTERACTIVE,
714 dw_5ghz=aconsts.POWER_DW_5_NON_INTERACTIVE,
715 num_iterations=100)
716 asserts.explicit_pass(
717 "test_discovery_latency_non_interactive_dws finished",
718 extras=results)
719
720 def test_discovery_latency_all_dws(self):
721 """Measure the service discovery latency with all DW combinations (low
722 iteration count)"""
723 results = {}
724 for dw24 in range(1, 6): # permitted values: 1-5
725 for dw5 in range(0, 6): # permitted values: 0, 1-5
726 self.run_discovery_latency(
727 results=results,
728 do_unsolicited_passive=True,
729 dw_24ghz=dw24,
730 dw_5ghz=dw5,
731 num_iterations=10)
732 asserts.explicit_pass(
733 "test_discovery_latency_all_dws finished", extras=results)
734
735 def test_message_latency_default_dws(self):
736 """Measure the send message latency with the default DW configuration. Test
Etan Cohen7185c482017-06-12 14:30:59 -0700737 performed on non-queued message transmission - i.e. waiting for confirmation
738 of reception (ACK) before sending the next message."""
Jaineel7e67a3f2019-08-28 15:58:49 -0700739 results = {}
740 self.run_message_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_message_latency_default_dws finished", extras=results)
Etan Cohen7185c482017-06-12 14:30:59 -0700747
Jaineel7e67a3f2019-08-28 15:58:49 -0700748 def test_message_latency_non_interactive_dws(self):
749 """Measure the send message latency with the DW configuration for
Etan Cohen7185c482017-06-12 14:30:59 -0700750 non-interactive mode. Test performed on non-queued message transmission -
751 i.e. waiting for confirmation of reception (ACK) before sending the next
752 message."""
Jaineel7e67a3f2019-08-28 15:58:49 -0700753 results = {}
754 self.run_message_latency(
755 results=results,
756 dw_24ghz=aconsts.POWER_DW_24_NON_INTERACTIVE,
757 dw_5ghz=aconsts.POWER_DW_5_NON_INTERACTIVE,
758 num_iterations=100)
759 asserts.explicit_pass(
760 "test_message_latency_non_interactive_dws finished",
761 extras=results)
Etan Cohen8e9104f2017-06-13 08:33:52 -0700762
Jaineel7e67a3f2019-08-28 15:58:49 -0700763 def test_oob_ndp_setup_latency_default_dws(self):
764 """Measure the NDP setup latency with the default DW configuration. The
Etan Cohen8e9104f2017-06-13 08:33:52 -0700765 NDP is setup with OOB (out-of-band) configuration."""
Jaineel7e67a3f2019-08-28 15:58:49 -0700766 results = {}
767 self.run_ndp_oob_latency(
768 results=results,
769 dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE,
770 dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE,
771 num_iterations=100)
772 asserts.explicit_pass(
773 "test_ndp_setup_latency_default_dws finished", extras=results)
Etan Cohen8e9104f2017-06-13 08:33:52 -0700774
Jaineel7e67a3f2019-08-28 15:58:49 -0700775 def test_oob_ndp_setup_latency_non_interactive_dws(self):
776 """Measure the NDP setup latency with the DW configuration for
Etan Cohen8e9104f2017-06-13 08:33:52 -0700777 non-interactive mode. The NDP is setup with OOB (out-of-band)
778 configuration"""
Jaineel7e67a3f2019-08-28 15:58:49 -0700779 results = {}
780 self.run_ndp_oob_latency(
781 results=results,
782 dw_24ghz=aconsts.POWER_DW_24_NON_INTERACTIVE,
783 dw_5ghz=aconsts.POWER_DW_5_NON_INTERACTIVE,
784 num_iterations=100)
785 asserts.explicit_pass(
786 "test_ndp_setup_latency_non_interactive_dws finished",
787 extras=results)
Etan Cohen3704c262018-05-01 14:38:23 -0700788
Jaineel7e67a3f2019-08-28 15:58:49 -0700789 def test_end_to_end_latency_default_dws(self):
790 """Measure the latency for end-to-end communication link setup:
Etan Cohen3704c262018-05-01 14:38:23 -0700791 - Start Aware
792 - Discovery
793 - Message from Sub -> Pub
794 - Message from Pub -> Sub
795 - NDP setup
796 """
Jaineel7e67a3f2019-08-28 15:58:49 -0700797 results = {}
798 self.run_end_to_end_latency(
799 results,
800 dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE,
801 dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE,
802 num_iterations=10,
803 startup_offset=0,
804 include_setup=True)
805 asserts.explicit_pass(
806 "test_end_to_end_latency_default_dws finished", extras=results)
Etan Cohen3704c262018-05-01 14:38:23 -0700807
Jaineel7e67a3f2019-08-28 15:58:49 -0700808 def test_end_to_end_latency_post_attach_default_dws(self):
809 """Measure the latency for end-to-end communication link setup without
Etan Cohen3704c262018-05-01 14:38:23 -0700810 the initial synchronization:
811 - Start Aware & synchronize initially
812 - Loop:
813 - Discovery
814 - Message from Sub -> Pub
815 - Message from Pub -> Sub
816 - NDP setup
817 """
Jaineel7e67a3f2019-08-28 15:58:49 -0700818 results = {}
819 self.run_end_to_end_latency(
820 results,
821 dw_24ghz=aconsts.POWER_DW_24_INTERACTIVE,
822 dw_5ghz=aconsts.POWER_DW_5_INTERACTIVE,
823 num_iterations=10,
824 startup_offset=0,
825 include_setup=False)
826 asserts.explicit_pass(
827 "test_end_to_end_latency_post_attach_default_dws finished",
828 extras=results)