• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 time
18
19from acts import asserts
20from acts.test_decorators import test_tracker_info
21from acts.test_utils.net import connectivity_const as cconsts
22from acts.test_utils.wifi import wifi_test_utils as wutils
23from acts.test_utils.wifi.aware import aware_const as aconsts
24from acts.test_utils.wifi.aware import aware_test_utils as autils
25from acts.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest
26
27
28class DataPathTest(AwareBaseTest):
29    """Set of tests for Wi-Fi Aware data-path."""
30
31    # configuration parameters used by tests
32    ENCR_TYPE_OPEN = 0
33    ENCR_TYPE_PASSPHRASE = 1
34    ENCR_TYPE_PMK = 2
35
36    PASSPHRASE = "This is some random passphrase - very very secure!!"
37    PASSPHRASE_MIN = "01234567"
38    PASSPHRASE_MAX = "012345678901234567890123456789012345678901234567890123456789012"
39    PMK = "ODU0YjE3YzdmNDJiNWI4NTQ2NDJjNDI3M2VkZTQyZGU="
40    PASSPHRASE2 = "This is some random passphrase - very very secure - but diff!!"
41    PMK2 = "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI="
42
43    PING_MSG = "ping"
44
45    # message re-transmit counter (increases reliability in open-environment)
46    # Note: reliability of message transmission is tested elsewhere
47    MSG_RETX_COUNT = 5  # hard-coded max value, internal API
48
49    # number of second to 'reasonably' wait to make sure that devices synchronize
50    # with each other - useful for OOB test cases, where the OOB discovery would
51    # take some time
52    WAIT_FOR_CLUSTER = 5
53
54    def __init__(self, controllers):
55        AwareBaseTest.__init__(self, controllers)
56
57    def create_config(self, dtype):
58        """Create a base configuration based on input parameters.
59
60    Args:
61      dtype: Publish or Subscribe discovery type
62
63    Returns:
64      Discovery configuration object.
65    """
66        config = {}
67        config[aconsts.DISCOVERY_KEY_DISCOVERY_TYPE] = dtype
68        config[
69            aconsts.DISCOVERY_KEY_SERVICE_NAME] = "GoogleTestServiceDataPath"
70        return config
71
72    def request_network(self, dut, ns):
73        """Request a Wi-Fi Aware network.
74
75    Args:
76      dut: Device
77      ns: Network specifier
78    Returns: the request key
79    """
80        network_req = {"TransportType": 5, "NetworkSpecifier": ns}
81        return dut.droid.connectivityRequestWifiAwareNetwork(network_req)
82
83    def set_up_discovery(self,
84                         ptype,
85                         stype,
86                         get_peer_id,
87                         pub_on_both=False,
88                         pub_on_both_same=True):
89        """Set up discovery sessions and wait for service discovery.
90
91    Args:
92      ptype: Publish discovery type
93      stype: Subscribe discovery type
94      get_peer_id: Send a message across to get the peer's id
95      pub_on_both: If True then set up a publisher on both devices. The second
96                   publisher isn't used (existing to test use-case).
97      pub_on_both_same: If True then the second publish uses an identical
98                        service name, otherwise a different service name.
99    """
100        p_dut = self.android_devices[0]
101        p_dut.pretty_name = "Publisher"
102        s_dut = self.android_devices[1]
103        s_dut.pretty_name = "Subscriber"
104
105        # Publisher+Subscriber: attach and wait for confirmation
106        p_id = p_dut.droid.wifiAwareAttach()
107        autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED)
108        time.sleep(self.device_startup_offset)
109        s_id = s_dut.droid.wifiAwareAttach()
110        autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED)
111
112        # Publisher: start publish and wait for confirmation
113        p_disc_id = p_dut.droid.wifiAwarePublish(p_id,
114                                                 self.create_config(ptype))
115        autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
116
117        # Optionally set up a publish session on the Subscriber device
118        if pub_on_both:
119            p2_config = self.create_config(ptype)
120            if not pub_on_both_same:
121                p2_config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = (
122                    p2_config[aconsts.DISCOVERY_KEY_SERVICE_NAME] + "-XYZXYZ")
123            s_dut.droid.wifiAwarePublish(s_id, p2_config)
124            autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
125
126        # Subscriber: start subscribe and wait for confirmation
127        s_disc_id = s_dut.droid.wifiAwareSubscribe(s_id,
128                                                   self.create_config(stype))
129        autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED)
130
131        # Subscriber: wait for service discovery
132        discovery_event = autils.wait_for_event(
133            s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
134        peer_id_on_sub = discovery_event["data"][
135            aconsts.SESSION_CB_KEY_PEER_ID]
136
137        peer_id_on_pub = None
138        if get_peer_id:  # only need message to receive peer ID
139            # Subscriber: send message to peer (Publisher - so it knows our address)
140            s_dut.droid.wifiAwareSendMessage(s_disc_id, peer_id_on_sub,
141                                             self.get_next_msg_id(),
142                                             self.PING_MSG,
143                                             self.MSG_RETX_COUNT)
144            autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_MESSAGE_SENT)
145
146            # Publisher: wait for received message
147            pub_rx_msg_event = autils.wait_for_event(
148                p_dut, aconsts.SESSION_CB_ON_MESSAGE_RECEIVED)
149            peer_id_on_pub = pub_rx_msg_event["data"][
150                aconsts.SESSION_CB_KEY_PEER_ID]
151
152        return (p_dut, s_dut, p_id, s_id, p_disc_id, s_disc_id, peer_id_on_sub,
153                peer_id_on_pub)
154
155    def run_ib_data_path_test(self,
156                              ptype,
157                              stype,
158                              encr_type,
159                              use_peer_id,
160                              passphrase_to_use=None,
161                              pub_on_both=False,
162                              pub_on_both_same=True,
163                              expect_failure=False):
164        """Runs the in-band data-path tests.
165
166    Args:
167      ptype: Publish discovery type
168      stype: Subscribe discovery type
169      encr_type: Encryption type, one of ENCR_TYPE_*
170      use_peer_id: On Responder (publisher): True to use peer ID, False to
171                   accept any request
172      passphrase_to_use: The passphrase to use if encr_type=ENCR_TYPE_PASSPHRASE
173                         If None then use self.PASSPHRASE
174      pub_on_both: If True then set up a publisher on both devices. The second
175                   publisher isn't used (existing to test use-case).
176      pub_on_both_same: If True then the second publish uses an identical
177                        service name, otherwise a different service name.
178      expect_failure: If True then don't expect NDP formation, otherwise expect
179                      NDP setup to succeed.
180    """
181        (p_dut, s_dut, p_id, s_id, p_disc_id, s_disc_id, peer_id_on_sub,
182         peer_id_on_pub) = self.set_up_discovery(
183             ptype,
184             stype,
185             use_peer_id,
186             pub_on_both=pub_on_both,
187             pub_on_both_same=pub_on_both_same)
188
189        passphrase = None
190        pmk = None
191        if encr_type == self.ENCR_TYPE_PASSPHRASE:
192            passphrase = (self.PASSPHRASE
193                          if passphrase_to_use == None else passphrase_to_use)
194        elif encr_type == self.ENCR_TYPE_PMK:
195            pmk = self.PMK
196
197        port = 1234
198        transport_protocol = 6  # TCP/IP
199
200        # Publisher: request network
201        if encr_type == self.ENCR_TYPE_OPEN:
202            p_req_key = self.request_network(
203                p_dut,
204                p_dut.droid.wifiAwareCreateNetworkSpecifier(
205                    p_disc_id, peer_id_on_pub
206                    if use_peer_id else None, passphrase, pmk))
207        else:
208            p_req_key = self.request_network(
209                p_dut,
210                p_dut.droid.wifiAwareCreateNetworkSpecifier(
211                    p_disc_id, peer_id_on_pub if use_peer_id else None,
212                    passphrase, pmk, port, transport_protocol))
213
214        # Subscriber: request network
215        s_req_key = self.request_network(
216            s_dut,
217            s_dut.droid.wifiAwareCreateNetworkSpecifier(
218                s_disc_id, peer_id_on_sub, passphrase, pmk))
219
220        if expect_failure:
221            # Publisher & Subscriber: expect unavailable callbacks
222            autils.wait_for_event_with_keys(
223                p_dut, cconsts.EVENT_NETWORK_CALLBACK,
224                autils.EVENT_NDP_TIMEOUT,
225                (cconsts.NETWORK_CB_KEY_EVENT, cconsts.NETWORK_CB_UNAVAILABLE))
226            autils.wait_for_event_with_keys(
227                s_dut, cconsts.EVENT_NETWORK_CALLBACK,
228                autils.EVENT_NDP_TIMEOUT,
229                (cconsts.NETWORK_CB_KEY_EVENT, cconsts.NETWORK_CB_UNAVAILABLE))
230        else:
231            # Publisher & Subscriber: wait for network formation
232            p_net_event_nc = autils.wait_for_event_with_keys(
233                p_dut, cconsts.EVENT_NETWORK_CALLBACK,
234                autils.EVENT_NDP_TIMEOUT,
235                (cconsts.NETWORK_CB_KEY_EVENT,
236                 cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
237                (cconsts.NETWORK_CB_KEY_ID, p_req_key))
238            s_net_event_nc = autils.wait_for_event_with_keys(
239                s_dut, cconsts.EVENT_NETWORK_CALLBACK,
240                autils.EVENT_NDP_TIMEOUT,
241                (cconsts.NETWORK_CB_KEY_EVENT,
242                 cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
243                (cconsts.NETWORK_CB_KEY_ID, s_req_key))
244
245            # validate no leak of information
246            asserts.assert_false(
247                cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in p_net_event_nc[
248                    "data"], "Network specifier leak!")
249            asserts.assert_false(
250                cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in s_net_event_nc[
251                    "data"], "Network specifier leak!")
252
253            # note that Pub <-> Sub since IPv6 are of peer's!
254            s_ipv6 = p_net_event_nc["data"][aconsts.NET_CAP_IPV6]
255            p_ipv6 = s_net_event_nc["data"][aconsts.NET_CAP_IPV6]
256
257            self.verify_network_info(
258                p_net_event_nc["data"], s_net_event_nc["data"],
259                encr_type == self.ENCR_TYPE_OPEN, port, transport_protocol)
260
261            p_net_event_lp = autils.wait_for_event_with_keys(
262                p_dut, cconsts.EVENT_NETWORK_CALLBACK,
263                autils.EVENT_NDP_TIMEOUT,
264                (cconsts.NETWORK_CB_KEY_EVENT,
265                 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
266                (cconsts.NETWORK_CB_KEY_ID, p_req_key))
267            s_net_event_lp = autils.wait_for_event_with_keys(
268                s_dut, cconsts.EVENT_NETWORK_CALLBACK,
269                autils.EVENT_NDP_TIMEOUT,
270                (cconsts.NETWORK_CB_KEY_EVENT,
271                 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
272                (cconsts.NETWORK_CB_KEY_ID, s_req_key))
273
274            p_aware_if = p_net_event_lp["data"][
275                cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
276            s_aware_if = s_net_event_lp["data"][
277                cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
278
279            self.log.info("Interface names: p=%s, s=%s", p_aware_if,
280                          s_aware_if)
281            self.log.info("Interface addresses (IPv6): p=%s, s=%s", p_ipv6,
282                          s_ipv6)
283
284            # open sockets to test connection
285            asserts.assert_true(
286                autils.verify_socket_connect(p_dut, s_dut, p_ipv6, s_ipv6, 0),
287                "Failed socket link with Pub as Server")
288            asserts.assert_true(
289                autils.verify_socket_connect(s_dut, p_dut, s_ipv6, p_ipv6, 0),
290                "Failed socket link with Sub as Server")
291
292            # terminate sessions and wait for ON_LOST callbacks
293            p_dut.droid.wifiAwareDestroy(p_id)
294            s_dut.droid.wifiAwareDestroy(s_id)
295
296            autils.wait_for_event_with_keys(
297                p_dut, cconsts.EVENT_NETWORK_CALLBACK,
298                autils.EVENT_NDP_TIMEOUT,
299                (cconsts.NETWORK_CB_KEY_EVENT, cconsts.NETWORK_CB_LOST),
300                (cconsts.NETWORK_CB_KEY_ID, p_req_key))
301            autils.wait_for_event_with_keys(
302                s_dut, cconsts.EVENT_NETWORK_CALLBACK,
303                autils.EVENT_NDP_TIMEOUT,
304                (cconsts.NETWORK_CB_KEY_EVENT, cconsts.NETWORK_CB_LOST),
305                (cconsts.NETWORK_CB_KEY_ID, s_req_key))
306
307        # clean-up
308        p_dut.droid.connectivityUnregisterNetworkCallback(p_req_key)
309        s_dut.droid.connectivityUnregisterNetworkCallback(s_req_key)
310
311    def run_oob_data_path_test(self,
312                               encr_type,
313                               use_peer_id,
314                               setup_discovery_sessions=False,
315                               expect_failure=False):
316        """Runs the out-of-band data-path tests.
317
318    Args:
319      encr_type: Encryption type, one of ENCR_TYPE_*
320      use_peer_id: On Responder: True to use peer ID, False to accept any
321                   request
322      setup_discovery_sessions: If True also set up a (spurious) discovery
323        session (pub on both sides, sub on Responder side). Validates a corner
324        case.
325      expect_failure: If True then don't expect NDP formation, otherwise expect
326                      NDP setup to succeed.
327    """
328        init_dut = self.android_devices[0]
329        init_dut.pretty_name = "Initiator"
330        resp_dut = self.android_devices[1]
331        resp_dut.pretty_name = "Responder"
332
333        # Initiator+Responder: attach and wait for confirmation & identity
334        init_id = init_dut.droid.wifiAwareAttach(True)
335        autils.wait_for_event(init_dut, aconsts.EVENT_CB_ON_ATTACHED)
336        init_ident_event = autils.wait_for_event(
337            init_dut, aconsts.EVENT_CB_ON_IDENTITY_CHANGED)
338        init_mac = init_ident_event["data"]["mac"]
339        time.sleep(self.device_startup_offset)
340        resp_id = resp_dut.droid.wifiAwareAttach(True)
341        autils.wait_for_event(resp_dut, aconsts.EVENT_CB_ON_ATTACHED)
342        resp_ident_event = autils.wait_for_event(
343            resp_dut, aconsts.EVENT_CB_ON_IDENTITY_CHANGED)
344        resp_mac = resp_ident_event["data"]["mac"]
345
346        # wait for for devices to synchronize with each other - there are no other
347        # mechanisms to make sure this happens for OOB discovery (except retrying
348        # to execute the data-path request)
349        time.sleep(self.WAIT_FOR_CLUSTER)
350
351        if setup_discovery_sessions:
352            init_dut.droid.wifiAwarePublish(
353                init_id, self.create_config(aconsts.PUBLISH_TYPE_UNSOLICITED))
354            autils.wait_for_event(init_dut,
355                                  aconsts.SESSION_CB_ON_PUBLISH_STARTED)
356            resp_dut.droid.wifiAwarePublish(
357                resp_id, self.create_config(aconsts.PUBLISH_TYPE_UNSOLICITED))
358            autils.wait_for_event(resp_dut,
359                                  aconsts.SESSION_CB_ON_PUBLISH_STARTED)
360            resp_dut.droid.wifiAwareSubscribe(
361                resp_id, self.create_config(aconsts.SUBSCRIBE_TYPE_PASSIVE))
362            autils.wait_for_event(resp_dut,
363                                  aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED)
364            autils.wait_for_event(resp_dut,
365                                  aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
366
367        passphrase = None
368        pmk = None
369        if encr_type == self.ENCR_TYPE_PASSPHRASE:
370            passphrase = self.PASSPHRASE
371        elif encr_type == self.ENCR_TYPE_PMK:
372            pmk = self.PMK
373
374        # Responder: request network
375        resp_req_key = self.request_network(
376            resp_dut,
377            resp_dut.droid.wifiAwareCreateNetworkSpecifierOob(
378                resp_id, aconsts.DATA_PATH_RESPONDER, init_mac
379                if use_peer_id else None, passphrase, pmk))
380
381        # Initiator: request network
382        init_req_key = self.request_network(
383            init_dut,
384            init_dut.droid.wifiAwareCreateNetworkSpecifierOob(
385                init_id, aconsts.DATA_PATH_INITIATOR, resp_mac, passphrase,
386                pmk))
387
388        if expect_failure:
389            # Initiator & Responder: expect unavailable callbacks
390            autils.wait_for_event_with_keys(
391                init_dut, cconsts.EVENT_NETWORK_CALLBACK,
392                autils.EVENT_NDP_TIMEOUT,
393                (cconsts.NETWORK_CB_KEY_EVENT, cconsts.NETWORK_CB_UNAVAILABLE))
394            autils.wait_for_event_with_keys(
395                resp_dut, cconsts.EVENT_NETWORK_CALLBACK,
396                autils.EVENT_NDP_TIMEOUT,
397                (cconsts.NETWORK_CB_KEY_EVENT, cconsts.NETWORK_CB_UNAVAILABLE))
398        else:
399            # Initiator & Responder: wait for network formation
400            init_net_event_nc = autils.wait_for_event_with_keys(
401                init_dut, cconsts.EVENT_NETWORK_CALLBACK,
402                autils.EVENT_NDP_TIMEOUT,
403                (cconsts.NETWORK_CB_KEY_EVENT,
404                 cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
405                (cconsts.NETWORK_CB_KEY_ID, init_req_key))
406            resp_net_event_nc = autils.wait_for_event_with_keys(
407                resp_dut, cconsts.EVENT_NETWORK_CALLBACK,
408                autils.EVENT_NDP_TIMEOUT,
409                (cconsts.NETWORK_CB_KEY_EVENT,
410                 cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
411                (cconsts.NETWORK_CB_KEY_ID, resp_req_key))
412
413            # validate no leak of information
414            asserts.assert_false(
415                cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in init_net_event_nc[
416                    "data"], "Network specifier leak!")
417            asserts.assert_false(
418                cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in resp_net_event_nc[
419                    "data"], "Network specifier leak!")
420
421            # note that Init <-> Resp since IPv6 are of peer's!
422            init_ipv6 = resp_net_event_nc["data"][aconsts.NET_CAP_IPV6]
423            resp_ipv6 = init_net_event_nc["data"][aconsts.NET_CAP_IPV6]
424
425            init_net_event_lp = autils.wait_for_event_with_keys(
426                init_dut, cconsts.EVENT_NETWORK_CALLBACK,
427                autils.EVENT_NDP_TIMEOUT,
428                (cconsts.NETWORK_CB_KEY_EVENT,
429                 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
430                (cconsts.NETWORK_CB_KEY_ID, init_req_key))
431            resp_net_event_lp = autils.wait_for_event_with_keys(
432                resp_dut, cconsts.EVENT_NETWORK_CALLBACK,
433                autils.EVENT_NDP_TIMEOUT,
434                (cconsts.NETWORK_CB_KEY_EVENT,
435                 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
436                (cconsts.NETWORK_CB_KEY_ID, resp_req_key))
437
438            init_aware_if = init_net_event_lp["data"][
439                cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
440            resp_aware_if = resp_net_event_lp["data"][
441                cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
442
443            self.log.info("Interface names: I=%s, R=%s", init_aware_if,
444                          resp_aware_if)
445            self.log.info("Interface addresses (IPv6): I=%s, R=%s", init_ipv6,
446                          resp_ipv6)
447
448            # open sockets to test connection
449            asserts.assert_true(
450                autils.verify_socket_connect(init_dut, resp_dut, init_ipv6,
451                                             resp_ipv6, 0),
452                "Failed socket link with Initiator as Server")
453            asserts.assert_true(
454                autils.verify_socket_connect(resp_dut, init_dut, resp_ipv6,
455                                             init_ipv6, 0),
456                "Failed socket link with Responder as Server")
457
458            # terminate sessions and wait for ON_LOST callbacks
459            init_dut.droid.wifiAwareDestroy(init_id)
460            resp_dut.droid.wifiAwareDestroy(resp_id)
461
462            autils.wait_for_event_with_keys(
463                init_dut, cconsts.EVENT_NETWORK_CALLBACK,
464                autils.EVENT_NDP_TIMEOUT,
465                (cconsts.NETWORK_CB_KEY_EVENT, cconsts.NETWORK_CB_LOST),
466                (cconsts.NETWORK_CB_KEY_ID, init_req_key))
467            autils.wait_for_event_with_keys(
468                resp_dut, cconsts.EVENT_NETWORK_CALLBACK,
469                autils.EVENT_NDP_TIMEOUT,
470                (cconsts.NETWORK_CB_KEY_EVENT, cconsts.NETWORK_CB_LOST),
471                (cconsts.NETWORK_CB_KEY_ID, resp_req_key))
472
473        # clean-up
474        resp_dut.droid.connectivityUnregisterNetworkCallback(resp_req_key)
475        init_dut.droid.connectivityUnregisterNetworkCallback(init_req_key)
476
477    def run_mismatched_ib_data_path_test(self, pub_mismatch, sub_mismatch):
478        """Runs the negative in-band data-path tests: mismatched peer ID.
479
480    Args:
481      pub_mismatch: Mismatch the publisher's ID
482      sub_mismatch: Mismatch the subscriber's ID
483    """
484        (p_dut, s_dut, p_id, s_id, p_disc_id, s_disc_id, peer_id_on_sub,
485         peer_id_on_pub) = self.set_up_discovery(
486             aconsts.PUBLISH_TYPE_UNSOLICITED, aconsts.SUBSCRIBE_TYPE_PASSIVE,
487             True)
488
489        if pub_mismatch:
490            peer_id_on_pub = peer_id_on_pub - 1
491        if sub_mismatch:
492            peer_id_on_sub = peer_id_on_sub - 1
493
494        # Publisher: request network
495        p_req_key = self.request_network(
496            p_dut,
497            p_dut.droid.wifiAwareCreateNetworkSpecifier(
498                p_disc_id, peer_id_on_pub, None))
499
500        # Subscriber: request network
501        s_req_key = self.request_network(
502            s_dut,
503            s_dut.droid.wifiAwareCreateNetworkSpecifier(
504                s_disc_id, peer_id_on_sub, None))
505
506        # Publisher & Subscriber:
507        # - expect unavailable callbacks on the party with the bad ID
508        # - also expect unavailable on the Initiator party (i.e. the
509        #   Subscriber) if the Publisher has a bad ID
510        # - but a Publisher with a valid ID will keep waiting ...
511        autils.wait_for_event_with_keys(
512            s_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
513            (cconsts.NETWORK_CB_KEY_EVENT, cconsts.NETWORK_CB_UNAVAILABLE))
514        if pub_mismatch:
515            autils.wait_for_event_with_keys(
516                p_dut, cconsts.EVENT_NETWORK_CALLBACK,
517                autils.EVENT_NDP_TIMEOUT,
518                (cconsts.NETWORK_CB_KEY_EVENT, cconsts.NETWORK_CB_UNAVAILABLE))
519        else:
520            time.sleep(autils.EVENT_NDP_TIMEOUT)
521            autils.fail_on_event_with_keys(
522                p_dut, cconsts.EVENT_NETWORK_CALLBACK, 0,
523                (cconsts.NETWORK_CB_KEY_ID, p_req_key))
524
525        # clean-up
526        p_dut.droid.connectivityUnregisterNetworkCallback(p_req_key)
527        s_dut.droid.connectivityUnregisterNetworkCallback(s_req_key)
528
529    def run_mismatched_oob_data_path_test(self,
530                                          init_mismatch_mac=False,
531                                          resp_mismatch_mac=False,
532                                          init_encr_type=ENCR_TYPE_OPEN,
533                                          resp_encr_type=ENCR_TYPE_OPEN):
534        """Runs the negative out-of-band data-path tests: mismatched information
535    between Responder and Initiator.
536
537    Args:
538      init_mismatch_mac: True to mismatch the Initiator MAC address
539      resp_mismatch_mac: True to mismatch the Responder MAC address
540      init_encr_type: Encryption type of Initiator - ENCR_TYPE_*
541      resp_encr_type: Encryption type of Responder - ENCR_TYPE_*
542    """
543        init_dut = self.android_devices[0]
544        init_dut.pretty_name = "Initiator"
545        resp_dut = self.android_devices[1]
546        resp_dut.pretty_name = "Responder"
547
548        # Initiator+Responder: attach and wait for confirmation & identity
549        init_id = init_dut.droid.wifiAwareAttach(True)
550        autils.wait_for_event(init_dut, aconsts.EVENT_CB_ON_ATTACHED)
551        init_ident_event = autils.wait_for_event(
552            init_dut, aconsts.EVENT_CB_ON_IDENTITY_CHANGED)
553        init_mac = init_ident_event["data"]["mac"]
554        time.sleep(self.device_startup_offset)
555        resp_id = resp_dut.droid.wifiAwareAttach(True)
556        autils.wait_for_event(resp_dut, aconsts.EVENT_CB_ON_ATTACHED)
557        resp_ident_event = autils.wait_for_event(
558            resp_dut, aconsts.EVENT_CB_ON_IDENTITY_CHANGED)
559        resp_mac = resp_ident_event["data"]["mac"]
560
561        if init_mismatch_mac:  # assumes legit ones don't start with "00"
562            init_mac = "00" + init_mac[2:]
563        if resp_mismatch_mac:
564            resp_mac = "00" + resp_mac[2:]
565
566        # wait for for devices to synchronize with each other - there are no other
567        # mechanisms to make sure this happens for OOB discovery (except retrying
568        # to execute the data-path request)
569        time.sleep(self.WAIT_FOR_CLUSTER)
570
571        # set up separate keys: even if types are the same we want a mismatch
572        init_passphrase = None
573        init_pmk = None
574        if init_encr_type == self.ENCR_TYPE_PASSPHRASE:
575            init_passphrase = self.PASSPHRASE
576        elif init_encr_type == self.ENCR_TYPE_PMK:
577            init_pmk = self.PMK
578
579        resp_passphrase = None
580        resp_pmk = None
581        if resp_encr_type == self.ENCR_TYPE_PASSPHRASE:
582            resp_passphrase = self.PASSPHRASE2
583        elif resp_encr_type == self.ENCR_TYPE_PMK:
584            resp_pmk = self.PMK2
585
586        # Responder: request network
587        resp_req_key = self.request_network(
588            resp_dut,
589            resp_dut.droid.wifiAwareCreateNetworkSpecifierOob(
590                resp_id, aconsts.DATA_PATH_RESPONDER, init_mac,
591                resp_passphrase, resp_pmk))
592
593        # Initiator: request network
594        init_req_key = self.request_network(
595            init_dut,
596            init_dut.droid.wifiAwareCreateNetworkSpecifierOob(
597                init_id, aconsts.DATA_PATH_INITIATOR, resp_mac,
598                init_passphrase, init_pmk))
599
600        # Initiator & Responder:
601        # - expect unavailable on the Initiator party if the
602        #   Initiator or Responder has a bad ID
603        # - but a Responder will keep waiting ...
604        autils.wait_for_event_with_keys(
605            init_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
606            (cconsts.NETWORK_CB_KEY_EVENT, cconsts.NETWORK_CB_UNAVAILABLE))
607        time.sleep(autils.EVENT_NDP_TIMEOUT)
608        autils.fail_on_event_with_keys(
609            resp_dut, cconsts.EVENT_NETWORK_CALLBACK, 0,
610            (cconsts.NETWORK_CB_KEY_ID, init_req_key))
611
612        # clean-up
613        resp_dut.droid.connectivityUnregisterNetworkCallback(resp_req_key)
614        init_dut.droid.connectivityUnregisterNetworkCallback(init_req_key)
615
616    def verify_network_info(self, p_data, s_data, open, port,
617                            transport_protocol):
618        """Verify that the port and transport protocol information is correct.
619            - should only exist on subscriber (received from publisher)
620              and match transmitted values
621            - should only exist on an encrypted NDP
622
623        Args:
624            p_data, s_data: Pub and Sub (respectively) net cap event data.
625            open: True if NDP unencrypted, False if encrypted.
626            port: Expected port value.
627            transport_protocol: Expected transport protocol value.
628        """
629        asserts.assert_true(aconsts.NET_CAP_PORT not in p_data,
630                            "port info not expected on Pub")
631        asserts.assert_true(aconsts.NET_CAP_TRANSPORT_PROTOCOL not in p_data,
632                            "transport protocol info not expected on Pub")
633        if open:
634            asserts.assert_true(aconsts.NET_CAP_PORT not in s_data,
635                                "port info not expected on Sub (open NDP)")
636            asserts.assert_true(
637                aconsts.NET_CAP_TRANSPORT_PROTOCOL not in s_data,
638                "transport protocol info not expected on Sub (open NDP)")
639        else:
640            asserts.assert_equal(s_data[aconsts.NET_CAP_PORT], port,
641                                 "Port info does not match on Sub (from Pub)")
642            asserts.assert_equal(
643                s_data[aconsts.NET_CAP_TRANSPORT_PROTOCOL], transport_protocol,
644                "Transport protocol info does not match on Sub (from Pub)")
645
646    #######################################
647    # Positive In-Band (IB) tests key:
648    #
649    # names is: test_ib_<pub_type>_<sub_type>_<encr_type>_<peer_spec>
650    # where:
651    #
652    # pub_type: Type of publish discovery session: unsolicited or solicited.
653    # sub_type: Type of subscribe discovery session: passive or active.
654    # encr_type: Encription type: open, passphrase
655    # peer_spec: Peer specification method: any or specific
656    #
657    # Note: In-Band means using Wi-Fi Aware for discovery and referring to the
658    # peer using the Aware-provided peer handle (as opposed to a MAC address).
659    #######################################
660
661    @test_tracker_info(uuid="fa30bedc-d1de-4440-bf25-ec00d10555af")
662    def test_ib_unsolicited_passive_open_specific(self):
663        """Data-path: in-band, unsolicited/passive, open encryption, specific peer
664
665    Verifies end-to-end discovery + data-path creation.
666    """
667        self.run_ib_data_path_test(
668            ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
669            stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
670            encr_type=self.ENCR_TYPE_OPEN,
671            use_peer_id=True)
672
673    @test_tracker_info(uuid="57fc9d53-32ae-470f-a8b1-2fe37893687d")
674    def test_ib_unsolicited_passive_open_any(self):
675        """Data-path: in-band, unsolicited/passive, open encryption, any peer
676
677    Verifies end-to-end discovery + data-path creation.
678    """
679        self.run_ib_data_path_test(
680            ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
681            stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
682            encr_type=self.ENCR_TYPE_OPEN,
683            use_peer_id=False)
684
685    @test_tracker_info(uuid="93b2a23d-8579-448a-936c-7812929464cf")
686    def test_ib_unsolicited_passive_passphrase_specific(self):
687        """Data-path: in-band, unsolicited/passive, passphrase, specific peer
688
689    Verifies end-to-end discovery + data-path creation.
690    """
691        self.run_ib_data_path_test(
692            ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
693            stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
694            encr_type=self.ENCR_TYPE_PASSPHRASE,
695            use_peer_id=True)
696
697    @test_tracker_info(uuid="1736126f-a0ff-4712-acc4-f89b4eef5716")
698    def test_ib_unsolicited_passive_passphrase_any(self):
699        """Data-path: in-band, unsolicited/passive, passphrase, any peer
700
701    Verifies end-to-end discovery + data-path creation.
702    """
703        self.run_ib_data_path_test(
704            ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
705            stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
706            encr_type=self.ENCR_TYPE_PASSPHRASE,
707            use_peer_id=False)
708
709    @test_tracker_info(uuid="b9353d5b-3f77-46bf-bfd9-65d56a7c939a")
710    def test_ib_unsolicited_passive_pmk_specific(self):
711        """Data-path: in-band, unsolicited/passive, PMK, specific peer
712
713    Verifies end-to-end discovery + data-path creation.
714    """
715        self.run_ib_data_path_test(
716            ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
717            stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
718            encr_type=self.ENCR_TYPE_PMK,
719            use_peer_id=True)
720
721    @test_tracker_info(uuid="06f3b2ab-4a10-4398-83a4-6a23851b1662")
722    def test_ib_unsolicited_passive_pmk_any(self):
723        """Data-path: in-band, unsolicited/passive, PMK, any peer
724
725    Verifies end-to-end discovery + data-path creation.
726    """
727        self.run_ib_data_path_test(
728            ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
729            stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
730            encr_type=self.ENCR_TYPE_PMK,
731            use_peer_id=False)
732
733    @test_tracker_info(uuid="0ed7d8b3-a69e-46ba-aeb7-13e507ecf290")
734    def test_ib_solicited_active_open_specific(self):
735        """Data-path: in-band, solicited/active, open encryption, specific peer
736
737    Verifies end-to-end discovery + data-path creation.
738    """
739        self.run_ib_data_path_test(
740            ptype=aconsts.PUBLISH_TYPE_SOLICITED,
741            stype=aconsts.SUBSCRIBE_TYPE_ACTIVE,
742            encr_type=self.ENCR_TYPE_OPEN,
743            use_peer_id=True)
744
745    @test_tracker_info(uuid="c7ba6d28-5ef6-45d9-95d5-583ad6d981f3")
746    def test_ib_solicited_active_open_any(self):
747        """Data-path: in-band, solicited/active, open encryption, any peer
748
749    Verifies end-to-end discovery + data-path creation.
750    """
751        self.run_ib_data_path_test(
752            ptype=aconsts.PUBLISH_TYPE_SOLICITED,
753            stype=aconsts.SUBSCRIBE_TYPE_ACTIVE,
754            encr_type=self.ENCR_TYPE_OPEN,
755            use_peer_id=False)
756
757    @test_tracker_info(uuid="388cea99-0e2e-49ea-b00e-f3e56b6236e5")
758    def test_ib_solicited_active_passphrase_specific(self):
759        """Data-path: in-band, solicited/active, passphrase, specific peer
760
761    Verifies end-to-end discovery + data-path creation.
762    """
763        self.run_ib_data_path_test(
764            ptype=aconsts.PUBLISH_TYPE_SOLICITED,
765            stype=aconsts.SUBSCRIBE_TYPE_ACTIVE,
766            encr_type=self.ENCR_TYPE_PASSPHRASE,
767            use_peer_id=True)
768
769    @test_tracker_info(uuid="fcd3e28a-5eab-4169-8a0c-dc7204dcdc13")
770    def test_ib_solicited_active_passphrase_any(self):
771        """Data-path: in-band, solicited/active, passphrase, any peer
772
773    Verifies end-to-end discovery + data-path creation.
774    """
775        self.run_ib_data_path_test(
776            ptype=aconsts.PUBLISH_TYPE_SOLICITED,
777            stype=aconsts.SUBSCRIBE_TYPE_ACTIVE,
778            encr_type=self.ENCR_TYPE_PASSPHRASE,
779            use_peer_id=False)
780
781    @test_tracker_info(uuid="9d4eaad7-ba53-4a06-8ce0-e308daea3309")
782    def test_ib_solicited_active_pmk_specific(self):
783        """Data-path: in-band, solicited/active, PMK, specific peer
784
785    Verifies end-to-end discovery + data-path creation.
786    """
787        self.run_ib_data_path_test(
788            ptype=aconsts.PUBLISH_TYPE_SOLICITED,
789            stype=aconsts.SUBSCRIBE_TYPE_ACTIVE,
790            encr_type=self.ENCR_TYPE_PMK,
791            use_peer_id=True)
792
793    @test_tracker_info(uuid="129d850e-c312-4137-a67b-05ae95fe66cc")
794    def test_ib_solicited_active_pmk_any(self):
795        """Data-path: in-band, solicited/active, PMK, any peer
796
797    Verifies end-to-end discovery + data-path creation.
798    """
799        self.run_ib_data_path_test(
800            ptype=aconsts.PUBLISH_TYPE_SOLICITED,
801            stype=aconsts.SUBSCRIBE_TYPE_ACTIVE,
802            encr_type=self.ENCR_TYPE_PMK,
803            use_peer_id=False)
804
805    #######################################
806    # Positive In-Band (IB) with a publish session running on the subscriber
807    # tests key:
808    #
809    # names is: test_ib_extra_pub_<same|diff>_<pub_type>_<sub_type>
810    #                                          _<encr_type>_<peer_spec>
811    # where:
812    #
813    # same|diff: Whether the extra publish session (on the subscriber) is the same
814    #            or different from the primary session.
815    # pub_type: Type of publish discovery session: unsolicited or solicited.
816    # sub_type: Type of subscribe discovery session: passive or active.
817    # encr_type: Encryption type: open, passphrase
818    # peer_spec: Peer specification method: any or specific
819    #
820    # Note: In-Band means using Wi-Fi Aware for discovery and referring to the
821    # peer using the Aware-provided peer handle (as opposed to a MAC address).
822    #######################################
823
824    @test_tracker_info(uuid="e855dd81-45c8-4bb2-a204-7687c48ff843")
825    def test_ib_extra_pub_same_unsolicited_passive_open_specific(self):
826        """Data-path: in-band, unsolicited/passive, open encryption, specific peer.
827
828    Configuration contains a publisher (for the same service) running on *both*
829    devices.
830
831    Verifies end-to-end discovery + data-path creation.
832    """
833        self.run_ib_data_path_test(
834            ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
835            stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
836            encr_type=self.ENCR_TYPE_OPEN,
837            use_peer_id=True,
838            pub_on_both=True,
839            pub_on_both_same=True)
840
841    @test_tracker_info(uuid="57fc9d53-32ae-470f-a8b1-2fe37893687d")
842    def test_ib_extra_pub_same_unsolicited_passive_open_any(self):
843        """Data-path: in-band, unsolicited/passive, open encryption, any peer.
844
845    Configuration contains a publisher (for the same service) running on *both*
846    devices.
847
848    Verifies end-to-end discovery + data-path creation.
849    """
850        self.run_ib_data_path_test(
851            ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
852            stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
853            encr_type=self.ENCR_TYPE_OPEN,
854            use_peer_id=False,
855            pub_on_both=True,
856            pub_on_both_same=True)
857
858    @test_tracker_info(uuid="7a32f439-d745-4716-a75e-b54109aaaf82")
859    def test_ib_extra_pub_diff_unsolicited_passive_open_specific(self):
860        """Data-path: in-band, unsolicited/passive, open encryption, specific peer.
861
862    Configuration contains a publisher (for a different service) running on
863    *both* devices.
864
865    Verifies end-to-end discovery + data-path creation.
866    """
867        self.run_ib_data_path_test(
868            ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
869            stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
870            encr_type=self.ENCR_TYPE_OPEN,
871            use_peer_id=True,
872            pub_on_both=True,
873            pub_on_both_same=False)
874
875    @test_tracker_info(uuid="a14ddc66-88fd-4b49-ab37-225533867c63")
876    def test_ib_extra_pub_diff_unsolicited_passive_open_any(self):
877        """Data-path: in-band, unsolicited/passive, open encryption, any peer.
878
879    Configuration contains a publisher (for a different service) running on
880    *both* devices.
881
882    Verifies end-to-end discovery + data-path creation.
883    """
884        self.run_ib_data_path_test(
885            ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
886            stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
887            encr_type=self.ENCR_TYPE_OPEN,
888            use_peer_id=False,
889            pub_on_both=True,
890            pub_on_both_same=False)
891
892    #######################################
893    # Positive Out-of-Band (OOB) tests key:
894    #
895    # names is: test_oob_<encr_type>_<peer_spec>
896    # where:
897    #
898    # encr_type: Encryption type: open, passphrase
899    # peer_spec: Peer specification method: any or specific
900    #
901    # Optionally set up an extra discovery session to test coexistence. If so
902    # add "ib_coex" to test name.
903    #
904    # Note: Out-of-Band means using a non-Wi-Fi Aware mechanism for discovery and
905    # exchange of MAC addresses and then Wi-Fi Aware for data-path.
906    #######################################
907
908    @test_tracker_info(uuid="7db17d8c-1dce-4084-b695-215bbcfe7d41")
909    def test_oob_open_specific(self):
910        """Data-path: out-of-band, open encryption, specific peer
911
912    Verifies end-to-end discovery + data-path creation.
913    """
914        self.run_oob_data_path_test(
915            encr_type=self.ENCR_TYPE_OPEN, use_peer_id=True)
916
917    @test_tracker_info(uuid="ad416d89-cb95-4a07-8d29-ee213117450b")
918    def test_oob_open_any(self):
919        """Data-path: out-of-band, open encryption, any peer
920
921    Verifies end-to-end discovery + data-path creation.
922    """
923        self.run_oob_data_path_test(
924            encr_type=self.ENCR_TYPE_OPEN, use_peer_id=False)
925
926    @test_tracker_info(uuid="74937a3a-d524-43e2-8979-4449271cab52")
927    def test_oob_passphrase_specific(self):
928        """Data-path: out-of-band, passphrase, specific peer
929
930    Verifies end-to-end discovery + data-path creation.
931    """
932        self.run_oob_data_path_test(
933            encr_type=self.ENCR_TYPE_PASSPHRASE, use_peer_id=True)
934
935    @test_tracker_info(uuid="afcbdc7e-d3a9-465b-b1da-ce2e42e3941e")
936    def test_oob_passphrase_any(self):
937        """Data-path: out-of-band, passphrase, any peer
938
939    Verifies end-to-end discovery + data-path creation.
940    """
941        self.run_oob_data_path_test(
942            encr_type=self.ENCR_TYPE_PASSPHRASE, use_peer_id=False)
943
944    @test_tracker_info(uuid="0d095031-160a-4537-aab5-41b6ad5d55f8")
945    def test_oob_pmk_specific(self):
946        """Data-path: out-of-band, PMK, specific peer
947
948    Verifies end-to-end discovery + data-path creation.
949    """
950        self.run_oob_data_path_test(
951            encr_type=self.ENCR_TYPE_PMK, use_peer_id=True)
952
953    @test_tracker_info(uuid="e45477bd-66cc-4eb7-88dd-4518c8aa2a74")
954    def test_oob_pmk_any(self):
955        """Data-path: out-of-band, PMK, any peer
956
957    Verifies end-to-end discovery + data-path creation.
958    """
959        self.run_oob_data_path_test(
960            encr_type=self.ENCR_TYPE_PMK, use_peer_id=False)
961
962    @test_tracker_info(uuid="dd464f24-b404-4eea-955c-d10c9e8adefc")
963    def test_oob_ib_coex_open_specific(self):
964        """Data-path: out-of-band, open encryption, specific peer - in-band coex:
965    set up a concurrent discovery session to verify no impact. The session
966    consists of Publisher on both ends, and a Subscriber on the Responder.
967
968    Verifies end-to-end discovery + data-path creation.
969    """
970        self.run_oob_data_path_test(
971            encr_type=self.ENCR_TYPE_OPEN,
972            use_peer_id=True,
973            setup_discovery_sessions=True)
974
975    @test_tracker_info(uuid="088fcd3a-b015-4179-a9a5-91f782b03e3b")
976    def test_oob_ib_coex_open_any(self):
977        """Data-path: out-of-band, open encryption, any peer - in-band coex:
978    set up a concurrent discovery session to verify no impact. The session
979    consists of Publisher on both ends, and a Subscriber on the Responder.
980
981    Verifies end-to-end discovery + data-path creation.
982    """
983        self.run_oob_data_path_test(
984            encr_type=self.ENCR_TYPE_OPEN,
985            use_peer_id=False,
986            setup_discovery_sessions=True)
987
988    ##############################################################
989
990    @test_tracker_info(uuid="1c2c9805-dc1e-43b5-a1b8-315e8c9a4337")
991    def test_passphrase_min(self):
992        """Data-path: minimum passphrase length
993
994    Use in-band, unsolicited/passive, any peer combination
995    """
996        self.run_ib_data_path_test(
997            ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
998            stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
999            encr_type=self.ENCR_TYPE_PASSPHRASE,
1000            use_peer_id=False,
1001            passphrase_to_use=self.PASSPHRASE_MIN)
1002
1003    @test_tracker_info(uuid="e696e2b9-87a9-4521-b337-61b9efaa2057")
1004    def test_passphrase_max(self):
1005        """Data-path: maximum passphrase length
1006
1007    Use in-band, unsolicited/passive, any peer combination
1008    """
1009        self.run_ib_data_path_test(
1010            ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
1011            stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
1012            encr_type=self.ENCR_TYPE_PASSPHRASE,
1013            use_peer_id=False,
1014            passphrase_to_use=self.PASSPHRASE_MAX)
1015
1016    @test_tracker_info(uuid="533cd44c-ff30-4283-ac28-f71fd7b4f02d")
1017    def test_negative_mismatch_publisher_peer_id(self):
1018        """Data-path: failure when publisher peer ID is mismatched"""
1019        self.run_mismatched_ib_data_path_test(
1020            pub_mismatch=True, sub_mismatch=False)
1021
1022    @test_tracker_info(uuid="682f275e-722a-4f8b-85e7-0dcea9d25532")
1023    def test_negative_mismatch_subscriber_peer_id(self):
1024        """Data-path: failure when subscriber peer ID is mismatched"""
1025        self.run_mismatched_ib_data_path_test(
1026            pub_mismatch=False, sub_mismatch=True)
1027
1028    @test_tracker_info(uuid="7fa82796-7fc9-4d9e-bbbb-84b751788943")
1029    def test_negative_mismatch_init_mac(self):
1030        """Data-path: failure when Initiator MAC address mismatch"""
1031        self.run_mismatched_oob_data_path_test(
1032            init_mismatch_mac=True, resp_mismatch_mac=False)
1033
1034    @test_tracker_info(uuid="edeae959-4644-44f9-8d41-bdeb5216954e")
1035    def test_negative_mismatch_resp_mac(self):
1036        """Data-path: failure when Responder MAC address mismatch"""
1037        self.run_mismatched_oob_data_path_test(
1038            init_mismatch_mac=False, resp_mismatch_mac=True)
1039
1040    @test_tracker_info(uuid="91f46949-c47f-49f9-a90f-6fae699613a7")
1041    def test_negative_mismatch_passphrase(self):
1042        """Data-path: failure when passphrases mismatch"""
1043        self.run_mismatched_oob_data_path_test(
1044            init_encr_type=self.ENCR_TYPE_PASSPHRASE,
1045            resp_encr_type=self.ENCR_TYPE_PASSPHRASE)
1046
1047    @test_tracker_info(uuid="01c49c2e-dc92-4a27-bb47-c4fc67617c23")
1048    def test_negative_mismatch_pmk(self):
1049        """Data-path: failure when PMK mismatch"""
1050        self.run_mismatched_oob_data_path_test(
1051            init_encr_type=self.ENCR_TYPE_PMK,
1052            resp_encr_type=self.ENCR_TYPE_PMK)
1053
1054    @test_tracker_info(uuid="4d651797-5fbb-408e-a4b6-a6e1944136da")
1055    def test_negative_mismatch_open_passphrase(self):
1056        """Data-path: failure when initiator is open, and responder passphrase"""
1057        self.run_mismatched_oob_data_path_test(
1058            init_encr_type=self.ENCR_TYPE_OPEN,
1059            resp_encr_type=self.ENCR_TYPE_PASSPHRASE)
1060
1061    @test_tracker_info(uuid="1ae697f4-5987-4187-aeef-1e22d07d4a7c")
1062    def test_negative_mismatch_open_pmk(self):
1063        """Data-path: failure when initiator is open, and responder PMK"""
1064        self.run_mismatched_oob_data_path_test(
1065            init_encr_type=self.ENCR_TYPE_OPEN,
1066            resp_encr_type=self.ENCR_TYPE_PMK)
1067
1068    @test_tracker_info(uuid="f027b1cc-0e7a-4075-b880-5e64b288afbd")
1069    def test_negative_mismatch_pmk_passphrase(self):
1070        """Data-path: failure when initiator is pmk, and responder passphrase"""
1071        self.run_mismatched_oob_data_path_test(
1072            init_encr_type=self.ENCR_TYPE_PMK,
1073            resp_encr_type=self.ENCR_TYPE_PASSPHRASE)
1074
1075    @test_tracker_info(uuid="0819bbd4-72ae-49c4-bd46-5448db2b0a06")
1076    def test_negative_mismatch_passphrase_open(self):
1077        """Data-path: failure when initiator is passphrase, and responder open"""
1078        self.run_mismatched_oob_data_path_test(
1079            init_encr_type=self.ENCR_TYPE_PASSPHRASE,
1080            resp_encr_type=self.ENCR_TYPE_OPEN)
1081
1082    @test_tracker_info(uuid="7ef24f62-8e6b-4732-88a3-80a43584dda4")
1083    def test_negative_mismatch_pmk_open(self):
1084        """Data-path: failure when initiator is PMK, and responder open"""
1085        self.run_mismatched_oob_data_path_test(
1086            init_encr_type=self.ENCR_TYPE_PMK,
1087            resp_encr_type=self.ENCR_TYPE_OPEN)
1088
1089    @test_tracker_info(uuid="7b9c9efc-1c06-465e-8a5e-d6a22ac1da97")
1090    def test_negative_mismatch_passphrase_pmk(self):
1091        """Data-path: failure when initiator is passphrase, and responder pmk"""
1092        self.run_mismatched_oob_data_path_test(
1093            init_encr_type=self.ENCR_TYPE_PASSPHRASE,
1094            resp_encr_type=self.ENCR_TYPE_OPEN)
1095
1096    ##########################################################################
1097
1098    def wait_for_request_responses(self, dut, req_keys, aware_ifs, aware_ipv6):
1099        """Wait for network request confirmation for all request keys.
1100
1101    Args:
1102      dut: Device under test
1103      req_keys: (in) A list of the network requests
1104      aware_ifs: (out) A list into which to append the network interface
1105      aware_ipv6: (out) A list into which to append the network ipv6 address
1106    """
1107        num_events = 0  # looking for 2 events per NDP: link-prop + net-cap
1108        while num_events != 2 * len(req_keys):
1109            event = autils.wait_for_event(
1110                dut,
1111                cconsts.EVENT_NETWORK_CALLBACK,
1112                timeout=autils.EVENT_NDP_TIMEOUT)
1113            if (event["data"][cconsts.NETWORK_CB_KEY_EVENT] ==
1114                    cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED):
1115                if event["data"][cconsts.NETWORK_CB_KEY_ID] in req_keys:
1116                    num_events = num_events + 1
1117                    aware_ifs.append(
1118                        event["data"][cconsts.NETWORK_CB_KEY_INTERFACE_NAME])
1119                else:
1120                    self.log.info(
1121                        "Received an unexpected connectivity, the revoked "
1122                        "network request probably went through -- %s", event)
1123            elif (event["data"][cconsts.NETWORK_CB_KEY_EVENT] ==
1124                  cconsts.NETWORK_CB_CAPABILITIES_CHANGED):
1125                if event["data"][cconsts.NETWORK_CB_KEY_ID] in req_keys:
1126                    num_events = num_events + 1
1127                    aware_ipv6.append(event["data"][aconsts.NET_CAP_IPV6])
1128                else:
1129                    self.log.info(
1130                        "Received an unexpected connectivity, the revoked "
1131                        "network request probably went through -- %s", event)
1132                # validate no leak of information
1133                asserts.assert_false(
1134                    cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in event["data"],
1135                    "Network specifier leak!")
1136
1137    @test_tracker_info(uuid="2e325e2b-d552-4890-b470-20b40284395d")
1138    def test_multiple_identical_networks(self):
1139        """Validate that creating multiple networks between 2 devices, each network
1140    with identical configuration is supported over a single NDP.
1141
1142    Verify that the interface and IPv6 address is the same for all networks.
1143    """
1144        init_dut = self.android_devices[0]
1145        init_dut.pretty_name = "Initiator"
1146        resp_dut = self.android_devices[1]
1147        resp_dut.pretty_name = "Responder"
1148
1149        N = 2  # first iteration (must be 2 to give us a chance to cancel the first)
1150        M = 5  # second iteration
1151
1152        init_ids = []
1153        resp_ids = []
1154
1155        # Initiator+Responder: attach and wait for confirmation & identity
1156        # create N+M sessions to be used in the different (but identical) NDPs
1157        for i in range(N + M):
1158            id, init_mac = autils.attach_with_identity(init_dut)
1159            init_ids.append(id)
1160            id, resp_mac = autils.attach_with_identity(resp_dut)
1161            resp_ids.append(id)
1162
1163        # wait for for devices to synchronize with each other - there are no other
1164        # mechanisms to make sure this happens for OOB discovery (except retrying
1165        # to execute the data-path request)
1166        time.sleep(autils.WAIT_FOR_CLUSTER)
1167
1168        resp_req_keys = []
1169        init_req_keys = []
1170        resp_aware_ifs = []
1171        init_aware_ifs = []
1172        resp_aware_ipv6 = []
1173        init_aware_ipv6 = []
1174
1175        # issue N quick requests for identical NDPs - without waiting for result
1176        # tests whether pre-setup multiple NDP procedure
1177        for i in range(N):
1178            # Responder: request network
1179            resp_req_keys.append(
1180                autils.request_network(
1181                    resp_dut,
1182                    resp_dut.droid.wifiAwareCreateNetworkSpecifierOob(
1183                        resp_ids[i], aconsts.DATA_PATH_RESPONDER, init_mac,
1184                        None)))
1185
1186            # Initiator: request network
1187            init_req_keys.append(
1188                autils.request_network(
1189                    init_dut,
1190                    init_dut.droid.wifiAwareCreateNetworkSpecifierOob(
1191                        init_ids[i], aconsts.DATA_PATH_INITIATOR, resp_mac,
1192                        None)))
1193
1194        # remove the first request (hopefully before completed) testing that NDP
1195        # is still created
1196        resp_dut.droid.connectivityUnregisterNetworkCallback(resp_req_keys[0])
1197        resp_req_keys.remove(resp_req_keys[0])
1198        init_dut.droid.connectivityUnregisterNetworkCallback(init_req_keys[0])
1199        init_req_keys.remove(init_req_keys[0])
1200
1201        # wait for network formation for all initial requests
1202        # note: for IPv6 Init <--> Resp since each reports the other's IPv6 address
1203        #       in it's transport-specific network info
1204        self.wait_for_request_responses(resp_dut, resp_req_keys,
1205                                        resp_aware_ifs, init_aware_ipv6)
1206        self.wait_for_request_responses(init_dut, init_req_keys,
1207                                        init_aware_ifs, resp_aware_ipv6)
1208
1209        # issue M more requests for the same NDPs - tests post-setup multiple NDP
1210        for i in range(M):
1211            # Responder: request network
1212            resp_req_keys.append(
1213                autils.request_network(
1214                    resp_dut,
1215                    resp_dut.droid.wifiAwareCreateNetworkSpecifierOob(
1216                        resp_ids[N + i], aconsts.DATA_PATH_RESPONDER, init_mac,
1217                        None)))
1218
1219            # Initiator: request network
1220            init_req_keys.append(
1221                autils.request_network(
1222                    init_dut,
1223                    init_dut.droid.wifiAwareCreateNetworkSpecifierOob(
1224                        init_ids[N + i], aconsts.DATA_PATH_INITIATOR, resp_mac,
1225                        None)))
1226
1227        # wait for network formation for all subsequent requests
1228        self.wait_for_request_responses(resp_dut, resp_req_keys[N - 1:],
1229                                        resp_aware_ifs, init_aware_ipv6)
1230        self.wait_for_request_responses(init_dut, init_req_keys[N - 1:],
1231                                        init_aware_ifs, resp_aware_ipv6)
1232
1233        # determine whether all interfaces and ipv6 addresses are identical
1234        # (single NDP)
1235        init_aware_ifs = list(set(init_aware_ifs))
1236        resp_aware_ifs = list(set(resp_aware_ifs))
1237        init_aware_ipv6 = list(set(init_aware_ipv6))
1238        resp_aware_ipv6 = list(set(resp_aware_ipv6))
1239
1240        self.log.info("Interface names: I=%s, R=%s", init_aware_ifs,
1241                      resp_aware_ifs)
1242        self.log.info("Interface IPv6: I=%s, R=%s", init_aware_ipv6,
1243                      resp_aware_ipv6)
1244        self.log.info("Initiator requests: %s", init_req_keys)
1245        self.log.info("Responder requests: %s", resp_req_keys)
1246
1247        asserts.assert_equal(
1248            len(init_aware_ifs), 1, "Multiple initiator interfaces")
1249        asserts.assert_equal(
1250            len(resp_aware_ifs), 1, "Multiple responder interfaces")
1251        asserts.assert_equal(
1252            len(init_aware_ipv6), 1, "Multiple initiator IPv6 addresses")
1253        asserts.assert_equal(
1254            len(resp_aware_ipv6), 1, "Multiple responder IPv6 addresses")
1255
1256        for i in range(
1257                init_dut.aware_capabilities[aconsts.CAP_MAX_NDI_INTERFACES]):
1258            # note: using get_ipv6_addr (ifconfig method) since want to verify
1259            # that interfaces which do not have any NDPs on them do not have
1260            # an IPv6 link-local address.
1261            if_name = "%s%d" % (aconsts.AWARE_NDI_PREFIX, i)
1262            init_ipv6 = autils.get_ipv6_addr(init_dut, if_name)
1263            resp_ipv6 = autils.get_ipv6_addr(resp_dut, if_name)
1264
1265            asserts.assert_equal(
1266                init_ipv6 is None, if_name not in init_aware_ifs,
1267                "Initiator interface %s in unexpected state" % if_name)
1268            asserts.assert_equal(
1269                resp_ipv6 is None, if_name not in resp_aware_ifs,
1270                "Responder interface %s in unexpected state" % if_name)
1271
1272        # release requests
1273        for resp_req_key in resp_req_keys:
1274            resp_dut.droid.connectivityUnregisterNetworkCallback(resp_req_key)
1275        for init_req_key in init_req_keys:
1276            init_dut.droid.connectivityUnregisterNetworkCallback(init_req_key)
1277
1278    def test_identical_network_from_both_sides(self):
1279        """Validate that requesting two identical NDPs (Open) each being initiated
1280    from a different side, results in the same/single NDP.
1281
1282    Verify that the interface and IPv6 address is the same for all networks.
1283    """
1284        dut1 = self.android_devices[0]
1285        dut2 = self.android_devices[1]
1286
1287        id1, mac1 = autils.attach_with_identity(dut1)
1288        id2, mac2 = autils.attach_with_identity(dut2)
1289
1290        # wait for for devices to synchronize with each other - there are no other
1291        # mechanisms to make sure this happens for OOB discovery (except retrying
1292        # to execute the data-path request)
1293        time.sleep(autils.WAIT_FOR_CLUSTER)
1294
1295        # first NDP: DUT1 (Init) -> DUT2 (Resp)
1296        req_a_resp = autils.request_network(
1297            dut2,
1298            dut2.droid.wifiAwareCreateNetworkSpecifierOob(
1299                id2, aconsts.DATA_PATH_RESPONDER, mac1))
1300
1301        req_a_init = autils.request_network(
1302            dut1,
1303            dut1.droid.wifiAwareCreateNetworkSpecifierOob(
1304                id1, aconsts.DATA_PATH_INITIATOR, mac2))
1305
1306        req_a_resp_event_nc = autils.wait_for_event_with_keys(
1307            dut2, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1308            (cconsts.NETWORK_CB_KEY_EVENT,
1309             cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
1310            (cconsts.NETWORK_CB_KEY_ID, req_a_resp))
1311        req_a_init_event_nc = autils.wait_for_event_with_keys(
1312            dut1, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1313            (cconsts.NETWORK_CB_KEY_EVENT,
1314             cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
1315            (cconsts.NETWORK_CB_KEY_ID, req_a_init))
1316
1317        # validate no leak of information
1318        asserts.assert_false(
1319            cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in req_a_resp_event_nc[
1320                "data"], "Network specifier leak!")
1321        asserts.assert_false(
1322            cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in req_a_init_event_nc[
1323                "data"], "Network specifier leak!")
1324
1325        # note that Init <-> Resp since IPv6 are of peer's!
1326        req_a_ipv6_init = req_a_resp_event_nc["data"][aconsts.NET_CAP_IPV6]
1327        req_a_ipv6_resp = req_a_init_event_nc["data"][aconsts.NET_CAP_IPV6]
1328
1329        req_a_resp_event_lp = autils.wait_for_event_with_keys(
1330            dut2, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1331            (cconsts.NETWORK_CB_KEY_EVENT,
1332             cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
1333            (cconsts.NETWORK_CB_KEY_ID, req_a_resp))
1334        req_a_init_event_lp = autils.wait_for_event_with_keys(
1335            dut1, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1336            (cconsts.NETWORK_CB_KEY_EVENT,
1337             cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
1338            (cconsts.NETWORK_CB_KEY_ID, req_a_init))
1339
1340        req_a_if_resp = req_a_resp_event_lp["data"][
1341            cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
1342        req_a_if_init = req_a_init_event_lp["data"][
1343            cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
1344
1345        self.log.info("Interface names for A: I=%s, R=%s", req_a_if_init,
1346                      req_a_if_resp)
1347        self.log.info("Interface addresses (IPv6) for A: I=%s, R=%s",
1348                      req_a_ipv6_init, req_a_ipv6_resp)
1349
1350        # second NDP: DUT2 (Init) -> DUT1 (Resp)
1351        req_b_resp = autils.request_network(
1352            dut1,
1353            dut1.droid.wifiAwareCreateNetworkSpecifierOob(
1354                id1, aconsts.DATA_PATH_RESPONDER, mac2))
1355
1356        req_b_init = autils.request_network(
1357            dut2,
1358            dut2.droid.wifiAwareCreateNetworkSpecifierOob(
1359                id2, aconsts.DATA_PATH_INITIATOR, mac1))
1360
1361        req_b_resp_event_nc = autils.wait_for_event_with_keys(
1362            dut1, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1363            (cconsts.NETWORK_CB_KEY_EVENT,
1364             cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
1365            (cconsts.NETWORK_CB_KEY_ID, req_b_resp))
1366        req_b_init_event_nc = autils.wait_for_event_with_keys(
1367            dut2, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1368            (cconsts.NETWORK_CB_KEY_EVENT,
1369             cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
1370            (cconsts.NETWORK_CB_KEY_ID, req_b_init))
1371
1372        # validate no leak of information
1373        asserts.assert_false(
1374            cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in req_b_resp_event_nc[
1375                "data"], "Network specifier leak!")
1376        asserts.assert_false(
1377            cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in req_b_init_event_nc[
1378                "data"], "Network specifier leak!")
1379
1380        # note that Init <-> Resp since IPv6 are of peer's!
1381        req_b_ipv6_init = req_b_resp_event_nc["data"][aconsts.NET_CAP_IPV6]
1382        req_b_ipv6_resp = req_b_init_event_nc["data"][aconsts.NET_CAP_IPV6]
1383
1384        req_b_resp_event_lp = autils.wait_for_event_with_keys(
1385            dut1, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1386            (cconsts.NETWORK_CB_KEY_EVENT,
1387             cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
1388            (cconsts.NETWORK_CB_KEY_ID, req_b_resp))
1389        req_b_init_event_lp = autils.wait_for_event_with_keys(
1390            dut2, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1391            (cconsts.NETWORK_CB_KEY_EVENT,
1392             cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
1393            (cconsts.NETWORK_CB_KEY_ID, req_b_init))
1394
1395        req_b_if_resp = req_b_resp_event_lp["data"][
1396            cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
1397        req_b_if_init = req_b_init_event_lp["data"][
1398            cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
1399
1400        self.log.info("Interface names for B: I=%s, R=%s", req_b_if_init,
1401                      req_b_if_resp)
1402        self.log.info("Interface addresses (IPv6) for B: I=%s, R=%s",
1403                      req_b_ipv6_init, req_b_ipv6_resp)
1404
1405        # validate equality of NDPs (using interface names & ipv6)
1406        asserts.assert_equal(req_a_if_init, req_b_if_resp,
1407                             "DUT1 NDPs are on different interfaces")
1408        asserts.assert_equal(req_a_if_resp, req_b_if_init,
1409                             "DUT2 NDPs are on different interfaces")
1410        asserts.assert_equal(req_a_ipv6_init, req_b_ipv6_resp,
1411                             "DUT1 NDPs are using different IPv6 addresses")
1412        asserts.assert_equal(req_a_ipv6_resp, req_b_ipv6_init,
1413                             "DUT2 NDPs are using different IPv6 addresses")
1414
1415        # release requests
1416        dut1.droid.connectivityUnregisterNetworkCallback(req_a_init)
1417        dut1.droid.connectivityUnregisterNetworkCallback(req_b_resp)
1418        dut2.droid.connectivityUnregisterNetworkCallback(req_a_resp)
1419        dut2.droid.connectivityUnregisterNetworkCallback(req_b_init)
1420
1421    ########################################################################
1422
1423    def run_multiple_ndi(self, sec_configs, flip_init_resp=False):
1424        """Validate that the device can create and use multiple NDIs.
1425
1426    The security configuration can be:
1427    - None: open
1428    - String: passphrase
1429    - otherwise: PMK (byte array)
1430
1431    Args:
1432      sec_configs: list of security configurations
1433      flip_init_resp: if True the roles of Initiator and Responder are flipped
1434                      between the 2 devices, otherwise same devices are always
1435                      configured in the same role.
1436    """
1437        dut1 = self.android_devices[0]
1438        dut2 = self.android_devices[1]
1439
1440        asserts.skip_if(
1441            dut1.aware_capabilities[aconsts.CAP_MAX_NDI_INTERFACES] <
1442            len(sec_configs)
1443            or dut2.aware_capabilities[aconsts.CAP_MAX_NDI_INTERFACES] <
1444            len(sec_configs), "DUTs do not support enough NDIs")
1445
1446        id1, mac1 = autils.attach_with_identity(dut1)
1447        id2, mac2 = autils.attach_with_identity(dut2)
1448
1449        # wait for for devices to synchronize with each other - there are no other
1450        # mechanisms to make sure this happens for OOB discovery (except retrying
1451        # to execute the data-path request)
1452        time.sleep(autils.WAIT_FOR_CLUSTER)
1453
1454        dut2_req_keys = []
1455        dut1_req_keys = []
1456        dut2_aware_ifs = []
1457        dut1_aware_ifs = []
1458        dut2_aware_ipv6s = []
1459        dut1_aware_ipv6s = []
1460
1461        dut2_type = aconsts.DATA_PATH_RESPONDER
1462        dut1_type = aconsts.DATA_PATH_INITIATOR
1463        dut2_is_responder = True
1464        for sec in sec_configs:
1465            if dut2_is_responder:
1466                # DUT2 (Responder): request network
1467                dut2_req_key = autils.request_network(
1468                    dut2,
1469                    autils.get_network_specifier(dut2, id2, dut2_type, mac1,
1470                                                 sec))
1471                dut2_req_keys.append(dut2_req_key)
1472
1473                # DUT1 (Initiator): request network
1474                dut1_req_key = autils.request_network(
1475                    dut1,
1476                    autils.get_network_specifier(dut1, id1, dut1_type, mac2,
1477                                                 sec))
1478                dut1_req_keys.append(dut1_req_key)
1479            else:
1480                # DUT1 (Responder): request network
1481                dut1_req_key = autils.request_network(
1482                    dut1,
1483                    autils.get_network_specifier(dut1, id1, dut1_type, mac2,
1484                                                 sec))
1485                dut1_req_keys.append(dut1_req_key)
1486
1487                # DUT2 (Initiator): request network
1488                dut2_req_key = autils.request_network(
1489                    dut2,
1490                    autils.get_network_specifier(dut2, id2, dut2_type, mac1,
1491                                                 sec))
1492                dut2_req_keys.append(dut2_req_key)
1493
1494            # Wait for network
1495            dut1_net_event_nc = autils.wait_for_event_with_keys(
1496                dut1, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1497                (cconsts.NETWORK_CB_KEY_EVENT,
1498                 cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
1499                (cconsts.NETWORK_CB_KEY_ID, dut1_req_key))
1500            dut2_net_event_nc = autils.wait_for_event_with_keys(
1501                dut2, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1502                (cconsts.NETWORK_CB_KEY_EVENT,
1503                 cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
1504                (cconsts.NETWORK_CB_KEY_ID, dut2_req_key))
1505
1506            # validate no leak of information
1507            asserts.assert_false(
1508                cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in dut1_net_event_nc[
1509                    "data"], "Network specifier leak!")
1510            asserts.assert_false(
1511                cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in dut2_net_event_nc[
1512                    "data"], "Network specifier leak!")
1513
1514            # Note: dut1 <--> dut2 IPv6's addresses since it is peer's info
1515            dut2_aware_ipv6 = dut1_net_event_nc["data"][aconsts.NET_CAP_IPV6]
1516            dut1_aware_ipv6 = dut2_net_event_nc["data"][aconsts.NET_CAP_IPV6]
1517
1518            dut1_net_event_lp = autils.wait_for_event_with_keys(
1519                dut1, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1520                (cconsts.NETWORK_CB_KEY_EVENT,
1521                 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
1522                (cconsts.NETWORK_CB_KEY_ID, dut1_req_key))
1523            dut2_net_event_lp = autils.wait_for_event_with_keys(
1524                dut2, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1525                (cconsts.NETWORK_CB_KEY_EVENT,
1526                 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
1527                (cconsts.NETWORK_CB_KEY_ID, dut2_req_key))
1528
1529            dut2_aware_if = dut2_net_event_lp["data"][
1530                cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
1531            dut1_aware_if = dut1_net_event_lp["data"][
1532                cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
1533
1534            dut2_aware_ifs.append(dut2_aware_if)
1535            dut1_aware_ifs.append(dut1_aware_if)
1536            dut2_aware_ipv6s.append(dut2_aware_ipv6)
1537            dut1_aware_ipv6s.append(dut1_aware_ipv6)
1538
1539            if flip_init_resp:
1540                if dut2_is_responder:
1541                    dut2_type = aconsts.DATA_PATH_INITIATOR
1542                    dut1_type = aconsts.DATA_PATH_RESPONDER
1543                else:
1544                    dut2_type = aconsts.DATA_PATH_RESPONDER
1545                    dut1_type = aconsts.DATA_PATH_INITIATOR
1546                dut2_is_responder = not dut2_is_responder
1547
1548        # check that we are using 2 NDIs & that they have unique IPv6 addresses
1549        dut1_aware_ifs = list(set(dut1_aware_ifs))
1550        dut2_aware_ifs = list(set(dut2_aware_ifs))
1551        dut1_aware_ipv6s = list(set(dut1_aware_ipv6s))
1552        dut2_aware_ipv6s = list(set(dut2_aware_ipv6s))
1553
1554        self.log.info("Interface names: DUT1=%s, DUT2=%s", dut1_aware_ifs,
1555                      dut2_aware_ifs)
1556        self.log.info("IPv6 addresses: DUT1=%s, DUT2=%s", dut1_aware_ipv6s,
1557                      dut2_aware_ipv6s)
1558        self.log.info("DUT1 requests: %s", dut1_req_keys)
1559        self.log.info("DUT2 requests: %s", dut2_req_keys)
1560
1561        asserts.assert_equal(
1562            len(dut1_aware_ifs), len(sec_configs), "Multiple DUT1 interfaces")
1563        asserts.assert_equal(
1564            len(dut2_aware_ifs), len(sec_configs), "Multiple DUT2 interfaces")
1565        asserts.assert_equal(
1566            len(dut1_aware_ipv6s), len(sec_configs),
1567            "Multiple DUT1 IPv6 addresses")
1568        asserts.assert_equal(
1569            len(dut2_aware_ipv6s), len(sec_configs),
1570            "Multiple DUT2 IPv6 addresses")
1571
1572        for i in range(len(sec_configs)):
1573            # note: using get_ipv6_addr (ifconfig method) since want to verify
1574            # that the system information is the same as the reported information
1575            if_name = "%s%d" % (aconsts.AWARE_NDI_PREFIX, i)
1576            dut1_ipv6 = autils.get_ipv6_addr(dut1, if_name)
1577            dut2_ipv6 = autils.get_ipv6_addr(dut2, if_name)
1578
1579            asserts.assert_equal(
1580                dut1_ipv6 is None, if_name not in dut1_aware_ifs,
1581                "DUT1 interface %s in unexpected state" % if_name)
1582            asserts.assert_equal(
1583                dut2_ipv6 is None, if_name not in dut2_aware_ifs,
1584                "DUT2 interface %s in unexpected state" % if_name)
1585
1586        # release requests
1587        for dut2_req_key in dut2_req_keys:
1588            dut2.droid.connectivityUnregisterNetworkCallback(dut2_req_key)
1589        for dut1_req_key in dut1_req_keys:
1590            dut1.droid.connectivityUnregisterNetworkCallback(dut1_req_key)
1591
1592    @test_tracker_info(uuid="2d728163-11cc-46ba-a973-c8e1e71397fc")
1593    def test_multiple_ndi_open_passphrase(self):
1594        """Verify that between 2 DUTs can create 2 NDPs with different security
1595    configuration (one open, one using passphrase). The result should use two
1596    different NDIs"""
1597        self.run_multiple_ndi([None, self.PASSPHRASE])
1598
1599    @test_tracker_info(uuid="5f2c32aa-20b2-41f0-8b1e-d0b68df73ada")
1600    def test_multiple_ndi_open_pmk(self):
1601        """Verify that between 2 DUTs can create 2 NDPs with different security
1602    configuration (one open, one using pmk). The result should use two
1603    different NDIs"""
1604        self.run_multiple_ndi([None, self.PMK])
1605
1606    @test_tracker_info(uuid="34467659-bcfb-40cd-ba25-7e50560fca63")
1607    def test_multiple_ndi_passphrase_pmk(self):
1608        """Verify that between 2 DUTs can create 2 NDPs with different security
1609    configuration (one using passphrase, one using pmk). The result should use
1610    two different NDIs"""
1611        self.run_multiple_ndi([self.PASSPHRASE, self.PMK])
1612
1613    @test_tracker_info(uuid="d9194ce6-45b6-41b1-9cc8-ada79968966d")
1614    def test_multiple_ndi_passphrases(self):
1615        """Verify that between 2 DUTs can create 2 NDPs with different security
1616    configuration (using different passphrases). The result should use two
1617    different NDIs"""
1618        self.run_multiple_ndi([self.PASSPHRASE, self.PASSPHRASE2])
1619
1620    @test_tracker_info(uuid="879df795-62d2-40d4-a862-bd46d8f7e67f")
1621    def test_multiple_ndi_pmks(self):
1622        """Verify that between 2 DUTs can create 2 NDPs with different security
1623    configuration (using different PMKS). The result should use two different
1624    NDIs"""
1625        self.run_multiple_ndi([self.PMK, self.PMK2])
1626
1627    @test_tracker_info(uuid="397d380a-8e41-466e-9ccb-cf8f413d83ba")
1628    def test_multiple_ndi_open_passphrase_flip(self):
1629        """Verify that between 2 DUTs can create 2 NDPs with different security
1630    configuration (one open, one using passphrase). The result should use two
1631    different NDIs.
1632
1633    Flip Initiator and Responder roles.
1634    """
1635        self.run_multiple_ndi([None, self.PASSPHRASE], flip_init_resp=True)
1636
1637    @test_tracker_info(uuid="b3a4300b-1514-4cb8-a814-9c2baa449700")
1638    def test_multiple_ndi_open_pmk_flip(self):
1639        """Verify that between 2 DUTs can create 2 NDPs with different security
1640    configuration (one open, one using pmk). The result should use two
1641    different NDIs
1642
1643    Flip Initiator and Responder roles.
1644    """
1645        self.run_multiple_ndi([None, self.PMK], flip_init_resp=True)
1646
1647    @test_tracker_info(uuid="0bfea9e4-e57d-417f-8db4-245741e9bbd5")
1648    def test_multiple_ndi_passphrase_pmk_flip(self):
1649        """Verify that between 2 DUTs can create 2 NDPs with different security
1650    configuration (one using passphrase, one using pmk). The result should use
1651    two different NDIs
1652
1653    Flip Initiator and Responder roles.
1654    """
1655        self.run_multiple_ndi([self.PASSPHRASE, self.PMK], flip_init_resp=True)
1656
1657    @test_tracker_info(uuid="74023483-5417-431b-a362-991ad4a03ab8")
1658    def test_multiple_ndi_passphrases_flip(self):
1659        """Verify that between 2 DUTs can create 2 NDPs with different security
1660    configuration (using different passphrases). The result should use two
1661    different NDIs
1662
1663    Flip Initiator and Responder roles.
1664    """
1665        self.run_multiple_ndi(
1666            [self.PASSPHRASE, self.PASSPHRASE2], flip_init_resp=True)
1667
1668    @test_tracker_info(uuid="873b2d91-28a1-403f-ae9c-d756bb2f59ee")
1669    def test_multiple_ndi_pmks_flip(self):
1670        """Verify that between 2 DUTs can create 2 NDPs with different security
1671    configuration (using different PMKS). The result should use two different
1672    NDIs
1673
1674    Flip Initiator and Responder roles.
1675    """
1676        self.run_multiple_ndi([self.PMK, self.PMK2], flip_init_resp=True)
1677
1678    #######################################
1679
1680    @test_tracker_info(uuid="2f10a9df-7fbd-490d-a238-3523f47ab54c")
1681    def test_ib_responder_any_usage(self):
1682        """Verify that configuring an in-band (Aware discovery) Responder to receive
1683    an NDP request from any peer is not permitted by current API level. Override
1684    API check to validate that possible (i.e. that failure at current API level
1685    is due to an API check and not some underlying failure).
1686    """
1687
1688        # configure all devices to override API check and allow a Responder from ANY
1689        for ad in self.android_devices:
1690            autils.configure_ndp_allow_any_override(ad, True)
1691        self.run_ib_data_path_test(
1692            ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
1693            stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
1694            encr_type=self.ENCR_TYPE_OPEN,
1695            use_peer_id=False)
1696
1697        # configure all devices to respect API check - i.e. disallow a Responder
1698        # from ANY
1699        for ad in self.android_devices:
1700            autils.configure_ndp_allow_any_override(ad, False)
1701        self.run_ib_data_path_test(
1702            ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
1703            stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
1704            encr_type=self.ENCR_TYPE_OPEN,
1705            use_peer_id=False,
1706            expect_failure=True)
1707
1708    @test_tracker_info(uuid="5889cd41-0a72-4b7b-ab82-5b9168b9b5b8")
1709    def test_oob_responder_any_usage(self):
1710        """Verify that configuring an out-of-band (Aware discovery) Responder to
1711    receive an NDP request from any peer is not permitted by current API level.
1712    Override API check to validate that possible (i.e. that failure at current
1713    API level is due to an API check and not some underlying failure).
1714    """
1715
1716        # configure all devices to override API check and allow a Responder from ANY
1717        for ad in self.android_devices:
1718            autils.configure_ndp_allow_any_override(ad, True)
1719        self.run_oob_data_path_test(
1720            encr_type=self.ENCR_TYPE_OPEN, use_peer_id=False)
1721
1722        # configure all devices to respect API check - i.e. disallow a Responder
1723        # from ANY
1724        for ad in self.android_devices:
1725            autils.configure_ndp_allow_any_override(ad, False)
1726        self.run_oob_data_path_test(
1727            encr_type=self.ENCR_TYPE_OPEN,
1728            use_peer_id=False,
1729            expect_failure=True)
1730
1731    #######################################
1732
1733    def run_multiple_regulatory_domains(self, use_ib, init_domain,
1734                                        resp_domain):
1735        """Verify that a data-path setup with two conflicting regulatory domains
1736    works (the result should be run in Channel 6 - but that is not tested).
1737
1738    Args:
1739      use_ib: True to use in-band discovery, False to use out-of-band discovery.
1740      init_domain: The regulatory domain of the Initiator/Subscriber.
1741      resp_domain: The regulator domain of the Responder/Publisher.
1742    """
1743        init_dut = self.android_devices[0]
1744        resp_dut = self.android_devices[1]
1745
1746        init_dut.droid.wifiSetCountryCode(init_domain)
1747        resp_dut.droid.wifiSetCountryCode(resp_domain)
1748
1749        if use_ib:
1750            (resp_req_key, init_req_key, resp_aware_if, init_aware_if,
1751             resp_ipv6, init_ipv6) = autils.create_ib_ndp(
1752                 resp_dut, init_dut,
1753                 autils.create_discovery_config(
1754                     "GoogleTestXyz", aconsts.PUBLISH_TYPE_UNSOLICITED),
1755                 autils.create_discovery_config(
1756                     "GoogleTestXyz", aconsts.SUBSCRIBE_TYPE_PASSIVE),
1757                 self.device_startup_offset)
1758        else:
1759            (init_req_key, resp_req_key, init_aware_if, resp_aware_if,
1760             init_ipv6, resp_ipv6) = autils.create_oob_ndp(init_dut, resp_dut)
1761
1762        self.log.info("Interface names: I=%s, R=%s", init_aware_if,
1763                      resp_aware_if)
1764        self.log.info("Interface addresses (IPv6): I=%s, R=%s", init_ipv6,
1765                      resp_ipv6)
1766
1767        # clean-up
1768        resp_dut.droid.connectivityUnregisterNetworkCallback(resp_req_key)
1769        init_dut.droid.connectivityUnregisterNetworkCallback(init_req_key)
1770
1771    @test_tracker_info(uuid="eff53739-35c5-47a6-81f0-d70b51d89c3b")
1772    def test_multiple_regulator_domains_ib_us_jp(self):
1773        """Verify data-path setup across multiple regulator domains.
1774
1775    - Uses in-band discovery
1776    - Subscriber=US, Publisher=JP
1777    """
1778        self.run_multiple_regulatory_domains(
1779            use_ib=True,
1780            init_domain=wutils.WifiEnums.CountryCode.US,
1781            resp_domain=wutils.WifiEnums.CountryCode.JAPAN)
1782
1783    @test_tracker_info(uuid="19af47cc-3204-40ef-b50f-14cf7b89cf4a")
1784    def test_multiple_regulator_domains_ib_jp_us(self):
1785        """Verify data-path setup across multiple regulator domains.
1786
1787    - Uses in-band discovery
1788    - Subscriber=JP, Publisher=US
1789    """
1790        self.run_multiple_regulatory_domains(
1791            use_ib=True,
1792            init_domain=wutils.WifiEnums.CountryCode.JAPAN,
1793            resp_domain=wutils.WifiEnums.CountryCode.US)
1794
1795    @test_tracker_info(uuid="65285ab3-977f-4dbd-b663-d5a02f4fc663")
1796    def test_multiple_regulator_domains_oob_us_jp(self):
1797        """Verify data-path setup across multiple regulator domains.
1798
1799    - Uses out-f-band discovery
1800    - Initiator=US, Responder=JP
1801    """
1802        self.run_multiple_regulatory_domains(
1803            use_ib=False,
1804            init_domain=wutils.WifiEnums.CountryCode.US,
1805            resp_domain=wutils.WifiEnums.CountryCode.JAPAN)
1806
1807    @test_tracker_info(uuid="8a417e24-aaf6-44b9-a089-a07c3ba8d954")
1808    def test_multiple_regulator_domains_oob_jp_us(self):
1809        """Verify data-path setup across multiple regulator domains.
1810
1811    - Uses out-of-band discovery
1812    - Initiator=JP, Responder=US
1813    """
1814        self.run_multiple_regulatory_domains(
1815            use_ib=False,
1816            init_domain=wutils.WifiEnums.CountryCode.JAPAN,
1817            resp_domain=wutils.WifiEnums.CountryCode.US)
1818
1819    ########################################################################
1820
1821    def run_mix_ib_oob(self, same_request, ib_first, inits_on_same_dut):
1822        """Validate that multiple network requests issued using both in-band and
1823    out-of-band discovery behave as expected.
1824
1825    The same_request parameter controls whether identical single NDP is
1826    expected, if True, or whether multiple NDPs on different NDIs are expected,
1827    if False.
1828
1829    Args:
1830      same_request: Issue canonically identical requests (same NMI peer, same
1831                    passphrase) if True, if False use different passphrases.
1832      ib_first: If True then the in-band network is requested first, otherwise
1833                (if False) then the out-of-band network is requested first.
1834      inits_on_same_dut: If True then the Initiators are run on the same device,
1835                         otherwise (if False) then the Initiators are run on
1836                         different devices. Note that Subscribe == Initiator.
1837    """
1838        if not same_request:
1839            asserts.skip_if(
1840                self.android_devices[0]
1841                .aware_capabilities[aconsts.CAP_MAX_NDI_INTERFACES] < 2
1842                or self.android_devices[1]
1843                .aware_capabilities[aconsts.CAP_MAX_NDI_INTERFACES] < 2,
1844                "DUTs do not support enough NDIs")
1845
1846        (p_dut, s_dut, p_id, s_id, p_disc_id, s_disc_id, peer_id_on_sub,
1847         peer_id_on_pub_null) = self.set_up_discovery(
1848             aconsts.PUBLISH_TYPE_UNSOLICITED, aconsts.SUBSCRIBE_TYPE_PASSIVE,
1849             False)
1850
1851        p_id2, p_mac = autils.attach_with_identity(p_dut)
1852        s_id2, s_mac = autils.attach_with_identity(s_dut)
1853
1854        if inits_on_same_dut:
1855            resp_dut = p_dut
1856            resp_id = p_id2
1857            resp_mac = p_mac
1858
1859            init_dut = s_dut
1860            init_id = s_id2
1861            init_mac = s_mac
1862        else:
1863            resp_dut = s_dut
1864            resp_id = s_id2
1865            resp_mac = s_mac
1866
1867            init_dut = p_dut
1868            init_id = p_id2
1869            init_mac = p_mac
1870
1871        passphrase = None if same_request else self.PASSPHRASE
1872
1873        if ib_first:
1874            # request in-band network (to completion)
1875            p_req_key = self.request_network(
1876                p_dut,
1877                p_dut.droid.wifiAwareCreateNetworkSpecifier(p_disc_id, None))
1878            s_req_key = self.request_network(
1879                s_dut,
1880                s_dut.droid.wifiAwareCreateNetworkSpecifier(
1881                    s_disc_id, peer_id_on_sub))
1882
1883            # Publisher & Subscriber: wait for network formation
1884            p_net_event_nc = autils.wait_for_event_with_keys(
1885                p_dut, cconsts.EVENT_NETWORK_CALLBACK,
1886                autils.EVENT_NDP_TIMEOUT,
1887                (cconsts.NETWORK_CB_KEY_EVENT,
1888                 cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
1889                (cconsts.NETWORK_CB_KEY_ID, p_req_key))
1890            s_net_event_nc = autils.wait_for_event_with_keys(
1891                s_dut, cconsts.EVENT_NETWORK_CALLBACK,
1892                autils.EVENT_NDP_TIMEOUT,
1893                (cconsts.NETWORK_CB_KEY_EVENT,
1894                 cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
1895                (cconsts.NETWORK_CB_KEY_ID, s_req_key))
1896            p_net_event_lp = autils.wait_for_event_with_keys(
1897                p_dut, cconsts.EVENT_NETWORK_CALLBACK,
1898                autils.EVENT_NDP_TIMEOUT,
1899                (cconsts.NETWORK_CB_KEY_EVENT,
1900                 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
1901                (cconsts.NETWORK_CB_KEY_ID, p_req_key))
1902            s_net_event_lp = autils.wait_for_event_with_keys(
1903                s_dut, cconsts.EVENT_NETWORK_CALLBACK,
1904                autils.EVENT_NDP_TIMEOUT,
1905                (cconsts.NETWORK_CB_KEY_EVENT,
1906                 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
1907                (cconsts.NETWORK_CB_KEY_ID, s_req_key))
1908
1909            # validate no leak of information
1910            asserts.assert_false(
1911                cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in p_net_event_nc[
1912                    "data"], "Network specifier leak!")
1913            asserts.assert_false(
1914                cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in s_net_event_nc[
1915                    "data"], "Network specifier leak!")
1916
1917        # request out-of-band network
1918        resp_req_key = autils.request_network(
1919            resp_dut,
1920            resp_dut.droid.wifiAwareCreateNetworkSpecifierOob(
1921                resp_id, aconsts.DATA_PATH_RESPONDER, init_mac, passphrase))
1922        init_req_key = autils.request_network(
1923            init_dut,
1924            init_dut.droid.wifiAwareCreateNetworkSpecifierOob(
1925                init_id, aconsts.DATA_PATH_INITIATOR, resp_mac, passphrase))
1926
1927        resp_net_event_nc = autils.wait_for_event_with_keys(
1928            resp_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1929            (cconsts.NETWORK_CB_KEY_EVENT,
1930             cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
1931            (cconsts.NETWORK_CB_KEY_ID, resp_req_key))
1932        init_net_event_nc = autils.wait_for_event_with_keys(
1933            init_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1934            (cconsts.NETWORK_CB_KEY_EVENT,
1935             cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
1936            (cconsts.NETWORK_CB_KEY_ID, init_req_key))
1937        resp_net_event_lp = autils.wait_for_event_with_keys(
1938            resp_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1939            (cconsts.NETWORK_CB_KEY_EVENT,
1940             cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
1941            (cconsts.NETWORK_CB_KEY_ID, resp_req_key))
1942        init_net_event_lp = autils.wait_for_event_with_keys(
1943            init_dut, cconsts.EVENT_NETWORK_CALLBACK, autils.EVENT_NDP_TIMEOUT,
1944            (cconsts.NETWORK_CB_KEY_EVENT,
1945             cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
1946            (cconsts.NETWORK_CB_KEY_ID, init_req_key))
1947
1948        # validate no leak of information
1949        asserts.assert_false(
1950            cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in resp_net_event_nc[
1951                "data"], "Network specifier leak!")
1952        asserts.assert_false(
1953            cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in init_net_event_nc[
1954                "data"], "Network specifier leak!")
1955
1956        if not ib_first:
1957            # request in-band network (to completion)
1958            p_req_key = self.request_network(
1959                p_dut,
1960                p_dut.droid.wifiAwareCreateNetworkSpecifier(p_disc_id, None))
1961            s_req_key = self.request_network(
1962                s_dut,
1963                s_dut.droid.wifiAwareCreateNetworkSpecifier(
1964                    s_disc_id, peer_id_on_sub))
1965
1966            # Publisher & Subscriber: wait for network formation
1967            p_net_event_nc = autils.wait_for_event_with_keys(
1968                p_dut, cconsts.EVENT_NETWORK_CALLBACK,
1969                autils.EVENT_NDP_TIMEOUT,
1970                (cconsts.NETWORK_CB_KEY_EVENT,
1971                 cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
1972                (cconsts.NETWORK_CB_KEY_ID, p_req_key))
1973            s_net_event_nc = autils.wait_for_event_with_keys(
1974                s_dut, cconsts.EVENT_NETWORK_CALLBACK,
1975                autils.EVENT_NDP_TIMEOUT,
1976                (cconsts.NETWORK_CB_KEY_EVENT,
1977                 cconsts.NETWORK_CB_CAPABILITIES_CHANGED),
1978                (cconsts.NETWORK_CB_KEY_ID, s_req_key))
1979            p_net_event_lp = autils.wait_for_event_with_keys(
1980                p_dut, cconsts.EVENT_NETWORK_CALLBACK,
1981                autils.EVENT_NDP_TIMEOUT,
1982                (cconsts.NETWORK_CB_KEY_EVENT,
1983                 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
1984                (cconsts.NETWORK_CB_KEY_ID, p_req_key))
1985            s_net_event_lp = autils.wait_for_event_with_keys(
1986                s_dut, cconsts.EVENT_NETWORK_CALLBACK,
1987                autils.EVENT_NDP_TIMEOUT,
1988                (cconsts.NETWORK_CB_KEY_EVENT,
1989                 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED),
1990                (cconsts.NETWORK_CB_KEY_ID, s_req_key))
1991
1992            # validate no leak of information
1993            asserts.assert_false(
1994                cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in p_net_event_nc[
1995                    "data"], "Network specifier leak!")
1996            asserts.assert_false(
1997                cconsts.NETWORK_CB_KEY_NETWORK_SPECIFIER in s_net_event_nc[
1998                    "data"], "Network specifier leak!")
1999
2000        # note that Init <-> Resp & Pub <--> Sub since IPv6 are of peer's!
2001        init_ipv6 = resp_net_event_nc["data"][aconsts.NET_CAP_IPV6]
2002        resp_ipv6 = init_net_event_nc["data"][aconsts.NET_CAP_IPV6]
2003        pub_ipv6 = s_net_event_nc["data"][aconsts.NET_CAP_IPV6]
2004        sub_ipv6 = p_net_event_nc["data"][aconsts.NET_CAP_IPV6]
2005
2006        # extract net info
2007        pub_interface = p_net_event_lp["data"][
2008            cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
2009        sub_interface = s_net_event_lp["data"][
2010            cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
2011        resp_interface = resp_net_event_lp["data"][
2012            cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
2013        init_interface = init_net_event_lp["data"][
2014            cconsts.NETWORK_CB_KEY_INTERFACE_NAME]
2015
2016        self.log.info("Interface names: Pub=%s, Sub=%s, Resp=%s, Init=%s",
2017                      pub_interface, sub_interface, resp_interface,
2018                      init_interface)
2019        self.log.info(
2020            "Interface addresses (IPv6): Pub=%s, Sub=%s, Resp=%s, Init=%s",
2021            pub_ipv6, sub_ipv6, resp_ipv6, init_ipv6)
2022
2023        # validate NDP/NDI conditions (using interface names & ipv6)
2024        if same_request:
2025            asserts.assert_equal(
2026                pub_interface, resp_interface if inits_on_same_dut else
2027                init_interface, "NDP interfaces don't match on Pub/other")
2028            asserts.assert_equal(
2029                sub_interface, init_interface if inits_on_same_dut else
2030                resp_interface, "NDP interfaces don't match on Sub/other")
2031
2032            asserts.assert_equal(pub_ipv6, resp_ipv6
2033                                 if inits_on_same_dut else init_ipv6,
2034                                 "NDP IPv6 don't match on Pub/other")
2035            asserts.assert_equal(sub_ipv6, init_ipv6
2036                                 if inits_on_same_dut else resp_ipv6,
2037                                 "NDP IPv6 don't match on Sub/other")
2038        else:
2039            asserts.assert_false(
2040                pub_interface == (resp_interface
2041                                  if inits_on_same_dut else init_interface),
2042                "NDP interfaces match on Pub/other")
2043            asserts.assert_false(
2044                sub_interface == (init_interface
2045                                  if inits_on_same_dut else resp_interface),
2046                "NDP interfaces match on Sub/other")
2047
2048            asserts.assert_false(
2049                pub_ipv6 == (resp_ipv6 if inits_on_same_dut else init_ipv6),
2050                "NDP IPv6 match on Pub/other")
2051            asserts.assert_false(
2052                sub_ipv6 == (init_ipv6 if inits_on_same_dut else resp_ipv6),
2053                "NDP IPv6 match on Sub/other")
2054
2055        # release requests
2056        p_dut.droid.connectivityUnregisterNetworkCallback(p_req_key)
2057        s_dut.droid.connectivityUnregisterNetworkCallback(s_req_key)
2058        resp_dut.droid.connectivityUnregisterNetworkCallback(resp_req_key)
2059        init_dut.droid.connectivityUnregisterNetworkCallback(init_req_key)
2060
2061    @test_tracker_info(uuid="d8a0839d-4ba0-43f2-af93-3cf1382f9f16")
2062    def test_identical_ndps_mix_ib_oob_ib_first_same_polarity(self):
2063        """Validate that a single NDP is created for multiple identical requests
2064    which are issued through either in-band (ib) or out-of-band (oob) APIs.
2065
2066    The in-band request is issued first. Both Initiators (Sub == Initiator) are
2067    run on the same device.
2068    """
2069        self.run_mix_ib_oob(
2070            same_request=True, ib_first=True, inits_on_same_dut=True)
2071
2072    @test_tracker_info(uuid="70bbb811-0bed-4a19-96b3-f2446e777c8a")
2073    def test_identical_ndps_mix_ib_oob_oob_first_same_polarity(self):
2074        """Validate that a single NDP is created for multiple identical requests
2075    which are issued through either in-band (ib) or out-of-band (oob) APIs.
2076
2077    The out-of-band request is issued first. Both Initiators (Sub == Initiator)
2078    are run on the same device.
2079    """
2080        self.run_mix_ib_oob(
2081            same_request=True, ib_first=False, inits_on_same_dut=True)
2082
2083    @test_tracker_info(uuid="d9796da5-f96a-4a51-be0f-89d6f5bfe3ad")
2084    def test_identical_ndps_mix_ib_oob_ib_first_diff_polarity(self):
2085        """Validate that a single NDP is created for multiple identical requests
2086    which are issued through either in-band (ib) or out-of-band (oob) APIs.
2087
2088    The in-band request is issued first. Initiators (Sub == Initiator) are
2089    run on different devices.
2090    """
2091        self.run_mix_ib_oob(
2092            same_request=True, ib_first=True, inits_on_same_dut=False)
2093
2094    @test_tracker_info(uuid="72b16cbf-53ad-4f98-8dcf-a8cc5fa812e3")
2095    def test_identical_ndps_mix_ib_oob_oob_first_diff_polarity(self):
2096        """Validate that a single NDP is created for multiple identical requests
2097    which are issued through either in-band (ib) or out-of-band (oob) APIs.
2098
2099    The out-of-band request is issued first. Initiators (Sub == Initiator) are
2100    run on different devices.
2101    """
2102        self.run_mix_ib_oob(
2103            same_request=True, ib_first=False, inits_on_same_dut=False)
2104
2105    @test_tracker_info(uuid="51f9581e-c5ee-48a7-84d2-adff4876c3d7")
2106    def test_multiple_ndis_mix_ib_oob_ib_first_same_polarity(self):
2107        """Validate that multiple NDIs are created for NDPs which are requested with
2108    different security configurations. Use a mix of in-band and out-of-band APIs
2109    to request the different NDPs.
2110
2111    The in-band request is issued first. Initiators (Sub == Initiator) are
2112    run on the same device.
2113    """
2114        self.run_mix_ib_oob(
2115            same_request=False, ib_first=True, inits_on_same_dut=True)
2116
2117    @test_tracker_info(uuid="b1e3070e-4d38-4b31-862d-39b82e0f2853")
2118    def test_multiple_ndis_mix_ib_oob_oob_first_same_polarity(self):
2119        """Validate that multiple NDIs are created for NDPs which are requested with
2120    different security configurations. Use a mix of in-band and out-of-band APIs
2121    to request the different NDPs.
2122
2123    The out-of-band request is issued first. Initiators (Sub == Initiator) are
2124    run on the same device.
2125    """
2126        self.run_mix_ib_oob(
2127            same_request=False, ib_first=False, inits_on_same_dut=True)
2128
2129    @test_tracker_info(uuid="b1e3070e-4d38-4b31-862d-39b82e0f2853")
2130    def test_multiple_ndis_mix_ib_oob_ib_first_diff_polarity(self):
2131        """Validate that multiple NDIs are created for NDPs which are requested with
2132    different security configurations. Use a mix of in-band and out-of-band APIs
2133    to request the different NDPs.
2134
2135    The in-band request is issued first. Initiators (Sub == Initiator) are
2136    run on different devices.
2137    """
2138        self.run_mix_ib_oob(
2139            same_request=False, ib_first=True, inits_on_same_dut=False)
2140
2141    @test_tracker_info(uuid="596caadf-028e-494b-bbce-8304ccec2cbb")
2142    def test_multiple_ndis_mix_ib_oob_oob_first_diff_polarity(self):
2143        """Validate that multiple NDIs are created for NDPs which are requested with
2144    different security configurations. Use a mix of in-band and out-of-band APIs
2145    to request the different NDPs.
2146
2147    The out-of-band request is issued first. Initiators (Sub == Initiator) are
2148    run on different devices.
2149    """
2150        self.run_mix_ib_oob(
2151            same_request=False, ib_first=False, inits_on_same_dut=False)
2152
2153    ########################################################################
2154
2155    def test_ndp_loop(self):
2156        """Validate that can create a loop (chain) of N NDPs between N devices,
2157    where N >= 3, e.g.
2158
2159    A - B
2160    B - C
2161    C - A
2162
2163    The NDPs are all OPEN (no encryption).
2164    """
2165        asserts.assert_true(
2166            len(self.android_devices) >= 3,
2167            'A minimum of 3 devices is needed to run the test, have %d' % len(
2168                self.android_devices))
2169
2170        duts = self.android_devices
2171        loop_len = len(duts)
2172        ids = []
2173        macs = []
2174        reqs = []
2175        ifs = []
2176        ipv6s = []
2177
2178        for i in range(loop_len):
2179            duts[i].pretty_name = chr(ord("A") + i)
2180            reqs.append([])
2181            ifs.append([])
2182            ipv6s.append([])
2183
2184        # start-up 3 devices (attach w/ identity)
2185        for i in range(loop_len):
2186            ids.append(duts[i].droid.wifiAwareAttach(True))
2187            autils.wait_for_event(duts[i], aconsts.EVENT_CB_ON_ATTACHED)
2188            ident_event = autils.wait_for_event(
2189                duts[i], aconsts.EVENT_CB_ON_IDENTITY_CHANGED)
2190            macs.append(ident_event['data']['mac'])
2191
2192        # wait for for devices to synchronize with each other - there are no other
2193        # mechanisms to make sure this happens for OOB discovery (except retrying
2194        # to execute the data-path request)
2195        time.sleep(autils.WAIT_FOR_CLUSTER)
2196
2197        # create the N NDPs: i to (i+1) % N
2198        for i in range(loop_len):
2199            peer_device = (i + 1) % loop_len
2200
2201            (init_req_key, resp_req_key, init_aware_if, resp_aware_if,
2202             init_ipv6, resp_ipv6) = autils.create_oob_ndp_on_sessions(
2203                 duts[i], duts[peer_device], ids[i], macs[i], ids[peer_device],
2204                 macs[peer_device])
2205
2206            reqs[i].append(init_req_key)
2207            reqs[peer_device].append(resp_req_key)
2208            ifs[i].append(init_aware_if)
2209            ifs[peer_device].append(resp_aware_if)
2210            ipv6s[i].append(init_ipv6)
2211            ipv6s[peer_device].append(resp_ipv6)
2212
2213        # clean-up
2214        for i in range(loop_len):
2215            for req in reqs[i]:
2216                duts[i].droid.connectivityUnregisterNetworkCallback(req)
2217
2218        # info
2219        self.log.info("MACs: %s", macs)
2220        self.log.info("Interface names: %s", ifs)
2221        self.log.info("IPv6 addresses: %s", ipv6s)
2222        asserts.explicit_pass(
2223            "NDP loop test", extras={
2224                "macs": macs,
2225                "ifs": ifs,
2226                "ipv6s": ipv6s
2227            })
2228