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