Merge "Add a CTS test for private DNS on VPNs." into qt-dev am: 17311d9af6 am: fe44dd21ba am: 523cc30322
Change-Id: If38d0c7e8b878e76ff4a52fcdd441b002ce9ddf0
diff --git a/tests/cts/hostside/Android.bp b/tests/cts/hostside/Android.bp
new file mode 100644
index 0000000..b6f5142
--- /dev/null
+++ b/tests/cts/hostside/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2014 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.
+
+java_test_host {
+ name: "CtsHostsideNetworkTests",
+ defaults: ["cts_defaults"],
+ // Only compile source java files in this apk.
+ srcs: ["src/**/*.java"],
+ libs: [
+ "cts-tradefed",
+ "tradefed",
+ ],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/cts/hostside/Android.mk b/tests/cts/hostside/Android.mk
deleted file mode 100644
index 7270580..0000000
--- a/tests/cts/hostside/Android.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (C) 2014 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := CtsHostsideNetworkTests
-
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed
-
-LOCAL_CTS_TEST_PACKAGE := android.net.hostsidenetwork
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-include $(BUILD_CTS_HOST_JAVA_LIBRARY)
-
-# Build the test APKs using their own makefiles
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/cts/hostside/AndroidTest.xml b/tests/cts/hostside/AndroidTest.xml
index c7cab7b..dbff179 100644
--- a/tests/cts/hostside/AndroidTest.xml
+++ b/tests/cts/hostside/AndroidTest.xml
@@ -18,6 +18,7 @@
<option name="config-descriptor:metadata" key="component" value="networking" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<target_preparer class="com.android.cts.net.NetPolicyTestsPreparer" />
diff --git a/tests/cts/hostside/aidl/Android.bp b/tests/cts/hostside/aidl/Android.bp
new file mode 100644
index 0000000..320a1fa
--- /dev/null
+++ b/tests/cts/hostside/aidl/Android.bp
@@ -0,0 +1,24 @@
+// Copyright (C) 2016 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.
+
+java_test_helper_library {
+ name: "CtsHostsideNetworkTestsAidl",
+ sdk_version: "current",
+ srcs: [
+ "com/android/cts/net/hostside/IMyService.aidl",
+ "com/android/cts/net/hostside/INetworkCallback.aidl",
+ "com/android/cts/net/hostside/INetworkStateObserver.aidl",
+ "com/android/cts/net/hostside/IRemoteSocketFactory.aidl",
+ ],
+}
diff --git a/tests/cts/hostside/aidl/Android.mk b/tests/cts/hostside/aidl/Android.mk
deleted file mode 100644
index 20dabc1..0000000
--- a/tests/cts/hostside/aidl/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2016 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := \
- com/android/cts/net/hostside/IMyService.aidl \
- com/android/cts/net/hostside/INetworkCallback.aidl \
- com/android/cts/net/hostside/INetworkStateObserver.aidl \
- com/android/cts/net/hostside/IRemoteSocketFactory.aidl
-LOCAL_MODULE := CtsHostsideNetworkTestsAidl
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/cts/hostside/app/Android.bp b/tests/cts/hostside/app/Android.bp
new file mode 100644
index 0000000..d66b71b
--- /dev/null
+++ b/tests/cts/hostside/app/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2014 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.
+//
+
+android_test_helper_app {
+ name: "CtsHostsideNetworkTestsApp",
+ defaults: ["cts_support_defaults"],
+ //sdk_version: "current",
+ platform_apis: true,
+ static_libs: [
+ "compatibility-device-util-axt",
+ "ctstestrunner-axt",
+ "ub-uiautomator",
+ "CtsHostsideNetworkTestsAidl",
+ ],
+ libs: [
+ "android.test.runner.stubs",
+ "android.test.base.stubs",
+ ],
+ srcs: ["src/**/*.java"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+}
diff --git a/tests/cts/hostside/app/Android.mk b/tests/cts/hostside/app/Android.mk
deleted file mode 100644
index 11f6bb1..0000000
--- a/tests/cts/hostside/app/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# Copyright (C) 2014 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-#LOCAL_SDK_VERSION := current
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util-axt ctstestrunner-axt ub-uiautomator \
- CtsHostsideNetworkTestsAidl
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsHostsideNetworkTestsApp
-
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_DEX_PREOPT := false
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
index fde8335..26397ef 100755
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
@@ -1008,6 +1008,32 @@
assertTrue(mCM.isActiveNetworkMetered());
}
+ public void testB141603906() throws Exception {
+ final InetSocketAddress src = new InetSocketAddress(0);
+ final InetSocketAddress dst = new InetSocketAddress(0);
+ final int NUM_THREADS = 8;
+ final int NUM_SOCKETS = 5000;
+ final Thread[] threads = new Thread[NUM_THREADS];
+ startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
+ new String[] {"0.0.0.0/0", "::/0"},
+ "", "", null, null /* underlyingNetworks */, false /* isAlwaysMetered */);
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ threads[i] = new Thread(() -> {
+ for (int j = 0; j < NUM_SOCKETS; j++) {
+ mCM.getConnectionOwnerUid(IPPROTO_TCP, src, dst);
+ }
+ });
+ }
+ for (Thread thread : threads) {
+ thread.start();
+ }
+ for (Thread thread : threads) {
+ thread.join();
+ }
+ stopVpn();
+ }
+
private boolean isNetworkMetered(Network network) {
NetworkCapabilities nc = mCM.getNetworkCapabilities(network);
return !nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
diff --git a/tests/cts/hostside/app2/Android.bp b/tests/cts/hostside/app2/Android.bp
new file mode 100644
index 0000000..8a3c8e7
--- /dev/null
+++ b/tests/cts/hostside/app2/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2016 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.
+//
+
+android_test_helper_app {
+ name: "CtsHostsideNetworkTestsApp2",
+ defaults: ["cts_support_defaults"],
+ sdk_version: "current",
+ static_libs: ["CtsHostsideNetworkTestsAidl"],
+ srcs: ["src/**/*.java"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ ],
+ certificate: ":cts-net-app",
+}
diff --git a/tests/cts/hostside/app2/Android.mk b/tests/cts/hostside/app2/Android.mk
deleted file mode 100644
index 5c0bae1..0000000
--- a/tests/cts/hostside/app2/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := CtsHostsideNetworkTestsAidl
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CtsHostsideNetworkTestsApp2
-
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_DEX_PREOPT := false
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
-
-LOCAL_CERTIFICATE := cts/hostsidetests/net/certs/cts-net-app
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/cts/hostside/certs/Android.bp b/tests/cts/hostside/certs/Android.bp
new file mode 100644
index 0000000..ab4cf34
--- /dev/null
+++ b/tests/cts/hostside/certs/Android.bp
@@ -0,0 +1,4 @@
+android_app_certificate {
+ name: "cts-net-app",
+ certificate: "cts-net-app",
+}
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
index 6e37a24..62925ad 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
@@ -91,4 +91,8 @@
TEST_PKG + ".VpnTest",
"testAlwaysMeteredVpnWithNonNullUnderlyingNetwork");
}
+
+ public void testB141603906() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testB141603906");
+ }
}
diff --git a/tests/cts/net/AndroidTest.xml b/tests/cts/net/AndroidTest.xml
index 1807a6b..3ff019e 100644
--- a/tests/cts/net/AndroidTest.xml
+++ b/tests/cts/net/AndroidTest.xml
@@ -18,6 +18,7 @@
<option name="config-descriptor:metadata" key="token" value="SIM_CARD" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<option name="not-shardable" value="true" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
diff --git a/tests/cts/net/api23Test/AndroidTest.xml b/tests/cts/net/api23Test/AndroidTest.xml
index 21f28fc..8042d50 100644
--- a/tests/cts/net/api23Test/AndroidTest.xml
+++ b/tests/cts/net/api23Test/AndroidTest.xml
@@ -17,6 +17,7 @@
<option name="config-descriptor:metadata" key="component" value="networking" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<option name="not-shardable" value="true" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
diff --git a/tests/cts/net/native/dns/AndroidTest.xml b/tests/cts/net/native/dns/AndroidTest.xml
index fe88cda..6d03c23 100644
--- a/tests/cts/net/native/dns/AndroidTest.xml
+++ b/tests/cts/net/native/dns/AndroidTest.xml
@@ -18,6 +18,7 @@
<option name="config-descriptor:metadata" key="component" value="networking" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
<option name="cleanup" value="true" />
<option name="push" value="CtsNativeNetDnsTestCases->/data/local/tmp/CtsNativeNetDnsTestCases" />
diff --git a/tests/cts/net/native/qtaguid/AndroidTest.xml b/tests/cts/net/native/qtaguid/AndroidTest.xml
index a55afe7..fa4b2cf 100644
--- a/tests/cts/net/native/qtaguid/AndroidTest.xml
+++ b/tests/cts/net/native/qtaguid/AndroidTest.xml
@@ -18,6 +18,7 @@
<option name="config-descriptor:metadata" key="component" value="networking" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
<option name="cleanup" value="true" />
<option name="push" value="CtsNativeNetTestCases->/data/local/tmp/CtsNativeNetTestCases" />
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index ca1f771..fa7e138 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -16,8 +16,10 @@
package android.net.cts;
+import static android.content.pm.PackageManager.FEATURE_ETHERNET;
import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
import static android.content.pm.PackageManager.FEATURE_WIFI;
+import static android.content.pm.PackageManager.FEATURE_USB_HOST;
import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
@@ -111,9 +113,7 @@
public static final int TYPE_WIFI = ConnectivityManager.TYPE_WIFI;
private static final int HOST_ADDRESS = 0x7f000001;// represent ip 127.0.0.1
- private static final int CONNECT_TIMEOUT_MS = 2000;
private static final int KEEPALIVE_CALLBACK_TIMEOUT_MS = 2000;
- private static final int KEEPALIVE_SOCKET_TIMEOUT_MS = 5000;
private static final int INTERVAL_KEEPALIVE_RETRY_MS = 500;
private static final int MAX_KEEPALIVE_RETRY_COUNT = 3;
private static final int MIN_KEEPALIVE_INTERVAL = 10;
@@ -259,7 +259,7 @@
public void testGetNetworkInfo() {
for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE+1; type++) {
- if (isSupported(type)) {
+ if (shouldBeSupported(type)) {
NetworkInfo ni = mCm.getNetworkInfo(type);
assertTrue("Info shouldn't be null for " + type, ni != null);
State state = ni.getState();
@@ -279,7 +279,7 @@
NetworkInfo[] ni = mCm.getAllNetworkInfo();
assertTrue(ni.length >= MIN_NUM_NETWORK_TYPES);
for (int type = 0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
- int desiredFoundCount = (isSupported(type) ? 1 : 0);
+ int desiredFoundCount = (shouldBeSupported(type) ? 1 : 0);
int foundCount = 0;
for (NetworkInfo i : ni) {
if (i.getType() == type) foundCount++;
@@ -387,20 +387,32 @@
assertStartUsingNetworkFeatureUnsupported(TYPE_WIFI, mmsFeature);
}
- private boolean isSupported(int networkType) {
+ private boolean shouldEthernetBeSupported() {
+ // Instant mode apps aren't allowed to query the Ethernet service due to selinux policies.
+ // When in instant mode, don't fail if the Ethernet service is available. Instead, rely on
+ // the fact that Ethernet should be supported if the device has a hardware Ethernet port, or
+ // if the device can be a USB host and thus can use USB Ethernet adapters.
+ //
+ // Note that this test this will still fail in instant mode if a device supports Ethernet
+ // via other hardware means. We are not currently aware of any such device.
+ return (mContext.getSystemService(Context.ETHERNET_SERVICE) != null) ||
+ mPackageManager.hasSystemFeature(FEATURE_ETHERNET) ||
+ mPackageManager.hasSystemFeature(FEATURE_USB_HOST);
+ }
+
+ private boolean shouldBeSupported(int networkType) {
return mNetworks.containsKey(networkType) ||
(networkType == ConnectivityManager.TYPE_VPN) ||
- (networkType == ConnectivityManager.TYPE_ETHERNET &&
- mContext.getSystemService(Context.ETHERNET_SERVICE) != null);
+ (networkType == ConnectivityManager.TYPE_ETHERNET && shouldEthernetBeSupported());
}
public void testIsNetworkSupported() {
for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
boolean supported = mCm.isNetworkSupported(type);
- if (isSupported(type)) {
- assertTrue(supported);
+ if (shouldBeSupported(type)) {
+ assertTrue("Network type " + type + " should be supported", supported);
} else {
- assertFalse(supported);
+ assertFalse("Network type " + type + " should not be supported", supported);
}
}
}
@@ -834,15 +846,14 @@
}
private Socket getConnectedSocket(final Network network, final String host, final int port,
- final int socketTimeOut, final int family) throws Exception {
+ final int family) throws Exception {
final Socket s = network.getSocketFactory().createSocket();
try {
final InetAddress addr = getAddrByName(host, family);
if (addr == null) fail("Fail to get destination address for " + family);
final InetSocketAddress sockAddr = new InetSocketAddress(addr, port);
- s.setSoTimeout(socketTimeOut);
- s.connect(sockAddr, CONNECT_TIMEOUT_MS);
+ s.connect(sockAddr);
} catch (Exception e) {
s.close();
throw e;
@@ -967,8 +978,7 @@
final byte[] requestBytes = CtsNetUtils.HTTP_REQUEST.getBytes("UTF-8");
// So far only ipv4 tcp keepalive offload is supported.
// TODO: add test case for ipv6 tcp keepalive offload when it is supported.
- try (Socket s = getConnectedSocket(network, TEST_HOST, HTTP_PORT,
- KEEPALIVE_SOCKET_TIMEOUT_MS, AF_INET)) {
+ try (Socket s = getConnectedSocket(network, TEST_HOST, HTTP_PORT, AF_INET)) {
// Should able to start keep alive offload when socket is idle.
final Executor executor = mContext.getMainExecutor();
@@ -1102,7 +1112,7 @@
// sockets will be duplicated and kept valid in service side if the keepalives are
// successfully started.
try (Socket tcpSocket = getConnectedSocket(network, TEST_HOST, HTTP_PORT,
- 0 /* Unused */, AF_INET)) {
+ AF_INET)) {
return mCm.createSocketKeepalive(network, tcpSocket, executor, callback);
} catch (Exception e) {
fail("Unexpected error when creating TCP socket: " + e);
diff --git a/tests/cts/net/src/android/net/cts/MultinetworkApiTest.java b/tests/cts/net/src/android/net/cts/MultinetworkApiTest.java
index 88e86f4..766c55e 100644
--- a/tests/cts/net/src/android/net/cts/MultinetworkApiTest.java
+++ b/tests/cts/net/src/android/net/cts/MultinetworkApiTest.java
@@ -25,6 +25,7 @@
import android.net.NetworkCapabilities;
import android.net.NetworkUtils;
import android.net.cts.util.CtsNetUtils;
+import android.platform.test.annotations.AppModeFull;
import android.provider.Settings;
import android.system.ErrnoException;
import android.system.OsConstants;
@@ -73,7 +74,6 @@
@Override
protected void tearDown() throws Exception {
- restorePrivateDnsSetting();
super.tearDown();
}
@@ -214,7 +214,7 @@
} catch (IllegalArgumentException e) {}
}
- public void testResNApi() throws InterruptedException {
+ public void testResNApi() throws Exception {
final Network[] testNetworks = getTestableNetworks();
for (Network network : testNetworks) {
@@ -232,16 +232,24 @@
runResNnxDomainCheck(network.getNetworkHandle());
}
}
+ }
+
+ @AppModeFull(reason = "WRITE_SECURE_SETTINGS permission can't be granted to instant apps")
+ public void testResNApiNXDomainPrivateDns() throws InterruptedException {
// Enable private DNS strict mode and set server to dns.google before doing NxDomain test.
// b/144521720
- Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_MODE, "hostname");
- Settings.Global.putString(mCR,
- Settings.Global.PRIVATE_DNS_SPECIFIER, GOOGLE_PRIVATE_DNS_SERVER);
- for (Network network : testNetworks) {
- // Wait for private DNS setting to propagate.
- mCtsNetUtils.awaitPrivateDnsSetting("NxDomain test wait private DNS setting timeout",
- network, GOOGLE_PRIVATE_DNS_SERVER, PRIVATE_DNS_SETTING_TIMEOUT_MS);
- runResNnxDomainCheck(network.getNetworkHandle());
+ try {
+ Settings.Global.putString(mCR, Settings.Global.PRIVATE_DNS_MODE, "hostname");
+ Settings.Global.putString(mCR,
+ Settings.Global.PRIVATE_DNS_SPECIFIER, GOOGLE_PRIVATE_DNS_SERVER);
+ for (Network network : getTestableNetworks()) {
+ // Wait for private DNS setting to propagate.
+ mCtsNetUtils.awaitPrivateDnsSetting("NxDomain test wait private DNS setting timeout",
+ network, GOOGLE_PRIVATE_DNS_SERVER, PRIVATE_DNS_SETTING_TIMEOUT_MS);
+ runResNnxDomainCheck(network.getNetworkHandle());
+ }
+ } finally {
+ restorePrivateDnsSetting();
}
}
}
diff --git a/tests/cts/net/src/android/net/cts/NetworkWatchlistTest.java b/tests/cts/net/src/android/net/cts/NetworkWatchlistTest.java
index e4e350c..81a9e30 100644
--- a/tests/cts/net/src/android/net/cts/NetworkWatchlistTest.java
+++ b/tests/cts/net/src/android/net/cts/NetworkWatchlistTest.java
@@ -19,6 +19,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assume.assumeTrue;
import android.content.Context;
@@ -72,6 +73,7 @@
setWatchlistConfig(TEST_EMPTY_WATCHLIST_XML);
// Verify test watchlist config is not set before testing
byte[] result = mConnectivityManager.getNetworkWatchlistConfigHash();
+ assertNotNull("Watchlist config does not exist", result);
assertNotEquals(TEST_WATCHLIST_CONFIG_HASH, byteArrayToHexString(result));
}
diff --git a/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java b/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
index 01ac3fd..cbe54f8 100644
--- a/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
+++ b/tests/cts/net/src/android/net/cts/SSLCertificateSocketFactoryTest.java
@@ -16,135 +16,333 @@
package android.net.cts;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Socket;
-
-import javax.net.SocketFactory;
-import javax.net.ssl.SSLPeerUnverifiedException;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.net.SSLCertificateSocketFactory;
import android.platform.test.annotations.AppModeFull;
-import android.test.AndroidTestCase;
-
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
import libcore.javax.net.ssl.SSLConfigurationAsserts;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
-public class SSLCertificateSocketFactoryTest extends AndroidTestCase {
- private SSLCertificateSocketFactory mFactory;
- private int mTimeout;
+@RunWith(JUnit4.class)
+public class SSLCertificateSocketFactoryTest {
+ // TEST_HOST should point to a web server with a valid TLS certificate.
+ private static final String TEST_HOST = "www.google.com";
+ private static final int HTTPS_PORT = 443;
+ private HostnameVerifier mDefaultVerifier;
+ private SSLCertificateSocketFactory mSocketFactory;
+ private InetAddress mLocalAddress;
+ // InetAddress obtained by resolving TEST_HOST.
+ private InetAddress mTestHostAddress;
+ // SocketAddress combining mTestHostAddress and HTTPS_PORT.
+ private List<SocketAddress> mTestSocketAddresses;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mTimeout = 1000;
- mFactory = (SSLCertificateSocketFactory) SSLCertificateSocketFactory.getDefault(mTimeout);
+ @Before
+ public void setUp() {
+ // Expected state before each test method is that
+ // HttpsURLConnection.getDefaultHostnameVerifier() will return the system default.
+ mDefaultVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
+ mSocketFactory = (SSLCertificateSocketFactory)
+ SSLCertificateSocketFactory.getDefault(1000 /* handshakeTimeoutMillis */);
+ assertNotNull(mSocketFactory);
+ InetAddress[] addresses;
+ try {
+ addresses = InetAddress.getAllByName(TEST_HOST);
+ mTestHostAddress = addresses[0];
+ } catch (UnknownHostException uhe) {
+ throw new AssertionError(
+ "Unable to test SSLCertificateSocketFactory: cannot resolve " + TEST_HOST, uhe);
+ }
+
+ mTestSocketAddresses = Arrays.stream(addresses)
+ .map(addr -> new InetSocketAddress(addr, HTTPS_PORT))
+ .collect(Collectors.toList());
+
+ // Find the local IP address which will be used to connect to TEST_HOST.
+ try {
+ Socket testSocket = new Socket(TEST_HOST, HTTPS_PORT);
+ mLocalAddress = testSocket.getLocalAddress();
+ testSocket.close();
+ } catch (IOException ioe) {
+ throw new AssertionError(""
+ + "Unable to test SSLCertificateSocketFactory: cannot connect to "
+ + TEST_HOST, ioe);
+ }
}
+ // Restore the system default hostname verifier after each test.
+ @After
+ public void restoreDefaultHostnameVerifier() {
+ HttpsURLConnection.setDefaultHostnameVerifier(mDefaultVerifier);
+ }
+
+ @Test
public void testDefaultConfiguration() throws Exception {
- SSLConfigurationAsserts.assertSSLSocketFactoryDefaultConfiguration(mFactory);
+ SSLConfigurationAsserts.assertSSLSocketFactoryDefaultConfiguration(mSocketFactory);
}
- public void testAccessProperties() throws Exception {
- mFactory.getSupportedCipherSuites();
- mFactory.getDefaultCipherSuites();
- SocketFactory sf = SSLCertificateSocketFactory.getDefault(mTimeout);
- assertNotNull(sf);
+ @Test
+ public void testAccessProperties() {
+ mSocketFactory.getSupportedCipherSuites();
+ mSocketFactory.getDefaultCipherSuites();
}
- public void testCreateSocket() throws Exception {
- new SSLCertificateSocketFactory(100);
- int port = 443;
- String host = "www.google.com";
- InetAddress inetAddress = null;
- inetAddress = InetAddress.getLocalHost();
+ /**
+ * Tests the {@code createSocket()} cases which are expected to fail with {@code IOException}.
+ */
+ @Test
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
+ public void createSocket_io_error_expected() {
+ // Connect to the localhost HTTPS port. Should result in connection refused IOException
+ // because no service should be listening on that port.
+ InetAddress localhostAddress = InetAddress.getLoopbackAddress();
try {
- mFactory.createSocket(inetAddress, port);
- fail("should throw exception!");
+ mSocketFactory.createSocket(localhostAddress, HTTPS_PORT);
+ fail();
} catch (IOException e) {
// expected
}
+ // Same, but also binding to a local address.
try {
- InetAddress inetAddress1 = InetAddress.getLocalHost();
- InetAddress inetAddress2 = InetAddress.getLocalHost();
- mFactory.createSocket(inetAddress1, port, inetAddress2, port);
- fail("should throw exception!");
+ mSocketFactory.createSocket(localhostAddress, HTTPS_PORT, localhostAddress, 0);
+ fail();
} catch (IOException e) {
// expected
}
+ // Same, wrapping an existing plain socket which is in an unconnected state.
try {
Socket socket = new Socket();
- mFactory.createSocket(socket, host, port, true);
- fail("should throw exception!");
+ mSocketFactory.createSocket(socket, "localhost", HTTPS_PORT, true);
+ fail();
} catch (IOException e) {
// expected
}
- Socket socket = null;
- socket = mFactory.createSocket(host, port);
+ }
+
+ /**
+ * Tests hostname verification for
+ * {@link SSLCertificateSocketFactory#createSocket(String, int)}.
+ *
+ * <p>This method should return a socket which is fully connected (i.e. TLS handshake complete)
+ * and whose peer TLS certificate has been verified to have the correct hostname.
+ *
+ * <p>{@link SSLCertificateSocketFactory} is documented to verify hostnames using
+ * the {@link HostnameVerifier} returned by
+ * {@link HttpsURLConnection#getDefaultHostnameVerifier}, so this test connects twice,
+ * once with the system default {@link HostnameVerifier} which is expected to succeed,
+ * and once after installing a {@link NegativeHostnameVerifier} which will cause
+ * {@link SSLCertificateSocketFactory#verifyHostname} to throw a
+ * {@link SSLPeerUnverifiedException}.
+ *
+ * <p>These tests only test the hostname verification logic in SSLCertificateSocketFactory,
+ * other TLS failure modes and the default HostnameVerifier are tested elsewhere, see
+ * {@link com.squareup.okhttp.internal.tls.HostnameVerifierTest} and
+ * https://android.googlesource.com/platform/external/boringssl/+/refs/heads/master/src/ssl/test
+ *
+ * <p>Tests the following behaviour:-
+ * <ul>
+ * <li>TEST_SERVER is available and has a valid TLS certificate
+ * <li>{@code createSocket()} verifies the remote hostname is correct using
+ * {@link HttpsURLConnection#getDefaultHostnameVerifier}
+ * <li>{@link SSLPeerUnverifiedException} is thrown when the remote hostname is invalid
+ * </ul>
+ *
+ * <p>See also http://b/2807618.
+ */
+ @Test
+ public void createSocket_simple_with_hostname_verification() throws Exception {
+ Socket socket = mSocketFactory.createSocket(TEST_HOST, HTTPS_PORT);
+ assertConnectedSocket(socket);
+ socket.close();
+
+ HttpsURLConnection.setDefaultHostnameVerifier(new NegativeHostnameVerifier());
+ try {
+ mSocketFactory.createSocket(TEST_HOST, HTTPS_PORT);
+ fail();
+ } catch (SSLPeerUnverifiedException expected) {
+ // expected
+ }
+ }
+
+ /**
+ * Tests hostname verification for
+ * {@link SSLCertificateSocketFactory#createSocket(Socket, String, int, boolean)}.
+ *
+ * <p>This method should return a socket which is fully connected (i.e. TLS handshake complete)
+ * and whose peer TLS certificate has been verified to have the correct hostname.
+ *
+ * <p>The TLS socket returned is wrapped around the plain socket passed into
+ * {@code createSocket()}.
+ *
+ * <p>See {@link #createSocket_simple_with_hostname_verification()} for test methodology.
+ */
+ @Test
+ public void createSocket_wrapped_with_hostname_verification() throws Exception {
+ Socket underlying = new Socket(TEST_HOST, HTTPS_PORT);
+ Socket socket = mSocketFactory.createSocket(underlying, TEST_HOST, HTTPS_PORT, true);
+ assertConnectedSocket(socket);
+ socket.close();
+
+ HttpsURLConnection.setDefaultHostnameVerifier(new NegativeHostnameVerifier());
+ try {
+ underlying = new Socket(TEST_HOST, HTTPS_PORT);
+ mSocketFactory.createSocket(underlying, TEST_HOST, HTTPS_PORT, true);
+ fail();
+ } catch (SSLPeerUnverifiedException expected) {
+ // expected
+ }
+ }
+
+ /**
+ * Tests hostname verification for
+ * {@link SSLCertificateSocketFactory#createSocket(String, int, InetAddress, int)}.
+ *
+ * <p>This method should return a socket which is fully connected (i.e. TLS handshake complete)
+ * and whose peer TLS certificate has been verified to have the correct hostname.
+ *
+ * <p>The TLS socket returned is also bound to the local address determined in {@link #setUp} to
+ * be used for connections to TEST_HOST, and a wildcard port.
+ *
+ * <p>See {@link #createSocket_simple_with_hostname_verification()} for test methodology.
+ */
+ @Test
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
+ public void createSocket_bound_with_hostname_verification() throws Exception {
+ Socket socket = mSocketFactory.createSocket(TEST_HOST, HTTPS_PORT, mLocalAddress, 0);
+ assertConnectedSocket(socket);
+ socket.close();
+
+ HttpsURLConnection.setDefaultHostnameVerifier(new NegativeHostnameVerifier());
+ try {
+ mSocketFactory.createSocket(TEST_HOST, HTTPS_PORT, mLocalAddress, 0);
+ fail();
+ } catch (SSLPeerUnverifiedException expected) {
+ // expected
+ }
+ }
+
+ /**
+ * Tests hostname verification for
+ * {@link SSLCertificateSocketFactory#createSocket(InetAddress, int)}.
+ *
+ * <p>This method should return a socket which the documentation describes as "unconnected",
+ * which actually means that the socket is fully connected at the TCP layer but TLS handshaking
+ * and hostname verification have not yet taken place.
+ *
+ * <p>Behaviour is tested by installing a {@link NegativeHostnameVerifier} and by calling
+ * {@link #assertConnectedSocket} to ensure TLS handshaking but no hostname verification takes
+ * place. Next, {@link SSLCertificateSocketFactory#verifyHostname} is called to ensure
+ * that hostname verification is using the {@link HostnameVerifier} returned by
+ * {@link HttpsURLConnection#getDefaultHostnameVerifier} as documented.
+ *
+ * <p>Tests the following behaviour:-
+ * <ul>
+ * <li>TEST_SERVER is available and has a valid TLS certificate
+ * <li>{@code createSocket()} does not verify the remote hostname
+ * <li>Calling {@link SSLCertificateSocketFactory#verifyHostname} on the returned socket
+ * throws {@link SSLPeerUnverifiedException} if the remote hostname is invalid
+ * </ul>
+ */
+ @Test
+ public void createSocket_simple_no_hostname_verification() throws Exception{
+ HttpsURLConnection.setDefaultHostnameVerifier(new NegativeHostnameVerifier());
+ Socket socket = mSocketFactory.createSocket(mTestHostAddress, HTTPS_PORT);
+ // Need to provide the expected hostname here or the TLS handshake will
+ // be unable to supply SNI to the remote host.
+ mSocketFactory.setHostname(socket, TEST_HOST);
+ assertConnectedSocket(socket);
+ try {
+ SSLCertificateSocketFactory.verifyHostname(socket, TEST_HOST);
+ fail();
+ } catch (SSLPeerUnverifiedException expected) {
+ // expected
+ }
+ HttpsURLConnection.setDefaultHostnameVerifier(mDefaultVerifier);
+ SSLCertificateSocketFactory.verifyHostname(socket, TEST_HOST);
+ socket.close();
+ }
+
+ /**
+ * Tests hostname verification for
+ * {@link SSLCertificateSocketFactory#createSocket(InetAddress, int, InetAddress, int)}.
+ *
+ * <p>This method should return a socket which the documentation describes as "unconnected",
+ * which actually means that the socket is fully connected at the TCP layer but TLS handshaking
+ * and hostname verification have not yet taken place.
+ *
+ * <p>The TLS socket returned is also bound to the local address determined in {@link #setUp} to
+ * be used for connections to TEST_HOST, and a wildcard port.
+ *
+ * <p>See {@link #createSocket_simple_no_hostname_verification()} for test methodology.
+ */
+ @Test
+ @AppModeFull(reason = "Socket cannot bind in instant app mode")
+ public void createSocket_bound_no_hostname_verification() throws Exception{
+ HttpsURLConnection.setDefaultHostnameVerifier(new NegativeHostnameVerifier());
+ Socket socket =
+ mSocketFactory.createSocket(mTestHostAddress, HTTPS_PORT, mLocalAddress, 0);
+ // Need to provide the expected hostname here or the TLS handshake will
+ // be unable to supply SNI to the peer.
+ mSocketFactory.setHostname(socket, TEST_HOST);
+ assertConnectedSocket(socket);
+ try {
+ SSLCertificateSocketFactory.verifyHostname(socket, TEST_HOST);
+ fail();
+ } catch (SSLPeerUnverifiedException expected) {
+ // expected
+ }
+ HttpsURLConnection.setDefaultHostnameVerifier(mDefaultVerifier);
+ SSLCertificateSocketFactory.verifyHostname(socket, TEST_HOST);
+ socket.close();
+ }
+
+ /**
+ * Asserts a socket is fully connected to the expected peer.
+ *
+ * <p>For the variants of createSocket which verify the remote hostname,
+ * {@code socket} should already be fully connected.
+ *
+ * <p>For the non-verifying variants, retrieving the input stream will trigger a TLS handshake
+ * and so may throw an exception, for example if the peer's certificate is invalid.
+ *
+ * <p>Does no hostname verification.
+ */
+ private void assertConnectedSocket(Socket socket) throws Exception {
assertNotNull(socket);
- assertNotNull(socket.getOutputStream());
+ assertTrue(socket.isConnected());
assertNotNull(socket.getInputStream());
-
- // it throw exception when calling createSocket(String, int, InetAddress, int)
- // The socket level is invalid.
- }
-
- // a host and port that are expected to be available but have
- // a cert with a different CN, in this case CN=mail.google.com
- private static String TEST_CREATE_SOCKET_HOST = "www3.l.google.com";
- private static int TEST_CREATE_SOCKET_PORT = 443;
-
- /**
- * b/2807618 Make sure that hostname verifcation in cases were it
- * is documented to be included by various
- * SSLCertificateSocketFactory.createSocket messages.
- *
- * NOTE: Test will fail if external server is not available.
- */
- @AppModeFull(reason = "Socket cannot bind in instant app mode")
- public void test_createSocket_simple() throws Exception {
- try {
- mFactory.createSocket(TEST_CREATE_SOCKET_HOST, TEST_CREATE_SOCKET_PORT);
- fail();
- } catch (SSLPeerUnverifiedException expected) {
- // expected
- }
+ assertNotNull(socket.getOutputStream());
+ assertTrue(mTestSocketAddresses.contains(socket.getRemoteSocketAddress()));
}
/**
- * b/2807618 Make sure that hostname verifcation in cases were it
- * is documented to be included by various
- * SSLCertificateSocketFactory.createSocket messages.
- *
- * NOTE: Test will fail if external server is not available.
+ * A HostnameVerifier which always returns false to simulate a server returning a
+ * certificate which does not match the expected hostname.
*/
- @AppModeFull(reason = "Socket cannot bind in instant app mode")
- public void test_createSocket_wrapping() throws Exception {
- try {
- Socket underlying = new Socket(TEST_CREATE_SOCKET_HOST, TEST_CREATE_SOCKET_PORT);
- mFactory.createSocket(
- underlying, TEST_CREATE_SOCKET_HOST, TEST_CREATE_SOCKET_PORT, true);
- fail();
- } catch (SSLPeerUnverifiedException expected) {
- // expected
- }
- }
-
- /**
- * b/2807618 Make sure that hostname verifcation in cases were it
- * is documented to be included by various
- * SSLCertificateSocketFactory.createSocket messages.
- *
- * NOTE: Test will fail if external server is not available.
- */
- @AppModeFull(reason = "Socket cannot bind in instant app mode")
- public void test_createSocket_bind() throws Exception {
- try {
- mFactory.createSocket(TEST_CREATE_SOCKET_HOST, TEST_CREATE_SOCKET_PORT, null, 0);
- fail();
- } catch (SSLPeerUnverifiedException expected) {
- // expected
+ private static class NegativeHostnameVerifier implements HostnameVerifier {
+ @Override
+ public boolean verify(String hostname, SSLSession sslSession) {
+ return false;
}
}
}
diff --git a/tests/cts/net/src/android/net/rtp/cts/AudioGroupTest.java b/tests/cts/net/src/android/net/rtp/cts/AudioGroupTest.java
index 1bd7fad..fee8621 100644
--- a/tests/cts/net/src/android/net/rtp/cts/AudioGroupTest.java
+++ b/tests/cts/net/src/android/net/rtp/cts/AudioGroupTest.java
@@ -62,7 +62,7 @@
mSocketB.connect(mStreamB.getLocalAddress(), mStreamB.getLocalPort());
mStreamB.associate(mSocketB.getLocalAddress(), mSocketB.getLocalPort());
- mGroup = new AudioGroup();
+ mGroup = new AudioGroup(mContext);
}
@Override
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 0ef5cd9..3e47764 100644
--- a/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/cts/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -921,9 +921,9 @@
.distinct()
.collect(Collectors.toList());
- if (uniquePackageNames.size() > 1) {
- fail("The NETWORK_CARRIER_PROVISIONING permission must not be held by more than one "
- + "application, but is held by " + uniquePackageNames.size() + " applications: "
+ if (uniquePackageNames.size() > 2) {
+ fail("The NETWORK_CARRIER_PROVISIONING permission must not be held by more than two "
+ + "applications, but is held by " + uniquePackageNames.size() + " applications: "
+ String.join(", ", uniquePackageNames));
}
}