Home | History | Annotate | Download | only in functional
      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 
     17 import string
     18 import time
     19 
     20 from acts import asserts
     21 from acts.test_decorators import test_tracker_info
     22 from acts.test_utils.wifi.aware import aware_const as aconsts
     23 from acts.test_utils.wifi.aware import aware_test_utils as autils
     24 from acts.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest
     25 
     26 
     27 class DiscoveryTest(AwareBaseTest):
     28   """Set of tests for Wi-Fi Aware discovery."""
     29 
     30   # configuration parameters used by tests
     31   PAYLOAD_SIZE_MIN = 0
     32   PAYLOAD_SIZE_TYPICAL = 1
     33   PAYLOAD_SIZE_MAX = 2
     34 
     35   # message strings
     36   query_msg = "How are you doing? "
     37   response_msg = "Doing ok - thanks!  - "
     38 
     39   # message re-transmit counter (increases reliability in open-environment)
     40   # Note: reliability of message transmission is tested elsewhere
     41   msg_retx_count = 5  # hard-coded max value, internal API
     42 
     43   def __init__(self, controllers):
     44     AwareBaseTest.__init__(self, controllers)
     45 
     46   def create_base_config(self, caps, is_publish, ptype, stype, payload_size,
     47                          ttl, term_ind_on, null_match):
     48     """Create a base configuration based on input parameters.
     49 
     50     Args:
     51       caps: device capability dictionary
     52       is_publish: True if a publish config, else False
     53       ptype: unsolicited or solicited (used if is_publish is True)
     54       stype: passive or active (used if is_publish is False)
     55       payload_size: min, typical, max (PAYLOAD_SIZE_xx)
     56       ttl: time-to-live configuration (0 - forever)
     57       term_ind_on: is termination indication enabled
     58       null_match: null-out the middle match filter
     59     Returns:
     60       publish discovery configuration object.
     61     """
     62     config = {}
     63     if is_publish:
     64       config[aconsts.DISCOVERY_KEY_DISCOVERY_TYPE] = ptype
     65     else:
     66       config[aconsts.DISCOVERY_KEY_DISCOVERY_TYPE] = stype
     67     config[aconsts.DISCOVERY_KEY_TTL] = ttl
     68     config[aconsts.DISCOVERY_KEY_TERM_CB_ENABLED] = term_ind_on
     69     if payload_size == self.PAYLOAD_SIZE_MIN:
     70       config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = "a"
     71       config[aconsts.DISCOVERY_KEY_SSI] = None
     72       config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = []
     73     elif payload_size == self.PAYLOAD_SIZE_TYPICAL:
     74       config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = "GoogleTestServiceX"
     75       if is_publish:
     76         config[aconsts.DISCOVERY_KEY_SSI] = string.ascii_letters
     77       else:
     78         config[aconsts.DISCOVERY_KEY_SSI] = string.ascii_letters[::
     79                                                                  -1]  # reverse
     80       config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = autils.encode_list(
     81           [(10).to_bytes(1, byteorder="big"), "hello there string"
     82           if not null_match else None,
     83            bytes(range(40))])
     84     else: # PAYLOAD_SIZE_MAX
     85       config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = "VeryLong" + "X" * (
     86         caps[aconsts.CAP_MAX_SERVICE_NAME_LEN] - 8)
     87       config[aconsts.DISCOVERY_KEY_SSI] = ("P" if is_publish else "S") * caps[
     88         aconsts.CAP_MAX_SERVICE_SPECIFIC_INFO_LEN]
     89       mf = autils.construct_max_match_filter(
     90           caps[aconsts.CAP_MAX_MATCH_FILTER_LEN])
     91       if null_match:
     92         mf[2] = None
     93       config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = autils.encode_list(mf)
     94 
     95     return config
     96 
     97   def create_publish_config(self, caps, ptype, payload_size, ttl, term_ind_on,
     98                             null_match):
     99     """Create a publish configuration based on input parameters.
    100 
    101     Args:
    102       caps: device capability dictionary
    103       ptype: unsolicited or solicited
    104       payload_size: min, typical, max (PAYLOAD_SIZE_xx)
    105       ttl: time-to-live configuration (0 - forever)
    106       term_ind_on: is termination indication enabled
    107       null_match: null-out the middle match filter
    108     Returns:
    109       publish discovery configuration object.
    110     """
    111     return self.create_base_config(caps, True, ptype, None, payload_size, ttl,
    112                                    term_ind_on, null_match)
    113 
    114   def create_subscribe_config(self, caps, stype, payload_size, ttl, term_ind_on,
    115                               null_match):
    116     """Create a subscribe configuration based on input parameters.
    117 
    118     Args:
    119       caps: device capability dictionary
    120       stype: passive or active
    121       payload_size: min, typical, max (PAYLOAD_SIZE_xx)
    122       ttl: time-to-live configuration (0 - forever)
    123       term_ind_on: is termination indication enabled
    124       null_match: null-out the middle match filter
    125     Returns:
    126       subscribe discovery configuration object.
    127     """
    128     return self.create_base_config(caps, False, None, stype, payload_size, ttl,
    129                                    term_ind_on, null_match)
    130 
    131   def positive_discovery_test_utility(self, ptype, stype, payload_size):
    132     """Utility which runs a positive discovery test:
    133     - Discovery (publish/subscribe) with TTL=0 (non-self-terminating)
    134     - Exchange messages
    135     - Update publish/subscribe
    136     - Terminate
    137 
    138     Args:
    139       ptype: Publish discovery type
    140       stype: Subscribe discovery type
    141       payload_size: One of PAYLOAD_SIZE_* constants - MIN, TYPICAL, MAX
    142     """
    143     p_dut = self.android_devices[0]
    144     p_dut.pretty_name = "Publisher"
    145     s_dut = self.android_devices[1]
    146     s_dut.pretty_name = "Subscriber"
    147 
    148     # Publisher+Subscriber: attach and wait for confirmation
    149     p_id = p_dut.droid.wifiAwareAttach(False)
    150     autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED)
    151     time.sleep(self.device_startup_offset)
    152     s_id = s_dut.droid.wifiAwareAttach(False)
    153     autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED)
    154 
    155     # Publisher: start publish and wait for confirmation
    156     p_config = self.create_publish_config(
    157         p_dut.aware_capabilities,
    158         ptype,
    159         payload_size,
    160         ttl=0,
    161         term_ind_on=False,
    162         null_match=False)
    163     p_disc_id = p_dut.droid.wifiAwarePublish(p_id, p_config)
    164     autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
    165 
    166     # Subscriber: start subscribe and wait for confirmation
    167     s_config = self.create_subscribe_config(
    168         s_dut.aware_capabilities,
    169         stype,
    170         payload_size,
    171         ttl=0,
    172         term_ind_on=False,
    173         null_match=True)
    174     s_disc_id = s_dut.droid.wifiAwareSubscribe(s_id, s_config)
    175     autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED)
    176 
    177     # Subscriber: wait for service discovery
    178     discovery_event = autils.wait_for_event(
    179         s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
    180     peer_id_on_sub = discovery_event["data"][aconsts.SESSION_CB_KEY_PEER_ID]
    181 
    182     # Subscriber: validate contents of discovery:
    183     # - SSI: publisher's
    184     # - Match filter: UNSOLICITED - publisher, SOLICITED - subscriber
    185     autils.assert_equal_strings(
    186         bytes(discovery_event["data"][
    187             aconsts.SESSION_CB_KEY_SERVICE_SPECIFIC_INFO]).decode("utf-8"),
    188         p_config[aconsts.DISCOVERY_KEY_SSI],
    189         "Discovery mismatch: service specific info (SSI)")
    190     asserts.assert_equal(
    191         autils.decode_list(
    192             discovery_event["data"][aconsts.SESSION_CB_KEY_MATCH_FILTER_LIST]),
    193         autils.decode_list(p_config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST]
    194                            if ptype == aconsts.PUBLISH_TYPE_UNSOLICITED else
    195                            s_config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST]),
    196         "Discovery mismatch: match filter")
    197 
    198     # Subscriber: send message to peer (Publisher)
    199     s_dut.droid.wifiAwareSendMessage(s_disc_id, peer_id_on_sub,
    200                                      self.get_next_msg_id(), self.query_msg,
    201                                      self.msg_retx_count)
    202     autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_MESSAGE_SENT)
    203 
    204     # Publisher: wait for received message
    205     pub_rx_msg_event = autils.wait_for_event(
    206         p_dut, aconsts.SESSION_CB_ON_MESSAGE_RECEIVED)
    207     peer_id_on_pub = pub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_PEER_ID]
    208 
    209     # Publisher: validate contents of message
    210     asserts.assert_equal(
    211         pub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING],
    212         self.query_msg, "Subscriber -> Publisher message corrupted")
    213 
    214     # Publisher: send message to peer (Subscriber)
    215     p_dut.droid.wifiAwareSendMessage(p_disc_id, peer_id_on_pub,
    216                                      self.get_next_msg_id(), self.response_msg,
    217                                      self.msg_retx_count)
    218     autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_MESSAGE_SENT)
    219 
    220     # Subscriber: wait for received message
    221     sub_rx_msg_event = autils.wait_for_event(
    222         s_dut, aconsts.SESSION_CB_ON_MESSAGE_RECEIVED)
    223 
    224     # Subscriber: validate contents of message
    225     asserts.assert_equal(
    226         sub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_PEER_ID],
    227         peer_id_on_sub,
    228         "Subscriber received message from different peer ID then discovery!?")
    229     autils.assert_equal_strings(
    230         sub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING],
    231         self.response_msg, "Publisher -> Subscriber message corrupted")
    232 
    233     # Subscriber: validate that we're not getting another Service Discovery
    234     autils.fail_on_event(s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
    235 
    236     # Publisher: update publish and wait for confirmation
    237     p_config[aconsts.DISCOVERY_KEY_SSI] = "something else"
    238     p_dut.droid.wifiAwareUpdatePublish(p_disc_id, p_config)
    239     autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED)
    240 
    241     # Subscriber: expect a new service discovery
    242     discovery_event = autils.wait_for_event(
    243         s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
    244 
    245     # Subscriber: validate contents of discovery
    246     autils.assert_equal_strings(
    247         bytes(discovery_event["data"][
    248             aconsts.SESSION_CB_KEY_SERVICE_SPECIFIC_INFO]).decode("utf-8"),
    249         p_config[aconsts.DISCOVERY_KEY_SSI],
    250         "Discovery mismatch (after pub update): service specific info (SSI)")
    251     asserts.assert_equal(
    252         autils.decode_list(
    253             discovery_event["data"][aconsts.SESSION_CB_KEY_MATCH_FILTER_LIST]),
    254         autils.decode_list(p_config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST]
    255                            if ptype == aconsts.PUBLISH_TYPE_UNSOLICITED else
    256                            s_config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST]),
    257         "Discovery mismatch: match filter")
    258 
    259     # Subscribe: update subscribe and wait for confirmation
    260     s_config = self.create_subscribe_config(
    261         s_dut.aware_capabilities,
    262         stype,
    263         payload_size,
    264         ttl=0,
    265         term_ind_on=False,
    266         null_match=False)
    267     s_dut.droid.wifiAwareUpdateSubscribe(s_disc_id, s_config)
    268     autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED)
    269 
    270     # Publisher+Subscriber: Terminate sessions
    271     p_dut.droid.wifiAwareDestroyDiscoverySession(p_disc_id)
    272     s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id)
    273 
    274     # sleep for timeout period and then verify all 'fail_on_event' together
    275     time.sleep(autils.EVENT_TIMEOUT)
    276 
    277     # verify that there were no other events
    278     autils.verify_no_more_events(p_dut, timeout=0)
    279     autils.verify_no_more_events(s_dut, timeout=0)
    280 
    281     # verify that forbidden callbacks aren't called
    282     autils.validate_forbidden_callbacks(p_dut, {aconsts.CB_EV_MATCH: 0})
    283 
    284   def verify_discovery_session_term(self, dut, disc_id, config, is_publish,
    285                                     term_ind_on):
    286     """Utility to verify that the specified discovery session has terminated (by
    287     waiting for the TTL and then attempting to reconfigure).
    288 
    289     Args:
    290       dut: device under test
    291       disc_id: discovery id for the existing session
    292       config: configuration of the existing session
    293       is_publish: True if the configuration was publish, False if subscribe
    294       term_ind_on: True if a termination indication is expected, False otherwise
    295     """
    296     # Wait for session termination
    297     if term_ind_on:
    298       autils.wait_for_event(
    299           dut,
    300           autils.decorate_event(aconsts.SESSION_CB_ON_SESSION_TERMINATED,
    301                                 disc_id))
    302     else:
    303       # can't defer wait to end since in any case have to wait for session to
    304       # expire
    305       autils.fail_on_event(
    306           dut,
    307           autils.decorate_event(aconsts.SESSION_CB_ON_SESSION_TERMINATED,
    308                                 disc_id))
    309 
    310     # Validate that session expired by trying to configure it (expect failure)
    311     config[aconsts.DISCOVERY_KEY_SSI] = "something else"
    312     if is_publish:
    313       dut.droid.wifiAwareUpdatePublish(disc_id, config)
    314     else:
    315       dut.droid.wifiAwareUpdateSubscribe(disc_id, config)
    316 
    317     # The response to update discovery session is:
    318     # term_ind_on=True: session was cleaned-up so won't get an explicit failure, but won't get a
    319     #                   success either. Can check for no SESSION_CB_ON_SESSION_CONFIG_UPDATED but
    320     #                   will defer to the end of the test (no events on queue).
    321     # term_ind_on=False: session was not cleaned-up (yet). So expect
    322     #                    SESSION_CB_ON_SESSION_CONFIG_FAILED.
    323     if not term_ind_on:
    324       autils.wait_for_event(
    325           dut,
    326           autils.decorate_event(aconsts.SESSION_CB_ON_SESSION_CONFIG_FAILED,
    327                                 disc_id))
    328 
    329   def positive_ttl_test_utility(self, is_publish, ptype, stype, term_ind_on):
    330     """Utility which runs a positive discovery session TTL configuration test
    331 
    332     Iteration 1: Verify session started with TTL
    333     Iteration 2: Verify session started without TTL and reconfigured with TTL
    334     Iteration 3: Verify session started with (long) TTL and reconfigured with
    335                  (short) TTL
    336 
    337     Args:
    338       is_publish: True if testing publish, False if testing subscribe
    339       ptype: Publish discovery type (used if is_publish is True)
    340       stype: Subscribe discovery type (used if is_publish is False)
    341       term_ind_on: Configuration of termination indication
    342     """
    343     SHORT_TTL = 5  # 5 seconds
    344     LONG_TTL = 100  # 100 seconds
    345     dut = self.android_devices[0]
    346 
    347     # Attach and wait for confirmation
    348     id = dut.droid.wifiAwareAttach(False)
    349     autils.wait_for_event(dut, aconsts.EVENT_CB_ON_ATTACHED)
    350 
    351     # Iteration 1: Start discovery session with TTL
    352     config = self.create_base_config(dut.aware_capabilities, is_publish, ptype,
    353                                      stype, self.PAYLOAD_SIZE_TYPICAL,
    354                                      SHORT_TTL, term_ind_on, False)
    355     if is_publish:
    356       disc_id = dut.droid.wifiAwarePublish(id, config, True)
    357       autils.wait_for_event(dut,
    358                             autils.decorate_event(
    359                                 aconsts.SESSION_CB_ON_PUBLISH_STARTED, disc_id))
    360     else:
    361       disc_id = dut.droid.wifiAwareSubscribe(id, config, True)
    362       autils.wait_for_event(
    363           dut,
    364           autils.decorate_event(aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED,
    365                                 disc_id))
    366 
    367     # Wait for session termination & verify
    368     self.verify_discovery_session_term(dut, disc_id, config, is_publish,
    369                                        term_ind_on)
    370 
    371     # Iteration 2: Start a discovery session without TTL
    372     config = self.create_base_config(dut.aware_capabilities, is_publish, ptype,
    373                                      stype, self.PAYLOAD_SIZE_TYPICAL, 0,
    374                                      term_ind_on, False)
    375     if is_publish:
    376       disc_id = dut.droid.wifiAwarePublish(id, config, True)
    377       autils.wait_for_event(dut,
    378                             autils.decorate_event(
    379                                 aconsts.SESSION_CB_ON_PUBLISH_STARTED, disc_id))
    380     else:
    381       disc_id = dut.droid.wifiAwareSubscribe(id, config, True)
    382       autils.wait_for_event(
    383           dut,
    384           autils.decorate_event(aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED,
    385                                 disc_id))
    386 
    387     # Update with a TTL
    388     config = self.create_base_config(dut.aware_capabilities, is_publish, ptype,
    389                                      stype, self.PAYLOAD_SIZE_TYPICAL,
    390                                      SHORT_TTL, term_ind_on, False)
    391     if is_publish:
    392       dut.droid.wifiAwareUpdatePublish(disc_id, config)
    393     else:
    394       dut.droid.wifiAwareUpdateSubscribe(disc_id, config)
    395     autils.wait_for_event(
    396         dut,
    397         autils.decorate_event(aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED,
    398                               disc_id))
    399 
    400     # Wait for session termination & verify
    401     self.verify_discovery_session_term(dut, disc_id, config, is_publish,
    402                                        term_ind_on)
    403 
    404     # Iteration 3: Start a discovery session with (long) TTL
    405     config = self.create_base_config(dut.aware_capabilities, is_publish, ptype,
    406                                      stype, self.PAYLOAD_SIZE_TYPICAL, LONG_TTL,
    407                                      term_ind_on, False)
    408     if is_publish:
    409       disc_id = dut.droid.wifiAwarePublish(id, config, True)
    410       autils.wait_for_event(dut,
    411                             autils.decorate_event(
    412                                 aconsts.SESSION_CB_ON_PUBLISH_STARTED, disc_id))
    413     else:
    414       disc_id = dut.droid.wifiAwareSubscribe(id, config, True)
    415       autils.wait_for_event(
    416           dut,
    417           autils.decorate_event(aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED,
    418                                 disc_id))
    419 
    420     # Update with a TTL
    421     config = self.create_base_config(dut.aware_capabilities, is_publish, ptype,
    422                                      stype, self.PAYLOAD_SIZE_TYPICAL,
    423                                      SHORT_TTL, term_ind_on, False)
    424     if is_publish:
    425       dut.droid.wifiAwareUpdatePublish(disc_id, config)
    426     else:
    427       dut.droid.wifiAwareUpdateSubscribe(disc_id, config)
    428     autils.wait_for_event(
    429         dut,
    430         autils.decorate_event(aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED,
    431                               disc_id))
    432 
    433     # Wait for session termination & verify
    434     self.verify_discovery_session_term(dut, disc_id, config, is_publish,
    435                                        term_ind_on)
    436 
    437     # verify that there were no other events
    438     autils.verify_no_more_events(dut)
    439 
    440     # verify that forbidden callbacks aren't called
    441     if not term_ind_on:
    442       autils.validate_forbidden_callbacks(dut, {
    443           aconsts.CB_EV_PUBLISH_TERMINATED: 0,
    444           aconsts.CB_EV_SUBSCRIBE_TERMINATED: 0
    445       })
    446 
    447   def discovery_mismatch_test_utility(self,
    448                                       is_expected_to_pass,
    449                                       p_type,
    450                                       s_type,
    451                                       p_service_name=None,
    452                                       s_service_name=None,
    453                                       p_mf_1=None,
    454                                       s_mf_1=None):
    455     """Utility which runs the negative discovery test for mismatched service
    456     configs.
    457 
    458     Args:
    459       is_expected_to_pass: True if positive test, False if negative
    460       p_type: Publish discovery type
    461       s_type: Subscribe discovery type
    462       p_service_name: Publish service name (or None to leave unchanged)
    463       s_service_name: Subscribe service name (or None to leave unchanged)
    464       p_mf_1: Publish match filter element [1] (or None to leave unchanged)
    465       s_mf_1: Subscribe match filter element [1] (or None to leave unchanged)
    466     """
    467     p_dut = self.android_devices[0]
    468     p_dut.pretty_name = "Publisher"
    469     s_dut = self.android_devices[1]
    470     s_dut.pretty_name = "Subscriber"
    471 
    472     # create configurations
    473     p_config = self.create_publish_config(
    474         p_dut.aware_capabilities,
    475         p_type,
    476         self.PAYLOAD_SIZE_TYPICAL,
    477         ttl=0,
    478         term_ind_on=False,
    479         null_match=False)
    480     if p_service_name is not None:
    481       p_config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = p_service_name
    482     if p_mf_1 is not None:
    483       p_config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = autils.encode_list(
    484           [(10).to_bytes(1, byteorder="big"),
    485            p_mf_1,
    486            bytes(range(40))])
    487     s_config = self.create_publish_config(
    488         s_dut.aware_capabilities,
    489         s_type,
    490         self.PAYLOAD_SIZE_TYPICAL,
    491         ttl=0,
    492         term_ind_on=False,
    493         null_match=False)
    494     if s_service_name is not None:
    495       s_config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = s_service_name
    496     if s_mf_1 is not None:
    497       s_config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = autils.encode_list(
    498           [(10).to_bytes(1, byteorder="big"),
    499            s_mf_1,
    500            bytes(range(40))])
    501 
    502     p_id = p_dut.droid.wifiAwareAttach(False)
    503     autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED)
    504     time.sleep(self.device_startup_offset)
    505     s_id = s_dut.droid.wifiAwareAttach(False)
    506     autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED)
    507 
    508     # Publisher: start publish and wait for confirmation
    509     p_disc_id = p_dut.droid.wifiAwarePublish(p_id, p_config)
    510     autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
    511 
    512     # Subscriber: start subscribe and wait for confirmation
    513     s_disc_id = s_dut.droid.wifiAwareSubscribe(s_id, s_config)
    514     autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED)
    515 
    516     # Subscriber: fail on service discovery
    517     if is_expected_to_pass:
    518       autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
    519     else:
    520       autils.fail_on_event(s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
    521 
    522     # Publisher+Subscriber: Terminate sessions
    523     p_dut.droid.wifiAwareDestroyDiscoverySession(p_disc_id)
    524     s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id)
    525 
    526     # verify that there were no other events (including terminations)
    527     time.sleep(autils.EVENT_TIMEOUT)
    528     autils.verify_no_more_events(p_dut, timeout=0)
    529     autils.verify_no_more_events(s_dut, timeout=0)
    530 
    531 
    532   #######################################
    533   # Positive tests key:
    534   #
    535   # names is: test_<pub_type>_<sub_type>_<size>
    536   # where:
    537   #
    538   # pub_type: Type of publish discovery session: unsolicited or solicited.
    539   # sub_type: Type of subscribe discovery session: passive or active.
    540   # size: Size of payload fields (service name, service specific info, and match
    541   # filter: typical, max, or min.
    542   #######################################
    543 
    544   @test_tracker_info(uuid="954ebbde-ed2b-4f04-9e68-88239187d69d")
    545   def test_positive_unsolicited_passive_typical(self):
    546     """Functional test case / Discovery test cases / positive test case:
    547     - Solicited publish + passive subscribe
    548     - Typical payload fields size
    549 
    550     Verifies that discovery and message exchange succeeds.
    551     """
    552     self.positive_discovery_test_utility(
    553         ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
    554         stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
    555         payload_size=self.PAYLOAD_SIZE_TYPICAL)
    556 
    557   @test_tracker_info(uuid="67fb22bb-6985-4345-95a4-90b76681a58b")
    558   def test_positive_unsolicited_passive_min(self):
    559     """Functional test case / Discovery test cases / positive test case:
    560     - Solicited publish + passive subscribe
    561     - Minimal payload fields size
    562 
    563     Verifies that discovery and message exchange succeeds.
    564     """
    565     self.positive_discovery_test_utility(
    566         ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
    567         stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
    568         payload_size=self.PAYLOAD_SIZE_MIN)
    569 
    570   @test_tracker_info(uuid="a02a47b9-41bb-47bb-883b-921024a2c30d")
    571   def test_positive_unsolicited_passive_max(self):
    572     """Functional test case / Discovery test cases / positive test case:
    573     - Solicited publish + passive subscribe
    574     - Maximal payload fields size
    575 
    576     Verifies that discovery and message exchange succeeds.
    577     """
    578     self.positive_discovery_test_utility(
    579         ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
    580         stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
    581         payload_size=self.PAYLOAD_SIZE_MAX)
    582 
    583   @test_tracker_info(uuid="586c657f-2388-4e7a-baee-9bce2f3d1a16")
    584   def test_positive_solicited_active_typical(self):
    585     """Functional test case / Discovery test cases / positive test case:
    586     - Unsolicited publish + active subscribe
    587     - Typical payload fields size
    588 
    589     Verifies that discovery and message exchange succeeds.
    590     """
    591     self.positive_discovery_test_utility(
    592         ptype=aconsts.PUBLISH_TYPE_SOLICITED,
    593         stype=aconsts.SUBSCRIBE_TYPE_ACTIVE,
    594         payload_size=self.PAYLOAD_SIZE_TYPICAL)
    595 
    596   @test_tracker_info(uuid="5369e4ff-f406-48c5-b41a-df38ec340146")
    597   def test_positive_solicited_active_min(self):
    598     """Functional test case / Discovery test cases / positive test case:
    599     - Unsolicited publish + active subscribe
    600     - Minimal payload fields size
    601 
    602     Verifies that discovery and message exchange succeeds.
    603     """
    604     self.positive_discovery_test_utility(
    605         ptype=aconsts.PUBLISH_TYPE_SOLICITED,
    606         stype=aconsts.SUBSCRIBE_TYPE_ACTIVE,
    607         payload_size=self.PAYLOAD_SIZE_MIN)
    608 
    609   @test_tracker_info(uuid="634c6eb8-2c4f-42bd-9bbb-d874d0ec22f3")
    610   def test_positive_solicited_active_max(self):
    611     """Functional test case / Discovery test cases / positive test case:
    612     - Unsolicited publish + active subscribe
    613     - Maximal payload fields size
    614 
    615     Verifies that discovery and message exchange succeeds.
    616     """
    617     self.positive_discovery_test_utility(
    618         ptype=aconsts.PUBLISH_TYPE_SOLICITED,
    619         stype=aconsts.SUBSCRIBE_TYPE_ACTIVE,
    620         payload_size=self.PAYLOAD_SIZE_MAX)
    621 
    622   #######################################
    623   # TTL tests key:
    624   #
    625   # names is: test_ttl_<pub_type|sub_type>_<term_ind>
    626   # where:
    627   #
    628   # pub_type: Type of publish discovery session: unsolicited or solicited.
    629   # sub_type: Type of subscribe discovery session: passive or active.
    630   # term_ind: ind_on or ind_off
    631   #######################################
    632 
    633   @test_tracker_info(uuid="9d7e758e-e0e2-4550-bcee-bfb6a2bff63e")
    634   def test_ttl_unsolicited_ind_on(self):
    635     """Functional test case / Discovery test cases / TTL test case:
    636     - Unsolicited publish
    637     - Termination indication enabled
    638     """
    639     self.positive_ttl_test_utility(
    640         is_publish=True,
    641         ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
    642         stype=None,
    643         term_ind_on=True)
    644 
    645   @test_tracker_info(uuid="48fd69bc-cc2a-4f65-a0a1-63d7c1720702")
    646   def test_ttl_unsolicited_ind_off(self):
    647     """Functional test case / Discovery test cases / TTL test case:
    648     - Unsolicited publish
    649     - Termination indication disabled
    650     """
    651     self.positive_ttl_test_utility(
    652         is_publish=True,
    653         ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
    654         stype=None,
    655         term_ind_on=False)
    656 
    657   @test_tracker_info(uuid="afb75fc1-9ba7-446a-b5ed-7cd37ab51b1c")
    658   def test_ttl_solicited_ind_on(self):
    659     """Functional test case / Discovery test cases / TTL test case:
    660     - Solicited publish
    661     - Termination indication enabled
    662     """
    663     self.positive_ttl_test_utility(
    664         is_publish=True,
    665         ptype=aconsts.PUBLISH_TYPE_SOLICITED,
    666         stype=None,
    667         term_ind_on=True)
    668 
    669   @test_tracker_info(uuid="703311a6-e444-4055-94ee-ea9b9b71799e")
    670   def test_ttl_solicited_ind_off(self):
    671     """Functional test case / Discovery test cases / TTL test case:
    672     - Solicited publish
    673     - Termination indication disabled
    674     """
    675     self.positive_ttl_test_utility(
    676         is_publish=True,
    677         ptype=aconsts.PUBLISH_TYPE_SOLICITED,
    678         stype=None,
    679         term_ind_on=False)
    680 
    681   @test_tracker_info(uuid="38a541c4-ff55-4387-87b7-4d940489da9d")
    682   def test_ttl_passive_ind_on(self):
    683     """Functional test case / Discovery test cases / TTL test case:
    684     - Passive subscribe
    685     - Termination indication enabled
    686     """
    687     self.positive_ttl_test_utility(
    688         is_publish=False,
    689         ptype=None,
    690         stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
    691         term_ind_on=True)
    692 
    693   @test_tracker_info(uuid="ba971e12-b0ca-417c-a1b5-9451598de47d")
    694   def test_ttl_passive_ind_off(self):
    695     """Functional test case / Discovery test cases / TTL test case:
    696     - Passive subscribe
    697     - Termination indication disabled
    698     """
    699     self.positive_ttl_test_utility(
    700         is_publish=False,
    701         ptype=None,
    702         stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
    703         term_ind_on=False)
    704 
    705   @test_tracker_info(uuid="7b5d96f2-2415-4b98-9a51-32957f0679a0")
    706   def test_ttl_active_ind_on(self):
    707     """Functional test case / Discovery test cases / TTL test case:
    708     - Active subscribe
    709     - Termination indication enabled
    710     """
    711     self.positive_ttl_test_utility(
    712         is_publish=False,
    713         ptype=None,
    714         stype=aconsts.SUBSCRIBE_TYPE_ACTIVE,
    715         term_ind_on=True)
    716 
    717   @test_tracker_info(uuid="c9268eca-0a30-42dd-8e6c-b8b0b84697fb")
    718   def test_ttl_active_ind_off(self):
    719     """Functional test case / Discovery test cases / TTL test case:
    720     - Active subscribe
    721     - Termination indication disabled
    722     """
    723     self.positive_ttl_test_utility(
    724         is_publish=False,
    725         ptype=None,
    726         stype=aconsts.SUBSCRIBE_TYPE_ACTIVE,
    727         term_ind_on=False)
    728 
    729   #######################################
    730   # Mismatched service name tests key:
    731   #
    732   # names is: test_mismatch_service_name_<pub_type>_<sub_type>
    733   # where:
    734   #
    735   # pub_type: Type of publish discovery session: unsolicited or solicited.
    736   # sub_type: Type of subscribe discovery session: passive or active.
    737   #######################################
    738 
    739   @test_tracker_info(uuid="175415e9-7d07-40d0-95f0-3a5f91ea4711")
    740   def test_mismatch_service_name_unsolicited_passive(self):
    741     """Functional test case / Discovery test cases / Mismatch service name
    742     - Unsolicited publish
    743     - Passive subscribe
    744     """
    745     self.discovery_mismatch_test_utility(
    746         is_expected_to_pass=False,
    747         p_type=aconsts.PUBLISH_TYPE_UNSOLICITED,
    748         s_type=aconsts.SUBSCRIBE_TYPE_PASSIVE,
    749         p_service_name="GoogleTestServiceXXX",
    750         s_service_name="GoogleTestServiceYYY")
    751 
    752   @test_tracker_info(uuid="c22a54ce-9e46-47a5-ac44-831faf93d317")
    753   def test_mismatch_service_name_solicited_active(self):
    754     """Functional test case / Discovery test cases / Mismatch service name
    755     - Solicited publish
    756     - Active subscribe
    757     """
    758     self.discovery_mismatch_test_utility(
    759         is_expected_to_pass=False,
    760         p_type=aconsts.PUBLISH_TYPE_SOLICITED,
    761         s_type=aconsts.SUBSCRIBE_TYPE_ACTIVE,
    762         p_service_name="GoogleTestServiceXXX",
    763         s_service_name="GoogleTestServiceYYY")
    764 
    765   #######################################
    766   # Mismatched discovery session type tests key:
    767   #
    768   # names is: test_mismatch_service_type_<pub_type>_<sub_type>
    769   # where:
    770   #
    771   # pub_type: Type of publish discovery session: unsolicited or solicited.
    772   # sub_type: Type of subscribe discovery session: passive or active.
    773   #######################################
    774 
    775   @test_tracker_info(uuid="4806f631-d9eb-45fd-9e75-24674962770f")
    776   def test_mismatch_service_type_unsolicited_active(self):
    777     """Functional test case / Discovery test cases / Mismatch service name
    778     - Unsolicited publish
    779     - Active subscribe
    780     """
    781     self.discovery_mismatch_test_utility(
    782         is_expected_to_pass=True,
    783         p_type=aconsts.PUBLISH_TYPE_UNSOLICITED,
    784         s_type=aconsts.SUBSCRIBE_TYPE_ACTIVE)
    785 
    786   @test_tracker_info(uuid="12d648fd-b8fa-4c0f-9467-95e2366047de")
    787   def test_mismatch_service_type_solicited_passive(self):
    788     """Functional test case / Discovery test cases / Mismatch service name
    789     - Unsolicited publish
    790     - Active subscribe
    791     """
    792     self.discovery_mismatch_test_utility(
    793         is_expected_to_pass=False,
    794         p_type=aconsts.PUBLISH_TYPE_SOLICITED,
    795         s_type=aconsts.SUBSCRIBE_TYPE_PASSIVE)
    796 
    797   #######################################
    798   # Mismatched discovery match filter tests key:
    799   #
    800   # names is: test_mismatch_match_filter_<pub_type>_<sub_type>
    801   # where:
    802   #
    803   # pub_type: Type of publish discovery session: unsolicited or solicited.
    804   # sub_type: Type of subscribe discovery session: passive or active.
    805   #######################################
    806 
    807   @test_tracker_info(uuid="d98454cb-64af-4266-8fed-f0b545a2d7c4")
    808   def test_mismatch_match_filter_unsolicited_passive(self):
    809     """Functional test case / Discovery test cases / Mismatch match filter
    810     - Unsolicited publish
    811     - Passive subscribe
    812     """
    813     self.discovery_mismatch_test_utility(
    814         is_expected_to_pass=False,
    815         p_type=aconsts.PUBLISH_TYPE_UNSOLICITED,
    816         s_type=aconsts.SUBSCRIBE_TYPE_PASSIVE,
    817         p_mf_1="hello there string",
    818         s_mf_1="goodbye there string")
    819 
    820   @test_tracker_info(uuid="663c1008-ae11-4e1a-87c7-c311d83f481c")
    821   def test_mismatch_match_filter_solicited_active(self):
    822     """Functional test case / Discovery test cases / Mismatch match filter
    823     - Solicited publish
    824     - Active subscribe
    825     """
    826     self.discovery_mismatch_test_utility(
    827         is_expected_to_pass=False,
    828         p_type=aconsts.PUBLISH_TYPE_SOLICITED,
    829         s_type=aconsts.SUBSCRIBE_TYPE_ACTIVE,
    830         p_mf_1="hello there string",
    831         s_mf_1="goodbye there string")
    832 
    833   #######################################
    834   # Multiple concurrent services
    835   #######################################
    836 
    837   def run_multiple_concurrent_services(self, type_x, type_y):
    838     """Validate multiple identical discovery services running on both devices:
    839     - DUT1 & DUT2 running Publish for X
    840     - DUT1 & DUT2 running Publish for Y
    841     - DUT1 Subscribes for X
    842     - DUT2 Subscribes for Y
    843     Message exchanges.
    844 
    845     Note: test requires that devices support 2 publish sessions concurrently.
    846     The test will be skipped if the devices are not capable.
    847 
    848     Args:
    849       type_x, type_y: A list of [ptype, stype] of the publish and subscribe
    850                       types for services X and Y respectively.
    851     """
    852     dut1 = self.android_devices[0]
    853     dut2 = self.android_devices[1]
    854 
    855     X_SERVICE_NAME = "ServiceXXX"
    856     Y_SERVICE_NAME = "ServiceYYY"
    857 
    858     asserts.skip_if(dut1.aware_capabilities[aconsts.CAP_MAX_PUBLISHES] < 2 or
    859                     dut2.aware_capabilities[aconsts.CAP_MAX_PUBLISHES] < 2,
    860                     "Devices do not support 2 publish sessions")
    861 
    862     # attach and wait for confirmation
    863     id1 = dut1.droid.wifiAwareAttach(False)
    864     autils.wait_for_event(dut1, aconsts.EVENT_CB_ON_ATTACHED)
    865     time.sleep(self.device_startup_offset)
    866     id2 = dut2.droid.wifiAwareAttach(False)
    867     autils.wait_for_event(dut2, aconsts.EVENT_CB_ON_ATTACHED)
    868 
    869     # DUT1 & DUT2: start publishing both X & Y services and wait for
    870     # confirmations
    871     dut1_x_pid = dut1.droid.wifiAwarePublish(id1,
    872                                              autils.create_discovery_config(
    873                                                X_SERVICE_NAME, type_x[0]))
    874     event = autils.wait_for_event(dut1, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
    875     asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID],
    876                          dut1_x_pid,
    877                          "Unexpected DUT1 X publish session discovery ID")
    878 
    879     dut1_y_pid = dut1.droid.wifiAwarePublish(id1,
    880                                              autils.create_discovery_config(
    881                                                Y_SERVICE_NAME, type_y[0]))
    882     event = autils.wait_for_event(dut1, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
    883     asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID],
    884                          dut1_y_pid,
    885                          "Unexpected DUT1 Y publish session discovery ID")
    886 
    887     dut2_x_pid = dut2.droid.wifiAwarePublish(id2,
    888                                              autils.create_discovery_config(
    889                                                  X_SERVICE_NAME, type_x[0]))
    890     event = autils.wait_for_event(dut2, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
    891     asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID],
    892                          dut2_x_pid,
    893                          "Unexpected DUT2 X publish session discovery ID")
    894 
    895     dut2_y_pid = dut2.droid.wifiAwarePublish(id2,
    896                                              autils.create_discovery_config(
    897                                                  Y_SERVICE_NAME, type_y[0]))
    898     event = autils.wait_for_event(dut2, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
    899     asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID],
    900                          dut2_y_pid,
    901                          "Unexpected DUT2 Y publish session discovery ID")
    902 
    903     # DUT1: start subscribing for X
    904     dut1_x_sid = dut1.droid.wifiAwareSubscribe(id1,
    905                                                autils.create_discovery_config(
    906                                                    X_SERVICE_NAME, type_x[1]))
    907     autils.wait_for_event(dut1, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED)
    908 
    909     # DUT2: start subscribing for Y
    910     dut2_y_sid = dut2.droid.wifiAwareSubscribe(id2,
    911                                                autils.create_discovery_config(
    912                                                    Y_SERVICE_NAME, type_y[1]))
    913     autils.wait_for_event(dut2, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED)
    914 
    915     # DUT1 & DUT2: wait for service discovery
    916     event = autils.wait_for_event(dut1,
    917                                   aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
    918     asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID],
    919                          dut1_x_sid,
    920                          "Unexpected DUT1 X subscribe session discovery ID")
    921     dut1_peer_id_for_dut2_x = event["data"][aconsts.SESSION_CB_KEY_PEER_ID]
    922 
    923     event = autils.wait_for_event(dut2,
    924                                   aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
    925     asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID],
    926                          dut2_y_sid,
    927                          "Unexpected DUT2 Y subscribe session discovery ID")
    928     dut2_peer_id_for_dut1_y = event["data"][aconsts.SESSION_CB_KEY_PEER_ID]
    929 
    930     # DUT1.X send message to DUT2
    931     x_msg = "Hello X on DUT2!"
    932     dut1.droid.wifiAwareSendMessage(dut1_x_sid, dut1_peer_id_for_dut2_x,
    933                                      self.get_next_msg_id(), x_msg,
    934                                      self.msg_retx_count)
    935     autils.wait_for_event(dut1, aconsts.SESSION_CB_ON_MESSAGE_SENT)
    936     event = autils.wait_for_event(dut2, aconsts.SESSION_CB_ON_MESSAGE_RECEIVED)
    937     asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID],
    938                          dut2_x_pid,
    939                         "Unexpected publish session ID on DUT2 for meesage "
    940                         "received on service X")
    941     asserts.assert_equal(
    942         event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING], x_msg,
    943         "Message on service X from DUT1 to DUT2 not received correctly")
    944 
    945     # DUT2.Y send message to DUT1
    946     y_msg = "Hello Y on DUT1!"
    947     dut2.droid.wifiAwareSendMessage(dut2_y_sid, dut2_peer_id_for_dut1_y,
    948                                     self.get_next_msg_id(), y_msg,
    949                                     self.msg_retx_count)
    950     autils.wait_for_event(dut2, aconsts.SESSION_CB_ON_MESSAGE_SENT)
    951     event = autils.wait_for_event(dut1, aconsts.SESSION_CB_ON_MESSAGE_RECEIVED)
    952     asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID],
    953                          dut1_y_pid,
    954                          "Unexpected publish session ID on DUT1 for meesage "
    955                          "received on service Y")
    956     asserts.assert_equal(
    957         event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING], y_msg,
    958         "Message on service Y from DUT2 to DUT1 not received correctly")
    959 
    960   @test_tracker_info(uuid="eef80cf3-1fd2-4526-969b-6af2dce785d7")
    961   def test_multiple_concurrent_services_both_unsolicited_passive(self):
    962     """Validate multiple concurrent discovery sessions running on both devices.
    963     - DUT1 & DUT2 running Publish for X
    964     - DUT1 & DUT2 running Publish for Y
    965     - DUT1 Subscribes for X
    966     - DUT2 Subscribes for Y
    967     Message exchanges.
    968 
    969     Both sessions are Unsolicited/Passive.
    970 
    971     Note: test requires that devices support 2 publish sessions concurrently.
    972     The test will be skipped if the devices are not capable.
    973     """
    974     self.run_multiple_concurrent_services(
    975       type_x=[aconsts.PUBLISH_TYPE_UNSOLICITED, aconsts.SUBSCRIBE_TYPE_PASSIVE],
    976       type_y=[aconsts.PUBLISH_TYPE_UNSOLICITED, aconsts.SUBSCRIBE_TYPE_PASSIVE])
    977 
    978   @test_tracker_info(uuid="46739f04-ab2b-4556-b1a4-9aa2774869b5")
    979   def test_multiple_concurrent_services_both_solicited_active(self):
    980     """Validate multiple concurrent discovery sessions running on both devices.
    981     - DUT1 & DUT2 running Publish for X
    982     - DUT1 & DUT2 running Publish for Y
    983     - DUT1 Subscribes for X
    984     - DUT2 Subscribes for Y
    985     Message exchanges.
    986 
    987     Both sessions are Solicited/Active.
    988 
    989     Note: test requires that devices support 2 publish sessions concurrently.
    990     The test will be skipped if the devices are not capable.
    991     """
    992     self.run_multiple_concurrent_services(
    993       type_x=[aconsts.PUBLISH_TYPE_SOLICITED, aconsts.SUBSCRIBE_TYPE_ACTIVE],
    994       type_y=[aconsts.PUBLISH_TYPE_SOLICITED, aconsts.SUBSCRIBE_TYPE_ACTIVE])
    995 
    996   @test_tracker_info(uuid="5f8f7fd2-4a0e-4cca-8cbb-6d54353f2baa")
    997   def test_multiple_concurrent_services_mix_unsolicited_solicited(self):
    998     """Validate multiple concurrent discovery sessions running on both devices.
    999     - DUT1 & DUT2 running Publish for X
   1000     - DUT1 & DUT2 running Publish for Y
   1001     - DUT1 Subscribes for X
   1002     - DUT2 Subscribes for Y
   1003     Message exchanges.
   1004 
   1005     Session A is Unsolicited/Passive.
   1006     Session B is Solicited/Active.
   1007 
   1008     Note: test requires that devices support 2 publish sessions concurrently.
   1009     The test will be skipped if the devices are not capable.
   1010     """
   1011     self.run_multiple_concurrent_services(
   1012       type_x=[aconsts.PUBLISH_TYPE_UNSOLICITED, aconsts.SUBSCRIBE_TYPE_PASSIVE],
   1013       type_y=[aconsts.PUBLISH_TYPE_SOLICITED, aconsts.SUBSCRIBE_TYPE_ACTIVE])
   1014 
   1015   #########################################################
   1016 
   1017   @test_tracker_info(uuid="908ec896-fc7a-4ee4-b633-a2f042b74448")
   1018   def test_upper_lower_service_name_equivalence(self):
   1019     """Validate that Service Name is case-insensitive. Publish a service name
   1020     with mixed case, subscribe to the same service name with alternative case
   1021     and verify that discovery happens."""
   1022     p_dut = self.android_devices[0]
   1023     s_dut = self.android_devices[1]
   1024 
   1025     pub_service_name = "GoogleAbCdEf"
   1026     sub_service_name = "GoogleaBcDeF"
   1027 
   1028     autils.create_discovery_pair(p_dut, s_dut,
   1029                                p_config=autils.create_discovery_config(
   1030                                  pub_service_name,
   1031                                  aconsts.PUBLISH_TYPE_UNSOLICITED),
   1032                                s_config=autils.create_discovery_config(
   1033                                  sub_service_name,
   1034                                  aconsts.SUBSCRIBE_TYPE_PASSIVE),
   1035                                device_startup_offset=self.device_startup_offset)
   1036