summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nate Jiang <qiangjiang@google.com> 2024-10-30 18:24:28 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2024-10-30 18:24:28 +0000
commitb3ce9a3f43cdff0bbd3b64e3260c26f3f7da42c2 (patch)
tree609aa8c5e4fe6b58f56099c9cc48b5ccf473a4b5
parentd244fa8d0d4787ad1e8103dc58c568ecce05af91 (diff)
parent4651640d498f38b7d2fdc78a71612581ba817788 (diff)
Merge "wifi_aware_discovery Test#4" into main am: 481acd9fd3 am: 4651640d49
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Wifi/+/3321494 Change-Id: I027c156ff01f7de6d5656754f9d349f51679d9ac Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareJsonDeserializer.java21
-rw-r--r--tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareManagerSnippet.java9
-rw-r--r--tests/hostsidetests/multidevices/test/aware/aware_lib_utils.py51
-rw-r--r--tests/hostsidetests/multidevices/test/aware/constants.py5
-rw-r--r--tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_discovery_test.py690
5 files changed, 761 insertions, 15 deletions
diff --git a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareJsonDeserializer.java b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareJsonDeserializer.java
index 0cb4b58d34..223ab1d3ef 100644
--- a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareJsonDeserializer.java
+++ b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareJsonDeserializer.java
@@ -30,9 +30,12 @@ import androidx.annotation.NonNull;
import org.json.JSONException;
import org.json.JSONObject;
+import com.android.modules.utils.build.SdkLevel;
+
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Deserializes JSONObject into data objects defined in Wi-Fi Aware API.
@@ -47,6 +50,8 @@ public class WifiAwareJsonDeserializer {
private static final String MAX_DISTANCE_MM = "max_distance_mm";
private static final String PAIRING_CONFIG = "pairing_config";
private static final String TTL_SEC = "TtlSec";
+ private static final String INSTANTMODE_ENABLE = "InstantModeEnabled";
+ private static final String BAND_5 = "5G";
// PublishConfig special
private static final String PUBLISH_TYPE = "publish_type";
private static final String RANGING_ENABLED = "ranging_enabled";
@@ -71,6 +76,12 @@ public class WifiAwareJsonDeserializer {
//WifiAwareDataPathSecurityConfig specific
private static final String CIPHER_SUITE = "cipher_suite";
private static final String SECURITY_CONFIG_PMK = "pmk";
+ /** 2.4 GHz band */
+ public static final int WIFI_BAND_24_GHZ = 1;
+ /** 5 GHz band excluding DFS channels */
+ public static final int WIFI_BAND_5_GHZ = 1;
+ /** DFS channels from 5 GHz band only */
+ public static final int WIFI_BAND_5_GHZ_DFS_ONLY = 1;
private WifiAwareJsonDeserializer() {
@@ -128,6 +139,11 @@ public class WifiAwareJsonDeserializer {
if (jsonObject.has(TTL_SEC)) {
builder.setTtlSec(jsonObject.getInt(TTL_SEC));
}
+ if (SdkLevel.isAtLeastT() && jsonObject.has(INSTANTMODE_ENABLE)) {
+ builder.setInstantCommunicationModeEnabled(true,
+ Objects.equals(jsonObject.getString(INSTANTMODE_ENABLE), BAND_5)
+ ? WIFI_BAND_5_GHZ :WIFI_BAND_24_GHZ);
+ }
return builder.build();
}
@@ -212,6 +228,11 @@ public class WifiAwareJsonDeserializer {
if (jsonObject.has(TTL_SEC)) {
builder.setTtlSec(jsonObject.getInt(TTL_SEC));
}
+ if (SdkLevel.isAtLeastT() && jsonObject.has(INSTANTMODE_ENABLE)) {
+ builder.setInstantCommunicationModeEnabled(true,
+ Objects.equals(jsonObject.getString(INSTANTMODE_ENABLE), BAND_5)
+ ? WIFI_BAND_5_GHZ :WIFI_BAND_24_GHZ);
+ }
return builder.build();
}
diff --git a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareManagerSnippet.java b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareManagerSnippet.java
index 1486f245a0..3f41cc763f 100644
--- a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareManagerSnippet.java
+++ b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareManagerSnippet.java
@@ -449,6 +449,15 @@ public class WifiAwareManagerSnippet implements Snippet {
event.getData().putInt("peerId", peerHandle.hashCode());
EventCache.getInstance().postEvent(event);
}
+
+ @Override
+ public void onServiceLost(PeerHandle peerHandle, int reason) {
+ SnippetEvent event = new SnippetEvent(mCallBackId, "WifiAwareSessionOnServiceLost");
+ event.getData().putString("discoverySessionId", mCallBackId);
+ event.getData().putInt("peerId", peerHandle.hashCode());
+ event.getData().putInt("lostReason", reason);
+ EventCache.getInstance().postEvent(event);
+ }
}
private WifiAwareSession getWifiAwareSession(String sessionId)
diff --git a/tests/hostsidetests/multidevices/test/aware/aware_lib_utils.py b/tests/hostsidetests/multidevices/test/aware/aware_lib_utils.py
index 21f3e60f3e..df22c89db0 100644
--- a/tests/hostsidetests/multidevices/test/aware/aware_lib_utils.py
+++ b/tests/hostsidetests/multidevices/test/aware/aware_lib_utils.py
@@ -322,4 +322,53 @@ def reset_device_statistics(ad: android_device.AndroidDevice,):
Args:
ad: device to be reset
"""
- ad.adb.shell("cmd wifiaware native_cb get_cb_count --reset") \ No newline at end of file
+ ad.adb.shell("cmd wifiaware native_cb get_cb_count --reset")
+
+def get_aware_capabilities(ad: android_device.AndroidDevice):
+ """Get the Wi-Fi Aware capabilities from the specified device. The
+ capabilities are a dictionary keyed by aware_const.CAP_* keys.
+
+ Args:
+ ad: the Android device
+ Returns: the capability dictionary.
+ """
+ return json.loads(ad.adb.shell('cmd wifiaware state_mgr get_capabilities'))
+
+def create_discovery_config(service_name,
+ p_type=None,
+ s_type=None,
+ ssi=None,
+ match_filter=None,
+ ttl=0,
+ term_cb_enable=True,
+ instant_mode=None):
+ """Create a publish discovery configuration based on input parameters.
+
+ Args:
+ service_name: Service name - required
+ d_type: Discovery type (publish or subscribe constants)
+ ssi: Supplemental information - defaults to None
+ match_filter, match_filter_list: The match_filter, only one mechanism can
+ be used to specify. Defaults to None.
+ ttl: Time-to-live - defaults to 0 (i.e. non-self terminating)
+ term_cb_enable: True (default) to enable callback on termination, False
+ means that no callback is called when session terminates.
+ instant_mode: set the band to use instant communication mode, 2G or 5G
+ Returns:
+ publish discovery configuration object.
+ """
+ config = {}
+ config[constants.SERVICE_NAME] = service_name
+ if p_type is not None:
+ config[constants.PUBLISH_TYPE] = p_type
+ if s_type is not None:
+ config[constants.SUBSCRIBE_TYPE] = s_type
+ if ssi is not None:
+ config[constants.SERVICE_SPECIFIC_INFO] = ssi
+ if match_filter is not None:
+ config[constants.MATCH_FILTER] = match_filter
+ if instant_mode is not None:
+ config[constants.INSTANTMODE_ENABLE] = instant_mode
+ config[constants.TTL_SEC] = ttl
+ config[constants.TERMINATE_NOTIFICATION_ENABLED] = term_cb_enable
+ return config \ No newline at end of file
diff --git a/tests/hostsidetests/multidevices/test/aware/constants.py b/tests/hostsidetests/multidevices/test/aware/constants.py
index cf71c587a5..06ae0d14d2 100644
--- a/tests/hostsidetests/multidevices/test/aware/constants.py
+++ b/tests/hostsidetests/multidevices/test/aware/constants.py
@@ -38,7 +38,10 @@ MAX_DISTANCE_MM = "max_distance_mm"
PAIRING_CONFIG = "pairing_config"
AWARE_NETWORK_INFO_CLASS_NAME = "android.net.wifi.aware.WifiAwareNetworkInfo"
TTL_SEC = "TtlSec"
+INSTANTMODE_ENABLE = "InstantModeEnabled"
+#onServiceLost reason code
+EASON_PEER_NOT_VISIBLE = 1
class WifiAwareTestConstants:
"""Constants for Wi-Fi Aware test."""
@@ -107,6 +110,8 @@ class DiscoverySessionCallbackMethodType(enum.StrEnum):
DISCOVER_RESULT = "discoveryResult"
# Event for the message send result.
MESSAGE_SEND_RESULT = "messageSendResult"
+ SESSION_CB_ON_SERVICE_LOST = "WifiAwareSessionOnServiceLost"
+ SESSION_CB_KEY_LOST_REASON = "lostReason"
@enum.unique
diff --git a/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_discovery_test.py b/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_discovery_test.py
index bd02c541e9..ebf36f5965 100644
--- a/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_discovery_test.py
+++ b/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_discovery_test.py
@@ -56,17 +56,6 @@ _SUBSCRIBE_TYPE_PASSIVE = 0
_SUBSCRIBE_TYPE_ACTIVE = 1
-@enum.unique
-class AttachCallBackMethodType(enum.StrEnum):
- """Represents Attach Callback Method Type in Wi-Fi Aware.
-
- https://developer.android.com/reference/android/net/wifi/aware/AttachCallback
- """
- ATTACHED = 'onAttached'
- ATTACH_FAILED = 'onAttachFailed'
- AWARE_SESSION_TERMINATED = 'onAwareSessionTerminated'
-
-
class WifiAwareDiscoveryTest(base_test.BaseTestClass):
"""Wi-Fi Aware test class."""
@@ -126,7 +115,6 @@ class WifiAwareDiscoveryTest(base_test.BaseTestClass):
def _teardown_test_on_device(self, ad: android_device.AndroidDevice) -> None:
ad.wifi_aware_snippet.wifiAwareCloseAllWifiAwareSession()
autils.reset_device_parameters(ad)
- autils.validate_forbidden_callbacks(ad)
autils.reset_device_statistics(ad)
def on_fail(self, record: records.TestResult) -> None:
@@ -138,11 +126,11 @@ class WifiAwareDiscoveryTest(base_test.BaseTestClass):
"""Starts the attach process on the provided device."""
handler = ad.wifi_aware_snippet.wifiAwareAttach()
attach_event = handler.waitAndGet(
- event_name=AttachCallBackMethodType.ATTACHED,
+ event_name=constants.AttachCallBackMethodType.ATTACHED,
timeout=_DEFAULT_TIMEOUT,
)
asserts.assert_true(
- ad.wifi_aware_snippet.wifiAwareIsSessionAttached(),
+ ad.wifi_aware_snippet.wifiAwareIsSessionAttached(handler.callback_id),
f'{ad} attach succeeded, but Wi-Fi Aware session is still null.'
)
ad.log.info('Attach Wi-Fi Aware session succeeded.')
@@ -683,6 +671,18 @@ class WifiAwareDiscoveryTest(base_test.BaseTestClass):
s_service_name=None,
p_mf_1=None,
s_mf_1=None):
+ """Utility which runs the negative discovery test for mismatched service
+ configs.
+
+ Args:
+ is_expected_to_pass: True if positive test, False if negative
+ p_type: Publish discovery type
+ s_type: Subscribe discovery type
+ p_service_name: Publish service name (or None to leave unchanged)
+ s_service_name: Subscribe service name (or None to leave unchanged)
+ p_mf_1: Publish match filter element [1] (or None to leave unchanged)
+ s_mf_1: Subscribe match filter element [1] (or None to leave unchanged)
+ """
p_dut = self.ads[0]
s_dut = self.ads[1]
# create configurations
@@ -757,6 +757,536 @@ class WifiAwareDiscoveryTest(base_test.BaseTestClass):
s_disc_id.waitAndGet(
constants.DiscoverySessionCallbackMethodType.SESSION_TERMINATED)
+ def create_discovery_pair(
+ self, p_dut, s_dut, p_config, s_config, msg_id=None):
+ """Creates a discovery session (publish and subscribe), and waits for
+ service discovery - at that point the sessions are connected and ready for
+ further messaging of data-path setup.
+
+ Args:
+ p_dut: Device to use as publisher.
+ s_dut: Device to use as subscriber.
+ p_config: Publish configuration.
+ s_config: Subscribe configuration.
+ device_startup_offset: Number of seconds to offset the enabling of NAN on
+ the two devices.
+ msg_id: Controls whether a message is sent from Subscriber to Publisher
+ (so that publisher has the sub's peer ID). If None then not sent,
+ otherwise should be an int for the message id.
+ Returns: variable size list of:
+ p_id: Publisher attach session id
+ s_id: Subscriber attach session id
+ p_disc_id: Publisher discovery session id
+ s_disc_id: Subscriber discovery session id
+ peer_id_on_sub: Peer ID of the Publisher as seen on the Subscriber
+ peer_id_on_pub: Peer ID of the Subscriber as seen on the Publisher. Only
+ included if |msg_id| is not None.
+ """
+
+ p_dut = self.ads[0]
+ s_dut = self.ads[1]
+ # attach and wait for confirmation
+ p_id = self._start_attach(p_dut)
+ s_id = self._start_attach(s_dut)
+ p_disc_id = p_dut.wifi_aware_snippet.wifiAwarePublish(
+ p_id, p_config
+ )
+ p_dut.log.info('Created the publish session.')
+ p_discovery = p_disc_id.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT)
+ callback_name = p_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.PUBLISH_STARTED,
+ callback_name,
+ f'{p_dut} publish failed, got callback: {callback_name}.',
+ )
+ # Subscriber: start subscribe and wait for confirmation
+ s_disc_id = s_dut.wifi_aware_snippet.wifiAwareSubscribe(
+ s_id, s_config
+ )
+ s_dut.log.info('Created the subscribe session.')
+ s_discovery = s_disc_id.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT)
+ callback_name = s_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.SUBSCRIBE_STARTED,
+ callback_name,
+ f'{s_dut} subscribe failed, got callback: {callback_name}.',
+ )
+ # Subscriber: wait for service discovery
+ discovery_event = s_disc_id.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.SERVICE_DISCOVERED)
+ peer_id_on_sub = discovery_event.data[constants.WifiAwareSnippetParams.PEER_ID]
+ # Optionally send a message from Subscriber to Publisher
+ if msg_id is not None:
+ ping_msg = 'PING'
+ # Subscriber: send message to peer (Publisher)
+ s_dut.sender.wifi_aware_snippet.wifiAwareSendMessage(
+ s_disc_id, peer_id_on_sub, _MSG_ID_SUB_TO_PUB, ping_msg
+ )
+ message_send_result = s_disc_id.waitAndGet(
+ event_name =
+ constants.DiscoverySessionCallbackMethodType.MESSAGE_SEND_RESULT,
+ timeout =_DEFAULT_TIMEOUT,
+ )
+ actual_send_message_id = message_send_result.data[
+ constants.DiscoverySessionCallbackParamsType.MESSAGE_ID
+ ]
+ asserts.assert_equal(
+ actual_send_message_id,
+ _MSG_ID_SUB_TO_PUB,
+ f'{s_dut} send message succeeded but message ID mismatched.'
+ )
+ pub_rx_msg_event = p_disc_id.waitAndGet(
+ event_name = constants.DiscoverySessionCallbackMethodType.MESSAGE_RECEIVED,
+ timeout = _DEFAULT_TIMEOUT,
+ )
+ peer_id_on_pub = pub_rx_msg_event.data[constants.WifiAwareSnippetParams.PEER_ID]
+ received_message_raw = pub_rx_msg_event.data[
+ constants.WifiAwareSnippetParams.RECEIVED_MESSAGE
+ ]
+ received_message = bytes(received_message_raw).decode('utf-8')
+ asserts.assert_equal(
+ received_message,
+ ping_msg,
+ f'{p_dut} Subscriber -> Publisher message corrupted.'
+ )
+ return p_id, s_id, p_disc_id, s_disc_id, peer_id_on_sub, peer_id_on_pub
+ return p_id, s_id, p_disc_id, s_disc_id, peer_id_on_sub
+
+ def exchange_messages(self, p_dut, p_disc_id, s_dut, s_disc_id, peer_id_on_sub, session_name):
+ """
+ Exchange message between Publisher and Subscriber on target discovery session
+
+ Args:
+ p_dut: Publisher device
+ p_disc_id: Publish discovery session id
+ s_dut: Subscriber device
+ s_disc_id: Subscribe discovery session id
+ peer_id_on_sub: Peer ID of the Publisher as seen on the Subscriber
+ session_name: dictionary of discovery session name base on role("pub" or "sub")
+ {role: {disc_id: name}}
+ """
+
+ msg_template = "Hello {} from {} !"
+ # Message send from Subscriber to Publisher
+ s_to_p_msg = msg_template.format(session_name["pub"][p_disc_id],
+ session_name["sub"][s_disc_id])
+ publisher_peer = self._send_msg_and_check_received(
+ sender = s_dut,
+ sender_aware_session_cb_handler= s_disc_id,
+ receiver = p_dut,
+ receiver_aware_session_cb_handler= p_disc_id,
+ discovery_session = s_disc_id.callback_id,
+ peer=peer_id_on_sub,
+ send_message =s_to_p_msg,
+ send_message_id = _MSG_ID_SUB_TO_PUB,
+ )
+ logging.info(
+ 'The subscriber sent a message and the publisher received it.'
+ )
+
+ # Publisher sends a message to subscriber.
+ p_to_s_msg = msg_template.format(session_name["sub"][s_disc_id],
+ session_name["pub"][p_disc_id])
+ self._send_msg_and_check_received(
+ sender=p_dut,
+ sender_aware_session_cb_handler=p_disc_id,
+ receiver=s_dut,
+ receiver_aware_session_cb_handler=s_disc_id,
+ discovery_session=p_disc_id.callback_id,
+ peer=publisher_peer,
+ send_message=p_to_s_msg,
+ send_message_id=_MSG_ID_PUB_TO_SUB,
+ )
+ logging.info(
+ 'The publisher sent a message and the subscriber received it.'
+ )
+
+ def run_multiple_concurrent_services(self, type_x, type_y):
+ """Validate same service name with multiple service specific info on publisher
+ and subscriber can see all service
+
+ - p_dut running Publish X and Y
+ - s_dut running subscribe A and B
+ - subscribe A find X and Y
+ - subscribe B find X and Y
+
+ Message exchanges:
+ - A to X and X to A
+ - B to X and X to B
+ - A to Y and Y to A
+ - B to Y and Y to B
+
+ Note: test requires that publisher device support 2 publish sessions concurrently,
+ and subscriber device support 2 subscribe sessions concurrently.
+ The test will be skipped if the devices are not capable.
+
+ Args:
+ type_x, type_y: A list of [ptype, stype] of the publish and subscribe
+ types for services X and Y respectively.
+ """
+
+ p_dut = self.ads[0]
+ s_dut = self.ads[1]
+ X_SERVICE_NAME = "ServiceXXX"
+ Y_SERVICE_NAME = "ServiceYYY"
+ asserts.skip_if(
+ autils.get_aware_capabilities(p_dut)["maxPublishes"] < 2
+ or autils.get_aware_capabilities(s_dut)["maxPublishes"] < 2
+ ,"Devices do not support 2 publish sessions"
+ )
+ # attach and wait for confirmation
+ p_id = self._start_attach(p_dut)
+ s_id = self._start_attach(s_dut)
+ # DUT1 & DUT2: start publishing both X & Y services and wait for
+ # confirmations
+ dut1_x_pid = p_dut.wifi_aware_snippet.wifiAwarePublish(
+ p_id, autils.create_discovery_config(X_SERVICE_NAME, type_x[0], None)
+ )
+ p_dut.log.info('Created the DUT1 X publish session.')
+ p_discovery = dut1_x_pid.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT)
+ callback_name = p_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.PUBLISH_STARTED,
+ callback_name,
+ f'{p_dut} DUT1 X publish failed, got callback: {callback_name}.',
+ )
+ dut1_y_pid = p_dut.wifi_aware_snippet.wifiAwarePublish(
+ p_id, autils.create_discovery_config(Y_SERVICE_NAME, type_y[0], None)
+ )
+ p_dut.log.info('Created the DUT1 Y publish session.')
+ p_discovery = dut1_y_pid.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT)
+ callback_name = p_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.PUBLISH_STARTED,
+ callback_name,
+ f'{p_dut} DUT1 Y publish failed, got callback: {callback_name}.',
+ )
+ dut2_x_pid = s_dut.wifi_aware_snippet.wifiAwarePublish(
+ s_id, autils.create_discovery_config(X_SERVICE_NAME, type_x[0], None)
+ )
+ s_dut.log.info('Created the DUT2 X publish session.')
+ p_discovery = dut2_x_pid.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT)
+ callback_name = p_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.PUBLISH_STARTED,
+ callback_name,
+ f'{s_dut} DUT2 X publish failed, got callback: {callback_name}.',
+ )
+ dut2_y_pid = s_dut.wifi_aware_snippet.wifiAwarePublish(
+ s_id, autils.create_discovery_config(Y_SERVICE_NAME, type_y[0], None)
+ )
+ s_dut.log.info('Created the DUT2 Y publish session.')
+ p_discovery = dut2_y_pid.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT)
+ callback_name = p_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.PUBLISH_STARTED,
+ callback_name,
+ f'{s_dut} DUT1 Y publish failed, got callback: {callback_name}.',
+ )
+ # DUT1: start subscribing for X
+ dut1_x_sid = p_dut.wifi_aware_snippet.wifiAwareSubscribe(
+ p_id, autils.create_discovery_config(X_SERVICE_NAME, None, type_x[1])
+ )
+ p_dut.log.info('Created the DUT1 X subscribe session.')
+ s_discovery = dut1_x_sid.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT,
+ timeout=_DEFAULT_TIMEOUT)
+ callback_name = s_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.SUBSCRIBE_STARTED,
+ callback_name,
+ f'{p_dut} DUT1 X subscribe failed, got callback: {callback_name}.',
+ )
+ # DUT1: start subscribing for Y
+ dut1_y_sid = p_dut.wifi_aware_snippet.wifiAwareSubscribe(
+ p_id, autils.create_discovery_config(Y_SERVICE_NAME, None, type_y[1])
+ )
+ p_dut.log.info('Created the DUT1 Y subscribe session.')
+ s_discovery = dut1_y_sid.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT)
+ callback_name = s_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.SUBSCRIBE_STARTED,
+ callback_name,
+ f'{p_dut} DUT1 Y subscribe failed, got callback: {callback_name}.',
+ )
+ # DUT2: start subscribing for X
+ dut2_x_sid = s_dut.wifi_aware_snippet.wifiAwareSubscribe(
+ s_id, autils.create_discovery_config(X_SERVICE_NAME, None, type_x[1])
+ )
+ s_dut.log.info('Created the DUT2 X subscribe session.')
+ s_discovery = dut2_x_sid.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT,
+ timeout=_DEFAULT_TIMEOUT)
+ callback_name = s_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.SUBSCRIBE_STARTED,
+ callback_name,
+ f'{s_dut} DUT2 X subscribe failed, got callback: {callback_name}.',
+ )
+ # DUT2: start subscribing for Y
+ dut2_y_sid = s_dut.wifi_aware_snippet.wifiAwareSubscribe(
+ s_id, autils.create_discovery_config(Y_SERVICE_NAME, None, type_y[1])
+ )
+ s_dut.log.info('Created the DUT2 Y subscribe session.')
+ s_discovery = dut2_y_sid.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT)
+ callback_name = s_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.SUBSCRIBE_STARTED,
+ callback_name,
+ f'{s_dut} DUT2 Y subscribe failed, got callback: {callback_name}.',
+ )
+ dut1_x_sid_event = dut1_x_sid.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.SERVICE_DISCOVERED)
+ dut1_peer_id_for_dut2_x = dut1_x_sid_event.data[constants.WifiAwareSnippetParams.PEER_ID]
+
+ dut2_y_sid_event = dut2_y_sid.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.SERVICE_DISCOVERED)
+ dut2_peer_id_for_dut1_y = dut2_y_sid_event.data[constants.WifiAwareSnippetParams.PEER_ID]
+
+ # DUT1.X send message to DUT2
+ x_msg = "Hello X on DUT2!"
+ publisher_peer = self._send_msg_and_check_received(
+ sender = p_dut,
+ sender_aware_session_cb_handler= dut1_x_sid,
+ receiver = s_dut,
+ receiver_aware_session_cb_handler= dut2_x_pid,
+ discovery_session = dut1_x_sid.callback_id,
+ peer=dut1_peer_id_for_dut2_x,
+ send_message =x_msg,
+ send_message_id = _MSG_ID_PUB_TO_SUB,
+ )
+ logging.info(
+ 'The DUT1.X sent a message and the DUT2 received it.'
+ )
+
+ # DUT2.Y send message to DUT1
+ y_msg = "Hello Y on DUT1!"
+ self._send_msg_and_check_received(
+ sender = s_dut,
+ sender_aware_session_cb_handler= dut2_y_sid,
+ receiver = p_dut,
+ receiver_aware_session_cb_handler= dut1_y_pid,
+ discovery_session = dut2_y_sid.callback_id,
+ peer=dut2_peer_id_for_dut1_y,
+ send_message =y_msg,
+ send_message_id = _MSG_ID_SUB_TO_PUB,
+ )
+ logging.info(
+ 'The DUT2.Y sent a message and the DUT1 received it.'
+ )
+
+ def run_multiple_concurrent_services_same_name_diff_ssi(self, type_x, type_y):
+ """Validate same service name with multiple service specific info on publisher
+ and subscriber can see all service
+
+ - p_dut running Publish X and Y
+ - s_dut running subscribe A and B
+ - subscribe A find X and Y
+ - subscribe B find X and Y
+
+ Message exchanges:
+ - A to X and X to A
+ - B to X and X to B
+ - A to Y and Y to A
+ - B to Y and Y to B
+
+ Note: test requires that publisher device support 2 publish sessions concurrently,
+ and subscriber device support 2 subscribe sessions concurrently.
+ The test will be skipped if the devices are not capable.
+
+ Args:
+ type_x, type_y: A list of [ptype, stype] of the publish and subscribe
+ types for services X and Y respectively.
+ """
+ p_dut = self.ads[0]
+ s_dut = self.ads[1]
+ asserts.skip_if(
+ autils.get_aware_capabilities(p_dut)["maxPublishes"] < 2
+ or autils.get_aware_capabilities(s_dut)["maxPublishes"] < 2
+ ,"Devices do not support 2 publish sessions"
+ )
+ SERVICE_NAME = "ServiceName"
+ X_SERVICE_SSI = "ServiceSpecificInfoXXX"
+ Y_SERVICE_SSI = "ServiceSpecificInfoYYY"
+ # use_id = True
+ # attach and wait for confirmation
+ p_id = self._start_attach(p_dut)
+ s_id = self._start_attach(s_dut)
+ p_disc_id_x = p_dut.wifi_aware_snippet.wifiAwarePublish(
+ p_id, autils.create_discovery_config(SERVICE_NAME, type_x[0], None, X_SERVICE_SSI)
+ )
+ p_dut.log.info('Created the DUT1 X publish session.')
+ p_discovery = p_disc_id_x.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT)
+ callback_name = p_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.PUBLISH_STARTED,
+ callback_name,
+ f'{p_dut} DUT1 X publish failed, got callback: {callback_name}.',
+ )
+ p_disc_id_y = p_dut.wifi_aware_snippet.wifiAwarePublish(
+ p_id, autils.create_discovery_config(SERVICE_NAME, type_x[0], None, Y_SERVICE_SSI)
+ )
+ p_dut.log.info('Created the DUT1 Y publish session.')
+ p_discovery = p_disc_id_y.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT)
+ callback_name = p_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.PUBLISH_STARTED,
+ callback_name,
+ f'{p_dut} DUT1 Y publish failed, got callback: {callback_name}.',
+ )
+ # Subscriber: start subscribe session A
+ s_disc_id_a = s_dut.wifi_aware_snippet.wifiAwareSubscribe(
+ s_id, autils.create_discovery_config(SERVICE_NAME, None, type_x[1] )
+ )
+ s_dut.log.info('Created the DUT2 X subscribe session.')
+ s_discovery = s_disc_id_a.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT,
+ timeout=_DEFAULT_TIMEOUT)
+ callback_name = s_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.SUBSCRIBE_STARTED,
+ callback_name,
+ f'{s_dut} DUT2 X subscribe failed, got callback: {callback_name}.',
+ )
+ # Subscriber: start subscribe session B
+ s_disc_id_b = s_dut.wifi_aware_snippet.wifiAwareSubscribe(
+ s_id, autils.create_discovery_config(SERVICE_NAME, None, type_y[1])
+ )
+ s_dut.log.info('Created the DUT2 Y subscribe session.')
+ s_discovery = s_disc_id_b.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT)
+ callback_name = s_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.SUBSCRIBE_STARTED,
+ callback_name,
+ f'{s_dut} DUT2 Y subscribe failed, got callback: {callback_name}.',
+ )
+ session_name = {"pub": {p_disc_id_x: "X", p_disc_id_y: "Y"},
+ "sub": {s_disc_id_a: "A", s_disc_id_b: "B"}}
+ # Subscriber: subscribe session A & B wait for service discovery
+ # Number of results on each session should be exactly 2
+ results_a = {}
+ for i in range(2):
+ event = s_disc_id_a.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.SERVICE_DISCOVERED)
+ results_a[
+ bytes(event.data[constants.WifiAwareSnippetParams.SERVICE_SPECIFIC_INFO]).decode("utf-8")] = event
+ autils.callback_no_response(
+ s_disc_id_a, constants.DiscoverySessionCallbackMethodType.SERVICE_DISCOVERED, 10, True
+ )
+ results_b = {}
+ for i in range(2):
+ event = s_disc_id_b.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.SERVICE_DISCOVERED)
+ results_b[
+ bytes(event.data[constants.WifiAwareSnippetParams.SERVICE_SPECIFIC_INFO]).decode("utf-8")] = event
+ autils.callback_no_response(
+ s_disc_id_b, constants.DiscoverySessionCallbackMethodType.SERVICE_DISCOVERED, 10, True
+ )
+ s_a_peer_id_for_p_x = results_a[X_SERVICE_SSI].data[constants.WifiAwareSnippetParams.PEER_ID]
+ s_a_peer_id_for_p_y = results_a[Y_SERVICE_SSI].data[constants.WifiAwareSnippetParams.PEER_ID]
+ s_b_peer_id_for_p_x = results_b[X_SERVICE_SSI].data[constants.WifiAwareSnippetParams.PEER_ID]
+ s_b_peer_id_for_p_y = results_b[Y_SERVICE_SSI].data[constants.WifiAwareSnippetParams.PEER_ID]
+
+ # Message exchange between Publisher and Subscribe
+ self.exchange_messages(p_dut, p_disc_id_x,
+ s_dut, s_disc_id_a, s_a_peer_id_for_p_x, session_name)
+
+ self.exchange_messages(p_dut, p_disc_id_x,
+ s_dut, s_disc_id_b, s_b_peer_id_for_p_x, session_name)
+
+ self.exchange_messages(p_dut, p_disc_id_y,
+ s_dut, s_disc_id_a, s_a_peer_id_for_p_y, session_name)
+
+ self.exchange_messages(p_dut, p_disc_id_y,
+ s_dut, s_disc_id_b, s_b_peer_id_for_p_y, session_name)
+
+ def run_service_discovery_on_service_lost(self, p_type, s_type):
+ """
+ Validate service lost callback will be receive on subscriber, when publisher stopped publish
+ - p_dut running Publish
+ - s_dut running subscribe
+ - s_dut discover p_dut
+ - p_dut stop publish
+ - s_dut receive service lost callback
+
+ Args:
+ p_type: Publish discovery type
+ s_type: Subscribe discovery type
+ """
+ p_dut = self.ads[0]
+ s_dut = self.ads[1]
+ # attach and wait for confirmation
+ p_id = self._start_attach(p_dut)
+ s_id = self._start_attach(s_dut)
+ p_config = self.create_publish_config(
+ p_dut.wifi_aware_snippet.getCharacteristics(),
+ p_type,
+ _PAYLOAD_SIZE_TYPICAL,
+ ttl=0,
+ term_ind_on=False,
+ null_match=False,
+ )
+ p_disc_id = p_dut.wifi_aware_snippet.wifiAwarePublish(
+ p_id, p_config
+ )
+ p_dut.log.info('Created the publish session.')
+ p_discovery = p_disc_id.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT)
+ callback_name = p_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.PUBLISH_STARTED,
+ callback_name,
+ f'{p_dut} publish failed, got callback: {callback_name}.',
+ )
+ s_config = self.create_subscribe_config(
+ s_dut.wifi_aware_snippet.getCharacteristics(),
+ s_type,
+ _PAYLOAD_SIZE_TYPICAL,
+ ttl=0,
+ term_ind_on=False,
+ null_match=True,
+ )
+ s_disc_id = s_dut.wifi_aware_snippet.wifiAwareSubscribe(
+ s_id, s_config
+ )
+ s_dut.log.info('Created the subscribe session.')
+ s_discovery = s_disc_id.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT)
+ callback_name = s_discovery.data[_CALLBACK_NAME]
+ asserts.assert_equal(
+ constants.DiscoverySessionCallbackMethodType.SUBSCRIBE_STARTED,
+ callback_name,
+ f'{s_dut} subscribe failed, got callback: {callback_name}.'
+ )
+ discovered_event = s_disc_id.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.SERVICE_DISCOVERED)
+ peer_id_on_sub = discovered_event.data[
+ constants.WifiAwareSnippetParams.PEER_ID]
+ # Publisher+Subscriber: Terminate sessions
+ p_dut.wifi_aware_snippet.wifiAwareCloseDiscoverSession(
+ p_disc_id.callback_id)
+ time.sleep(10)
+ # service_lost_event = s_disc_id.waitAndGet("WifiAwareSessionOnServiceLost")
+ service_lost_event = s_disc_id.waitAndGet(
+ constants.DiscoverySessionCallbackMethodType.SESSION_CB_ON_SERVICE_LOST)
+ asserts.assert_equal(peer_id_on_sub,
+ service_lost_event.data[constants.WifiAwareSnippetParams.PEER_ID])
+ asserts.assert_equal(
+ constants.EASON_PEER_NOT_VISIBLE,
+ service_lost_event.data[constants.DiscoverySessionCallbackMethodType.SESSION_CB_KEY_LOST_REASON]
+ )
+
def test_positive_unsolicited_passive_typical(self)-> None:
"""Functional test case / Discovery test cases / positive test case:
- Unsolicited publish + passive subscribe
@@ -1032,6 +1562,138 @@ class WifiAwareDiscoveryTest(base_test.BaseTestClass):
p_mf_1="hello there string",
s_mf_1="goodbye there string")
+ #########################################################
+ # Multiple concurrent services
+ #######################################
+
+ def test_multiple_concurrent_services_both_unsolicited_passive(self):
+ """Validate multiple concurrent discovery sessions running on both devices.
+ - DUT1 & DUT2 running Publish for X
+ - DUT1 & DUT2 running Publish for Y
+ - DUT1 Subscribes for X
+ - DUT2 Subscribes for Y
+ Message exchanges.
+
+ Both sessions are Unsolicited/Passive.
+
+ Note: test requires that devices support 2 publish sessions concurrently.
+ The test will be skipped if the devices are not capable.
+ """
+ self.run_multiple_concurrent_services(
+ type_x=[
+ _PUBLISH_TYPE_UNSOLICITED,
+ _SUBSCRIBE_TYPE_PASSIVE
+ ],
+ type_y=[
+ _PUBLISH_TYPE_UNSOLICITED,
+ _SUBSCRIBE_TYPE_PASSIVE
+ ])
+
+ def test_multiple_concurrent_services_both_solicited_active(self):
+ """Validate multiple concurrent discovery sessions running on both devices.
+ - DUT1 & DUT2 running Publish for X
+ - DUT1 & DUT2 running Publish for Y
+ - DUT1 Subscribes for X
+ - DUT2 Subscribes for Y
+ Message exchanges.
+
+ Both sessions are Solicited/Active.
+
+ Note: test requires that devices support 2 publish sessions concurrently.
+ The test will be skipped if the devices are not capable.
+ """
+ self.run_multiple_concurrent_services(
+ type_x=[
+ _PUBLISH_TYPE_SOLICITED,
+ _SUBSCRIBE_TYPE_ACTIVE
+ ],
+ type_y=[
+ _PUBLISH_TYPE_SOLICITED, _SUBSCRIBE_TYPE_ACTIVE
+ ])
+
+ def test_multiple_concurrent_services_mix_unsolicited_solicited(self):
+ """Validate multiple concurrent discovery sessions running on both devices.
+ - DUT1 & DUT2 running Publish for X
+ - DUT1 & DUT2 running Publish for Y
+ - DUT1 Subscribes for X
+ - DUT2 Subscribes for Y
+ Message exchanges.
+
+ Session A is Unsolicited/Passive.
+ Session B is Solicited/Active.
+
+ Note: test requires that devices support 2 publish sessions concurrently.
+ The test will be skipped if the devices are not capable.
+ """
+ self.run_multiple_concurrent_services(
+ type_x=[
+ _PUBLISH_TYPE_UNSOLICITED,
+ _SUBSCRIBE_TYPE_PASSIVE
+ ],
+ type_y=[
+ _PUBLISH_TYPE_SOLICITED, _SUBSCRIBE_TYPE_ACTIVE
+ ])
+
+ #########################################################
+ # Multiple concurrent services with diff ssi
+ #########################################################
+
+ def test_multiple_concurrent_services_diff_ssi_unsolicited_passive(self):
+ """Multi service test on same service name but different Service Specific Info
+ - Unsolicited publish
+ - Passive subscribe
+ """
+ self.run_multiple_concurrent_services_same_name_diff_ssi(
+ type_x=[_PUBLISH_TYPE_UNSOLICITED, _SUBSCRIBE_TYPE_PASSIVE],
+ type_y=[_PUBLISH_TYPE_UNSOLICITED, _SUBSCRIBE_TYPE_PASSIVE])
+
+ def test_multiple_concurrent_services_diff_ssi_solicited_active(self):
+ """Multi service test on same service name but different Service Specific Info
+ - Solicited publish
+ - Active subscribe
+ """
+ self.run_multiple_concurrent_services_same_name_diff_ssi(
+ type_x=[_PUBLISH_TYPE_SOLICITED, _SUBSCRIBE_TYPE_ACTIVE],
+ type_y=[_PUBLISH_TYPE_SOLICITED, _SUBSCRIBE_TYPE_ACTIVE])
+
+ #########################################################
+
+ def test_upper_lower_service_name_equivalence(self):
+ """Validate that Service Name is case-insensitive. Publish a service name
+ with mixed case, subscribe to the same service name with alternative case
+ and verify that discovery happens."""
+ p_dut = self.ads[0]
+ s_dut = self.ads[1]
+
+ pub_service_name = "GoogleAbCdEf"
+ sub_service_name = "GoogleaBcDeF"
+ p_config = autils.create_discovery_config(pub_service_name)
+ p_config[constants.PUBLISH_TYPE] = _PUBLISH_TYPE_UNSOLICITED
+ s_config = autils.create_discovery_config(sub_service_name)
+ s_config[constants.SUBSCRIBE_TYPE] = _SUBSCRIBE_TYPE_PASSIVE
+ self.create_discovery_pair(
+ p_dut,
+ s_dut,
+ p_config,
+ s_config)
+
+ #########################################################
+ # service discovery on service lost
+ #########################################################
+
+ def test_service_discovery_on_service_lost_unsolicited_passive(self):
+ """
+ Test service discovery lost with unsolicited publish and passive subscribe
+ """
+ self.run_service_discovery_on_service_lost(_PUBLISH_TYPE_UNSOLICITED,
+ _SUBSCRIBE_TYPE_PASSIVE)
+
+ def test_service_discovery_on_service_lost_solicited_active(self):
+ """
+ Test service discovery lost with solicited publish and active subscribe
+ """
+ self.run_service_discovery_on_service_lost(_PUBLISH_TYPE_SOLICITED,
+ _SUBSCRIBE_TYPE_ACTIVE)
if __name__ == '__main__':
# Take test args