Merge "Add WiFi Aware ApiTest description for the following cases." into main
diff --git a/tests/OWNERS b/tests/OWNERS
index bde7824..288dd24 100644
--- a/tests/OWNERS
+++ b/tests/OWNERS
@@ -4,4 +4,3 @@
# Engprod - Not owner of the test but help maintaining the module as an example
[email protected]
[email protected]
[email protected]
diff --git a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/Android.bp b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/Android.bp
index 09249b5..c0edd52 100644
--- a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/Android.bp
+++ b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/Android.bp
@@ -53,6 +53,7 @@
"compatibility-device-util-axt",
"guava",
"mobly-snippet-lib",
+ "mobly-bundled-snippets-lib",
],
min_sdk_version: "31",
}
diff --git a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/AndroidManifestNew.xml b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/AndroidManifestNew.xml
index 7dc04df..cf13a13 100644
--- a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/AndroidManifestNew.xml
+++ b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/AndroidManifestNew.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
package="com.google.snippet.wifi.aware">
<!-- Declare the minimum Android SDK version and internet permission,
which are required by Mobly Snippet Lib since it uses network socket. -->
@@ -20,8 +21,10 @@
of a snippet class -->
<meta-data
android:name="mobly-snippets"
+ tools:replace="android:value"
android:value="com.google.snippet.wifi.aware.WifiAwareManagerSnippet,
- com.google.snippet.wifi.aware.ConnectivityManagerSnippet,"/>
+ com.google.snippet.wifi.aware.ConnectivityManagerSnippet,
+ com.google.android.mobly.snippet.bundled.WifiManagerSnippet"/>
<meta-data
android:name="mobly-object-converter"
android:value="com.google.snippet.wifi.aware.WifiAwareSnippetConverter"/>
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 7c4eb88..70a0a63 100644
--- a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareJsonDeserializer.java
+++ b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareJsonDeserializer.java
@@ -96,7 +96,6 @@
private static final String RANGING_REQUEST_PEER_IDS = "peer_ids";
private static final String RANGING_REQUEST_PEER_MACS = "peer_mac_addresses";
-
private WifiAwareJsonDeserializer() {
}
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 f7d8673..3cf9fff 100644
--- a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareManagerSnippet.java
+++ b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareManagerSnippet.java
@@ -43,6 +43,7 @@
import android.net.wifi.rtt.RangingResult;
import android.net.wifi.rtt.RangingResultCallback;
import android.net.wifi.rtt.WifiRttManager;
+import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
@@ -65,11 +66,15 @@
import com.google.android.mobly.snippet.rpc.RpcOptional;
import com.google.android.mobly.snippet.util.Log;
+import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.ListIterator;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -347,6 +352,10 @@
/**
* Checks if Wi-Fi RTT is available.
*/
+ @Rpc(description = "Check if Wi-Fi Aware is available")
+ public Boolean wifiRttIsAvailable() {
+ return mWifiRttManager.isAvailable();
+ }
private void checkWifiRttAvailable() throws WifiAwareManagerSnippetException {
if (!mWifiRttManager.isAvailable()) {
throw new WifiAwareManagerSnippetException("WiFi RTT is not available now.");
@@ -833,6 +842,98 @@
}
/**
+ * Converts a JSON representation of a ScanResult to an actual ScanResult object. Mirror of
+ * the code in
+ * {@link com.googlecode.android_scripting.jsonrpc.JsonBuilder#buildJsonScanResult(ScanResult)}.
+ *
+ * @param j JSON object representing a ScanResult.
+ * @return a ScanResult object
+ * @throws JSONException on any JSON errors
+ */
+ public static ScanResult getScanResult(JSONObject j) throws JSONException {
+ if (j == null) {
+ return null;
+ }
+
+ ScanResult scanResult = new ScanResult();
+
+ if (j.has("BSSID")) {
+ scanResult.BSSID = j.getString("BSSID");
+ }
+ if (j.has("SSID")) {
+ scanResult.SSID = j.getString("SSID");
+ }
+ if (j.has("frequency")) {
+ scanResult.frequency = j.getInt("frequency");
+ }
+ if (j.has("level")) {
+ scanResult.level = j.getInt("level");
+ }
+ if (j.has("capabilities")) {
+ scanResult.capabilities = j.getString("capabilities");
+ }
+ if (j.has("timestamp")) {
+ scanResult.timestamp = j.getLong("timestamp");
+ }
+ if (j.has("centerFreq0")) {
+ scanResult.centerFreq0 = j.getInt("centerFreq0");
+ }
+ if (j.has("centerFreq1")) {
+ scanResult.centerFreq1 = j.getInt("centerFreq1");
+ }
+ if (j.has("channelWidth")) {
+ scanResult.channelWidth = j.getInt("channelWidth");
+ }
+ if (j.has("operatorFriendlyName")) {
+ scanResult.operatorFriendlyName = j.getString("operatorFriendlyName");
+ }
+ if (j.has("venueName")) {
+ scanResult.venueName = j.getString("venueName");
+ }
+
+ return scanResult;
+ }
+
+ /**
+ * Converts a JSONArray toa a list of ScanResult.
+ *
+ * @param j JSONArray representing a collection of ScanResult objects
+ * @return a list of ScanResult objects
+ * @throws JSONException on any JSON error
+ */
+ public static List<ScanResult> getScanResults(JSONArray j) throws JSONException {
+ if (j == null || j.length() == 0) {
+ return null;
+ }
+
+ ArrayList<ScanResult> scanResults = new ArrayList<>(j.length());
+ for (int i = 0; i < j.length(); ++i) {
+ scanResults.add(getScanResult(j.getJSONObject(i)));
+ }
+
+ return scanResults;
+ }
+
+ /**
+ * Starts Wi-Fi RTT ranging with Wi-Fi Aware access points.
+ *
+ * @param callbackId Assigned automatically by mobly for all async RPCs.
+ * @param requestJsonObject The ranging request in JSONArray type for calling {@link
+ * android.net.wifi.ScanResult}.
+ */
+ @AsyncRpc(description = "Start ranging to an Access Points.")
+ public void wifiRttStartRangingToAccessPoints(
+ String callbackId, JSONArray requestJsonObject
+ ) throws JSONException, WifiAwareManagerSnippetException {
+ Log.v("wifiRttStartRangingToAccessPoints: " + requestJsonObject);
+ RangingRequest request = new RangingRequest.Builder().addAccessPoints(
+ getScanResults(requestJsonObject)).build();
+ Log.v("Starting Wi-Fi RTT ranging with access point: " + request.toString());
+ RangingCallback rangingCb = new RangingCallback(eventCache, callbackId);
+ mWifiRttManager.startRanging(request, command -> mHandler.post(command), rangingCb);
+ }
+
+ /**
* Starts Wi-Fi RTT ranging with Wi-Fi Aware peers.
*
* @param callbackId Assigned automatically by mobly for all async RPCs.
@@ -869,7 +970,7 @@
public void onRangingFailure(int code) {
SnippetEvent event = new SnippetEvent(mCallbackId, EVENT_NAME_RANGING_RESULT);
event.getData().putString("callbackName", "onRangingFailure");
- event.getData().putInt("statusCode", code);
+ event.getData().putInt("status", code);
mEventCache.postEvent(event);
}
diff --git a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareSnippetConverter.java b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareSnippetConverter.java
index 154d0eb..edcfeac 100644
--- a/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareSnippetConverter.java
+++ b/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareSnippetConverter.java
@@ -19,14 +19,17 @@
import android.net.NetworkRequest;
import android.net.wifi.aware.PublishConfig;
import android.net.wifi.aware.SubscribeConfig;
+import android.net.wifi.ScanResult;
import android.net.wifi.aware.WifiAwareNetworkSpecifier;
import com.google.android.mobly.snippet.SnippetObjectConverter;
+import com.google.android.mobly.snippet.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.reflect.Type;
+import java.util.List;
/**
* The converter class that allows users to use custom type as snippet RPC arguments and return
@@ -34,6 +37,19 @@
*/
public class WifiAwareSnippetConverter implements SnippetObjectConverter {
+
+ public static String trimQuotationMarks(String originalString) {
+ String result = originalString;
+ if (originalString == null)
+ return result;
+ if (originalString.length() > 2
+ && originalString.charAt(0) == '"'
+ && originalString.charAt(originalString.length() - 1) == '"') {
+ result = originalString.substring(1, originalString.length() - 1);
+ }
+ return result;
+ }
+
@Override
public JSONObject serialize(Object object) throws JSONException {
// If the RPC method requires a custom return type, e.g. SubscribeConfig, PublishConfig, we
@@ -49,6 +65,24 @@
return null;
}
+ public static JSONObject serializeScanResult(ScanResult data) throws JSONException {
+ JSONObject result = new JSONObject();
+ result.put("BSSID", data.BSSID);
+ result.put("SSID", trimQuotationMarks(data.getWifiSsid().toString()));
+ result.put("capabilities", data.capabilities);
+ result.put("centerFreq0", data.centerFreq0);
+ result.put("centerFreq1", data.centerFreq1);
+ result.put("channelWidth", data.channelWidth);
+ result.put("frequency", data.frequency);
+ result.put("level", data.level);
+ result.put("operatorFriendlyName",
+ (data.operatorFriendlyName != null) ? data.operatorFriendlyName.toString() : "");
+ result.put("timestamp", data.timestamp);
+ result.put("venueName", (data.venueName != null) ? data.venueName.toString() : "");
+ result.put("scan_result_parcel", SerializationUtil.parcelableToString(data));
+ return result;
+ }
+
@Override
public Object deserialize(JSONObject jsonObject, Type type) throws JSONException {
// The parameters of Mobly RPC directly reference the Object type.
diff --git a/tests/hostsidetests/multidevices/com.google.snippet.wifi/direct/WifiP2pManagerSnippet.java b/tests/hostsidetests/multidevices/com.google.snippet.wifi/direct/WifiP2pManagerSnippet.java
index ab5fa1c..78b58b3 100644
--- a/tests/hostsidetests/multidevices/com.google.snippet.wifi/direct/WifiP2pManagerSnippet.java
+++ b/tests/hostsidetests/multidevices/com.google.snippet.wifi/direct/WifiP2pManagerSnippet.java
@@ -205,6 +205,21 @@
}
/**
+ * Request the connection information in the form of WifiP2pDevice.
+ *
+ * @param callbackId The callback ID assigned by Mobly.
+ * @param channelId The ID of the channel for Wi-Fi P2P to operate on.
+ */
+ @AsyncRpc(description = "Request the connection information in the form of WifiP2pDevice.")
+ public void wifiP2pRequestConnectionInfo(String callbackId,
+ @RpcDefault(value = "0") Integer channelId)
+ throws WifiP2pManagerException {
+ WifiP2pManager.Channel channel = getChannel(channelId);
+ mP2pManager.requestConnectionInfo(channel,
+ new WifiP2pConnectionInfoListener(callbackId));
+ }
+
+ /**
* Initiate peer discovery. A discovery process involves scanning for available Wi-Fi peers for
* the purpose of establishing a connection.
*
@@ -866,6 +881,27 @@
}
}
+ private static class WifiP2pConnectionInfoListener
+ implements WifiP2pManager.ConnectionInfoListener {
+ public static final String EVENT_NAME_ON_CONNECTION_INFO =
+ "WifiP2pOnConnectionInfoAvailable";
+ private final String mCallbackId;
+
+ public WifiP2pConnectionInfoListener(String callbackId) {
+ this.mCallbackId = callbackId;
+ }
+
+ @Override
+ public void onConnectionInfoAvailable(WifiP2pInfo info) {
+ Log.d(TAG + ": onConnectionInfoAvailable: " + info.toString());
+ SnippetEvent event = new SnippetEvent(mCallbackId, EVENT_NAME_ON_CONNECTION_INFO);
+ event.getData().putBoolean("groupFormed", info.groupFormed);
+ event.getData().putBoolean("isGroupOwner", info.isGroupOwner);
+ event.getData().putString("groupOwnerHostAddress", info.groupOwnerAddress.toString());
+ EventCache.getInstance().postEvent(event);
+ }
+ }
+
private static class DeviceInfoListener implements WifiP2pManager.DeviceInfoListener {
public static final String EVENT_NAME_ON_DEVICE_INFO = "WifiP2pOnDeviceInfoAvailable";
diff --git a/tests/hostsidetests/multidevices/test/aware/integration/Android.bp b/tests/hostsidetests/multidevices/test/aware/integration/Android.bp
index 68c7666..55483e3 100644
--- a/tests/hostsidetests/multidevices/test/aware/integration/Android.bp
+++ b/tests/hostsidetests/multidevices/test/aware/integration/Android.bp
@@ -226,3 +226,22 @@
tags: ["mobly"],
},
}
+
+python_test_host {
+ name: "WifiRttDisableTestCases",
+ main: "wifi_rtt_disable_test.py",
+ srcs: ["wifi_rtt_disable_test.py"],
+ device_common_data: [":wifi_aware_snippet_new"],
+ libs: [
+ "aware_lib_utils",
+ "mobly",
+ "wifi_aware_constants",
+ ],
+ test_suites: [
+ "general-tests",
+ ],
+ test_options: {
+ unit_test: false,
+ tags: ["mobly"],
+ },
+}
diff --git a/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_datapath_test.py b/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_datapath_test.py
index 21d26aa..6233347 100644
--- a/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_datapath_test.py
+++ b/tests/hostsidetests/multidevices/test/aware/integration/wifi_aware_datapath_test.py
@@ -1046,7 +1046,7 @@
_DATA_PATH_INITIATOR,
resp_mac,
init_passphrase,
- resp_pmk,
+ init_pmk,
network_id
)
# Initiator & Responder:
@@ -1657,6 +1657,14 @@
# peer using the Aware-provided peer handle (as opposed to a MAC address).
#######################################
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
+
def test_ib_unsolicited_passive_open_specific(self):
"""Data-path: in-band, unsolicited/passive, open encryption, specific peer
@@ -1668,6 +1676,14 @@
encr_type=self.ENCR_TYPE_OPEN,
use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
+
def test_ib_unsolicited_passive_open_any(self):
"""Data-path: in-band, unsolicited/passive, open encryption, any peer
@@ -1679,6 +1695,15 @@
encr_type=self.ENCR_TYPE_OPEN,
use_peer_id=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase(String)',
+ ]
+ )
+
def test_ib_unsolicited_passive_passphrase_specific(self):
"""Data-path: in-band, unsolicited/passive, passphrase, specific peer
@@ -1690,6 +1715,15 @@
encr_type=self.ENCR_TYPE_PASSPHRASE,
use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase(String)',
+ ]
+ )
+
def test_ib_unsolicited_passive_passphrase_any(self):
"""Data-path: in-band, unsolicited/passive, passphrase, any peer
@@ -1701,6 +1735,15 @@
encr_type=self.ENCR_TYPE_PASSPHRASE,
use_peer_id=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk(byte[])',
+ ]
+ )
+
def test_ib_unsolicited_passive_pmk_specific(self):
"""Data-path: in-band, unsolicited/passive, PMK, specific peer
@@ -1712,6 +1755,15 @@
encr_type=self.ENCR_TYPE_PMK,
use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk(byte[])',
+ ]
+ )
+
def test_ib_unsolicited_passive_pmk_any(self):
"""Data-path: in-band, unsolicited/passive, PMK, any peer
@@ -1723,6 +1775,14 @@
encr_type=self.ENCR_TYPE_PMK,
use_peer_id=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_SOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
+
def test_ib_solicited_active_open_specific(self):
"""Data-path: in-band, solicited/active, open encryption, specific peer
@@ -1734,6 +1794,14 @@
encr_type=self.ENCR_TYPE_OPEN,
use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_SOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
+
def test_ib_solicited_active_open_any(self):
"""Data-path: in-band, solicited/active, open encryption, any peer
@@ -1745,6 +1813,15 @@
encr_type=self.ENCR_TYPE_OPEN,
use_peer_id=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_SOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase(String)',
+ ]
+ )
+
def test_ib_solicited_active_passphrase_specific(self):
"""Data-path: in-band, solicited/active, passphrase, specific peer
@@ -1756,6 +1833,15 @@
encr_type=self.ENCR_TYPE_PASSPHRASE,
use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_SOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase(String)',
+ ]
+ )
+
def test_ib_solicited_active_passphrase_any(self):
"""Data-path: in-band, solicited/active, passphrase, any peer
@@ -1767,6 +1853,15 @@
encr_type=self.ENCR_TYPE_PASSPHRASE,
use_peer_id=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_SOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk(byte[])',
+ ]
+ )
+
def test_ib_solicited_active_pmk_specific(self):
"""Data-path: in-band, solicited/active, PMK, specific peer
@@ -1778,6 +1873,15 @@
encr_type=self.ENCR_TYPE_PMK,
use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_SOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_ACTIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPmk(byte[])',
+ ]
+ )
+
def test_ib_solicited_active_pmk_any(self):
"""Data-path: in-band, solicited/active, PMK, any peer
@@ -1809,9 +1913,17 @@
# peer using the Aware-provided peer handle (as opposed to a MAC address).
#######################################
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
+
def test_ib_extra_pub_same_unsolicited_passive_open_specific(self):
"""Data-path: in-band, unsolicited/passive, open encryption.
- specific peer.
+ specific peer.
Configuration contains a publisher (for the same service)
running on *both* devices.
@@ -1826,10 +1938,17 @@
pub_on_both=True,
pub_on_both_same=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
def test_ib_extra_pub_same_unsolicited_passive_open_any(self):
"""Data-path: in-band, unsolicited/passive, open encryption.
- any peer.
+ any peer.
Configuration contains a publisher (for the same service) running on
*both* devices.
@@ -1844,9 +1963,17 @@
pub_on_both=True,
pub_on_both_same=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
+
def test_ib_extra_pub_diff_unsolicited_passive_open_specific(self):
"""Data-path: in-band, unsolicited/passive, open encryption.
- specific peer.
+ specific peer.
Configuration contains a publisher (for a different service) running on
*both* devices.
@@ -1861,6 +1988,14 @@
pub_on_both=True,
pub_on_both_same=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ ]
+ )
+
def test_ib_extra_pub_diff_unsolicited_passive_open_any(self):
"""Data-path: in-band, unsolicited/passive, open encryption, any peer.
@@ -1879,6 +2014,14 @@
##############################################################
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareSession#subscrible(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase(String)',
+ ]
+ )
+
def test_passphrase_min(self):
"""Data-path: minimum passphrase length
@@ -1891,11 +2034,19 @@
use_peer_id=False,
passphrase_to_use=self.PASSPHRASE_MIN)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareSession#subscrible(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#setPskPassphrase(String)',
+ ]
+ )
+
def test_passphrase_max(self):
"""Data-path: maximum passphrase length
Use in-band, unsolicited/passive, any peer combination
- """
+ """
self.run_ib_data_path_test(
ptype=_PUBLISH_TYPE_UNSOLICITED,
stype=_SUBSCRIBE_TYPE_PASSIVE,
@@ -1903,22 +2054,51 @@
use_peer_id=False,
passphrase_to_use=self.PASSPHRASE_MAX)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_negative_mismatch_init_mac(self):
"""Data-path: failure when Initiator MAC address mismatch"""
self.run_mismatched_oob_data_path_test(
init_mismatch_mac=True, resp_mismatch_mac=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_negative_mismatch_resp_mac(self):
"""Data-path: failure when Responder MAC address mismatch"""
self.run_mismatched_oob_data_path_test(
init_mismatch_mac=False, resp_mismatch_mac=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_passphrase(self):
"""Data-path: failure when passphrases mismatch"""
self.run_mismatched_oob_data_path_test(
init_encr_type=self.ENCR_TYPE_PASSPHRASE,
resp_encr_type=self.ENCR_TYPE_PASSPHRASE)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_open_passphrase(self):
"""Data-path:
failure when initiator is open, and responder passphrase
@@ -1927,6 +2107,14 @@
init_encr_type=self.ENCR_TYPE_OPEN,
resp_encr_type=self.ENCR_TYPE_PASSPHRASE)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_passphrase_open(self):
"""Data-path:
failure when initiator is passphrase, and responder open
@@ -1935,30 +2123,69 @@
init_encr_type=self.ENCR_TYPE_PASSPHRASE,
resp_encr_type=self.ENCR_TYPE_OPEN)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_pmk(self):
"""Data-path: failure when PMK mismatch"""
self.run_mismatched_oob_data_path_test(
init_encr_type=self.ENCR_TYPE_PMK,
resp_encr_type=self.ENCR_TYPE_PMK)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_open_pmk(self):
"""Data-path: failure when initiator is open, and responder PMK"""
self.run_mismatched_oob_data_path_test(
init_encr_type=self.ENCR_TYPE_OPEN,
resp_encr_type=self.ENCR_TYPE_PMK)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_pmk_passphrase(self):
"""Data-path: failure when initiator is pmk, and responder passphrase"""
self.run_mismatched_oob_data_path_test(
init_encr_type=self.ENCR_TYPE_PMK,
resp_encr_type=self.ENCR_TYPE_PASSPHRASE)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_pmk_open(self):
"""Data-path: failure when initiator is PMK, and responder open"""
self.run_mismatched_oob_data_path_test(
init_encr_type=self.ENCR_TYPE_PMK,
resp_encr_type=self.ENCR_TYPE_OPEN)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ ]
+ )
+
def test_negative_mismatch_passphrase_pmk(self):
"""Data-path: failure when initiator is passphrase, and responder pmk"""
self.run_mismatched_oob_data_path_test(
@@ -1981,6 +2208,13 @@
# and exchange of MAC addresses and then Wi-Fi Aware for data-path.
#######################################
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_oob_open_specific(self):
"""Data-path: out-of-band, open encryption, specific peer
@@ -1989,6 +2223,13 @@
self.run_oob_data_path_test(
encr_type=self.ENCR_TYPE_OPEN, use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_oob_passphrase_specific(self):
"""Data-path: out-of-band, passphrase, specific peer
@@ -1997,6 +2238,13 @@
self.run_oob_data_path_test(
encr_type=self.ENCR_TYPE_PASSPHRASE, use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ ]
+ )
+
def test_oob_pmk_specific(self):
"""Data-path: out-of-band, PMK, specific peer
@@ -2005,6 +2253,15 @@
self.run_oob_data_path_test(
encr_type=self.ENCR_TYPE_PMK, use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_oob_ib_coex_open_specific(self):
"""Data-path: out-of-band, open encryption, specific peer - in-band coex:
set up a concurrent discovery session to verify no impact. The session
@@ -2016,6 +2273,15 @@
encr_type=self.ENCR_TYPE_OPEN,
setup_discovery_sessions=True , use_peer_id=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_identical_networks(self):
"""Validate that creating multiple networks between 2 devices, each network
with identical configuration is supported over a single NDP.
@@ -2150,6 +2416,15 @@
init_dut.wifi_aware_snippet.connectivityUnregisterNetwork(
init_req_callback_event.callback_id)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_identical_network_from_both_sides(self):
"""Validate that requesting two identical NDPs (Open) each being initiated
from a different side, results in the same/single NDP.
@@ -2550,6 +2825,15 @@
dut2.wifi_aware_snippet.connectivityUnregisterNetwork(
dut2_key_even.callback_id)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_open_passphrase(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one open, one using passphrase). The result should use
@@ -2558,6 +2842,14 @@
# self.run_multiple_ndi(self.PASSPHRASE)
self.run_multiple_ndi([None, self.PASSPHRASE])
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_passphrases(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (using different passphrases). The result should use two
@@ -2565,6 +2857,15 @@
"""
self.run_multiple_ndi([self.PASSPHRASE, self.PASSPHRASE2])
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_open_passphrase_flip(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one open, one using passphrase). The result should use
@@ -2574,6 +2875,14 @@
"""
self.run_multiple_ndi([None, self.PASSPHRASE], flip_init_resp=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_passphrases_flip(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (using different passphrases). The result should use two
@@ -2584,6 +2893,15 @@
self.run_multiple_ndi(
[self.PASSPHRASE, self.PASSPHRASE2], flip_init_resp=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_open_pmk(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one open, one using pmk). The result should use two
@@ -2591,6 +2909,15 @@
"""
self.run_multiple_ndi([None, self.PMK])
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_passphrase_pmk(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one using passphrase, one using pmk). The result should
@@ -2598,6 +2925,14 @@
"""
self.run_multiple_ndi([self.PASSPHRASE, self.PMK])
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_pmks(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (using different PMKS). The result should use two
@@ -2605,6 +2940,15 @@
"""
self.run_multiple_ndi([self.PMK, self.PMK2])
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_open_pmk_flip(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one open, one using pmk). The result should use two
@@ -2614,6 +2958,15 @@
"""
self.run_multiple_ndi([None, self.PMK], flip_init_resp=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_passphrase_pmk_flip(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (one using passphrase, one using pmk). The result should
@@ -2623,6 +2976,14 @@
"""
self.run_multiple_ndi([self.PASSPHRASE, self.PMK], flip_init_resp=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPmk(byte[],string)',
+ 'android.net.NetworkCapabilities#TRANSPORT_WIFI_AWARE',
+ ]
+ )
+
def test_multiple_ndi_pmks_flip(self):
"""Verify that between 2 DUTs can create 2 NDPs with different security
configuration (using different PMKS). The result should use two
@@ -2649,6 +3010,16 @@
#
#######################################
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_identical_ndps_mix_ib_oob_ib_first_same_polarity(self):
"""Validate that a single NDP is created for multiple identical
requests which are issued through either in-band (ib) or out-of-band
@@ -2660,6 +3031,16 @@
self.run_mix_ib_oob(
same_request=True, ib_first=True, inits_on_same_dut=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_identical_ndps_mix_ib_oob_oob_first_same_polarity(self):
"""Validate that a single NDP is created for multiple identical
requests which are issued through either in-band (ib) or out-of-band
@@ -2672,6 +3053,16 @@
self.run_mix_ib_oob(
same_request=True, ib_first=False, inits_on_same_dut=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_identical_ndps_mix_ib_oob_ib_first_diff_polarity(self):
"""Validate that a single NDP is created for multiple identical
requests which are issued through either in-band (ib) or out-of-band
@@ -2683,6 +3074,16 @@
self.run_mix_ib_oob(
same_request=True, ib_first=True, inits_on_same_dut=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_identical_ndps_mix_ib_oob_oob_first_diff_polarity(self):
"""Validate that a single NDP is created for multiple identical
requests which are issued through either in-band (ib) or out-of-band
@@ -2694,6 +3095,16 @@
self.run_mix_ib_oob(
same_request=True, ib_first=False, inits_on_same_dut=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_multiple_ndis_mix_ib_oob_ib_first_same_polarity(self):
"""Validate that multiple NDIs are created for NDPs which are requested
@@ -2706,6 +3117,16 @@
self.run_mix_ib_oob(
same_request=False, ib_first=True, inits_on_same_dut=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_multiple_ndis_mix_ib_oob_oob_first_same_polarity(self):
"""Validate that multiple NDIs are created for NDPs which are requested
with different security configurations. Use a mix of in-band and
@@ -2717,6 +3138,16 @@
self.run_mix_ib_oob(
same_request=False, ib_first=False, inits_on_same_dut=True)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
+
def test_multiple_ndis_mix_ib_oob_ib_first_diff_polarity(self):
"""Validate that multiple NDIs are created for NDPs which are requested
with different security configurations. Use a mix of in-band and
@@ -2728,6 +3159,15 @@
self.run_mix_ib_oob(
same_request=False, ib_first=True, inits_on_same_dut=False)
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.PublishConfig.Builder#setPublishType(PublishConfig.PUBLISH_TYPE_UNSOLICITED)',
+ 'android.net.wifi.aware.SubscribeConfig.Builder#setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build()',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierPassphrase(byte[],string)',
+ ]
+ )
def test_multiple_ndis_mix_ib_oob_oob_first_diff_polarity(self):
"""Validate that multiple NDIs are created for NDPs which are requested
@@ -2749,6 +3189,16 @@
#
#######################################
+ @ApiTest(
+ apis=[
+ 'android.net.wifi.aware.WifiAwareManager#attach(android.net.wifi.aware.AttachCallback, android.net.wifi.aware.IdentityChangedListener, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#publish(android.net.wifi.aware.PublishConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareSession#subscrible(android.net.wifi.aware.SubscribeConfig, android.net.wifi.aware.DiscoverySessionCallback, android.os.Handler)',
+ 'android.net.wifi.aware.WifiAwareNetworkSpecifier.Builder#build',
+ 'android.net.wifi.aware.WifiAwareSession#createNetworkSpecifierOpen(byte[])',
+ ]
+ )
+
def test_multiple_regulator_domains_ib_us_jp(self):
"""Verify data-path setup across multiple regulator domains.
diff --git a/tests/hostsidetests/multidevices/test/aware/integration/wifi_rtt_disable_test.py b/tests/hostsidetests/multidevices/test/aware/integration/wifi_rtt_disable_test.py
new file mode 100644
index 0000000..d87de30
--- /dev/null
+++ b/tests/hostsidetests/multidevices/test/aware/integration/wifi_rtt_disable_test.py
@@ -0,0 +1,375 @@
+# Copyright (C) 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Lint as: python3
+"""Wi-Fi Aware Rtt Disable test reimplemented in Mobly."""
+import functools
+import logging
+import signal
+import sys
+import time
+
+from aware import aware_lib_utils as autils
+from aware import constants
+from mobly import asserts
+from mobly import base_test
+from mobly import records
+from mobly import test_runner
+from mobly import utils
+from mobly.controllers import android_device
+from mobly.snippet import errors
+
+RUNTIME_PERMISSIONS = (
+ 'android.permission.ACCESS_FINE_LOCATION',
+ 'android.permission.ACCESS_COARSE_LOCATION',
+ 'android.permission.NEARBY_WIFI_DEVICES',
+)
+PACKAGE_NAME = constants.WIFI_AWARE_SNIPPET_PACKAGE_NAME
+
+# Alias variable.
+_DEFAULT_TIMEOUT = constants.WAIT_WIFI_STATE_TIME_OUT.total_seconds()
+_CALLBACK_NAME = constants.DiscoverySessionCallbackParamsType.CALLBACK_NAME
+
+######################################################
+# status codes
+######################################################
+_RANGING_FAIL_CODE_GENERIC = 1
+_RANGING_FAIL_CODE_RTT_NOT_AVAILABLE = 2
+
+
+# Timeout decorator block
+class TimeoutError(Exception):
+ """Exception for timeout decorator related errors."""
+
+
+def _timeout_handler():
+ """Handler function used by signal to terminate a timed out function."""
+ raise TimeoutError()
+
+
+def timeout(sec):
+ """A decorator used to add time out check to a function.
+
+ This only works in main thread due to its dependency on signal module.
+ Do NOT use it if the decorated function does not run in the Main thread.
+
+ Args:
+ sec: Number of seconds to wait before the function times out. No timeout
+ if set to 0
+
+ Returns:
+ What the decorated function returns.
+
+ Raises:
+ TimeoutError is raised when time out happens.
+ """
+
+ def decorator(func):
+
+ @functools.wraps(func)
+ def wrapper(*args, **kwargs):
+ if sec:
+ signal.signal(signal.SIGALRM, _timeout_handler)
+ signal.alarm(sec)
+ try:
+ return func(*args, **kwargs)
+ except TimeoutError as exc:
+ raise TimeoutError(
+ ('Function {} timed out after {} seconds.').format(
+ func.__name__, sec
+ )
+ ) from exc
+ finally:
+ signal.alarm(0)
+
+ return wrapper
+
+ return decorator
+
+
+class RttDisableTest(base_test.BaseTestClass):
+ """Test class for RTT ranging enable/disable flows."""
+
+ MODE_DISABLE_WIFI = 0
+ MODE_DISABLE_LOCATIONING = 1
+
+ ads: list[android_device.AndroidDevice]
+
+ def setup_class(self):
+ self.ads = self.register_controller(android_device, min_number=1)
+
+ def setup_device(device: android_device.AndroidDevice):
+ autils.control_wifi(device, True)
+ device.load_snippet('wifi_aware_snippet', PACKAGE_NAME)
+ for permission in RUNTIME_PERMISSIONS:
+ device.adb.shell(['pm', 'grant', PACKAGE_NAME, permission])
+ asserts.abort_all_if(
+ not device.wifi_aware_snippet.wifiAwareIsAvailable(),
+ f'{device} Wi-Fi Aware is not available.',
+ )
+
+ # Set up devices in parallel.
+ utils.concurrent_exec(
+ setup_device,
+ param_list=[[ad] for ad in self.ads],
+ max_workers=1,
+ raise_on_exception=True,
+ )
+
+ def setup_test(self):
+ for ad in self.ads:
+ autils.control_wifi(ad, True)
+ self.set_location_service(ad, True)
+ aware_avail = ad.wifi_aware_snippet.wifiAwareIsAvailable()
+ if not aware_avail:
+ ad.log.info('Aware not available. Waiting ...')
+ state_handler = ad.wifi_aware_snippet.wifiAwareMonitorStateChange()
+ state_handler.waitAndGet(
+ constants.WifiAwareBroadcast.WIFI_AWARE_AVAILABLE
+ )
+
+ def teardown_test(self):
+ utils.concurrent_exec(
+ self._teardown_test_on_device,
+ param_list=[[ad] for ad in self.ads],
+ max_workers=1,
+ raise_on_exception=True,
+ )
+ utils.concurrent_exec(
+ lambda d: d.services.create_output_excerpts_all(self.current_test_info),
+ param_list=[[ad] for ad in self.ads],
+ raise_on_exception=True,
+ )
+
+ def _teardown_test_on_device(self, ad: android_device.AndroidDevice) -> None:
+ ad.wifi_aware_snippet.wifiAwareCloseAllWifiAwareSession()
+ ad.wifi_aware_snippet.wifiAwareMonitorStopStateChange()
+ # autils.control_wifi(ad, True)
+
+ def on_fail(self, record: records.TestResult) -> None:
+ android_device.take_bug_reports(
+ self.ads, destination=self.current_test_info.output_path
+ )
+
+ def scan_networks(
+ self, dut: android_device.AndroidDevice, max_tries: int = 3
+ ) -> list[dict[str, str]]:
+ """Perform a scan and return scan results.
+
+ Args:
+ dut: Device under test.
+ max_tries: Retry scan to ensure network is found
+
+ Returns:
+ an array of scan results.
+ """
+ scan_results = []
+ for _ in range(max_tries):
+ scan_results = dut.wifi_aware_snippet.wifiScanAndGetResults()
+ if scan_results:
+ break
+
+ return scan_results
+
+ def select_best_scan_results(
+ self,
+ scans: list[dict[str, str]],
+ select_count: int,
+ lowest_rssi: int = -80,
+ ):
+ """Select best result based on RSSI.
+
+ Select the strongest 'select_count' scans in the input list based on
+ highest RSSI. Exclude all very weak signals, even if results in a shorter
+ list.
+
+ Args:
+ scans: List of scan results.
+ select_count: An integer specifying how many scans to return at most.
+ lowest_rssi: The lowest RSSI to accept into the output.
+
+ Returns:
+ a list of the strongest 'select_count' scan results from the scans
+ list.
+ """
+
+ def _take_rssi(element):
+ return element['level']
+
+ result = []
+ scans.sort(key=_take_rssi, reverse=True)
+ for scan in scans:
+ logging.info(
+ 'scan type: %s, %s, %s', scan['SSID'], scan['level'], scan['BSSID']
+ )
+ if len(result) == select_count:
+ break
+ if scan['level'] < lowest_rssi:
+ break # rest are lower since we're sorted
+ result.append(scan)
+
+ return result
+
+ def set_location_service(self, ad, new_state):
+ """Set Location service on/off in Settings->Location.
+
+ Args:
+ ad: android device object.
+ new_state: new state for "Location service".
+ If new_state is False, turn off location service.
+ If new_state if True, set location service to "High accuracy".
+ """
+ ad.adb.shell('content insert --uri '
+ ' content://com.google.settings/partner --bind '
+ 'name:s:network_location_opt_in --bind value:s:1')
+ ad.adb.shell('content insert --uri '
+ ' content://com.google.settings/partner --bind '
+ 'name:s:use_location_for_services --bind value:s:1')
+ if new_state:
+ ad.adb.shell('settings put secure location_mode 3')
+ else:
+ ad.adb.shell('settings put secure location_mode 0')
+
+ def force_airplane_mode(self, ad, new_state, timeout_value=60):
+ """Force the device to set airplane mode on or off by adb shell command.
+
+ Args:
+ ad: android device object.
+ new_state: Turn on airplane mode if True.
+ Turn off airplane mode if False.
+ timeout_value: max wait time for 'adb wait-for-device'
+
+ Returns:
+ True if success.
+ False if timeout.
+ """
+
+ # Using timeout decorator.
+ # Wait for device with timeout. If after <timeout_value> seconds, adb
+ # is still waiting for device, throw TimeoutError exception.
+ @timeout(timeout_value)
+ def wait_for_device_with_timeout(ad):
+ ad.adb.wait_for_device()
+
+ try:
+ wait_for_device_with_timeout(ad)
+ ad.adb.shell('settings put global airplane_mode_on {}'.format(
+ 1 if new_state else 0))
+ ad.adb.shell('am broadcast -a android.intent.action.AIRPLANE_MODE')
+ except TimeoutError:
+ # adb wait for device timeout
+ return False
+ return True
+
+ def run_disable_rtt(self, disable_mode):
+ """Validate the RTT ranging feature if RTT disabled.
+
+ Validate the RTT disabled flows: whether by disabling Wi-Fi or entering
+ doze mode.
+
+ Args:
+ disable_mode: The particular mechanism in which RTT is disabled. One of
+ the MODE_* constants.
+ """
+ dut = self.ads[0]
+
+ # validate start-up conditions
+ asserts.assert_true(
+ dut.wifi_aware_snippet.wifiRttIsAvailable(), 'RTT is not available'
+ )
+
+ # scan to get some APs to be used later
+ all_aps = self.select_best_scan_results(
+ self.scan_networks(dut), select_count=1
+ )
+ asserts.assert_true(all_aps, 'Need at least one visible AP!')
+
+ # disable RTT and validate broadcast & API
+ if disable_mode == self.MODE_DISABLE_WIFI:
+ # disabling Wi-Fi is not sufficient: since scan mode (and hence RTT) will
+ # remain enabled - we need to disable the Wi-Fi chip aka Airplane Mode
+ asserts.assert_true(
+ self.force_airplane_mode(dut, True),
+ 'Can not turn on airplane mode on: %s' % dut.serial,
+ )
+ autils.control_wifi(dut, False)
+ elif disable_mode == self.MODE_DISABLE_LOCATIONING:
+ self.set_location_service(dut, False)
+ time.sleep(10)
+ dut.log.info(
+ 'WiFi RTT status: %s', dut.wifi_aware_snippet.wifiRttIsAvailable()
+ )
+ asserts.assert_false(
+ dut.wifi_aware_snippet.wifiRttIsAvailable(), 'RTT is available'
+ )
+
+ # request a range and validate error
+ dut.log.info('access points input: %s', all_aps[0:1])
+ ranging_cb_handler = (
+ dut.wifi_aware_snippet.wifiRttStartRangingToAccessPoints(all_aps[0:1])
+ )
+ event = ranging_cb_handler.waitAndGet(
+ event_name=constants.RangingResultCb.EVENT_NAME_ON_RANGING_RESULT,
+ timeout=_DEFAULT_TIMEOUT,
+ )
+
+ callback_name = event.data.get(
+ constants.RangingResultCb.DATA_KEY_CALLBACK_NAME, None
+ )
+ dut.log.info('StartRangingToAccessPoints callback = %s', callback_name)
+ asserts.assert_equal(
+ callback_name,
+ constants.RangingResultCb.CB_METHOD_ON_RANGING_FAILURE,
+ 'Should be ranging failed.',
+ )
+ status_code = event.data.get(
+ constants.RangingResultCb.DATA_KEY_RESULT_STATUS, None
+ )
+ dut.log.info('StartRangingToAccessPoints status code = %s', status_code)
+ asserts.assert_equal(
+ status_code, _RANGING_FAIL_CODE_RTT_NOT_AVAILABLE, 'Invalid error code'
+ )
+
+ # enable RTT and validate broadcast & API
+ if disable_mode == self.MODE_DISABLE_WIFI:
+ asserts.assert_true(
+ self.force_airplane_mode(dut, False),
+ 'Can not turn off airplane mode on: %s' % dut.serial,
+ )
+ autils.control_wifi(dut, True)
+ elif disable_mode == self.MODE_DISABLE_LOCATIONING:
+ self.set_location_service(dut, True)
+
+ asserts.assert_true(
+ dut.wifi_aware_snippet.wifiRttIsAvailable(), 'RTT is not available'
+ )
+
+ def test_disable_wifi(self):
+ """Validate that getting expected broadcast when Wi-Fi is disabled and that any range requests are rejected.
+ """
+ self.run_disable_rtt(self.MODE_DISABLE_WIFI)
+
+ def test_disable_location(self):
+ """Validate that getting expected broadcast when locationing is disabled and that any range requests are rejected.
+ """
+ self.run_disable_rtt(self.MODE_DISABLE_LOCATIONING)
+
+
+if __name__ == '__main__':
+ # Take test args
+ if '--' in sys.argv:
+ index = sys.argv.index('--')
+ sys.argv = sys.argv[:1] + sys.argv[index + 1 :]
+
+ test_runner.main()
diff --git a/tests/hostsidetests/multidevices/test/direct/constants.py b/tests/hostsidetests/multidevices/test/direct/constants.py
index 903b108..a3bcdf5 100644
--- a/tests/hostsidetests/multidevices/test/direct/constants.py
+++ b/tests/hostsidetests/multidevices/test/direct/constants.py
@@ -52,6 +52,7 @@
EXTRA_WIFI_P2P_GROUP = 'p2pGroupInfo'
EXTRA_WIFI_STATE = 'wifi_p2p_state'
+ON_CONNECTION_INFO_AVAILABLE = 'WifiP2pOnConnectionInfoAvailable'
ON_DEVICE_INFO_AVAILABLE = 'WifiP2pOnDeviceInfoAvailable'
ON_PERSISTENT_GROUP_INFO_AVAILABLE = 'onPersistentGroupInfoAvailable'
ON_UPNP_SERVICE_AVAILABLE = 'onUpnpServiceAvailable'
diff --git a/tests/hostsidetests/multidevices/test/direct/integration/Android.bp b/tests/hostsidetests/multidevices/test/direct/integration/Android.bp
new file mode 100644
index 0000000..c1332f5
--- /dev/null
+++ b/tests/hostsidetests/multidevices/test/direct/integration/Android.bp
@@ -0,0 +1,50 @@
+// Copyright (C) 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_team: "trendy_team_fwk_wifi_hal",
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+python_library_host {
+ name: "wifi_p2p_lib",
+ srcs: ["wifi_p2p_lib.py"],
+}
+
+python_test_host {
+ name: "WifiP2pGroupTestCases",
+ main: "wifi_p2p_group_test.py",
+ srcs: [
+ "wifi_p2p_group_test.py",
+ ],
+ libs: [
+ "mobly",
+ "wifi_direct_constants",
+ "wifi_direct_test_utils",
+ "wifi_p2p_lib",
+ "wifi_test_utils",
+ "platform-test-py-annotations",
+ ],
+ device_common_data: [":wifi_mobly_snippet"],
+ test_options: {
+ unit_test: false,
+ tags: ["mobly"],
+ },
+ test_suites: ["general-tests"],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
+}
diff --git a/tests/hostsidetests/multidevices/test/direct/integration/wifi_p2p_group_test.py b/tests/hostsidetests/multidevices/test/direct/integration/wifi_p2p_group_test.py
new file mode 100644
index 0000000..a34255e
--- /dev/null
+++ b/tests/hostsidetests/multidevices/test/direct/integration/wifi_p2p_group_test.py
@@ -0,0 +1,197 @@
+# Copyright (C) 2025 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Lint as: python3
+"""ACTS Wifi P2p Group Test reimplemented in Mobly."""
+
+from collections.abc import Sequence
+import datetime
+import time
+
+from android.platform.test.annotations import ApiTest
+from direct import constants
+from direct import p2p_utils
+from mobly import base_test
+from mobly import test_runner
+from mobly import utils
+from mobly.controllers import android_device
+import wifi_p2p_lib as wp2putils
+
+
+_DEFAULT_TIMEOUT = datetime.timedelta(seconds=30)
+DEFAULT_SLEEPTIME = 5
+_DEFAULT_FUNCTION_SWITCH_TIME = 10
+_DEFAULT_GROUP_CLIENT_LOST_TIME = 60
+
+P2P_CONNECT_NEGOTIATION = 0
+P2P_CONNECT_JOIN = 1
+P2P_CONNECT_INVITATION = 2
+
+WPS_PBC = wp2putils.WifiP2PEnums.WpsInfo.WIFI_WPS_INFO_PBC
+WPS_DISPLAY = wp2putils.WifiP2PEnums.WpsInfo.WIFI_WPS_INFO_DISPLAY
+WPS_KEYPAD = wp2putils.WifiP2PEnums.WpsInfo.WIFI_WPS_INFO_KEYPAD
+
+
+class WifiP2pGroupTest(base_test.BaseTestClass):
+ """Tests Wi-Fi Direct between 2 Android devices."""
+
+ ads: Sequence[android_device.AndroidDevice]
+ group_owner_ad: android_device.AndroidDevice
+ client_ad: android_device.AndroidDevice
+ network_name = 'DIRECT-xy-Hello'
+ passphrase = 'P2pWorld1234'
+ group_band = '2'
+
+ def setup_class(self) -> None:
+ super().setup_class()
+ self.ads = self.register_controller(android_device, min_number=2)
+ utils.concurrent_exec(
+ self._setup_device,
+ param_list=[[ad] for ad in self.ads],
+ raise_on_exception=True,
+ )
+ self.group_owner_ad, self.client_ad, *_ = self.ads
+ self.group_owner_ad.debug_tag = (
+ f'{self.group_owner_ad.serial}(Group Owner)'
+ )
+ self.client_ad.debug_tag = f'{self.client_ad.serial}(Client)'
+
+ def _setup_device(self, ad: android_device.AndroidDevice) -> None:
+ ad.load_snippet('wifi', constants.WIFI_SNIPPET_PACKAGE_NAME)
+ # Clear all saved Wi-Fi networks.
+ ad.wifi.wifiDisable()
+ ad.wifi.wifiClearConfiguredNetworks()
+ ad.wifi.wifiEnable()
+
+ def teardown_test(self) -> None:
+ for ad in self.ads:
+ ad.wifi.p2pClose()
+
+ utils.concurrent_exec(
+ lambda d: d.services.create_output_excerpts_all(
+ self.current_test_info
+ ),
+ param_list=[[ad] for ad in self.ads],
+ raise_on_exception=True,
+ )
+
+ def p2p_group_join(self, wps_config: constants.WpsInfo):
+ """General flow for p2p group join.
+
+ Steps:
+ 1. GO creates a group.
+ 2. GC joins the group.
+ 3. connection check via ping from GC to GO
+
+ Args:
+ wps_config: WPS configuration for the group.
+ """
+ go_dut = self.ads[0]
+ gc_dut = self.ads[1]
+
+ go_dut.log.info('Initializing Wi-Fi p2p.')
+ group_owner = p2p_utils.setup_wifi_p2p(go_dut)
+ client = p2p_utils.setup_wifi_p2p(gc_dut)
+ # Create a group.
+ p2p_utils.create_group(group_owner, config=None)
+ time.sleep(_DEFAULT_FUNCTION_SWITCH_TIME)
+
+ # Request the connection.
+ wp2putils.p2p_connect(client, group_owner, wps_config,
+ p2p_connect_type=P2P_CONNECT_JOIN)
+
+ go_ip = wp2putils.p2p_go_ip(gc_dut)
+ wp2putils.p2p_connection_ping_test(gc_dut, go_ip)
+ # Trigger p2p disconnect.
+ p2p_utils.remove_group_and_verify_disconnected(
+ client, group_owner, is_group_negotiation=False
+ )
+ time.sleep(_DEFAULT_FUNCTION_SWITCH_TIME)
+
+ @ApiTest([
+ 'android.net.wifi.WpsInfo#PBC',
+ 'android.net.wifi.p2p.WifiP2pManager#createGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pConfig, android.net.wifi.p2p.WifiP2pManager.ActionListener)',
+ 'android.net.wifi.p2p.WifiP2pManager#connect(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pConfig, android.net.wifi.p2p.WifiP2pManager.ActionListener)',
+ 'android.net.wifi.p2p.WifiP2pManager#removeGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener)',
+ ])
+ def test_p2p_group_join_via_pbc(self):
+ """Verify the p2p creates a group and join this group via WPS PBC method."""
+ self.p2p_group_join(constants.WpsInfo.PBC)
+
+ @ApiTest([
+ 'android.net.wifi.WpsInfo#DISPLAY',
+ 'android.net.wifi.p2p.WifiP2pManager#createGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pConfig, android.net.wifi.p2p.WifiP2pManager.ActionListener)',
+ 'android.net.wifi.p2p.WifiP2pManager#connect(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pConfig, android.net.wifi.p2p.WifiP2pManager.ActionListener)',
+ 'android.net.wifi.p2p.WifiP2pManager#removeGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener)',
+ ])
+ def test_p2p_group_join_via_display(self):
+ """Verify the p2p creates a group and join this group via WPS DISPLAY method."""
+ self.p2p_group_join(WPS_DISPLAY)
+
+ @ApiTest([
+ 'android.net.wifi.p2p.WifiP2pConfig.Builder#setPassphrase(String passphrase)',
+ 'android.net.wifi.p2p.WifiP2pConfig.Builder#setGroupOperatingBand(int band)',
+ 'android.net.wifi.p2p.WifiP2pManager#createGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pConfig, android.net.wifi.p2p.WifiP2pManager.ActionListener)',
+ 'android.net.wifi.p2p.WifiP2pManager#connect(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pConfig, android.net.wifi.p2p.WifiP2pManager.ActionListener)',
+ 'android.net.wifi.p2p.WifiP2pManager#removeGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener)',
+ ])
+ def test_p2p_group_with_config(self):
+ """Verify the p2p creates a group and join this group with config.
+
+ Steps:
+ 1. GO creates a group with config.
+ 2. GC joins the group with config.
+ 3. connection check via ping from GC to GO
+ """
+ go_dut = self.ads[0]
+ gc_dut = self.ads[1]
+ # Initialize Wi-Fi p2p on both devices.
+ group_owner = p2p_utils.setup_wifi_p2p(go_dut)
+ client = p2p_utils.setup_wifi_p2p(gc_dut)
+
+ # Create a p2p group on one device (group owner device) with
+ # specific group configuration.
+ p2p_config = constants.WifiP2pConfig(
+ network_name='DIRECT-XY-HELLO-%s' % utils.rand_ascii_str(5),
+ passphrase=self.passphrase,
+ group_operating_band=self.group_band,
+ )
+ p2p_utils.create_group(group_owner, config=p2p_config)
+ time.sleep(_DEFAULT_FUNCTION_SWITCH_TIME)
+ # Request the connection. Since config is known, this is reconnection.
+ p2p_utils.p2p_connect(client, group_owner, p2p_config)
+
+ go_ip = wp2putils.p2p_go_ip(gc_dut)
+ wp2putils.p2p_connection_ping_test(gc_dut, go_ip)
+ # Trigger disconnect.
+ p2p_utils.remove_group_and_verify_disconnected(
+ client, group_owner, is_group_negotiation=False
+ )
+ time.sleep(_DEFAULT_FUNCTION_SWITCH_TIME)
+
+if __name__ == '__main__':
+ test_runner.main()
+
diff --git a/tests/hostsidetests/multidevices/test/direct/integration/wifi_p2p_lib.py b/tests/hostsidetests/multidevices/test/direct/integration/wifi_p2p_lib.py
new file mode 100644
index 0000000..566145c
--- /dev/null
+++ b/tests/hostsidetests/multidevices/test/direct/integration/wifi_p2p_lib.py
@@ -0,0 +1,221 @@
+"""WiFi P2P library for multi-devices tests."""
+# Copyright (C) 2025 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Lint as: python3
+
+import datetime
+import time
+
+from direct import constants
+from direct import p2p_utils
+from mobly import asserts
+from mobly.controllers import android_device
+from mobly.controllers.android_device_lib import adb
+
+_DEFAULT_TIMEOUT = datetime.timedelta(seconds=30)
+_DEFAULT_SLEEPTIME = 5
+
+P2P_CONNECT_NEGOTIATION = 0
+P2P_CONNECT_JOIN = 1
+P2P_CONNECT_INVITATION = 2
+
+
+# Trigger p2p connect to device_go from device_gc.
+def p2p_connect(
+ device_gc: p2p_utils.DeviceState,
+ device_go: p2p_utils.DeviceState,
+ wps_setup,
+ p2p_connect_type=P2P_CONNECT_NEGOTIATION,
+ go_ad=None,
+):
+ """Trigger p2p connect to ad2 from ad1.
+
+ Args:
+ device_gc: The android device (Client)
+ device_go: The android device (GO)
+ wps_setup: which wps connection would like to use
+ p2p_connect_type: enumeration, which type this p2p connection is
+ go_ad: The group owner android device which is used for the invitation
+ connection
+ """
+ device_gc.ad.log.info(
+ 'Create p2p connection from %s to %s via wps: %s type %d'
+ % (device_gc.ad.serial, device_go.ad.serial, wps_setup, p2p_connect_type)
+ )
+ if p2p_connect_type == P2P_CONNECT_INVITATION:
+ if go_ad is None:
+ go_ad = device_gc
+ p2p_utils.discover_p2p_peer(device_gc, device_go)
+ # GO might be another peer, so ad2 needs to find it first.
+ p2p_utils.discover_group_owner(
+ client=device_go, group_owner_address=go_ad.p2p_device.device_address
+ )
+ elif p2p_connect_type == P2P_CONNECT_JOIN:
+ peer_p2p_device = p2p_utils.discover_group_owner(
+ client=device_gc,
+ group_owner_address=device_go.p2p_device.device_address
+ )
+ asserts.assert_true(
+ peer_p2p_device.is_group_owner,
+ f"P2p device {peer_p2p_device} should be group owner.",
+ )
+ else:
+ p2p_utils.discover_p2p_peer(device_gc, device_go)
+ time.sleep(_DEFAULT_SLEEPTIME)
+ device_gc.ad.log.info(
+ 'from device1: %s -> device2: %s',
+ device_gc.p2p_device.device_address,
+ device_go.p2p_device.device_address,
+ )
+ p2p_config = constants.WifiP2pConfig(
+ device_address=device_go.p2p_device.device_address,
+ wps_setup=wps_setup,
+ )
+ p2p_utils.p2p_connect(device_gc, device_go, p2p_config)
+
+
+def is_go(ad):
+ """Check an Android p2p role is Go or not.
+
+ Args:
+ ad: The android device
+
+ Returns:
+ True: An Android device is p2p go
+ False: An Android device is p2p gc
+ """
+ callback_handler = ad.wifi.wifiP2pRequestConnectionInfo()
+ event = callback_handler.waitAndGet(
+ event_name=constants.ON_CONNECTION_INFO_AVAILABLE,
+ timeout=_DEFAULT_TIMEOUT.total_seconds(),
+ )
+ if event.data['isGroupOwner']:
+ return True
+ return False
+
+
+def p2p_go_ip(ad):
+ """Get Group Owner IP address.
+
+ Args:
+ ad: The android device
+
+ Returns:
+ GO IP address
+ """
+ ad.log.info('p2p go ip')
+ event_handler = ad.wifi.wifiP2pRequestConnectionInfo()
+ ad.log.info(type(event_handler))
+ result = event_handler.waitAndGet(
+ event_name=constants.ON_CONNECTION_INFO_AVAILABLE,
+ timeout=_DEFAULT_TIMEOUT.total_seconds(),
+ )
+ ip = result.data['groupOwnerHostAddress'].replace('/', '')
+ ad.log.info('p2p go ip: %s' % ip)
+ return ip
+
+
+def p2p_disconnect(ad):
+ """Invoke an Android device removeGroup to trigger p2p disconnect.
+
+ Args:
+ ad: The android device
+ """
+ ad.log.debug('P2p Disconnect')
+ try:
+ ad.wifi.wifiP2pStopPeerDiscovery()
+ ad.wifi.wifiP2pCancelConnect()
+ ad.wifi.wifiP2pRemoveGroup()
+ finally:
+ # Make sure to call `p2pClose`, otherwise `_setup_wifi_p2p` won't be
+ # able to run again.
+ ad.wifi.p2pClose()
+
+
+def p2p_connection_ping_test(dut: android_device.AndroidDevice, peer_ip: str):
+ """Run a ping over the specified device/link.
+
+ Args:
+ dut: Device on which to execute ping6.
+ peer_ip: Scoped IPv4 address of the peer to ping.
+ """
+ cmd = 'ping -c 3 -W 1 %s' % peer_ip
+ try:
+ dut.log.info(cmd)
+ results = dut.adb.shell(cmd)
+ except adb.AdbError:
+ time.sleep(1)
+ dut.log.info('CMD RETRY: %s', cmd)
+ results = dut.adb.shell(cmd)
+
+ dut.log.info(results)
+
+
+class WifiP2PEnums:
+ """Enums for WifiP2p."""
+
+ class WifiP2pConfig:
+ DEVICEADDRESS_KEY = 'deviceAddress'
+ WPSINFO_KEY = 'wpsInfo'
+ GO_INTENT_KEY = 'groupOwnerIntent'
+ NETID_KEY = 'netId'
+ NETWORK_NAME = 'networkName'
+ PASSPHRASE = 'passphrase'
+ GROUP_BAND = 'groupOwnerBand'
+
+ class WpsInfo:
+ WPS_SETUP_KEY = 'setup'
+ BSSID_KEY = 'BSSID'
+ WPS_PIN_KEY = 'pin'
+ WIFI_WPS_INFO_PBC = 0
+ WIFI_WPS_INFO_DISPLAY = 1
+ WIFI_WPS_INFO_KEYPAD = 2
+ WIFI_WPS_INFO_LABEL = 3
+ WIFI_WPS_INFO_INVALID = 4
+
+ class WifiP2pServiceInfo:
+ # Macros for wifi p2p.
+ WIFI_P2P_SERVICE_TYPE_ALL = 0
+ WIFI_P2P_SERVICE_TYPE_BONJOUR = 1
+ WIFI_P2P_SERVICE_TYPE_UPNP = 2
+ WIFI_P2P_SERVICE_TYPE_VENDOR_SPECIFIC = 255
+
+ class WifiP2pDnsSdServiceResponse:
+ InstanceName = ''
+ RegistrationType = ''
+ FullDomainName = ''
+ TxtRecordMap = {}
+
+ def __init__(self):
+ pass
+
+ def toString(self):
+ return (
+ self.InstanceName
+ + self.RegistrationType
+ + (self.FullDomainName + str(self.TxtRecordMap))
+ )