Merge "Create CTS test folder for IKE and EAP" into rvc-dev
diff --git a/tests/cts/net/assets/OWNERS b/tests/cts/net/assets/OWNERS
new file mode 100644
index 0000000..14edd1d
--- /dev/null
+++ b/tests/cts/net/assets/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 31808
+etancohen@google.com
+lorenzo@google.com
+satk@google.com
diff --git a/tests/cts/net/assets/ValidPasspointProfile.base64 b/tests/cts/net/assets/ValidPasspointProfile.base64
new file mode 100644
index 0000000..3f60eb8
--- /dev/null
+++ b/tests/cts/net/assets/ValidPasspointProfile.base64
@@ -0,0 +1 @@
+Q29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5PXtib3VuZGFyeX0KQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTY0CgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94LXBhc3Nwb2ludC1wcm9maWxlCkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJhc2U2NAoKUEUxbmJYUlVjbVZsSUhodGJHNXpQU0p6ZVc1amJXdzZaRzFrWkdZeExqSWlQZ29nSUR4V1pYSkVWRVErTVM0eVBDOVdaWEpFVkVRK0NpQWdQRTV2WkdVK0NpQWdJQ0E4VG05a1pVNWhiV1UrVUdWeVVISnZkbWxrWlhKVGRXSnpZM0pwY0hScGIyNDhMMDV2WkdWT1lXMWxQZ29nSUNBZ1BGSlVVSEp2Y0dWeWRHbGxjejRLSUNBZ0lDQWdQRlI1Y0dVK0NpQWdJQ0FnSUNBZ1BFUkVSazVoYldVK2RYSnVPbmRtWVRwdGJ6cG9iM1J6Y0c5ME1tUnZkREF0Y0dWeWNISnZkbWxrWlhKemRXSnpZM0pwY0hScGIyNDZNUzR3UEM5RVJFWk9ZVzFsUGdvZ0lDQWdJQ0E4TDFSNWNHVStDaUFnSUNBOEwxSlVVSEp2Y0dWeWRHbGxjejRLSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0E4VG05a1pVNWhiV1UrYVRBd01Ud3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxUbUZ0WlQ1SWIyMWxVMUE4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGtaeWFXVnVaR3g1VG1GdFpUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4Vm1Gc2RXVStRVlJVSUZCaGMzTndiMmx1ZER3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWxQa1pSUkU0OEwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBtRjBkSGRwWm1rdVkyOXRQQzlXWVd4MVpUNEtJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUR3dlRtOWtaVDRLSUNBZ0lDQWdQRTV2WkdVK0NpQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrTnlaV1JsYm5ScFlXdzhMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWxQbEpsWVd4dFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJRHhXWVd4MVpUNTNiR0Z1TG0xdVl6UXhNQzV0WTJNek1UQXVNMmR3Y0c1bGRIZHZjbXN1YjNKblBDOVdZV3gxWlQ0S0lDQWdJQ0FnSUNBOEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0E4VG05a1pVNWhiV1UrVTBsTlBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0E4VG05a1pVNWhiV1UrU1UxVFNUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lXeDFaVDR6TVRBME1UQXFQQzlXWVd4MVpUNEtJQ0FnSUNBZ0lDQWdJRHd2VG05a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrVkJVRlI1Y0dVOEwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUR4V1lXeDFaVDR5TXp3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lDQWdJQ0FnSUNBOEwwNXZaR1UrQ2lBZ0lDQWdJRHd2VG05a1pUNEtJQ0FnSUR3dlRtOWtaVDRLSUNBOEwwNXZaR1UrQ2p3dlRXZHRkRlJ5WldVKwotLXtib3VuZGFyeX0tLQo=
diff --git a/tests/cts/net/src/android/net/wifi/cts/ConcurrencyTest.java b/tests/cts/net/src/android/net/wifi/cts/ConcurrencyTest.java
index ba0832f..d91bce8 100644
--- a/tests/cts/net/src/android/net/wifi/cts/ConcurrencyTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/ConcurrencyTest.java
@@ -30,15 +30,23 @@
import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.wifi.WifiManager;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.net.wifi.p2p.WifiP2pGroup;
+import android.net.wifi.p2p.WifiP2pGroupList;
+import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
+import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
+import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceInfo;
import android.provider.Settings;
import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import android.util.Log;
+import com.android.compatibility.common.util.ShellIdentityUtils;
import com.android.compatibility.common.util.SystemUtil;
import java.util.Arrays;
+import java.util.ArrayList;
import java.util.BitSet;
import java.util.LinkedList;
import java.util.List;
@@ -69,6 +77,10 @@
public int p2pState;
public int discoveryState;
public NetworkInfo networkInfo;
+ public WifiP2pInfo p2pInfo;
+ public String deviceName;
+ public WifiP2pGroupList persistentGroups;
+ public WifiP2pGroup group = new WifiP2pGroup();
}
private WifiManager mWifiManager;
@@ -76,6 +88,7 @@
private WifiP2pManager.Channel mWifiP2pChannel;
private MySync mMySync = new MySync();
private MyResponse mMyResponse = new MyResponse();
+ private boolean mWasVerboseLoggingEnabled;
private static final String TAG = "ConcurrencyTest";
private static final int TIMEOUT_MSEC = 6000;
@@ -119,6 +132,27 @@
}
};
+ private WifiP2pManager.ActionListener mActionListener = new WifiP2pManager.ActionListener() {
+ @Override
+ public void onSuccess() {
+ synchronized (mMyResponse) {
+ mMyResponse.valid = true;
+ mMyResponse.success = true;
+ mMyResponse.notify();
+ }
+ }
+
+ @Override
+ public void onFailure(int reason) {
+ synchronized (mMyResponse) {
+ Log.d(TAG, "failure reason: " + reason);
+ mMyResponse.valid = true;
+ mMyResponse.success = false;
+ mMyResponse.notify();
+ }
+ }
+ };
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -127,6 +161,7 @@
// skip the test if WiFi && p2p are not supported
return;
}
+
mIntentFilter = new IntentFilter();
mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
@@ -140,6 +175,13 @@
SystemUtil.runShellCommand("svc wifi disable");
Thread.sleep(DURATION);
}
+
+ // turn on verbose logging for tests
+ mWasVerboseLoggingEnabled = ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.isVerboseLoggingEnabled());
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.setVerboseLoggingEnabled(true));
+
assertTrue(!mWifiManager.isWifiEnabled());
mMySync.expectedWifiState = WifiManager.WIFI_STATE_DISABLED;
mMySync.expectedP2pState = WifiP2pManager.WIFI_P2P_STATE_DISABLED;
@@ -157,6 +199,9 @@
}
mContext.unregisterReceiver(mReceiver);
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.setVerboseLoggingEnabled(mWasVerboseLoggingEnabled));
+
enableWifi();
super.tearDown();
}
@@ -221,6 +266,10 @@
synchronized (responseObj) {
responseObj.valid = false;
responseObj.networkInfo = null;
+ responseObj.p2pInfo = null;
+ responseObj.deviceName = null;
+ responseObj.persistentGroups = null;
+ responseObj.group = null;
}
}
@@ -344,26 +393,7 @@
assertEquals(WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED, mMyResponse.discoveryState);
resetResponse(mMyResponse);
- mWifiP2pManager.discoverPeers(mWifiP2pChannel, new WifiP2pManager.ActionListener() {
- @Override
- public void onSuccess() {
- synchronized (mMyResponse) {
- mMyResponse.valid = true;
- mMyResponse.success = true;
- mMyResponse.notify();
- }
- }
-
- @Override
- public void onFailure(int reason) {
- synchronized (mMyResponse) {
- Log.d(TAG, "discoveryPeers failure reason: " + reason);
- mMyResponse.valid = true;
- mMyResponse.success = false;
- mMyResponse.notify();
- }
- }
- });
+ mWifiP2pManager.discoverPeers(mWifiP2pChannel, mActionListener);
assertTrue(waitForServiceResponse(mMyResponse));
assertTrue(mMyResponse.success);
assertTrue(waitForBroadcasts(MySync.DISCOVERY_STATE));
@@ -411,26 +441,7 @@
mMySync.expectedNetworkInfo.getDetailedState());
resetResponse(mMyResponse);
- mWifiP2pManager.createGroup(mWifiP2pChannel, new WifiP2pManager.ActionListener() {
- @Override
- public void onSuccess() {
- synchronized (mMyResponse) {
- mMyResponse.valid = true;
- mMyResponse.success = true;
- mMyResponse.notify();
- }
- }
-
- @Override
- public void onFailure(int reason) {
- synchronized (mMyResponse) {
- Log.d(TAG, "createGroup failure reason: " + reason);
- mMyResponse.valid = true;
- mMyResponse.success = false;
- mMyResponse.notify();
- }
- }
- });
+ mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener);
assertTrue(waitForServiceResponse(mMyResponse));
assertTrue(mMyResponse.success);
assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
@@ -455,7 +466,239 @@
assertEquals(NetworkInfo.DetailedState.CONNECTED,
mMyResponse.networkInfo.getDetailedState());
- mWifiP2pManager.removeGroup(mWifiP2pChannel, null);
+ resetResponse(mMyResponse);
+ mWifiP2pManager.requestConnectionInfo(mWifiP2pChannel,
+ new WifiP2pManager.ConnectionInfoListener() {
+ @Override
+ public void onConnectionInfoAvailable(WifiP2pInfo info) {
+ synchronized (mMyResponse) {
+ mMyResponse.valid = true;
+ mMyResponse.p2pInfo = new WifiP2pInfo(info);
+ mMyResponse.notify();
+ }
+ }
+ });
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertNotNull(mMyResponse.p2pInfo);
+ assertTrue(mMyResponse.p2pInfo.groupFormed);
+ assertTrue(mMyResponse.p2pInfo.isGroupOwner);
+
+ resetResponse(mMyResponse);
+ mWifiP2pManager.requestGroupInfo(mWifiP2pChannel,
+ new WifiP2pManager.GroupInfoListener() {
+ @Override
+ public void onGroupInfoAvailable(WifiP2pGroup group) {
+ synchronized (mMyResponse) {
+ mMyResponse.group = new WifiP2pGroup(group);
+ mMyResponse.valid = true;
+ mMyResponse.notify();
+ }
+ }
+ });
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertNotNull(mMyResponse.group);
+ assertNotEquals(0, mMyResponse.group.getFrequency());
+ assertTrue(mMyResponse.group.getNetworkId() >= 0);
+
+ resetResponse(mMyResponse);
+ mWifiP2pManager.removeGroup(mWifiP2pChannel, mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
}
+ private String getDeviceName() {
+ resetResponse(mMyResponse);
+ mWifiP2pManager.requestDeviceInfo(mWifiP2pChannel,
+ new WifiP2pManager.DeviceInfoListener() {
+ @Override
+ public void onDeviceInfoAvailable(WifiP2pDevice wifiP2pDevice) {
+ synchronized (mMyResponse) {
+ mMyResponse.deviceName = wifiP2pDevice.deviceName;
+ mMyResponse.valid = true;
+ mMyResponse.notify();
+ }
+ }
+ });
+ assertTrue(waitForServiceResponse(mMyResponse));
+ return mMyResponse.deviceName;
+ }
+
+ public void testSetDeviceName() {
+ if (!setupWifiP2p()) {
+ return;
+ }
+
+ String testDeviceName = "test";
+ String originalDeviceName = getDeviceName();
+ assertNotNull(originalDeviceName);
+
+ ShellIdentityUtils.invokeWithShellPermissions(() -> {
+ mWifiP2pManager.setDeviceName(
+ mWifiP2pChannel, testDeviceName, mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
+ });
+
+ String currentDeviceName = getDeviceName();
+ assertEquals(testDeviceName, currentDeviceName);
+
+ // restore the device name at the end
+ ShellIdentityUtils.invokeWithShellPermissions(() -> {
+ mWifiP2pManager.setDeviceName(
+ mWifiP2pChannel, originalDeviceName, mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
+ });
+ }
+
+ private WifiP2pGroupList getPersistentGroups() {
+ resetResponse(mMyResponse);
+ ShellIdentityUtils.invokeWithShellPermissions(() -> {
+ mWifiP2pManager.requestPersistentGroupInfo(mWifiP2pChannel,
+ new WifiP2pManager.PersistentGroupInfoListener() {
+ @Override
+ public void onPersistentGroupInfoAvailable(WifiP2pGroupList groups) {
+ synchronized (mMyResponse) {
+ mMyResponse.persistentGroups = groups;
+ mMyResponse.valid = true;
+ mMyResponse.notify();
+ }
+ }
+ });
+ assertTrue(waitForServiceResponse(mMyResponse));
+ });
+ return mMyResponse.persistentGroups;
+ }
+
+ public void testPersistentGroupOperation() {
+ if (!setupWifiP2p()) {
+ return;
+ }
+
+ resetResponse(mMyResponse);
+ mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
+ assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
+ assertNotNull(mMySync.expectedNetworkInfo);
+ assertEquals(NetworkInfo.DetailedState.CONNECTED,
+ mMySync.expectedNetworkInfo.getDetailedState());
+
+ resetResponse(mMyResponse);
+ mWifiP2pManager.removeGroup(mWifiP2pChannel, mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
+
+ WifiP2pGroupList persistentGroups = getPersistentGroups();
+ assertNotNull(persistentGroups);
+ assertEquals(1, persistentGroups.getGroupList().size());
+
+ resetResponse(mMyResponse);
+ final int firstNetworkId = persistentGroups.getGroupList().get(0).getNetworkId();
+ ShellIdentityUtils.invokeWithShellPermissions(() -> {
+ mWifiP2pManager.deletePersistentGroup(mWifiP2pChannel,
+ firstNetworkId,
+ mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
+ });
+
+ persistentGroups = getPersistentGroups();
+ assertNotNull(persistentGroups);
+ assertEquals(0, persistentGroups.getGroupList().size());
+
+ resetResponse(mMyResponse);
+ mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
+ assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
+ assertNotNull(mMySync.expectedNetworkInfo);
+ assertEquals(NetworkInfo.DetailedState.CONNECTED,
+ mMySync.expectedNetworkInfo.getDetailedState());
+
+ resetResponse(mMyResponse);
+ mWifiP2pManager.removeGroup(mWifiP2pChannel, mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
+
+ resetResponse(mMyResponse);
+ ShellIdentityUtils.invokeWithShellPermissions(() -> {
+ mWifiP2pManager.factoryReset(mWifiP2pChannel, mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
+ });
+
+ persistentGroups = getPersistentGroups();
+ assertNotNull(persistentGroups);
+ assertEquals(0, persistentGroups.getGroupList().size());
+ }
+
+ public void testP2pListening() {
+ if (!setupWifiP2p()) {
+ return;
+ }
+
+ resetResponse(mMyResponse);
+ ShellIdentityUtils.invokeWithShellPermissions(() -> {
+ mWifiP2pManager.setWifiP2pChannels(mWifiP2pChannel, 6, 11, mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
+ });
+
+ resetResponse(mMyResponse);
+ ShellIdentityUtils.invokeWithShellPermissions(() -> {
+ mWifiP2pManager.startListening(mWifiP2pChannel, mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
+ });
+
+ resetResponse(mMyResponse);
+ ShellIdentityUtils.invokeWithShellPermissions(() -> {
+ mWifiP2pManager.stopListening(mWifiP2pChannel, mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
+ });
+ }
+
+ public void testP2pService() {
+ if (!setupWifiP2p()) {
+ return;
+ }
+
+ // This only store the listener to the WifiP2pManager internal variable, nothing to fail.
+ mWifiP2pManager.setServiceResponseListener(mWifiP2pChannel,
+ new WifiP2pManager.ServiceResponseListener() {
+ @Override
+ public void onServiceAvailable(
+ int protocolType, byte[] responseData, WifiP2pDevice srcDevice) {
+ }
+ });
+
+ resetResponse(mMyResponse);
+ List<String> services = new ArrayList<String>();
+ services.add("urn:schemas-upnp-org:service:AVTransport:1");
+ services.add("urn:schemas-upnp-org:service:ConnectionManager:1");
+ WifiP2pServiceInfo rendererService = WifiP2pUpnpServiceInfo.newInstance(
+ "6859dede-8574-59ab-9332-123456789011",
+ "urn:schemas-upnp-org:device:MediaRenderer:1",
+ services);
+ mWifiP2pManager.addLocalService(mWifiP2pChannel,
+ rendererService,
+ mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
+
+ resetResponse(mMyResponse);
+ mWifiP2pManager.removeLocalService(mWifiP2pChannel,
+ rendererService,
+ mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
+
+ resetResponse(mMyResponse);
+ mWifiP2pManager.clearLocalServices(mWifiP2pChannel,
+ mActionListener);
+ assertTrue(waitForServiceResponse(mMyResponse));
+ assertTrue(mMyResponse.success);
+ }
}
diff --git a/tests/cts/net/src/android/net/wifi/cts/EasyConnectStatusCallbackTest.java b/tests/cts/net/src/android/net/wifi/cts/EasyConnectStatusCallbackTest.java
new file mode 100644
index 0000000..eef50a0
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/cts/EasyConnectStatusCallbackTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.cts;
+
+import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_TIMEOUT;
+import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_PSK;
+import static android.net.wifi.WifiManager.EASY_CONNECT_NETWORK_ROLE_STA;
+
+import android.app.UiAutomation;
+import android.content.Context;
+import android.net.wifi.EasyConnectStatusCallback;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.HandlerThread;
+import android.test.AndroidTestCase;
+import android.util.SparseArray;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import java.util.concurrent.Executor;
+
+public class EasyConnectStatusCallbackTest extends AndroidTestCase {
+ private static final String TEST_SSID = "\"testSsid\"";
+ private static final String TEST_PASSPHRASE = "\"testPassword\"";
+ private static final int TEST_WAIT_DURATION_MS = 12_000; // Long delay is necessary, see below
+ private WifiManager mWifiManager;
+ private static final String TEST_DPP_URI =
+ "DPP:C:81/1;I:Easy_Connect_Demo;M:000102030405;"
+ + "K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgACDmtXD1Sz6/5B4YRdmTkbkkFLDwk8f0yRnfm1Go"
+ + "kpx/0=;;";
+ private final HandlerThread mHandlerThread = new HandlerThread("EasyConnectTest");
+ protected final Executor mExecutor;
+ {
+ mHandlerThread.start();
+ mExecutor = new HandlerExecutor(new Handler(mHandlerThread.getLooper()));
+ }
+ private final Object mLock = new Object();
+ private boolean mOnFailureCallback = false;
+ private int mErrorCode;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
+ mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ private EasyConnectStatusCallback mEasyConnectStatusCallback = new EasyConnectStatusCallback() {
+ @Override
+ public void onEnrolleeSuccess(int newNetworkId) {
+
+ }
+
+ @Override
+ public void onConfiguratorSuccess(int code) {
+
+ }
+
+ @Override
+ public void onProgress(int code) {
+
+ }
+
+ @Override
+ public void onFailure(int code) {
+ synchronized (mLock) {
+ mOnFailureCallback = true;
+ mErrorCode = code;
+ mLock.notify();
+ }
+ }
+
+ public void onFailure(int code, String ssid, SparseArray<int[]> channelListArray,
+ int[] operatingClassArray) {
+ synchronized (mLock) {
+ mOnFailureCallback = true;
+ mErrorCode = code;
+ mLock.notify();
+ }
+ }
+ };
+
+ /**
+ * Tests {@link android.net.wifi.EasyConnectStatusCallback} class.
+ *
+ * Since Easy Connect requires 2 devices, start Easy Connect session and expect an error.
+ */
+ public void testConfiguratorInitiatorOnFailure() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ WifiConfiguration config;
+ config = new WifiConfiguration();
+ config.SSID = TEST_SSID;
+ config.preSharedKey = TEST_PASSPHRASE;
+ config.setSecurityParams(SECURITY_TYPE_PSK);
+ int networkId = mWifiManager.addNetwork(config);
+ assertFalse(networkId == -1);
+ synchronized (mLock) {
+ mWifiManager.startEasyConnectAsConfiguratorInitiator(TEST_DPP_URI, networkId,
+ EASY_CONNECT_NETWORK_ROLE_STA, mExecutor, mEasyConnectStatusCallback);
+ // Note: A long delay is necessary because there is no enrollee, and the system
+ // tries to discover it. We will wait for a timeout error to occur.
+ mLock.wait(TEST_WAIT_DURATION_MS);
+ }
+ mWifiManager.removeNetwork(networkId);
+ assertTrue(mOnFailureCallback);
+ assertEquals(EASY_CONNECT_EVENT_FAILURE_TIMEOUT, mErrorCode);
+ mWifiManager.stopEasyConnectSession();
+ } finally {
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Tests {@link android.net.wifi.EasyConnectStatusCallback} class.
+ *
+ * Since Easy Connect requires 2 devices, start Easy Connect session and expect an error.
+ */
+ public void testEnrolleeInitiatorOnFailure() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ synchronized (mLock) {
+ mWifiManager.startEasyConnectAsEnrolleeInitiator(TEST_DPP_URI, mExecutor,
+ mEasyConnectStatusCallback);
+ // Note: A long delay is necessary because there is no configurator, and the system
+ // tries to discover it. We will wait for a timeout error to occur.
+ mLock.wait(TEST_WAIT_DURATION_MS);
+ }
+ assertTrue(mOnFailureCallback);
+ assertEquals(EASY_CONNECT_EVENT_FAILURE_TIMEOUT, mErrorCode);
+ mWifiManager.stopEasyConnectSession();
+ } finally {
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+}
diff --git a/tests/cts/net/src/android/net/wifi/cts/ScanResultTest.java b/tests/cts/net/src/android/net/wifi/cts/ScanResultTest.java
index 3347cb6..161b0b4 100644
--- a/tests/cts/net/src/android/net/wifi/cts/ScanResultTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/ScanResultTest.java
@@ -16,6 +16,10 @@
package android.net.wifi.cts;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import java.nio.ByteBuffer;
import java.util.List;
import android.content.BroadcastReceiver;
@@ -23,12 +27,12 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
+import android.net.wifi.ScanResult.InformationElement;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
-import android.util.Log;
import com.android.compatibility.common.util.SystemUtil;
@@ -57,6 +61,14 @@
private static final int SCAN_MAX_RETRY_COUNT = 6;
private static final int SCAN_FIND_BSSID_MAX_RETRY_COUNT = 5;
private static final long SCAN_FIND_BSSID_WAIT_MSEC = 5_000L;
+
+ private static final String TEST_SSID = "TEST_SSID";
+ public static final String TEST_BSSID = "04:ac:fe:45:34:10";
+ public static final String TEST_CAPS = "CCMP";
+ public static final int TEST_LEVEL = -56;
+ public static final int TEST_FREQUENCY = 2412;
+ public static final long TEST_TIMESTAMP = 4660L;
+
private IntentFilter mIntentFilter;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
@@ -100,13 +112,13 @@
mContext.registerReceiver(mReceiver, mIntentFilter);
mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
- assertNotNull(mWifiManager);
+ assertThat(mWifiManager).isNotNull();
mWifiLock = mWifiManager.createWifiLock(TAG);
mWifiLock.acquire();
if (!mWifiManager.isWifiEnabled())
setWifiEnabled(true);
Thread.sleep(ENABLE_WAIT_MSEC);
- assertTrue(mWifiManager.isWifiEnabled());
+ assertThat(mWifiManager.isWifiEnabled()).isTrue();
mMySync.expectedState = STATE_NULL;
}
@@ -150,14 +162,50 @@
// skip the test if WiFi is not supported
return;
}
- List<ScanResult> scanResults = mWifiManager.getScanResults();
// this test case should in Wifi environment
- for (int i = 0; i < scanResults.size(); i++) {
- ScanResult mScanResult = scanResults.get(i);
- assertNotNull(mScanResult.toString());
+ for (ScanResult scanResult : mWifiManager.getScanResults()) {
+ assertThat(scanResult.toString()).isNotNull();
+
+ for (InformationElement ie : scanResult.getInformationElements()) {
+ testInformationElementCopyConstructor(ie);
+ testInformationElementFields(ie);
+ }
+
+ assertThat(scanResult.getWifiStandard()).isAnyOf(
+ ScanResult.WIFI_STANDARD_UNKNOWN,
+ ScanResult.WIFI_STANDARD_LEGACY,
+ ScanResult.WIFI_STANDARD_11N,
+ ScanResult.WIFI_STANDARD_11AC,
+ ScanResult.WIFI_STANDARD_11AX
+ );
+
+ scanResult.isPasspointNetwork();
}
}
+ private void testInformationElementCopyConstructor(InformationElement ie) {
+ InformationElement copy = new InformationElement(ie);
+
+ assertThat(copy.getId()).isEqualTo(ie.getId());
+ assertThat(copy.getIdExt()).isEqualTo(ie.getIdExt());
+ assertThat(copy.getBytes()).isEqualTo(ie.getBytes());
+ }
+
+ private void testInformationElementFields(InformationElement ie) {
+ // id is 1 octet
+ int id = ie.getId();
+ assertThat(id).isAtLeast(0);
+ assertThat(id).isAtMost(255);
+
+ // idExt is 0 or 1 octet
+ int idExt = ie.getIdExt();
+ assertThat(idExt).isAtLeast(0);
+ assertThat(idExt).isAtMost(255);
+
+ ByteBuffer bytes = ie.getBytes();
+ assertThat(bytes).isNotNull();
+ }
+
/* Multiple scans to ensure bssid is updated */
private void scanAndWait() throws Exception {
synchronized (mMySync) {
@@ -186,7 +234,7 @@
for (ScanResult result : scanResults) {
BSSID = result.BSSID;
timestamp = result.timestamp;
- assertTrue(timestamp != 0);
+ assertThat(timestamp).isNotEqualTo(0);
break;
}
@@ -196,11 +244,34 @@
for (ScanResult result : scanResults) {
if (result.BSSID.equals(BSSID)) {
long timeDiff = (result.timestamp - timestamp) / 1000;
- assertTrue (timeDiff > 0);
- assertTrue (timeDiff < 6 * SCAN_WAIT_MSEC);
+ assertThat(timeDiff).isGreaterThan(0L);
+ assertThat(timeDiff).isLessThan(6L * SCAN_WAIT_MSEC);
}
}
+ }
+ /** Test that the copy constructor copies fields correctly. */
+ public void testScanResultConstructors() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
+ ScanResult scanResult = new ScanResult();
+ scanResult.SSID = TEST_SSID;
+ scanResult.BSSID = TEST_BSSID;
+ scanResult.capabilities = TEST_CAPS;
+ scanResult.level = TEST_LEVEL;
+ scanResult.frequency = TEST_FREQUENCY;
+ scanResult.timestamp = TEST_TIMESTAMP;
+
+ ScanResult scanResult2 = new ScanResult(scanResult);
+ assertThat(scanResult2.SSID).isEqualTo(TEST_SSID);
+ assertThat(scanResult2.BSSID).isEqualTo(TEST_BSSID);
+ assertThat(scanResult2.capabilities).isEqualTo(TEST_CAPS);
+ assertThat(scanResult2.level).isEqualTo(TEST_LEVEL);
+ assertThat(scanResult2.frequency).isEqualTo(TEST_FREQUENCY);
+ assertThat(scanResult2.timestamp).isEqualTo(TEST_TIMESTAMP);
}
public void testScanResultMatchesWifiInfo() throws Exception {
@@ -211,7 +282,7 @@
// This test case should run while connected to Wifi
final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
- assertNotNull(wifiInfo);
+ assertThat(wifiInfo).isNotNull();
ScanResult currentNetwork = null;
for (int i = 0; i < SCAN_FIND_BSSID_MAX_RETRY_COUNT; i++) {
@@ -225,16 +296,17 @@
}
Thread.sleep(SCAN_FIND_BSSID_WAIT_MSEC);
}
- assertNotNull("Current network not found in scan results", currentNetwork);
+ assertWithMessage("Current network not found in scan results")
+ .that(currentNetwork).isNotNull();
String wifiInfoSsidQuoted = wifiInfo.getSSID();
String scanResultSsidUnquoted = currentNetwork.SSID;
- assertEquals(
+ assertWithMessage(
"SSID mismatch: make sure this isn't a hidden network or an SSID containing "
- + "non-UTF-8 characters - neither is supported by this CTS test.",
- wifiInfoSsidQuoted,
- "\"" + scanResultSsidUnquoted + "\"");
- assertEquals(wifiInfo.getFrequency(), currentNetwork.frequency);
+ + "non-UTF-8 characters - neither is supported by this CTS test.")
+ .that("\"" + scanResultSsidUnquoted + "\"")
+ .isEqualTo(wifiInfoSsidQuoted);
+ assertThat(currentNetwork.frequency).isEqualTo(wifiInfo.getFrequency());
}
}
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiFrameworkInitializerTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiFrameworkInitializerTest.java
new file mode 100644
index 0000000..d714ed6
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiFrameworkInitializerTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.cts;
+
+import android.net.wifi.WifiFrameworkInitializer;
+import android.test.AndroidTestCase;
+
+public class WifiFrameworkInitializerTest extends AndroidTestCase {
+ /**
+ * WifiFrameworkInitializer.registerServiceWrappers() should only be called by
+ * SystemServiceRegistry during boot up when Wifi is first initialized. Calling this API at
+ * any other time should throw an exception.
+ */
+ public void testRegisterServiceWrappers_failsWhenCalledOutsideOfSystemServiceRegistry() {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ try {
+ WifiFrameworkInitializer.registerServiceWrappers();
+ fail("Expected exception when calling "
+ + "WifiFrameworkInitializer.registerServiceWrappers() outside of "
+ + "SystemServiceRegistry!");
+ } catch (IllegalStateException expected) {}
+ }
+}
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiInfoTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiInfoTest.java
index 6f94fea..557710d 100644
--- a/tests/cts/net/src/android/net/wifi/cts/WifiInfoTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiInfoTest.java
@@ -33,6 +33,7 @@
import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.SystemUtil;
+import java.nio.charset.StandardCharsets;
import java.util.concurrent.Callable;
@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@@ -49,6 +50,12 @@
private static final int STATE_WIFI_CHANGING = 1;
private static final int STATE_WIFI_CHANGED = 2;
+ private static final String TEST_SSID = "Test123";
+ private static final String TEST_BSSID = "12:12:12:12:12:12";
+ private static final int TEST_RSSI = -60;
+ private static final int TEST_NETWORK_ID = 5;
+ private static final int TEST_NETWORK_ID2 = 6;
+
private static final String TAG = "WifiInfoTest";
private static final int TIMEOUT_MSEC = 6000;
private static final int WAIT_MSEC = 60;
@@ -207,4 +214,42 @@
assertThat(wifiInfo.getMaxSupportedTxLinkSpeedMbps()).isAtLeast(-1);
assertThat(wifiInfo.getMaxSupportedRxLinkSpeedMbps()).isAtLeast(-1);
}
+
+ /**
+ * Test that the WifiInfo Builder returns the same values that was set, and that
+ * calling build multiple times returns different instances.
+ */
+ public void testWifiInfoBuilder() throws Exception {
+ WifiInfo.Builder builder = new WifiInfo.Builder()
+ .setSsid(TEST_SSID.getBytes(StandardCharsets.UTF_8))
+ .setBssid(TEST_BSSID)
+ .setRssi(TEST_RSSI)
+ .setNetworkId(TEST_NETWORK_ID);
+
+ WifiInfo info1 = builder.build();
+
+ assertThat(info1.getSSID()).isEqualTo("\"" + TEST_SSID + "\"");
+ assertThat(info1.getBSSID()).isEqualTo(TEST_BSSID);
+ assertThat(info1.getRssi()).isEqualTo(TEST_RSSI);
+ assertThat(info1.getNetworkId()).isEqualTo(TEST_NETWORK_ID);
+
+ WifiInfo info2 = builder
+ .setNetworkId(TEST_NETWORK_ID2)
+ .build();
+
+ // different instances
+ assertThat(info1).isNotSameAs(info2);
+
+ // assert that info1 didn't change
+ assertThat(info1.getSSID()).isEqualTo("\"" + TEST_SSID + "\"");
+ assertThat(info1.getBSSID()).isEqualTo(TEST_BSSID);
+ assertThat(info1.getRssi()).isEqualTo(TEST_RSSI);
+ assertThat(info1.getNetworkId()).isEqualTo(TEST_NETWORK_ID);
+
+ // assert that info2 changed
+ assertThat(info2.getSSID()).isEqualTo("\"" + TEST_SSID + "\"");
+ assertThat(info2.getBSSID()).isEqualTo(TEST_BSSID);
+ assertThat(info2.getRssi()).isEqualTo(TEST_RSSI);
+ assertThat(info2.getNetworkId()).isEqualTo(TEST_NETWORK_ID2);
+ }
}
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiLockTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiLockTest.java
index 6ac92d4..fee9ef0 100644
--- a/tests/cts/net/src/android/net/wifi/cts/WifiLockTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiLockTest.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
+import android.os.WorkSource;
import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
@@ -50,6 +51,7 @@
WifiLock wl = wm.createWifiLock(lockType, WIFI_TAG);
wl.setReferenceCounted(true);
+ wl.setWorkSource(new WorkSource());
assertFalse(wl.isHeld());
wl.acquire();
assertTrue(wl.isHeld());
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java
index 743454f..870cf72 100644
--- a/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -16,6 +16,13 @@
package android.net.wifi.cts;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
+import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assert.assertNotEquals;
import android.app.UiAutomation;
import android.content.BroadcastReceiver;
@@ -25,20 +32,30 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.net.util.MacAddressUtils;
import android.net.ConnectivityManager;
+import android.net.LinkProperties;
import android.net.MacAddress;
+import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
+import android.net.NetworkRequest;
import android.net.wifi.ScanResult;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
+import android.net.wifi.WifiNetworkConnectionStatistics;
+import android.net.wifi.hotspot2.ConfigParser;
+import android.net.wifi.hotspot2.PasspointConfiguration;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
import android.platform.test.annotations.AppModeFull;
import android.provider.Settings;
import android.support.test.uiautomator.UiDevice;
+import android.telephony.TelephonyManager;
import android.test.AndroidTestCase;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -46,12 +63,24 @@
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.compatibility.common.util.PollingCheck;
+import com.android.compatibility.common.util.ShellIdentityUtils;
import com.android.compatibility.common.util.SystemUtil;
+import com.android.compatibility.common.util.ThrowingRunnable;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
import java.util.List;
+import java.util.Locale;
import java.util.Objects;
+import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -62,12 +91,14 @@
}
private WifiManager mWifiManager;
+ private ConnectivityManager mConnectivityManager;
private WifiLock mWifiLock;
private static MySync mMySync;
private List<ScanResult> mScanResults = null;
private NetworkInfo mNetworkInfo;
- private Object mLOHSLock = new Object();
+ private final Object mLock = new Object();
private UiDevice mUiDevice;
+ private boolean mWasVerboseLoggingEnabled;
// Please refer to WifiManager
private static final int MIN_RSSI = -100;
@@ -88,8 +119,9 @@
private static final int SCAN_TIMEOUT_MSEC = 9000;
private static final int TIMEOUT_MSEC = 6000;
private static final int WAIT_MSEC = 60;
- private static final int DURATION = 10000;
+ private static final int DURATION = 10_000;
private static final int DURATION_SCREEN_TOGGLE = 2000;
+ private static final int DURATION_SETTINGS_TOGGLE = 1_000;
private static final int WIFI_SCAN_TEST_INTERVAL_MILLIS = 60 * 1000;
private static final int WIFI_SCAN_TEST_CACHE_DELAY_MILLIS = 3 * 60 * 1000;
private static final int WIFI_SCAN_TEST_ITERATIONS = 5;
@@ -103,6 +135,9 @@
private static final String TEST_SSID_UNQUOTED = "testSsid1";
private static final MacAddress TEST_MAC = MacAddress.fromString("aa:bb:cc:dd:ee:ff");
private static final String TEST_PASSPHRASE = "passphrase";
+ private static final String PASSPOINT_INSTALLATION_FILE_WITH_CA_CERT =
+ "assets/ValidPasspointProfile.base64";
+ private static final String TYPE_WIFI_CONFIG = "application/x-wifi-config";
private IntentFilter mIntentFilter;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -165,7 +200,15 @@
mContext.registerReceiver(mReceiver, mIntentFilter);
mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
+ mConnectivityManager = getContext().getSystemService(ConnectivityManager.class);
assertNotNull(mWifiManager);
+
+ // turn on verbose logging for tests
+ mWasVerboseLoggingEnabled = ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.isVerboseLoggingEnabled());
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.setVerboseLoggingEnabled(true));
+
mWifiLock = mWifiManager.createWifiLock(TAG);
mWifiLock.acquire();
if (!mWifiManager.isWifiEnabled())
@@ -177,6 +220,10 @@
synchronized (mMySync) {
mMySync.expectedState = STATE_NULL;
}
+
+ List<WifiConfiguration> savedNetworks = ShellIdentityUtils.invokeWithShellPermissions(
+ mWifiManager::getConfiguredNetworks);
+ assertFalse("Need at least one saved network", savedNetworks.isEmpty());
}
@Override
@@ -190,6 +237,8 @@
setWifiEnabled(true);
mWifiLock.release();
mContext.unregisterReceiver(mReceiver);
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.setVerboseLoggingEnabled(mWasVerboseLoggingEnabled));
Thread.sleep(DURATION);
super.tearDown();
}
@@ -242,15 +291,24 @@
}
}
- private void connectWifi() throws Exception {
+ private void waitForNetworkInfoState(NetworkInfo.State state) throws Exception {
synchronized (mMySync) {
- if (mNetworkInfo.getState() == NetworkInfo.State.CONNECTED) return;
+ if (mNetworkInfo.getState() == state) return;
long timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
while (System.currentTimeMillis() < timeout
- && mNetworkInfo.getState() != NetworkInfo.State.CONNECTED)
+ && mNetworkInfo.getState() != state)
mMySync.wait(WAIT_MSEC);
- assertTrue(mNetworkInfo.getState() == NetworkInfo.State.CONNECTED);
+ assertTrue(mNetworkInfo.getState() == state);
}
+
+ }
+
+ private void waitForConnection() throws Exception {
+ waitForNetworkInfoState(NetworkInfo.State.CONNECTED);
+ }
+
+ private void waitForDisconnection() throws Exception {
+ waitForNetworkInfoState(NetworkInfo.State.DISCONNECTED);
}
private boolean existSSID(String ssid) {
@@ -423,6 +481,33 @@
assertTrue(WifiManager.compareSignalLevel(rssiA, rssiB) > 0);
}
+ /**
+ * Test that {@link WifiManager#calculateSignalLevel(int)} returns a value in the range
+ * [0, {@link WifiManager#getMaxSignalLevel()}], and its value is monotonically increasing as
+ * the RSSI increases.
+ */
+ public void testCalculateSignalLevel() {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
+ int maxSignalLevel = mWifiManager.getMaxSignalLevel();
+
+ int prevSignalLevel = 0;
+ for (int rssi = -150; rssi <= 50; rssi++) {
+ int signalLevel = mWifiManager.calculateSignalLevel(rssi);
+
+ // between [0, maxSignalLevel]
+ assertWithMessage("For RSSI=%s", rssi).that(signalLevel).isAtLeast(0);
+ assertWithMessage("For RSSI=%s", rssi).that(signalLevel).isAtMost(maxSignalLevel);
+
+ // calculateSignalLevel(rssi) <= calculateSignalLevel(rssi + 1)
+ assertWithMessage("For RSSI=%s", rssi).that(signalLevel).isAtLeast(prevSignalLevel);
+ prevSignalLevel = signalLevel;
+ }
+ }
+
private static class TestLocalOnlyHotspotCallback extends WifiManager.LocalOnlyHotspotCallback {
Object hotspotLock;
WifiManager.LocalOnlyHotspotReservation reservation = null;
@@ -468,12 +553,12 @@
fail("Please enable location for this test");
}
- TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLOHSLock);
- synchronized (mLOHSLock) {
+ TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLock);
+ synchronized (mLock) {
try {
mWifiManager.startLocalOnlyHotspot(callback, null);
// now wait for callback
- mLOHSLock.wait(DURATION);
+ mLock.wait(DURATION);
} catch (InterruptedException e) {
}
// check if we got the callback
@@ -543,15 +628,15 @@
return;
}
setWifiEnabled(true);
- connectWifi(); // ensures that there is at-least 1 saved network on the device.
+ waitForConnection(); // ensures that there is at-least 1 saved network on the device.
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = SSID1;
wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
- assertEquals(WifiConfiguration.INVALID_NETWORK_ID,
+ assertEquals(INVALID_NETWORK_ID,
mWifiManager.addNetwork(wifiConfiguration));
- assertEquals(WifiConfiguration.INVALID_NETWORK_ID,
+ assertEquals(INVALID_NETWORK_ID,
mWifiManager.updateNetwork(wifiConfiguration));
assertFalse(mWifiManager.enableNetwork(0, true));
assertFalse(mWifiManager.disableNetwork(0));
@@ -590,7 +675,7 @@
TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot();
// now make a second request - this should fail.
- TestLocalOnlyHotspotCallback callback2 = new TestLocalOnlyHotspotCallback(mLOHSLock);
+ TestLocalOnlyHotspotCallback callback2 = new TestLocalOnlyHotspotCallback(mLock);
try {
mWifiManager.startLocalOnlyHotspot(callback2, null);
} catch (IllegalStateException e) {
@@ -641,7 +726,7 @@
.setPassphrase(TEST_PASSPHRASE, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
.build();
TestExecutor executor = new TestExecutor();
- TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLOHSLock);
+ TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(mLock);
UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
try {
uiAutomation.adoptShellPermissionIdentity();
@@ -671,6 +756,51 @@
}
/**
+ * Read the content of the given resource file into a String.
+ *
+ * @param filename String name of the file
+ * @return String
+ * @throws IOException
+ */
+ private String loadResourceFile(String filename) throws IOException {
+ InputStream in = getClass().getClassLoader().getResourceAsStream(filename);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ StringBuilder builder = new StringBuilder();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ builder.append(line).append("\n");
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Verify that changing the mac randomization setting of a Passpoint configuration.
+ */
+ public void testMacRandomizationSettingPasspoint() throws Exception {
+ String configStr = loadResourceFile(PASSPOINT_INSTALLATION_FILE_WITH_CA_CERT);
+ PasspointConfiguration config =
+ ConfigParser.parsePasspointConfig(TYPE_WIFI_CONFIG, configStr.getBytes());
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+
+ mWifiManager.addOrUpdatePasspointConfiguration(config);
+ List<PasspointConfiguration> passpointConfigs =
+ mWifiManager.getPasspointConfigurations();
+ PasspointConfiguration passpointConfig = passpointConfigs.get(0);
+ assertEquals(1, passpointConfigs.size());
+ assertTrue("Mac randomization should be enabled for passpoint networks by default.",
+ passpointConfig.isMacRandomizationEnabled());
+
+ String fqdn = passpointConfig.getHomeSp().getFqdn();
+ mWifiManager.setMacRandomizationSettingPasspointEnabled(fqdn, false);
+ assertFalse("Mac randomization should be disabled by the API call.",
+ mWifiManager.getPasspointConfigurations().get(0).isMacRandomizationEnabled());
+ } finally {
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+ /**
* Verify that the {@link android.Manifest.permission#NETWORK_STACK} permission is never held by
* any package.
* <p>
@@ -933,6 +1063,29 @@
Thread.sleep(DURATION_SCREEN_TOGGLE);
}
+ private void assertWifiScanningIsOn() {
+ if (!mWifiManager.isScanAlwaysAvailable()) {
+ fail("Wi-Fi scanning should be on.");
+ }
+ }
+
+ private void runWithScanningEnabled(ThrowingRunnable r) throws Exception {
+ boolean wasScanEnabledForTest = false;
+ if (!mWifiManager.isScanAlwaysAvailable()) {
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.setScanAlwaysAvailable(true));
+ wasScanEnabledForTest = true;
+ }
+ try {
+ r.run();
+ } finally {
+ if (wasScanEnabledForTest) {
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.setScanAlwaysAvailable(false));
+ }
+ }
+ }
+
/**
* Verify that Wi-Fi scanning is not turned off when the screen turns off while wifi is disabled
* but location is on.
@@ -951,17 +1104,16 @@
fail("Please enable location for this test - since Marshmallow WiFi scan results are"
+ " empty when location is disabled!");
}
- if(!mWifiManager.isScanAlwaysAvailable()) {
- fail("Please enable Wi-Fi scanning for this test!");
- }
- setWifiEnabled(false);
- turnScreenOn();
- assertWifiScanningIsOn();
- // Toggle screen and verify Wi-Fi scanning is still on.
- turnScreenOff();
- assertWifiScanningIsOn();
- turnScreenOn();
- assertWifiScanningIsOn();
+ runWithScanningEnabled(() -> {
+ setWifiEnabled(false);
+ turnScreenOn();
+ assertWifiScanningIsOn();
+ // Toggle screen and verify Wi-Fi scanning is still on.
+ turnScreenOff();
+ assertWifiScanningIsOn();
+ turnScreenOn();
+ assertWifiScanningIsOn();
+ });
}
/**
@@ -981,17 +1133,16 @@
fail("Please enable location for this test - since Marshmallow WiFi scan results are"
+ " empty when location is disabled!");
}
- if(!mWifiManager.isScanAlwaysAvailable()) {
- fail("Please enable Wi-Fi scanning for this test!");
- }
- setWifiEnabled(true);
- turnScreenOn();
- assertWifiScanningIsOn();
- // Toggle screen and verify Wi-Fi scanning is still on.
- turnScreenOff();
- assertWifiScanningIsOn();
- turnScreenOn();
- assertWifiScanningIsOn();
+ runWithScanningEnabled(() -> {
+ setWifiEnabled(true);
+ turnScreenOn();
+ assertWifiScanningIsOn();
+ // Toggle screen and verify Wi-Fi scanning is still on.
+ turnScreenOff();
+ assertWifiScanningIsOn();
+ turnScreenOn();
+ assertWifiScanningIsOn();
+ });
}
/**
@@ -1007,9 +1158,622 @@
> ENFORCED_NUM_NETWORK_SUGGESTIONS_PER_APP);
}
- private void assertWifiScanningIsOn() {
- if(!mWifiManager.isScanAlwaysAvailable()) {
- fail("Wi-Fi scanning should be on.");
+ private static class TestActionListener implements WifiManager.ActionListener {
+ private final Object mLock;
+ public boolean onSuccessCalled = false;
+ public boolean onFailedCalled = false;
+ public int failureReason = -1;
+
+ TestActionListener(Object lock) {
+ mLock = lock;
}
+
+ @Override
+ public void onSuccess() {
+ synchronized (mLock) {
+ onSuccessCalled = true;
+ mLock.notify();
+ }
+ }
+
+ @Override
+ public void onFailure(int reason) {
+ synchronized (mLock) {
+ onFailedCalled = true;
+ failureReason = reason;
+ mLock.notify();
+ }
+ }
+ }
+
+ /**
+ * Triggers connection to one of the saved networks using {@link WifiManager#connect(
+ * int, WifiManager.ActionListener)} or {@link WifiManager#connect(WifiConfiguration,
+ * WifiManager.ActionListener)}
+ *
+ * @param withNetworkId Use networkId for triggering connection, false for using
+ * WifiConfiguration.
+ * @throws Exception
+ */
+ private void testConnect(boolean withNetworkId) throws Exception {
+ TestActionListener actionListener = new TestActionListener(mLock);
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ List<WifiConfiguration> savedNetworks = null;
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ // These below API's only work with privileged permissions (obtained via shell identity
+ // for test)
+ savedNetworks = mWifiManager.getConfiguredNetworks();
+
+ // Disable all the saved networks to trigger disconnect & disable autojoin.
+ for (WifiConfiguration network : savedNetworks) {
+ assertTrue(mWifiManager.disableNetwork(network.networkId));
+ }
+ waitForDisconnection();
+
+ // Now trigger connection to the first saved network.
+ synchronized (mLock) {
+ try {
+ if (withNetworkId) {
+ mWifiManager.connect(savedNetworks.get(0).networkId, actionListener);
+ } else {
+ mWifiManager.connect(savedNetworks.get(0), actionListener);
+ }
+ // now wait for callback
+ mLock.wait(DURATION);
+ } catch (InterruptedException e) {
+ }
+ }
+ // check if we got the success callback
+ assertTrue(actionListener.onSuccessCalled);
+ // Wait for connection to complete & ensure we are connected to the saved network.
+ waitForConnection();
+ assertEquals(savedNetworks.get(0).networkId,
+ mWifiManager.getConnectionInfo().getNetworkId());
+ } finally {
+ // Re-enable all saved networks before exiting.
+ if (savedNetworks != null) {
+ for (WifiConfiguration network : savedNetworks) {
+ mWifiManager.enableNetwork(network.networkId, false);
+ }
+ }
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Tests {@link WifiManager#connect(int, WifiManager.ActionListener)} to an existing saved
+ * network.
+ */
+ public void testConnectWithNetworkId() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ testConnect(true);
+ }
+
+ /**
+ * Tests {@link WifiManager#connect(WifiConfiguration, WifiManager.ActionListener)} to an
+ * existing saved network.
+ */
+ public void testConnectWithWifiConfiguration() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ testConnect(false);
+
+ }
+
+ private static class TestNetworkCallback extends ConnectivityManager.NetworkCallback {
+ private final Object mLock;
+ public boolean onAvailableCalled = false;
+ public Network network;
+ public NetworkCapabilities networkCapabilities;
+
+ TestNetworkCallback(Object lock) {
+ mLock = lock;
+ }
+
+ @Override
+ public void onAvailable(Network network, NetworkCapabilities networkCapabilities,
+ LinkProperties linkProperties, boolean blocked) {
+ synchronized (mLock) {
+ onAvailableCalled = true;
+ this.network = network;
+ this.networkCapabilities = networkCapabilities;
+ mLock.notify();
+ }
+ }
+ }
+
+ private void waitForNetworkCallbackAndCheckForMeteredness(boolean expectMetered) {
+ TestNetworkCallback networkCallbackListener = new TestNetworkCallback(mLock);
+ synchronized (mLock) {
+ try {
+ // File a request for wifi network.
+ mConnectivityManager.registerNetworkCallback(
+ new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .build(),
+ networkCallbackListener);
+ // now wait for callback
+ mLock.wait(DURATION);
+ } catch (InterruptedException e) {
+ }
+ }
+ assertTrue(networkCallbackListener.onAvailableCalled);
+ assertNotEquals(expectMetered, networkCallbackListener.networkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_METERED));
+ }
+
+ /**
+ * Tests {@link WifiManager#save(WifiConfiguration, WifiManager.ActionListener)} by marking
+ * an existing saved network metered.
+ */
+ public void testSave() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ TestActionListener actionListener = new TestActionListener(mLock);
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ List<WifiConfiguration> savedNetworks = null;
+ WifiConfiguration savedNetwork = null;
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ // These below API's only work with privileged permissions (obtained via shell identity
+ // for test)
+ savedNetworks = mWifiManager.getConfiguredNetworks();
+
+ // Ensure that the saved network is not metered.
+ savedNetwork = savedNetworks.get(0);
+ assertNotEquals("Ensure that the saved network is configured as unmetered",
+ savedNetwork.meteredOverride,
+ WifiConfiguration.METERED_OVERRIDE_METERED);
+
+ // Trigger a scan & wait for connection to one of the saved networks.
+ mWifiManager.startScan();
+ waitForConnection();
+
+ // Check the network capabilities to ensure that the network is marked not metered.
+ waitForNetworkCallbackAndCheckForMeteredness(false);
+
+ // Now mark the network metered and save.
+ synchronized (mLock) {
+ try {
+ WifiConfiguration modSavedNetwork = new WifiConfiguration(savedNetwork);
+ modSavedNetwork.meteredOverride = WifiConfiguration.METERED_OVERRIDE_METERED;
+ mWifiManager.save(modSavedNetwork, actionListener);
+ // now wait for callback
+ mLock.wait(DURATION);
+ } catch (InterruptedException e) {
+ }
+ }
+ // check if we got the success callback
+ assertTrue(actionListener.onSuccessCalled);
+ // Check the network capabilities to ensure that the network is marked metered now.
+ waitForNetworkCallbackAndCheckForMeteredness(true);
+
+ } finally {
+ // Restore original network config (restore the meteredness back);
+ if (savedNetwork != null) {
+ mWifiManager.updateNetwork(savedNetwork);
+ }
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Tests {@link WifiManager#forget(int, WifiManager.ActionListener)} by adding/removing a new
+ * network.
+ */
+ public void testForget() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ TestActionListener actionListener = new TestActionListener(mLock);
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ int newNetworkId = INVALID_NETWORK_ID;
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ // These below API's only work with privileged permissions (obtained via shell identity
+ // for test)
+ List<WifiConfiguration> savedNetworks = mWifiManager.getConfiguredNetworks();
+
+ WifiConfiguration newOpenNetwork = new WifiConfiguration();
+ newOpenNetwork.SSID = "\"" + TEST_SSID_UNQUOTED + "\"";
+ newNetworkId = mWifiManager.addNetwork(newOpenNetwork);
+ assertNotEquals(INVALID_NETWORK_ID, newNetworkId);
+
+ assertEquals(savedNetworks.size() + 1, mWifiManager.getConfiguredNetworks().size());
+
+ // Now remove the network
+ synchronized (mLock) {
+ try {
+ mWifiManager.forget(newNetworkId, actionListener);
+ // now wait for callback
+ mLock.wait(DURATION);
+ } catch (InterruptedException e) {
+ }
+ }
+ // check if we got the success callback
+ assertTrue(actionListener.onSuccessCalled);
+
+ // Ensure that the new network has been successfully removed.
+ assertEquals(savedNetworks.size(), mWifiManager.getConfiguredNetworks().size());
+ } finally {
+ // For whatever reason, if the forget fails, try removing using the public remove API.
+ if (newNetworkId != INVALID_NETWORK_ID) mWifiManager.removeNetwork(newNetworkId);
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Tests {@link WifiManager#getFactoryMacAddresses()} returns at least one valid MAC address.
+ */
+ public void testGetFactoryMacAddresses() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ TestActionListener actionListener = new TestActionListener(mLock);
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ int newNetworkId = INVALID_NETWORK_ID;
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ // Obtain the factory MAC address
+ String[] macAddresses = mWifiManager.getFactoryMacAddresses();
+ assertTrue("At list one MAC address should be returned.", macAddresses.length > 0);
+ try {
+ MacAddress mac = MacAddress.fromString(macAddresses[0]);
+ assertNotEquals(WifiInfo.DEFAULT_MAC_ADDRESS, mac);
+ assertFalse(MacAddressUtils.isMulticastAddress(mac));
+ } catch (IllegalArgumentException e) {
+ fail("Factory MAC address is invalid");
+ }
+ } finally {
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Tests {@link WifiManager#isApMacRandomizationSupported()} does not crash.
+ */
+ public void testIsApMacRandomizationSupported() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ mWifiManager.isApMacRandomizationSupported();
+ }
+
+ /**
+ * Tests {@link WifiManager#isConnectedMacRandomizationSupported()} does not crash.
+ */
+ public void testIsConnectedMacRandomizationSupported() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ mWifiManager.isConnectedMacRandomizationSupported();
+ }
+
+ /**
+ * Tests {@link WifiManager#isPreferredNetworkOffloadSupported()} does not crash.
+ */
+ public void testIsPreferredNetworkOffloadSupported() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ mWifiManager.isPreferredNetworkOffloadSupported();
+ }
+
+ private static class TestTrafficStateCallback implements WifiManager.TrafficStateCallback {
+ private final Object mLock;
+ public boolean onStateChangedCalled = false;
+ public int state = -1;
+
+ TestTrafficStateCallback(Object lock) {
+ mLock = lock;
+ }
+
+ @Override
+ public void onStateChanged(int state) {
+ synchronized (mLock) {
+ onStateChangedCalled = true;
+ this.state = state;
+ mLock.notify();
+ }
+ }
+ }
+
+ private void sendTraffic() {
+ for (int i = 0; i < 10; i ++) {
+ // Do some network operations
+ HttpURLConnection connection = null;
+ try {
+ URL url = new URL("http://www.google.com/");
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setInstanceFollowRedirects(false);
+ connection.setConnectTimeout(TIMEOUT_MSEC);
+ connection.setReadTimeout(TIMEOUT_MSEC);
+ connection.setUseCaches(false);
+ connection.getInputStream();
+ } catch (Exception e) {
+ // ignore
+ } finally {
+ if (connection != null) connection.disconnect();
+ }
+ }
+ }
+
+ /**
+ * Tests {@link WifiManager#registerTrafficStateCallback(Executor,
+ * WifiManager.TrafficStateCallback)} by sending some traffic.
+ */
+ public void testTrafficStateCallback() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ TestTrafficStateCallback trafficStateCallback = new TestTrafficStateCallback(mLock);
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ // Trigger a scan & wait for connection to one of the saved networks.
+ mWifiManager.startScan();
+ waitForConnection();
+
+ // Turn screen on for wifi traffic polling.
+ turnScreenOn();
+ synchronized (mLock) {
+ try {
+ mWifiManager.registerTrafficStateCallback(
+ Executors.newSingleThreadExecutor(), trafficStateCallback);
+ // Send some traffic to trigger the traffic state change callbacks.
+ sendTraffic();
+ // now wait for callback
+ mLock.wait(DURATION);
+ } catch (InterruptedException e) {
+ }
+ }
+ // check if we got the state changed callback
+ assertTrue(trafficStateCallback.onStateChangedCalled);
+ assertEquals(DATA_ACTIVITY_INOUT, trafficStateCallback.state);
+ } finally {
+ turnScreenOff();
+ mWifiManager.unregisterTrafficStateCallback(trafficStateCallback);
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Tests {@link WifiManager#setScanAlwaysAvailable(boolean)} &
+ * {@link WifiManager#isScanAlwaysAvailable()}.
+ */
+ public void testScanAlwaysAvailable() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ Boolean currState = null;
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ currState = mWifiManager.isScanAlwaysAvailable();
+ boolean newState = !currState;
+ mWifiManager.setScanAlwaysAvailable(newState);
+ PollingCheck.check(
+ "Wifi settings toggle failed!",
+ DURATION_SETTINGS_TOGGLE,
+ () -> mWifiManager.isScanAlwaysAvailable() == newState);
+ assertEquals(newState, mWifiManager.isScanAlwaysAvailable());
+ } finally {
+ if (currState != null) mWifiManager.setScanAlwaysAvailable(currState);
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Tests {@link WifiManager#setScanThrottleEnabled(boolean)} &
+ * {@link WifiManager#isScanThrottleEnabled()}.
+ */
+ public void testScanThrottleEnabled() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ Boolean currState = null;
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ currState = mWifiManager.isScanThrottleEnabled();
+ boolean newState = !currState;
+ mWifiManager.setScanThrottleEnabled(newState);
+ PollingCheck.check(
+ "Wifi settings toggle failed!",
+ DURATION_SETTINGS_TOGGLE,
+ () -> mWifiManager.isScanThrottleEnabled() == newState);
+ assertEquals(newState, mWifiManager.isScanThrottleEnabled());
+ } finally {
+ if (currState != null) mWifiManager.setScanThrottleEnabled(currState);
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Tests {@link WifiManager#setAutoWakeupEnabled(boolean)} &
+ * {@link WifiManager#isAutoWakeupEnabled()}.
+ */
+ public void testAutoWakeUpEnabled() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ Boolean currState = null;
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ currState = mWifiManager.isAutoWakeupEnabled();
+ boolean newState = !currState;
+ mWifiManager.setAutoWakeupEnabled(newState);
+ PollingCheck.check(
+ "Wifi settings toggle failed!",
+ DURATION_SETTINGS_TOGGLE,
+ () -> mWifiManager.isAutoWakeupEnabled() == newState);
+ assertEquals(newState, mWifiManager.isAutoWakeupEnabled());
+ } finally {
+ if (currState != null) mWifiManager.setAutoWakeupEnabled(currState);
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Tests {@link WifiManager#setVerboseLoggingEnabled(boolean)} &
+ * {@link WifiManager#isVerboseLoggingEnabled()}.
+ */
+ public void testVerboseLoggingEnabled() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ Boolean currState = null;
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ currState = mWifiManager.isVerboseLoggingEnabled();
+ boolean newState = !currState;
+ mWifiManager.setVerboseLoggingEnabled(newState);
+ PollingCheck.check(
+ "Wifi settings toggle failed!",
+ DURATION_SETTINGS_TOGGLE,
+ () -> mWifiManager.isVerboseLoggingEnabled() == newState);
+ assertEquals(newState, mWifiManager.isVerboseLoggingEnabled());
+ } finally {
+ if (currState != null) mWifiManager.setVerboseLoggingEnabled(currState);
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Tests {@link WifiManager#factoryReset()}.
+ *
+ * Note: This test assumes that the device only has 1 or more saved networks before the test.
+ * The test will restore those when the test exits. But, it does not restore the softap
+ * configuration, suggestions, etc which will also have been lost on factory reset.
+ */
+ public void testFactoryReset() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ List<WifiConfiguration> savedNetworks = null;
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ // These below API's only work with privileged permissions (obtained via shell identity
+ // for test)
+ savedNetworks = mWifiManager.getConfiguredNetworks();
+
+ mWifiManager.factoryReset();
+ // Ensure all the saved networks are removed.
+ assertEquals(0, mWifiManager.getConfiguredNetworks().size());
+ } finally {
+ // Restore the original saved networks.
+ if (savedNetworks != null) {
+ for (WifiConfiguration network : savedNetworks) {
+ mWifiManager.save(network, null);
+ }
+ }
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Test {@link WifiNetworkConnectionStatistics} does not crash.
+ * TODO(b/150891569): deprecate it in Android S, this API is not used anywhere.
+ */
+ public void testWifiNetworkConnectionStatistics() {
+ new WifiNetworkConnectionStatistics();
+ WifiNetworkConnectionStatistics stats = new WifiNetworkConnectionStatistics(0, 0);
+ new WifiNetworkConnectionStatistics(stats);
+ }
+
+ /**
+ * Test that the wifi country code is either null, or a length-2 string.
+ */
+ public void testGetCountryCode() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
+ String wifiCountryCode = ShellIdentityUtils.invokeWithShellPermissions(
+ mWifiManager::getCountryCode);
+
+ if (wifiCountryCode == null) {
+ return;
+ }
+ assertEquals(2, wifiCountryCode.length());
+
+ // assert that the country code is all uppercase
+ assertEquals(wifiCountryCode.toUpperCase(Locale.US), wifiCountryCode);
+
+ String telephonyCountryCode = getContext().getSystemService(TelephonyManager.class)
+ .getNetworkCountryIso();
+ assertEquals(telephonyCountryCode, wifiCountryCode.toLowerCase(Locale.US));
+ }
+
+ /**
+ * Test that {@link WifiManager#getCurrentNetwork()} returns a Network obeject consistent
+ * with {@link ConnectivityManager#registerNetworkCallback} when connected to a Wifi network,
+ * and returns null when not connected.
+ */
+ public void testGetCurrentNetwork() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
+ // wait for Wifi to be connected
+ PollingCheck.check(
+ "Wifi not connected - Please ensure there is a saved network in range of this "
+ + "device",
+ 20000,
+ () -> mWifiManager.getConnectionInfo().getNetworkId() != -1);
+
+ Network wifiCurrentNetwork = ShellIdentityUtils.invokeWithShellPermissions(
+ mWifiManager::getCurrentNetwork);
+ assertNotNull(wifiCurrentNetwork);
+
+ TestNetworkCallback networkCallbackListener = new TestNetworkCallback(mLock);
+ synchronized (mLock) {
+ try {
+ // File a request for wifi network.
+ mConnectivityManager.registerNetworkCallback(
+ new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .build(),
+ networkCallbackListener);
+ // now wait for callback
+ mLock.wait(DURATION);
+ } catch (InterruptedException e) {
+ }
+ }
+ assertTrue(networkCallbackListener.onAvailableCalled);
+ Network connectivityCurrentNetwork = networkCallbackListener.network;
+ assertEquals(connectivityCurrentNetwork, wifiCurrentNetwork);
+
+ setWifiEnabled(false);
+ PollingCheck.check(
+ "Wifi not disconnected!",
+ 20000,
+ () -> mWifiManager.getConnectionInfo().getNetworkId() == -1);
+
+ assertNull(ShellIdentityUtils.invokeWithShellPermissions(mWifiManager::getCurrentNetwork));
}
}
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiMigrationTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiMigrationTest.java
new file mode 100644
index 0000000..6e19a21
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiMigrationTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.cts;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.net.wifi.SoftApConfiguration;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiMigration;
+import android.test.AndroidTestCase;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class WifiMigrationTest extends AndroidTestCase {
+ private static final String TEST_SSID_UNQUOTED = "testSsid1";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ super.tearDown();
+ return;
+ }
+ super.tearDown();
+ }
+
+ /**
+ * Tests {@link android.net.wifi.WifiMigration.ConfigStoreMigrationData} class.
+ */
+ public void testWifiMigrationConfigStoreDataBuilder() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ WifiConfiguration savedNetwork1 = new WifiConfiguration();
+ savedNetwork1.SSID = "\"test1\"";
+ WifiConfiguration savedNetwork2 = new WifiConfiguration();
+ savedNetwork1.SSID = "\"test2\"";
+ List<WifiConfiguration> savedNetworks = Arrays.asList(savedNetwork1, savedNetwork2);
+
+ SoftApConfiguration softApConfiguration = new SoftApConfiguration.Builder()
+ .setSsid("\"test3\"")
+ .build();
+
+ WifiMigration.ConfigStoreMigrationData migrationData =
+ new WifiMigration.ConfigStoreMigrationData.Builder()
+ .setUserSavedNetworkConfigurations(savedNetworks)
+ .setUserSoftApConfiguration(softApConfiguration)
+ .build();
+
+ assertNotNull(migrationData);
+ assertEquals(savedNetworks.size(),
+ migrationData.getUserSavedNetworkConfigurations().size());
+ assertEquals(savedNetwork1.SSID,
+ migrationData.getUserSavedNetworkConfigurations().get(0).SSID);
+ assertEquals(savedNetwork2.SSID,
+ migrationData.getUserSavedNetworkConfigurations().get(1).SSID);
+ assertEquals(softApConfiguration.getSsid(),
+ migrationData.getUserSoftApConfiguration().getSsid());
+ }
+
+ /**
+ * Tests {@link android.net.wifi.WifiMigration.ConfigStoreMigrationData} class.
+ */
+ public void testWifiMigrationSettingsDataBuilder() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ WifiMigration.SettingsMigrationData migrationData =
+ new WifiMigration.SettingsMigrationData.Builder()
+ .setScanAlwaysAvailable(true)
+ .setP2pFactoryResetPending(true)
+ .setScanThrottleEnabled(true)
+ .setSoftApTimeoutEnabled(true)
+ .setWakeUpEnabled(true)
+ .setVerboseLoggingEnabled(true)
+ .setP2pDeviceName(TEST_SSID_UNQUOTED)
+ .build();
+
+ assertNotNull(migrationData);
+ assertTrue(migrationData.isScanAlwaysAvailable());
+ assertTrue(migrationData.isP2pFactoryResetPending());
+ assertTrue(migrationData.isScanThrottleEnabled());
+ assertTrue(migrationData.isSoftApTimeoutEnabled());
+ assertTrue(migrationData.isWakeUpEnabled());
+ assertTrue(migrationData.isVerboseLoggingEnabled());
+ assertEquals(TEST_SSID_UNQUOTED, migrationData.getP2pDeviceName());
+ }
+}
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
new file mode 100644
index 0000000..96cf45f
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiNetworkSpecifierTest.java
@@ -0,0 +1,509 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.cts;
+
+import static android.net.NetworkCapabilitiesProto.TRANSPORT_WIFI;
+import static android.os.Process.myUid;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.UiAutomation;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.MacAddress;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
+import android.net.wifi.WifiNetworkSpecifier;
+import android.os.PatternMatcher;
+import android.os.WorkSource;
+import android.platform.test.annotations.AppModeFull;
+import android.support.test.uiautomator.UiDevice;
+import android.test.AndroidTestCase;
+import android.text.TextUtils;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.PollingCheck;
+import com.android.compatibility.common.util.ShellIdentityUtils;
+import com.android.compatibility.common.util.SystemUtil;
+
+import java.util.List;
+import java.util.concurrent.Executors;
+
+/**
+ * Tests the entire connection flow using {@link WifiNetworkSpecifier} embedded in a
+ * {@link NetworkRequest} & passed into {@link ConnectivityManager#requestNetwork(NetworkRequest,
+ * ConnectivityManager.NetworkCallback)}.
+ *
+ * Assumes that all the saved networks is either open/WPA1/WPA2/WPA3 authenticated network.
+ * TODO(b/150716005): Use assumeTrue for wifi support check.
+ */
+@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
+public class WifiNetworkSpecifierTest extends AndroidTestCase {
+ private static final String TAG = "WifiNetworkSpecifierTest";
+
+ private WifiManager mWifiManager;
+ private ConnectivityManager mConnectivityManager;
+ private UiDevice mUiDevice;
+ private final Object mLock = new Object();
+ private final Object mUiLock = new Object();
+ private WifiConfiguration mTestNetwork;
+ private boolean mWasVerboseLoggingEnabled;
+
+ private static final int DURATION = 10_000;
+ private static final int DURATION_UI_INTERACTION = 15_000;
+ private static final int DURATION_NETWORK_CONNECTION = 30_000;
+ private static final int DURATION_SCREEN_TOGGLE = 2000;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
+ mConnectivityManager = getContext().getSystemService(ConnectivityManager.class);
+ assertNotNull(mWifiManager);
+
+ // turn on verbose logging for tests
+ mWasVerboseLoggingEnabled = ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.isVerboseLoggingEnabled());
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.setVerboseLoggingEnabled(true));
+
+ if (!mWifiManager.isWifiEnabled()) setWifiEnabled(true);
+ mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ turnScreenOn();
+ PollingCheck.check("Wifi not enabled", DURATION, () -> mWifiManager.isWifiEnabled());
+
+ List<WifiConfiguration> savedNetworks = ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.getPrivilegedConfiguredNetworks());
+ assertFalse("Need at least one saved network", savedNetworks.isEmpty());
+ // Pick any one of the saved networks on the device (assumes that it is in range)
+ mTestNetwork = savedNetworks.get(0);
+ // Disconnect & disable auto-join on the saved network to prevent auto-connect from
+ // interfering with the test.
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.disableNetwork(mTestNetwork.networkId));
+ // wait for Wifi to be disconnected
+ PollingCheck.check(
+ "Wifi not disconnected",
+ 20000,
+ () -> mWifiManager.getConnectionInfo().getNetworkId() == -1);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ super.tearDown();
+ return;
+ }
+ if (!mWifiManager.isWifiEnabled()) setWifiEnabled(true);
+ turnScreenOff();
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.enableNetwork(mTestNetwork.networkId, false));
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.setVerboseLoggingEnabled(mWasVerboseLoggingEnabled));
+ super.tearDown();
+ }
+
+ private void setWifiEnabled(boolean enable) throws Exception {
+ // now trigger the change using shell commands.
+ SystemUtil.runShellCommand("svc wifi " + (enable ? "enable" : "disable"));
+ }
+
+ private void turnScreenOn() throws Exception {
+ mUiDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ mUiDevice.executeShellCommand("wm dismiss-keyguard");
+ // Since the screen on/off intent is ordered, they will not be sent right now.
+ Thread.sleep(DURATION_SCREEN_TOGGLE);
+ }
+
+ private void turnScreenOff() throws Exception {
+ mUiDevice.executeShellCommand("input keyevent KEYCODE_SLEEP");
+ // Since the screen on/off intent is ordered, they will not be sent right now.
+ Thread.sleep(DURATION_SCREEN_TOGGLE);
+ }
+
+ private static class TestNetworkCallback extends ConnectivityManager.NetworkCallback {
+ private final Object mLock;
+ public boolean onAvailableCalled = false;
+ public boolean onUnavailableCalled = false;
+ public NetworkCapabilities networkCapabilities;
+
+ TestNetworkCallback(Object lock) {
+ mLock = lock;
+ }
+
+ @Override
+ public void onAvailable(Network network, NetworkCapabilities networkCapabilities,
+ LinkProperties linkProperties, boolean blocked) {
+ synchronized (mLock) {
+ onAvailableCalled = true;
+ this.networkCapabilities = networkCapabilities;
+ mLock.notify();
+ }
+ }
+
+ @Override
+ public void onUnavailable() {
+ synchronized (mLock) {
+ onUnavailableCalled = true;
+ mLock.notify();
+ }
+ }
+ }
+
+ private static class TestNetworkRequestMatchCallback implements NetworkRequestMatchCallback {
+ private final Object mLock;
+
+ public boolean onRegistrationCalled = false;
+ public boolean onAbortCalled = false;
+ public boolean onMatchCalled = false;
+ public boolean onConnectSuccessCalled = false;
+ public boolean onConnectFailureCalled = false;
+ public WifiManager.NetworkRequestUserSelectionCallback userSelectionCallback = null;
+ public List<ScanResult> matchedScanResults = null;
+
+ TestNetworkRequestMatchCallback(Object lock) {
+ mLock = lock;
+ }
+
+ @Override
+ public void onUserSelectionCallbackRegistration(
+ WifiManager.NetworkRequestUserSelectionCallback userSelectionCallback) {
+ synchronized (mLock) {
+ onRegistrationCalled = true;
+ this.userSelectionCallback = userSelectionCallback;
+ mLock.notify();
+ }
+ }
+
+ @Override
+ public void onAbort() {
+ synchronized (mLock) {
+ onAbortCalled = true;
+ mLock.notify();
+ }
+ }
+
+ @Override
+ public void onMatch(List<ScanResult> scanResults) {
+ synchronized (mLock) {
+ // This can be invoked multiple times. So, ignore after the first one to avoid
+ // disturbing the rest of the test sequence.
+ if (onMatchCalled) return;
+ onMatchCalled = true;
+ matchedScanResults = scanResults;
+ mLock.notify();
+ }
+ }
+
+ @Override
+ public void onUserSelectionConnectSuccess(WifiConfiguration config) {
+ synchronized (mLock) {
+ onConnectSuccessCalled = true;
+ mLock.notify();
+ }
+ }
+
+ @Override
+ public void onUserSelectionConnectFailure(WifiConfiguration config) {
+ synchronized (mLock) {
+ onConnectFailureCalled = true;
+ mLock.notify();
+ }
+ }
+ }
+
+ private void handleUiInteractions(boolean shouldUserReject) {
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ TestNetworkRequestMatchCallback networkRequestMatchCallback =
+ new TestNetworkRequestMatchCallback(mUiLock);
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+
+ // 1. Wait for registration callback.
+ synchronized (mUiLock) {
+ try {
+ mWifiManager.registerNetworkRequestMatchCallback(
+ Executors.newSingleThreadExecutor(), networkRequestMatchCallback);
+ // now wait for the registration callback first.
+ mUiLock.wait(DURATION_UI_INTERACTION);
+ } catch (InterruptedException e) {
+ }
+ }
+ assertTrue(networkRequestMatchCallback.onRegistrationCalled);
+ assertNotNull(networkRequestMatchCallback.userSelectionCallback);
+
+ // 2. Wait for matching scan results
+ synchronized (mUiLock) {
+ try {
+ // now wait for the registration callback first.
+ mUiLock.wait(DURATION_UI_INTERACTION);
+ } catch (InterruptedException e) {
+ }
+ }
+ assertTrue(networkRequestMatchCallback.onMatchCalled);
+ assertNotNull(networkRequestMatchCallback.matchedScanResults);
+ assertThat(networkRequestMatchCallback.matchedScanResults.size()).isAtLeast(1);
+
+ // 3. Trigger connection to one of the matched networks or reject the request.
+ if (shouldUserReject) {
+ networkRequestMatchCallback.userSelectionCallback.reject();
+ } else {
+ networkRequestMatchCallback.userSelectionCallback.select(mTestNetwork);
+ }
+
+ // 4. Wait for connection success or abort.
+ synchronized (mUiLock) {
+ try {
+ // now wait for the registration callback first.
+ mUiLock.wait(DURATION_UI_INTERACTION);
+ } catch (InterruptedException e) {
+ }
+ }
+ if (shouldUserReject) {
+ assertTrue(networkRequestMatchCallback.onAbortCalled);
+ } else {
+ assertTrue(networkRequestMatchCallback.onConnectSuccessCalled);
+ }
+ } finally {
+ mWifiManager.unregisterNetworkRequestMatchCallback(networkRequestMatchCallback);
+ uiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ /**
+ * Tests the entire connection flow using the provided specifier.
+ *
+ * @param specifier Specifier to use for network request.
+ * @param shouldUserReject Whether to simulate user rejection or not.
+ */
+ private void testConnectionFlowWithSpecifier(
+ WifiNetworkSpecifier specifier, boolean shouldUserReject) {
+ // Fork a thread to handle the UI interactions.
+ Thread uiThread = new Thread(() -> handleUiInteractions(shouldUserReject));
+
+ // File the network request & wait for the callback.
+ TestNetworkCallback networkCallbackListener = new TestNetworkCallback(mLock);
+ synchronized (mLock) {
+ try {
+ // File a request for wifi network.
+ mConnectivityManager.requestNetwork(
+ new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .setNetworkSpecifier(specifier)
+ .build(),
+ networkCallbackListener);
+ // Wait for the request to reach the wifi stack before kick-starting the UI
+ // interactions.
+ Thread.sleep(100);
+ // Start the UI interactions.
+ uiThread.run();
+ // now wait for callback
+ mLock.wait(DURATION_NETWORK_CONNECTION);
+ } catch (InterruptedException e) {
+ }
+ }
+ if (shouldUserReject) {
+ assertTrue(networkCallbackListener.onUnavailableCalled);
+ } else {
+ assertTrue(networkCallbackListener.onAvailableCalled);
+ }
+
+ try {
+ // Ensure that the UI interaction thread has completed.
+ uiThread.join(DURATION_UI_INTERACTION);
+ } catch (InterruptedException e) {
+ fail("UI interaction interrupted");
+ }
+
+ // Release the request after the test.
+ mConnectivityManager.unregisterNetworkCallback(networkCallbackListener);
+ }
+
+ private void testSuccessfulConnectionWithSpecifier(WifiNetworkSpecifier specifier) {
+ testConnectionFlowWithSpecifier(specifier, false);
+ }
+
+ private void testUserRejectionWithSpecifier(WifiNetworkSpecifier specifier) {
+ testConnectionFlowWithSpecifier(specifier, true);
+ }
+
+ private WifiNetworkSpecifier.Builder createSpecifierBuilderWithCredentialFromSavedNetwork() {
+ WifiNetworkSpecifier.Builder specifierBuilder = new WifiNetworkSpecifier.Builder();
+ if (mTestNetwork.preSharedKey != null) {
+ if (mTestNetwork.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
+ specifierBuilder.setWpa2Passphrase(mTestNetwork.preSharedKey);
+ } else if (mTestNetwork.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SAE)) {
+ specifierBuilder.setWpa3Passphrase(mTestNetwork.preSharedKey);
+ } else {
+ fail("Unsupported security type found in saved networks");
+ }
+ } else if (!mTestNetwork.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.OWE)) {
+ specifierBuilder.setIsEnhancedOpen(false);
+ } else if (!mTestNetwork.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) {
+ fail("Unsupported security type found in saved networks");
+ }
+ specifierBuilder.setIsHiddenSsid(mTestNetwork.hiddenSSID);
+ return specifierBuilder;
+ }
+
+ /**
+ * Tests the entire connection flow using a specific SSID in the specifier.
+ */
+ public void testConnectionWithSpecificSsid() {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ WifiNetworkSpecifier specifier = createSpecifierBuilderWithCredentialFromSavedNetwork()
+ .setSsid(WifiInfo.sanitizeSsid(mTestNetwork.SSID))
+ .build();
+ testSuccessfulConnectionWithSpecifier(specifier);
+ }
+
+ /**
+ * Tests the entire connection flow using a SSID pattern in the specifier.
+ */
+ public void testConnectionWithSsidPattern() {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ // Creates a ssid pattern by dropping the last char in the saved network & pass that
+ // as a prefix match pattern in the request.
+ String ssidUnquoted = WifiInfo.sanitizeSsid(mTestNetwork.SSID);
+ assertThat(ssidUnquoted.length()).isAtLeast(2);
+ String ssidPrefix = ssidUnquoted.substring(0, ssidUnquoted.length() - 1);
+ // Note: The match may return more than 1 network in this case since we use a prefix match,
+ // But, we will still ensure that the UI interactions in the test still selects the
+ // saved network for connection.
+ WifiNetworkSpecifier specifier = createSpecifierBuilderWithCredentialFromSavedNetwork()
+ .setSsidPattern(new PatternMatcher(ssidPrefix, PatternMatcher.PATTERN_PREFIX))
+ .build();
+ testSuccessfulConnectionWithSpecifier(specifier);
+ }
+
+ private static class TestScanResultsCallback extends WifiManager.ScanResultsCallback {
+ private final Object mLock;
+ public boolean onAvailableCalled = false;
+
+ TestScanResultsCallback(Object lock) {
+ mLock = lock;
+ }
+
+ @Override
+ public void onScanResultsAvailable() {
+ synchronized (mLock) {
+ onAvailableCalled = true;
+ mLock.notify();
+ }
+ }
+ }
+
+ /**
+ * Loops through all available scan results and finds the first match for the saved network.
+ *
+ * Note:
+ * a) If there are more than 2 networks with the same SSID, but different credential type, then
+ * this matching may pick the wrong one.
+ */
+ private ScanResult findScanResultMatchingSavedNetwork() {
+ // Trigger a scan to get fresh scan results.
+ TestScanResultsCallback scanResultsCallback = new TestScanResultsCallback(mLock);
+ synchronized (mLock) {
+ try {
+ mWifiManager.registerScanResultsCallback(
+ Executors.newSingleThreadExecutor(), scanResultsCallback);
+ mWifiManager.startScan(new WorkSource(myUid()));
+ // now wait for callback
+ mLock.wait(DURATION_NETWORK_CONNECTION);
+ } catch (InterruptedException e) {
+ } finally {
+ mWifiManager.unregisterScanResultsCallback(scanResultsCallback);
+ }
+ }
+ List<ScanResult> scanResults = mWifiManager.getScanResults();
+ if (scanResults == null || scanResults.isEmpty()) fail("No scan results available");
+ for (ScanResult scanResult : scanResults) {
+ if (TextUtils.equals(scanResult.SSID, WifiInfo.sanitizeSsid(mTestNetwork.SSID))) {
+ return scanResult;
+ }
+ }
+ fail("No matching scan results found");
+ return null;
+ }
+
+ /**
+ * Tests the entire connection flow using a specific BSSID in the specifier.
+ */
+ public void testConnectionWithSpecificBssid() {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ ScanResult scanResult = findScanResultMatchingSavedNetwork();
+ WifiNetworkSpecifier specifier = createSpecifierBuilderWithCredentialFromSavedNetwork()
+ .setBssid(MacAddress.fromString(scanResult.BSSID))
+ .build();
+ testSuccessfulConnectionWithSpecifier(specifier);
+ }
+
+ /**
+ * Tests the entire connection flow using a BSSID pattern in the specifier.
+ */
+ public void testConnectionWithBssidPattern() {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ ScanResult scanResult = findScanResultMatchingSavedNetwork();
+ // Note: The match may return more than 1 network in this case since we use a prefix match,
+ // But, we will still ensure that the UI interactions in the test still selects the
+ // saved network for connection.
+ WifiNetworkSpecifier specifier = createSpecifierBuilderWithCredentialFromSavedNetwork()
+ .setBssidPattern(MacAddress.fromString(scanResult.BSSID),
+ MacAddress.fromString("ff:ff:ff:00:00:00"))
+ .build();
+ testSuccessfulConnectionWithSpecifier(specifier);
+ }
+
+ /**
+ * Tests the entire connection flow using a BSSID pattern in the specifier.
+ */
+ public void testUserRejectionWithSpecificSsid() {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ WifiNetworkSpecifier specifier = createSpecifierBuilderWithCredentialFromSavedNetwork()
+ .setSsid(WifiInfo.sanitizeSsid(mTestNetwork.SSID))
+ .build();
+ testUserRejectionWithSpecifier(specifier);
+ }
+}
diff --git a/tests/cts/net/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java b/tests/cts/net/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java
new file mode 100644
index 0000000..994b6c9
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiNetworkSuggestionTest.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.cts;
+
+import static android.net.wifi.WifiEnterpriseConfig.Eap.AKA;
+
+import android.net.MacAddress;
+import android.net.wifi.WifiEnterpriseConfig;
+import android.net.wifi.WifiNetworkSuggestion;
+import android.net.wifi.hotspot2.PasspointConfiguration;
+import android.net.wifi.hotspot2.pps.Credential;
+import android.net.wifi.hotspot2.pps.HomeSp;
+import android.telephony.TelephonyManager;
+import android.test.AndroidTestCase;
+
+public class WifiNetworkSuggestionTest extends AndroidTestCase {
+ private static final String TEST_SSID = "testSsid";
+ private static final String TEST_BSSID = "00:df:aa:bc:12:23";
+ private static final String TEST_PASSPHRASE = "testPassword";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ super.tearDown();
+ return;
+ }
+ super.tearDown();
+ }
+
+ private WifiNetworkSuggestion.Builder createBuilderWithCommonParams() {
+ return createBuilderWithCommonParams(false);
+ }
+
+ private WifiNetworkSuggestion.Builder createBuilderWithCommonParams(boolean isPasspoint) {
+ WifiNetworkSuggestion.Builder builder = new WifiNetworkSuggestion.Builder();
+ if (!isPasspoint) {
+ builder.setSsid(TEST_SSID);
+ builder.setBssid(MacAddress.fromString(TEST_BSSID));
+ builder.setIsEnhancedOpen(false);
+ builder.setIsHiddenSsid(true);
+ }
+ builder.setPriority(0);
+ builder.setIsAppInteractionRequired(true);
+ builder.setIsUserInteractionRequired(true);
+ builder.setIsMetered(true);
+ builder.setCarrierId(TelephonyManager.UNKNOWN_CARRIER_ID);
+ builder.setCredentialSharedWithUser(true);
+ builder.setIsInitialAutojoinEnabled(true);
+ builder.setUntrusted(false);
+ return builder;
+ }
+
+ private void validateCommonParams(WifiNetworkSuggestion suggestion) {
+ validateCommonParams(suggestion, false);
+ }
+
+ private void validateCommonParams(WifiNetworkSuggestion suggestion, boolean isPasspoint) {
+ assertNotNull(suggestion);
+ assertNotNull(suggestion.getWifiConfiguration());
+ if (!isPasspoint) {
+ assertEquals(TEST_SSID, suggestion.getSsid());
+ assertEquals(TEST_BSSID, suggestion.getBssid().toString());
+ assertFalse(suggestion.isEnhancedOpen());
+ assertTrue(suggestion.isHiddenSsid());
+ }
+ assertEquals(0, suggestion.getPriority());
+ assertTrue(suggestion.isAppInteractionRequired());
+ assertTrue(suggestion.isUserInteractionRequired());
+ assertTrue(suggestion.isMetered());
+ assertTrue(suggestion.isCredentialSharedWithUser());
+ assertTrue(suggestion.isInitialAutojoinEnabled());
+ assertFalse(suggestion.isUntrusted());
+ }
+
+ /**
+ * Tests {@link android.net.wifi.WifiNetworkSuggestion.Builder} class.
+ */
+ public void testBuilderWithWpa2Passphrase() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ WifiNetworkSuggestion suggestion =
+ createBuilderWithCommonParams()
+ .setWpa2Passphrase(TEST_PASSPHRASE)
+ .build();
+ validateCommonParams(suggestion);
+ assertEquals(TEST_PASSPHRASE, suggestion.getPassphrase());
+ assertNotNull(suggestion.getEnterpriseConfig());
+ assertNull(suggestion.getPasspointConfig());
+ }
+
+ /**
+ * Tests {@link android.net.wifi.WifiNetworkSuggestion.Builder} class.
+ */
+ public void testBuilderWithWpa3Passphrase() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ WifiNetworkSuggestion suggestion =
+ createBuilderWithCommonParams()
+ .setWpa3Passphrase(TEST_PASSPHRASE)
+ .build();
+ validateCommonParams(suggestion);
+ assertEquals(TEST_PASSPHRASE, suggestion.getPassphrase());
+ assertNotNull(suggestion.getEnterpriseConfig());
+ assertNull(suggestion.getPasspointConfig());
+ }
+
+ /**
+ * Tests {@link android.net.wifi.WifiNetworkSuggestion.Builder} class.
+ */
+ public void testBuilderWithWapiPassphrase() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ WifiNetworkSuggestion suggestion =
+ createBuilderWithCommonParams()
+ .setWapiPassphrase(TEST_PASSPHRASE)
+ .build();
+ validateCommonParams(suggestion);
+ assertEquals(TEST_PASSPHRASE, suggestion.getPassphrase());
+ assertNotNull(suggestion.getEnterpriseConfig());
+ assertNull(suggestion.getPasspointConfig());
+ }
+
+ private static WifiEnterpriseConfig createEnterpriseConfig() {
+ WifiEnterpriseConfig config = new WifiEnterpriseConfig();
+ config.setEapMethod(AKA);
+ return config;
+ }
+
+ /**
+ * Tests {@link android.net.wifi.WifiNetworkSuggestion.Builder} class.
+ */
+ public void testBuilderWithWpa2Enterprise() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ WifiEnterpriseConfig enterpriseConfig = createEnterpriseConfig();
+ WifiNetworkSuggestion suggestion =
+ createBuilderWithCommonParams()
+ .setWpa2EnterpriseConfig(enterpriseConfig)
+ .build();
+ validateCommonParams(suggestion);
+ assertNull(suggestion.getPassphrase());
+ assertNotNull(suggestion.getEnterpriseConfig());
+ assertEquals(enterpriseConfig.getEapMethod(),
+ suggestion.getEnterpriseConfig().getEapMethod());
+ assertNull(suggestion.getPasspointConfig());
+ }
+
+ /**
+ * Tests {@link android.net.wifi.WifiNetworkSuggestion.Builder} class.
+ */
+ public void testBuilderWithWpa3Enterprise() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ WifiEnterpriseConfig enterpriseConfig = createEnterpriseConfig();
+ WifiNetworkSuggestion suggestion =
+ createBuilderWithCommonParams()
+ .setWpa3EnterpriseConfig(enterpriseConfig)
+ .build();
+ validateCommonParams(suggestion);
+ assertNull(suggestion.getPassphrase());
+ assertNotNull(suggestion.getEnterpriseConfig());
+ assertEquals(enterpriseConfig.getEapMethod(),
+ suggestion.getEnterpriseConfig().getEapMethod());
+ assertNull(suggestion.getPasspointConfig());
+ }
+
+ /**
+ * Helper function for creating a {@link PasspointConfiguration} for testing.
+ *
+ * @return {@link PasspointConfiguration}
+ */
+ private static PasspointConfiguration createPasspointConfig() {
+ HomeSp homeSp = new HomeSp();
+ homeSp.setFqdn("fqdn");
+ homeSp.setFriendlyName("friendly name");
+ homeSp.setRoamingConsortiumOis(new long[] {0x55, 0x66});
+ Credential cred = new Credential();
+ cred.setRealm("realm");
+ cred.setUserCredential(null);
+ cred.setCertCredential(null);
+ cred.setSimCredential(new Credential.SimCredential());
+ cred.getSimCredential().setImsi("1234*");
+ cred.getSimCredential().setEapType(23); // EAP-AKA
+ cred.setCaCertificate(null);
+ cred.setClientCertificateChain(null);
+ cred.setClientPrivateKey(null);
+ PasspointConfiguration config = new PasspointConfiguration();
+ config.setHomeSp(homeSp);
+ config.setCredential(cred);
+ return config;
+ }
+
+ /**
+ * Tests {@link android.net.wifi.WifiNetworkSuggestion.Builder} class.
+ */
+ public void testBuilderWithPasspointConfig() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+ PasspointConfiguration passpointConfig = createPasspointConfig();
+ WifiNetworkSuggestion suggestion =
+ createBuilderWithCommonParams(true)
+ .setPasspointConfig(passpointConfig)
+ .build();
+ validateCommonParams(suggestion, true);
+ assertNull(suggestion.getPassphrase());
+ assertNotNull(suggestion.getEnterpriseConfig());
+ assertEquals(passpointConfig, suggestion.getPasspointConfig());
+ }
+}
diff --git a/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pConfigTest.java b/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pConfigTest.java
index ee7e1ed..0a2a2e6 100644
--- a/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pConfigTest.java
+++ b/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pConfigTest.java
@@ -28,6 +28,24 @@
private static final int TEST_OWNER_FREQ = 2447;
private static final String TEST_DEVICE_ADDRESS = "aa:bb:cc:dd:ee:ff";
+ public void testWifiP2pConfigCopyConstructor() {
+ WifiP2pConfig config = new WifiP2pConfig.Builder()
+ .setNetworkName(TEST_NETWORK_NAME)
+ .setPassphrase(TEST_PASSPHRASE)
+ .setGroupOperatingBand(TEST_OWNER_BAND)
+ .setDeviceAddress(MacAddress.fromString(TEST_DEVICE_ADDRESS))
+ .enablePersistentMode(true)
+ .build();
+
+ WifiP2pConfig copiedConfig = new WifiP2pConfig(config);
+
+ assertEquals(copiedConfig.deviceAddress, TEST_DEVICE_ADDRESS);
+ assertEquals(copiedConfig.getNetworkName(), TEST_NETWORK_NAME);
+ assertEquals(copiedConfig.getPassphrase(), TEST_PASSPHRASE);
+ assertEquals(copiedConfig.getGroupOwnerBand(), TEST_OWNER_BAND);
+ assertEquals(copiedConfig.getNetworkId(), WifiP2pGroup.NETWORK_ID_PERSISTENT);
+ }
+
public void testWifiP2pConfigBuilderForPersist() {
WifiP2pConfig config = new WifiP2pConfig.Builder()
.setNetworkName(TEST_NETWORK_NAME)
diff --git a/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pDeviceTest.java b/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pDeviceTest.java
new file mode 100644
index 0000000..1510d7c
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pDeviceTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.p2p.cts;
+
+import android.net.InetAddresses;
+import android.net.wifi.p2p.WifiP2pDevice;
+import android.test.AndroidTestCase;
+
+public class WifiP2pDeviceTest extends AndroidTestCase {
+
+ public void testDefaultWpsMethodSupportCheck() {
+ WifiP2pDevice dev = new WifiP2pDevice();
+
+ assertFalse(dev.wpsPbcSupported());
+ assertFalse(dev.wpsDisplaySupported());
+ assertFalse(dev.wpsKeypadSupported());
+ }
+
+ public void testDefaultDeviceCapabilityCheck() {
+ WifiP2pDevice dev = new WifiP2pDevice();
+
+ assertFalse(dev.isServiceDiscoveryCapable());
+ }
+}
diff --git a/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pInfoTest.java b/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pInfoTest.java
new file mode 100644
index 0000000..8504f15
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pInfoTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.p2p.cts;
+
+import android.net.InetAddresses;
+import android.net.wifi.p2p.WifiP2pInfo;
+import android.test.AndroidTestCase;
+
+public class WifiP2pInfoTest extends AndroidTestCase {
+
+ public String TEST_GROUP_OWNER_ADDRESS = "192.168.43.1";
+
+ public void testWifiP2pInfoNoGroup() {
+ WifiP2pInfo info = new WifiP2pInfo();
+ info.groupFormed = false;
+
+ WifiP2pInfo copiedInfo = new WifiP2pInfo(info);
+ assertEquals(info.groupFormed, copiedInfo.groupFormed);
+ assertEquals(info.isGroupOwner, copiedInfo.isGroupOwner);
+ assertEquals(info.groupOwnerAddress, copiedInfo.groupOwnerAddress);
+ }
+
+ public void testWifiP2pInfoGroupOwner() {
+ WifiP2pInfo info = new WifiP2pInfo();
+ info.groupFormed = true;
+ info.isGroupOwner = true;
+ info.groupOwnerAddress = InetAddresses.parseNumericAddress(TEST_GROUP_OWNER_ADDRESS);
+
+ WifiP2pInfo copiedInfo = new WifiP2pInfo(info);
+ assertEquals(info.groupFormed, copiedInfo.groupFormed);
+ assertEquals(info.isGroupOwner, copiedInfo.isGroupOwner);
+ assertEquals(info.groupOwnerAddress, copiedInfo.groupOwnerAddress);
+ }
+
+ public void testWifiP2pInfoGroupClient() {
+ WifiP2pInfo info = new WifiP2pInfo();
+ info.groupFormed = true;
+ info.isGroupOwner = false;
+ info.groupOwnerAddress = InetAddresses.parseNumericAddress(TEST_GROUP_OWNER_ADDRESS);
+
+ WifiP2pInfo copiedInfo = new WifiP2pInfo(info);
+ assertEquals(info.groupFormed, copiedInfo.groupFormed);
+ assertEquals(info.isGroupOwner, copiedInfo.isGroupOwner);
+ assertEquals(info.groupOwnerAddress, copiedInfo.groupOwnerAddress);
+ }
+}
diff --git a/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pServiceRequestTest.java b/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pServiceRequestTest.java
new file mode 100644
index 0000000..b363b1e
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pServiceRequestTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.p2p.cts;
+
+import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
+import android.net.wifi.p2p.nsd.WifiP2pServiceRequest;
+import android.net.wifi.p2p.nsd.WifiP2pUpnpServiceRequest;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.stream.Collectors;
+
+public class WifiP2pServiceRequestTest extends AndroidTestCase {
+
+ private final int TEST_UPNP_VERSION = 0x10;
+ private final String TEST_UPNP_QUERY = "ssdp:all";
+
+ private String bin2HexStr(byte[] data) {
+ StringBuffer sb = new StringBuffer();
+ for (byte b: data) {
+ sb.append(String.format(Locale.US, "%02x", b & 0xff));
+ }
+ return sb.toString();
+ }
+
+ public void testValidRawRequest() throws IllegalArgumentException {
+ StringBuffer sb = new StringBuffer();
+ sb.append(String.format(Locale.US, "%02x", TEST_UPNP_VERSION));
+ sb.append(bin2HexStr(TEST_UPNP_QUERY.getBytes()));
+
+ WifiP2pServiceRequest rawRequest =
+ WifiP2pServiceRequest.newInstance(
+ WifiP2pServiceInfo.SERVICE_TYPE_UPNP,
+ sb.toString());
+
+ WifiP2pUpnpServiceRequest upnpRequest =
+ WifiP2pUpnpServiceRequest.newInstance(
+ TEST_UPNP_QUERY);
+
+ assertEquals(rawRequest, upnpRequest);
+ }
+
+ public void testInvalidRawRequest() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(String.format(Locale.US, "%02x", TEST_UPNP_VERSION));
+ sb.append(bin2HexStr(TEST_UPNP_QUERY.getBytes()));
+ sb.append("x");
+
+ try {
+ WifiP2pServiceRequest request =
+ WifiP2pServiceRequest.newInstance(
+ WifiP2pServiceInfo.SERVICE_TYPE_UPNP, sb.toString());
+ fail("Expected IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ return;
+ }
+ }
+}
diff --git a/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pWfdInfoTest.java b/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pWfdInfoTest.java
new file mode 100644
index 0000000..75df5bf
--- /dev/null
+++ b/tests/cts/net/src/android/net/wifi/p2p/cts/WifiP2pWfdInfoTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 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 android.net.wifi.p2p.cts;
+
+import android.net.wifi.p2p.WifiP2pWfdInfo;
+import android.test.AndroidTestCase;
+
+public class WifiP2pWfdInfoTest extends AndroidTestCase {
+
+ private final int TEST_DEVICE_TYPE = WifiP2pWfdInfo.DEVICE_TYPE_WFD_SOURCE;
+ private final boolean TEST_DEVICE_ENABLE_STATUS = true;
+ private final boolean TEST_SESSION_STATUS = true;
+ private final int TEST_CONTROL_PORT = 9999;
+ private final int TEST_MAX_THROUGHPUT = 1024;
+ private final boolean TEST_CONTENT_PROTECTION_SUPPORTED_STATUS = true;
+
+ public void testWifiP2pWfdInfo() {
+ WifiP2pWfdInfo info = new WifiP2pWfdInfo();
+
+ info.setDeviceType(TEST_DEVICE_TYPE);
+ info.setEnabled(TEST_DEVICE_ENABLE_STATUS);
+ info.setSessionAvailable(true);
+ info.setControlPort(TEST_CONTROL_PORT);
+ info.setMaxThroughput(TEST_MAX_THROUGHPUT);
+ info.setContentProtectionSupported(true);
+
+ WifiP2pWfdInfo copiedInfo = new WifiP2pWfdInfo(info);
+ assertEquals(TEST_DEVICE_TYPE, copiedInfo.getDeviceType());
+ assertEquals(TEST_DEVICE_ENABLE_STATUS, copiedInfo.isEnabled());
+ assertEquals(TEST_SESSION_STATUS, copiedInfo.isSessionAvailable());
+ assertEquals(TEST_CONTROL_PORT, copiedInfo.getControlPort());
+ assertEquals(TEST_MAX_THROUGHPUT, copiedInfo.getMaxThroughput());
+ assertEquals(TEST_CONTENT_PROTECTION_SUPPORTED_STATUS,
+ copiedInfo.isContentProtectionSupported());
+ }
+}
diff --git a/tests/cts/net/src/android/net/wifi/rtt/cts/WifiRttTest.java b/tests/cts/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
index 44a9cc2..d5361d7 100644
--- a/tests/cts/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
+++ b/tests/cts/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
@@ -163,7 +163,7 @@
// Analyze results
assertTrue("Wi-Fi RTT failure rate exceeds threshold: FAIL=" + numFailures + ", ITERATIONS="
- + NUM_OF_RTT_ITERATIONS,
+ + NUM_OF_RTT_ITERATIONS + ", AP RSSI=" + testAp.level,
numFailures <= NUM_OF_RTT_ITERATIONS * MAX_FAILURE_RATE_PERCENT / 100);
if (numFailures != NUM_OF_RTT_ITERATIONS) {
double distanceAvg = distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures);