DO NOT MERGE - Merge pie-platform-release (PPRL.181205.001) into master
Bug: 120502534
Change-Id: I9857d44f5eeabf6c1ed6b4d872a1bdf22e351a6c
diff --git a/tests/cts/hostside/app/Android.mk b/tests/cts/hostside/app/Android.mk
index c03e70b..62e0172 100644
--- a/tests/cts/hostside/app/Android.mk
+++ b/tests/cts/hostside/app/Android.mk
@@ -19,7 +19,8 @@
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
+#LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util ctstestrunner ub-uiautomator \
CtsHostsideNetworkTestsAidl
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 bc982ce..48f0afb 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
@@ -16,6 +16,7 @@
package com.android.cts.net.hostside;
+import static android.os.Process.INVALID_UID;
import static android.system.OsConstants.*;
import android.content.Intent;
@@ -29,6 +30,7 @@
import android.net.VpnService;
import android.os.ParcelFileDescriptor;
import android.os.Process;
+import android.os.SystemProperties;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
@@ -36,6 +38,7 @@
import android.support.test.uiautomator.UiSelector;
import android.system.ErrnoException;
import android.system.Os;
+import android.system.OsConstants;
import android.system.StructPollfd;
import android.test.InstrumentationTestCase;
import android.test.MoreAsserts;
@@ -353,7 +356,7 @@
MoreAsserts.assertEquals(data, read);
}
- private static void checkTcpReflection(String to, String expectedFrom) throws IOException {
+ private void checkTcpReflection(String to, String expectedFrom) throws IOException {
// Exercise TCP over the VPN by "connecting to ourselves". We open a server socket and a
// client socket, and connect the client socket to a remote host, with the port of the
// server socket. The PacketReflector reflects the packets, changing the source addresses
@@ -391,7 +394,8 @@
// Accept the connection on the server side.
listen.setSoTimeout(SOCKET_TIMEOUT_MS);
server = listen.accept();
-
+ checkConnectionOwnerUidTcp(client);
+ checkConnectionOwnerUidTcp(server);
// Check that the source and peer addresses are as expected.
assertEquals(expectedFrom, client.getLocalAddress().getHostAddress());
assertEquals(expectedFrom, server.getLocalAddress().getHostAddress());
@@ -424,7 +428,23 @@
}
}
- private static void checkUdpEcho(String to, String expectedFrom) throws IOException {
+ private void checkConnectionOwnerUidUdp(DatagramSocket s, boolean expectSuccess) {
+ final int expectedUid = expectSuccess ? Process.myUid() : INVALID_UID;
+ InetSocketAddress loc = new InetSocketAddress(s.getLocalAddress(), s.getLocalPort());
+ InetSocketAddress rem = new InetSocketAddress(s.getInetAddress(), s.getPort());
+ int uid = mCM.getConnectionOwnerUid(OsConstants.IPPROTO_UDP, loc, rem);
+ assertEquals(expectedUid, uid);
+ }
+
+ private void checkConnectionOwnerUidTcp(Socket s) {
+ final int expectedUid = Process.myUid();
+ InetSocketAddress loc = new InetSocketAddress(s.getLocalAddress(), s.getLocalPort());
+ InetSocketAddress rem = new InetSocketAddress(s.getInetAddress(), s.getPort());
+ int uid = mCM.getConnectionOwnerUid(OsConstants.IPPROTO_TCP, loc, rem);
+ assertEquals(expectedUid, uid);
+ }
+
+ private void checkUdpEcho(String to, String expectedFrom) throws IOException {
DatagramSocket s;
InetAddress address = InetAddress.getByName(to);
if (address instanceof Inet6Address) { // http://b/18094870
@@ -448,6 +468,7 @@
try {
if (expectedFrom != null) {
s.send(p);
+ checkConnectionOwnerUidUdp(s, true);
s.receive(p);
MoreAsserts.assertEquals(data, p.getData());
} else {
@@ -455,7 +476,9 @@
s.send(p);
s.receive(p);
fail("Received unexpected reply");
- } catch(IOException expected) {}
+ } catch (IOException expected) {
+ checkConnectionOwnerUidUdp(s, false);
+ }
}
} finally {
s.close();
@@ -537,6 +560,14 @@
public void testDefault() throws Exception {
if (!supportedHardware()) return;
+ // If adb TCP port opened, this test may running by adb over network.
+ // All of socket would be destroyed in this test. So this test don't
+ // support adb over network, see b/119382723.
+ if (SystemProperties.getInt("persist.adb.tcp.port", -1) > -1
+ || SystemProperties.getInt("service.adb.tcp.port", -1) > -1) {
+ Log.i(TAG, "adb is running over the network, so skip this test");
+ return;
+ }
FileDescriptor fd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
@@ -554,6 +585,7 @@
FileDescriptor fd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
+ // Shell app must not be put in here or it would kill the ADB-over-network use case
String allowedApps = mRemoteSocketFactoryClient.getPackageName() + "," + mPackageName;
startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
new String[] {"192.0.2.0/24", "2001:db8::/32"},
@@ -571,6 +603,12 @@
FileDescriptor remoteFd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
String disallowedApps = mRemoteSocketFactoryClient.getPackageName() + "," + mPackageName;
+ // If adb TCP port opened, this test may running by adb over TCP.
+ // Add com.android.shell appllication into blacklist to exclude adb socket for VPN test,
+ // see b/119382723.
+ // Note: The test don't support running adb over network for root device
+ disallowedApps = disallowedApps + ",com.android.shell";
+ Log.i(TAG, "Append shell app to disallowedApps: " + disallowedApps);
startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
new String[] {"192.0.2.0/24", "2001:db8::/32"},
"", disallowedApps);
@@ -580,4 +618,23 @@
checkNoTrafficOnVpn();
}
+
+ public void testGetConnectionOwnerUidSecurity() throws Exception {
+
+ if (!supportedHardware()) return;
+
+ DatagramSocket s;
+ InetAddress address = InetAddress.getByName("localhost");
+ s = new DatagramSocket();
+ s.setSoTimeout(SOCKET_TIMEOUT_MS);
+ s.connect(address, 7);
+ InetSocketAddress loc = new InetSocketAddress(s.getLocalAddress(), s.getLocalPort());
+ InetSocketAddress rem = new InetSocketAddress(s.getInetAddress(), s.getPort());
+ try {
+ int uid = mCM.getConnectionOwnerUid(OsConstants.IPPROTO_TCP, loc, rem);
+ fail("Only an active VPN app may call this API.");
+ } catch (SecurityException expected) {
+ return;
+ }
+ }
}
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 69b07af..853668c 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
@@ -44,4 +44,8 @@
public void testAppDisallowed() throws Exception {
runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testAppDisallowed");
}
+
+ public void testGetConnectionOwnerUidSecurity() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testGetConnectionOwnerUidSecurity");
+ }
}
diff --git a/tests/cts/hostside/src/com/android/cts/net/ProcNetTest.java b/tests/cts/hostside/src/com/android/cts/net/ProcNetTest.java
new file mode 100644
index 0000000..19e61c6
--- /dev/null
+++ b/tests/cts/hostside/src/com/android/cts/net/ProcNetTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2018 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.security.cts;
+
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IDeviceTest;
+
+import java.lang.Integer;
+import java.lang.String;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Host-side tests for values in /proc/net.
+ *
+ * These tests analyze /proc/net to verify that certain networking properties are correct.
+ */
+public class ProcNetTest extends DeviceTestCase implements IBuildReceiver, IDeviceTest {
+ private static final String SPI_TIMEOUT_SYSCTL = "/proc/sys/net/core/xfrm_acq_expires";
+ private static final int MIN_ACQ_EXPIRES = 3600;
+ // Global sysctls. Must be present and set to 1.
+ private static final String[] GLOBAL_SYSCTLS = {
+ "/proc/sys/net/ipv4/fwmark_reflect",
+ "/proc/sys/net/ipv6/fwmark_reflect",
+ "/proc/sys/net/ipv4/tcp_fwmark_accept",
+ };
+
+ // Per-interface IPv6 autoconf sysctls.
+ private static final String IPV6_SYSCTL_DIR = "/proc/sys/net/ipv6/conf";
+ private static final String AUTOCONF_SYSCTL = "accept_ra_rt_table";
+
+ // Expected values for MIN|MAX_PLEN.
+ private static final String ACCEPT_RA_RT_INFO_MIN_PLEN_STRING = "accept_ra_rt_info_min_plen";
+ private static final int ACCEPT_RA_RT_INFO_MIN_PLEN_VALUE = 48;
+ private static final String ACCEPT_RA_RT_INFO_MAX_PLEN_STRING = "accept_ra_rt_info_max_plen";
+ private static final int ACCEPT_RA_RT_INFO_MAX_PLEN_VALUE = 64;
+ // Expected values for RFC 7559 router soliciations.
+ // Maximum number of router solicitations to send. -1 means no limit.
+ private static final int IPV6_WIFI_ROUTER_SOLICITATIONS = -1;
+ private ITestDevice mDevice;
+ private IBuildInfo mBuild;
+ private String[] mSysctlDirs;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setBuild(IBuildInfo build) {
+ mBuild = build;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setDevice(ITestDevice device) {
+ super.setDevice(device);
+ mDevice = device;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mSysctlDirs = getSysctlDirs();
+ }
+
+ private String[] getSysctlDirs() throws Exception {
+ String interfaceDirs[] = mDevice.executeAdbCommand("shell", "ls", "-1",
+ IPV6_SYSCTL_DIR).split("\n");
+ List<String> interfaceDirsList = new ArrayList<String>(Arrays.asList(interfaceDirs));
+ interfaceDirsList.remove("all");
+ interfaceDirsList.remove("lo");
+ return interfaceDirsList.toArray(new String[interfaceDirsList.size()]);
+ }
+
+
+ protected void assertLess(String sysctl, int a, int b) {
+ assertTrue("value of " + sysctl + ": expected < " + b + " but was: " + a, a < b);
+ }
+
+ protected void assertAtLeast(String sysctl, int a, int b) {
+ assertTrue("value of " + sysctl + ": expected >= " + b + " but was: " + a, a >= b);
+ }
+
+ public int readIntFromPath(String path) throws Exception {
+ String mode = mDevice.executeAdbCommand("shell", "stat", "-c", "%a", path).trim();
+ String user = mDevice.executeAdbCommand("shell", "stat", "-c", "%u", path).trim();
+ String group = mDevice.executeAdbCommand("shell", "stat", "-c", "%g", path).trim();
+ assertEquals(mode, "644");
+ assertEquals(user, "0");
+ assertEquals(group, "0");
+ return Integer.parseInt(mDevice.executeAdbCommand("shell", "cat", path).trim());
+ }
+
+ /**
+ * Checks that SPI default timeouts are overridden, and set to a reasonable length of time
+ */
+ public void testMinAcqExpires() throws Exception {
+ int value = readIntFromPath(SPI_TIMEOUT_SYSCTL);
+ assertAtLeast(SPI_TIMEOUT_SYSCTL, value, MIN_ACQ_EXPIRES);
+ }
+
+ /**
+ * Checks that the sysctls for multinetwork kernel features are present and
+ * enabled.
+ */
+ public void testProcSysctls() throws Exception {
+ for (String sysctl : GLOBAL_SYSCTLS) {
+ int value = readIntFromPath(sysctl);
+ assertEquals(sysctl, 1, value);
+ }
+
+ for (String interfaceDir : mSysctlDirs) {
+ String path = IPV6_SYSCTL_DIR + "/" + interfaceDir + "/" + AUTOCONF_SYSCTL;
+ int value = readIntFromPath(path);
+ assertLess(path, value, 0);
+ }
+ }
+
+ /**
+ * Verify that accept_ra_rt_info_{min,max}_plen exists and is set to the expected value
+ */
+ public void testAcceptRaRtInfoMinMaxPlen() throws Exception {
+ for (String interfaceDir : mSysctlDirs) {
+ String path = IPV6_SYSCTL_DIR + "/" + interfaceDir + "/" + "accept_ra_rt_info_min_plen";
+ int value = readIntFromPath(path);
+ assertEquals(path, value, ACCEPT_RA_RT_INFO_MIN_PLEN_VALUE);
+ path = IPV6_SYSCTL_DIR + "/" + interfaceDir + "/" + "accept_ra_rt_info_max_plen";
+ value = readIntFromPath(path);
+ assertEquals(path, value, ACCEPT_RA_RT_INFO_MAX_PLEN_VALUE);
+ }
+ }
+
+ /**
+ * Verify that router_solicitations exists and is set to the expected value
+ * and verify that router_solicitation_max_interval exists and is in an acceptable interval.
+ */
+ public void testRouterSolicitations() throws Exception {
+ for (String interfaceDir : mSysctlDirs) {
+ String path = IPV6_SYSCTL_DIR + "/" + interfaceDir + "/" + "router_solicitations";
+ int value = readIntFromPath(path);
+ assertEquals(IPV6_WIFI_ROUTER_SOLICITATIONS, value);
+ path = IPV6_SYSCTL_DIR + "/" + interfaceDir + "/" + "router_solicitation_max_interval";
+ int interval = readIntFromPath(path);
+ final int lowerBoundSec = 15 * 60;
+ final int upperBoundSec = 60 * 60;
+ assertTrue(lowerBoundSec <= interval);
+ assertTrue(interval <= upperBoundSec);
+ }
+ }
+}
diff --git a/tests/cts/net/Android.mk b/tests/cts/net/Android.mk
index 1430071..6967adb 100644
--- a/tests/cts/net/Android.mk
+++ b/tests/cts/net/Android.mk
@@ -26,7 +26,6 @@
LOCAL_JAVA_LIBRARIES := \
voip-common \
- conscrypt \
org.apache.http.legacy \
android.test.base.stubs \
diff --git a/tests/cts/net/native/qtaguid/src/NativeQtaguidTest.cpp b/tests/cts/net/native/qtaguid/src/NativeQtaguidTest.cpp
index 1892a44..7dc6240 100644
--- a/tests/cts/net/native/qtaguid/src/NativeQtaguidTest.cpp
+++ b/tests/cts/net/native/qtaguid/src/NativeQtaguidTest.cpp
@@ -18,36 +18,29 @@
#include <error.h>
#include <errno.h>
#include <inttypes.h>
+#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
-#include <sys/utsname.h>
#include <gtest/gtest.h>
#include <qtaguid/qtaguid.h>
-int hasQtaguidKernelSupport() {
- struct utsname buf;
- int kernel_version_major;
- int kernel_version_minor;
-
- int ret = uname(&buf);
- if (ret) {
- ret = -errno;
- return ret;
- }
- char dummy;
- ret = sscanf(buf.release, "%d.%d%c", &kernel_version_major, &kernel_version_minor, &dummy);
- if (ret < 3)
- return -EINVAL;
-
- if ((kernel_version_major == 4 && kernel_version_minor < 9) ||
- (kernel_version_major < 4)) {
- return 1;
- } else {
- return access("/proc/net/xt_qtaguid/ctrl", F_OK) != -1;
- }
+int canAccessQtaguidFile() {
+ int fd = open("/proc/net/xt_qtaguid/ctrl", O_RDONLY | O_CLOEXEC);
+ close(fd);
+ return fd != -1;
}
+#define SKIP_IF_QTAGUID_NOT_SUPPORTED() \
+ do { \
+ int res = canAccessQtaguidFile(); \
+ ASSERT_LE(0, res); \
+ if (!res) { \
+ GTEST_LOG_(INFO) << "This test is skipped since kernel may not have the module\n"; \
+ return; \
+ } \
+ } while (0)
+
int getCtrlSkInfo(int tag, uid_t uid, uint64_t* sk_addr, int* ref_cnt) {
FILE *fp;
fp = fopen("/proc/net/xt_qtaguid/ctrl", "r");
@@ -95,12 +88,8 @@
}
TEST (NativeQtaguidTest, close_socket_without_untag) {
- int res = hasQtaguidKernelSupport();
- ASSERT_LE(0, res);
- if (!res) {
- GTEST_LOG_(INFO) << "This test is skipped since kernel may not have the module\n";
- return;
- }
+ SKIP_IF_QTAGUID_NOT_SUPPORTED();
+
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
uid_t uid = getuid();
int tag = arc4random();
@@ -114,12 +103,8 @@
}
TEST (NativeQtaguidTest, close_socket_without_untag_ipv6) {
- int res = hasQtaguidKernelSupport();
- ASSERT_LE(0, res);
- if (!res) {
- GTEST_LOG_(INFO) << "This test is skipped since kernel may not have the module\n";
- return;
- }
+ SKIP_IF_QTAGUID_NOT_SUPPORTED();
+
int sockfd = socket(AF_INET6, SOCK_STREAM, 0);
uid_t uid = getuid();
int tag = arc4random();
@@ -133,12 +118,8 @@
}
TEST (NativeQtaguidTest, no_socket_addr_leak) {
- int res = hasQtaguidKernelSupport();
- ASSERT_LE(0, res);
- if (!res) {
- GTEST_LOG_(INFO) << "This test is skipped since kernel may not have the module\n";
- return;
- }
+ SKIP_IF_QTAGUID_NOT_SUPPORTED();
+
checkNoSocketPointerLeaks(AF_INET);
checkNoSocketPointerLeaks(AF_INET6);
}
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 441bee3..6e4f34e 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -107,17 +107,6 @@
"Host: " + TEST_HOST + "\r\n" +
"Connection: keep-alive\r\n\r\n";
- // Base path for IPv6 sysctls
- private static final String IPV6_SYSCTL_DIR = "/proc/sys/net/ipv6/conf";
-
- // Expected values for MIN|MAX_PLEN.
- private static final int IPV6_WIFI_ACCEPT_RA_RT_INFO_MIN_PLEN = 48;
- private static final int IPV6_WIFI_ACCEPT_RA_RT_INFO_MAX_PLEN = 64;
-
- // Expected values for RFC 7559 router soliciations.
- // Maximum number of router solicitations to send. -1 means no limit.
- private static final int IPV6_WIFI_ROUTER_SOLICITATIONS = -1;
-
// Action sent to ConnectivityActionReceiver when a network callback is sent via PendingIntent.
private static final String NETWORK_CALLBACK_ACTION =
"ConnectivityManagerTest.NetworkCallbackAction";
@@ -908,60 +897,6 @@
} catch (SecurityException expected) {}
}
- private Scanner makeWifiSysctlScanner(String key) throws FileNotFoundException {
- Network network = ensureWifiConnected();
- String iface = mCm.getLinkProperties(network).getInterfaceName();
- String path = IPV6_SYSCTL_DIR + "/" + iface + "/" + key;
- return new Scanner(new File(path));
- }
-
- /** Verify that accept_ra_rt_info_min_plen exists and is set to the expected value */
- public void testAcceptRaRtInfoMinPlen() throws Exception {
- if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
- Log.i(TAG, "testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent cannot execute unless device supports WiFi");
- return;
- }
- Scanner s = makeWifiSysctlScanner("accept_ra_rt_info_min_plen");
- assertEquals(IPV6_WIFI_ACCEPT_RA_RT_INFO_MIN_PLEN, s.nextInt());
- }
-
- /** Verify that accept_ra_rt_info_max_plen exists and is set to the expected value */
- public void testAcceptRaRtInfoMaxPlen() throws Exception {
- if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
- Log.i(TAG, "testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent cannot execute unless device supports WiFi");
- return;
- }
- Scanner s = makeWifiSysctlScanner("accept_ra_rt_info_max_plen");
- assertEquals(IPV6_WIFI_ACCEPT_RA_RT_INFO_MAX_PLEN, s.nextInt());
- }
-
- /** Verify that router_solicitations exists and is set to the expected value */
- public void testRouterSolicitations() throws Exception {
- if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
- Log.i(TAG, "testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent cannot execute unless device supports WiFi");
- return;
- }
- Scanner s = makeWifiSysctlScanner("router_solicitations");
- assertEquals(IPV6_WIFI_ROUTER_SOLICITATIONS, s.nextInt());
- }
-
- /** Verify that router_solicitation_max_interval exists and is in an acceptable interval */
- public void testRouterSolicitationMaxInterval() throws Exception {
- if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)) {
- Log.i(TAG, "testConnectivityChanged_manifestRequestOnlyPreN_shouldReceiveIntent cannot execute unless device supports WiFi");
- return;
- }
- Scanner s = makeWifiSysctlScanner("router_solicitation_max_interval");
- int interval = s.nextInt();
- // Verify we're in the interval [15 minutes, 60 minutes]. Lower values may adversely
- // impact battery life and higher values can decrease the probability of detecting
- // network changes.
- final int lowerBoundSec = 15 * 60;
- final int upperBoundSec = 60 * 60;
- assertTrue(lowerBoundSec <= interval);
- assertTrue(interval <= upperBoundSec);
- }
-
// Returns "true", "false" or "none"
private String getWifiMeteredStatus(String ssid) throws Exception {
// Interestingly giving the SSID as an argument to list wifi-networks
diff --git a/tests/cts/net/src/android/net/cts/IpSecSysctlTest.java b/tests/cts/net/src/android/net/cts/IpSecSysctlTest.java
deleted file mode 100644
index b362282..0000000
--- a/tests/cts/net/src/android/net/cts/IpSecSysctlTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts;
-
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-import android.system.StructStat;
-import android.test.AndroidTestCase;
-
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.IOException;
-
-/**
- * Tests for multinetwork sysctl functionality.
- */
-public class IpSecSysctlTest extends SysctlBaseTest {
-
- // SPI expiration sysctls. Must be present and set greater than 1h.
- private static final String SPI_TIMEOUT_SYSCTL = "/proc/sys/net/core/xfrm_acq_expires";
- private static final int MIN_ACQ_EXPIRES = 3600;
-
- /**
- * Checks that SPI default timeouts are overridden, and set to a reasonable length of time
- */
- public void testProcFiles() throws ErrnoException, IOException, NumberFormatException {
- int value = getIntValue(SPI_TIMEOUT_SYSCTL);
- assertAtLeast(SPI_TIMEOUT_SYSCTL, value, MIN_ACQ_EXPIRES);
- }
-}
diff --git a/tests/cts/net/src/android/net/cts/MultinetworkSysctlTest.java b/tests/cts/net/src/android/net/cts/MultinetworkSysctlTest.java
deleted file mode 100644
index 1d0c111..0000000
--- a/tests/cts/net/src/android/net/cts/MultinetworkSysctlTest.java
+++ /dev/null
@@ -1,73 +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.
- */
-
-package android.net.cts;
-
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-import android.system.StructStat;
-import android.test.AndroidTestCase;
-
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.IOException;
-
-/**
- * Tests for multinetwork sysctl functionality.
- */
-public class MultinetworkSysctlTest extends SysctlBaseTest {
-
- // Global sysctls. Must be present and set to 1.
- private static final String[] GLOBAL_SYSCTLS = {
- "/proc/sys/net/ipv4/fwmark_reflect",
- "/proc/sys/net/ipv6/fwmark_reflect",
- "/proc/sys/net/ipv4/tcp_fwmark_accept",
- };
-
- // Per-interface IPv6 autoconf sysctls.
- private static final String IPV6_SYSCTL_DIR = "/proc/sys/net/ipv6/conf";
- private static final String AUTOCONF_SYSCTL = "accept_ra_rt_table";
-
- /**
- * Checks that the sysctls for multinetwork kernel features are present and
- * enabled. The necessary kernel commits are:
- *
- * Mainline Linux:
- * e110861 net: add a sysctl to reflect the fwmark on replies
- * 1b3c61d net: Use fwmark reflection in PMTU discovery.
- * 84f39b0 net: support marking accepting TCP sockets
- *
- * Common Android tree (e.g., 3.10):
- * a03f539 net: ipv6: autoconf routes into per-device tables
- */
- public void testProcFiles() throws ErrnoException, IOException, NumberFormatException {
- for (String sysctl : GLOBAL_SYSCTLS) {
- int value = getIntValue(sysctl);
- assertEquals(sysctl, 1, value);
- }
-
- File[] interfaceDirs = new File(IPV6_SYSCTL_DIR).listFiles();
- for (File interfaceDir : interfaceDirs) {
- if (interfaceDir.getName().equals("all") || interfaceDir.getName().equals("lo")) {
- continue;
- }
- String sysctl = new File(interfaceDir, AUTOCONF_SYSCTL).getAbsolutePath();
- int value = getIntValue(sysctl);
- assertLess(sysctl, value, 0);
- }
- }
-}
diff --git a/tests/cts/net/src/android/net/cts/SysctlBaseTest.java b/tests/cts/net/src/android/net/cts/SysctlBaseTest.java
deleted file mode 100644
index a5966d4..0000000
--- a/tests/cts/net/src/android/net/cts/SysctlBaseTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2018 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.cts;
-
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-import android.system.StructStat;
-import android.test.AndroidTestCase;
-
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.IOException;
-
-/**
- * Tests for multinetwork sysctl functionality.
- */
-public class SysctlBaseTest extends AndroidTestCase {
-
- // Expected mode, UID, and GID of sysctl files.
- private static final int SYSCTL_MODE = 0100644;
- private static final int SYSCTL_UID = 0;
- private static final int SYSCTL_GID = 0;
-
- private void checkSysctlPermissions(String fileName) throws ErrnoException {
- StructStat stat = Os.stat(fileName);
- assertEquals("mode of " + fileName + ":", SYSCTL_MODE, stat.st_mode);
- assertEquals("UID of " + fileName + ":", SYSCTL_UID, stat.st_uid);
- assertEquals("GID of " + fileName + ":", SYSCTL_GID, stat.st_gid);
- }
-
- protected void assertLess(String sysctl, int a, int b) {
- assertTrue("value of " + sysctl + ": expected < " + b + " but was: " + a, a < b);
- }
-
- protected void assertAtLeast(String sysctl, int a, int b) {
- assertTrue("value of " + sysctl + ": expected >= " + b + " but was: " + a, a >= b);
- }
-
- private String readFile(String fileName) throws ErrnoException, IOException {
- byte[] buf = new byte[1024];
- FileDescriptor fd = Os.open(fileName, 0, OsConstants.O_RDONLY);
- int bytesRead = Os.read(fd, buf, 0, buf.length);
- assertLess("length of " + fileName + ":", bytesRead, buf.length);
- return new String(buf);
- }
-
- /*
- * Checks permissions and retrieves the sysctl's value. Retrieval of value should always use
- * this method
- */
- protected int getIntValue(String filename) throws ErrnoException, IOException {
- checkSysctlPermissions(filename);
- return Integer.parseInt(readFile(filename).trim());
- }
-}
diff --git a/tests/cts/net/src/android/net/cts/UriTest.java b/tests/cts/net/src/android/net/cts/UriTest.java
index 5c54cda..5344f93 100644
--- a/tests/cts/net/src/android/net/cts/UriTest.java
+++ b/tests/cts/net/src/android/net/cts/UriTest.java
@@ -22,6 +22,7 @@
import android.test.AndroidTestCase;
import java.io.File;
import java.util.Arrays;
+import java.util.ArrayList;
public class UriTest extends AndroidTestCase {
public void testParcelling() {
@@ -73,6 +74,12 @@
assertEquals("new", b.getFragment());
assertEquals("bar", b.getSchemeSpecificPart());
assertEquals("foo", b.getScheme());
+
+ a = Uri.fromParts("scheme", "[2001:db8::dead:e1f]/foo", "bar");
+ b = a.buildUpon().fragment("qux").build();
+ assertEquals("qux", b.getFragment());
+ assertEquals("[2001:db8::dead:e1f]/foo", b.getSchemeSpecificPart());
+ assertEquals("scheme", b.getScheme());
}
public void testStringUri() {
@@ -120,6 +127,38 @@
assertEquals("a.foo.com", uri.getHost());
assertEquals(-1, uri.getPort());
assertEquals("\\.example.com/path", uri.getPath());
+
+ uri = Uri.parse("https://[2001:db8::dead:e1f]/foo");
+ assertEquals("[2001:db8::dead:e1f]", uri.getAuthority());
+ assertNull(uri.getUserInfo());
+ assertEquals("[2001:db8::dead:e1f]", uri.getHost());
+ assertEquals(-1, uri.getPort());
+ assertEquals("/foo", uri.getPath());
+ assertEquals(null, uri.getFragment());
+ assertEquals("//[2001:db8::dead:e1f]/foo", uri.getSchemeSpecificPart());
+
+ uri = Uri.parse("https://[2001:db8::dead:e1f]/#foo");
+ assertEquals("[2001:db8::dead:e1f]", uri.getAuthority());
+ assertNull(uri.getUserInfo());
+ assertEquals("[2001:db8::dead:e1f]", uri.getHost());
+ assertEquals(-1, uri.getPort());
+ assertEquals("/", uri.getPath());
+ assertEquals("foo", uri.getFragment());
+ assertEquals("//[2001:db8::dead:e1f]/", uri.getSchemeSpecificPart());
+
+ uri = Uri.parse(
+ "https://some:user@[2001:db8::dead:e1f]:1234/foo?corge=thud&corge=garp#bar");
+ assertEquals("some:user@[2001:db8::dead:e1f]:1234", uri.getAuthority());
+ assertEquals("some:user", uri.getUserInfo());
+ assertEquals("[2001:db8::dead:e1f]", uri.getHost());
+ assertEquals(1234, uri.getPort());
+ assertEquals("/foo", uri.getPath());
+ assertEquals("bar", uri.getFragment());
+ assertEquals("//some:user@[2001:db8::dead:e1f]:1234/foo?corge=thud&corge=garp",
+ uri.getSchemeSpecificPart());
+ assertEquals("corge=thud&corge=garp", uri.getQuery());
+ assertEquals("thud", uri.getQueryParameter("corge"));
+ assertEquals(Arrays.asList("thud", "garp"), uri.getQueryParameters("corge"));
}
public void testCompareTo() {
@@ -164,22 +203,62 @@
String encoded = Uri.encode("Bob:/", "/");
assertEquals(-1, encoded.indexOf(':'));
assertTrue(encoded.indexOf('/') > -1);
- assertDecode(null);
- assertDecode("");
- assertDecode("Bob");
- assertDecode(":Bob");
- assertDecode("::Bob");
- assertDecode("Bob::Lee");
- assertDecode("Bob:Lee");
- assertDecode("Bob::");
- assertDecode("Bob:");
- assertDecode("::Bob::");
+ assertEncodeDecodeRoundtripExact(null);
+ assertEncodeDecodeRoundtripExact("");
+ assertEncodeDecodeRoundtripExact("Bob");
+ assertEncodeDecodeRoundtripExact(":Bob");
+ assertEncodeDecodeRoundtripExact("::Bob");
+ assertEncodeDecodeRoundtripExact("Bob::Lee");
+ assertEncodeDecodeRoundtripExact("Bob:Lee");
+ assertEncodeDecodeRoundtripExact("Bob::");
+ assertEncodeDecodeRoundtripExact("Bob:");
+ assertEncodeDecodeRoundtripExact("::Bob::");
+ assertEncodeDecodeRoundtripExact("https:/some:user@[2001:db8::dead:e1f]:1234/foo#bar");
}
- private void assertDecode(String s) {
+ private static void assertEncodeDecodeRoundtripExact(String s) {
assertEquals(s, Uri.decode(Uri.encode(s, null)));
}
+ public void testDecode_emptyString_returnsEmptyString() {
+ assertEquals("", Uri.decode(""));
+ }
+
+ public void testDecode_null_returnsNull() {
+ assertNull(Uri.decode(null));
+ }
+
+ public void testDecode_wrongHexDigit() {
+ // %p in the end.
+ assertEquals("ab/$\u0102%\u0840\uFFFD\u0000", Uri.decode("ab%2f$%C4%82%25%e0%a1%80%p"));
+ }
+
+ public void testDecode_secondHexDigitWrong() {
+ // %1p in the end.
+ assertEquals("ab/$\u0102%\u0840\uFFFD\u0001", Uri.decode("ab%2f$%c4%82%25%e0%a1%80%1p"));
+ }
+
+ public void testDecode_endsWithPercent_appendsUnknownCharacter() {
+ // % in the end.
+ assertEquals("ab/$\u0102%\u0840\uFFFD", Uri.decode("ab%2f$%c4%82%25%e0%a1%80%"));
+ }
+
+ public void testDecode_plusNotConverted() {
+ assertEquals("ab/$\u0102%+\u0840", Uri.decode("ab%2f$%c4%82%25+%e0%a1%80"));
+ }
+
+ // Last character needs decoding (make sure we are flushing the buffer with chars to decode).
+ public void testDecode_lastCharacter() {
+ assertEquals("ab/$\u0102%\u0840", Uri.decode("ab%2f$%c4%82%25%e0%a1%80"));
+ }
+
+ // Check that a second row of encoded characters is decoded properly (internal buffers are
+ // reset properly).
+ public void testDecode_secondRowOfEncoded() {
+ assertEquals("ab/$\u0102%\u0840aa\u0840",
+ Uri.decode("ab%2f$%c4%82%25%e0%a1%80aa%e0%a1%80"));
+ }
+
public void testFromFile() {
File f = new File("/tmp/bob");
Uri uri = Uri.fromFile(f);
@@ -425,4 +504,78 @@
Uri.parse("HTTP://USER@WWW.ANDROID.COM:100/ABOUT?foo=blah@bar=bleh#c")
.normalizeScheme());
}
+
+ public void testToSafeString_tel() {
+ checkToSafeString("tel:xxxxxx", "tel:Google");
+ checkToSafeString("tel:xxxxxxxxxx", "tel:1234567890");
+ checkToSafeString("tEl:xxx.xxx-xxxx", "tEl:123.456-7890");
+ }
+
+ public void testToSafeString_sip() {
+ checkToSafeString("sip:xxxxxxx@xxxxxxx.xxxxxxxx", "sip:android@android.com:1234");
+ checkToSafeString("sIp:xxxxxxx@xxxxxxx.xxx", "sIp:android@android.com");
+ }
+
+ public void testToSafeString_sms() {
+ checkToSafeString("sms:xxxxxx", "sms:123abc");
+ checkToSafeString("smS:xxx.xxx-xxxx", "smS:123.456-7890");
+ }
+
+ public void testToSafeString_smsto() {
+ checkToSafeString("smsto:xxxxxx", "smsto:123abc");
+ checkToSafeString("SMSTo:xxx.xxx-xxxx", "SMSTo:123.456-7890");
+ }
+
+ public void testToSafeString_mailto() {
+ checkToSafeString("mailto:xxxxxxx@xxxxxxx.xxx", "mailto:android@android.com");
+ checkToSafeString("Mailto:xxxxxxx@xxxxxxx.xxxxxxxxxx",
+ "Mailto:android@android.com/secret");
+ }
+
+ public void testToSafeString_nfc() {
+ checkToSafeString("nfc:xxxxxx", "nfc:123abc");
+ checkToSafeString("nfc:xxx.xxx-xxxx", "nfc:123.456-7890");
+ checkToSafeString("nfc:xxxxxxx@xxxxxxx.xxx", "nfc:android@android.com");
+ }
+
+ public void testToSafeString_http() {
+ checkToSafeString("http://www.android.com/...", "http://www.android.com");
+ checkToSafeString("HTTP://www.android.com/...", "HTTP://www.android.com");
+ checkToSafeString("http://www.android.com/...", "http://www.android.com/");
+ checkToSafeString("http://www.android.com/...", "http://www.android.com/secretUrl?param");
+ checkToSafeString("http://www.android.com/...",
+ "http://user:pwd@www.android.com/secretUrl?param");
+ checkToSafeString("http://www.android.com/...",
+ "http://user@www.android.com/secretUrl?param");
+ checkToSafeString("http://www.android.com/...", "http://www.android.com/secretUrl?param");
+ checkToSafeString("http:///...", "http:///path?param");
+ checkToSafeString("http:///...", "http://");
+ checkToSafeString("http://:12345/...", "http://:12345/");
+ }
+
+ public void testToSafeString_https() {
+ checkToSafeString("https://www.android.com/...", "https://www.android.com/secretUrl?param");
+ checkToSafeString("https://www.android.com:8443/...",
+ "https://user:pwd@www.android.com:8443/secretUrl?param");
+ checkToSafeString("https://www.android.com/...", "https://user:pwd@www.android.com");
+ checkToSafeString("Https://www.android.com/...", "Https://user:pwd@www.android.com");
+ }
+
+ public void testToSafeString_ftp() {
+ checkToSafeString("ftp://ftp.android.com/...", "ftp://ftp.android.com/");
+ checkToSafeString("ftP://ftp.android.com/...", "ftP://anonymous@ftp.android.com/");
+ checkToSafeString("ftp://ftp.android.com:2121/...",
+ "ftp://root:love@ftp.android.com:2121/");
+ }
+
+ public void testToSafeString_notSupport() {
+ checkToSafeString("unsupported://ajkakjah/askdha/secret?secret",
+ "unsupported://ajkakjah/askdha/secret?secret");
+ checkToSafeString("unsupported:ajkakjah/askdha/secret?secret",
+ "unsupported:ajkakjah/askdha/secret?secret");
+ }
+
+ private void checkToSafeString(String expectedSafeString, String original) {
+ assertEquals(expectedSafeString, Uri.parse(original).toSafeString());
+ }
}
diff --git a/tests/cts/net/src/android/net/http/cts/SslCertificateTest.java b/tests/cts/net/src/android/net/http/cts/SslCertificateTest.java
index 70ae496..95f415c 100644
--- a/tests/cts/net/src/android/net/http/cts/SslCertificateTest.java
+++ b/tests/cts/net/src/android/net/http/cts/SslCertificateTest.java
@@ -230,6 +230,19 @@
final String EXPECTED = "Issued to: c=ccc,o=testOName,ou=testUName,cn=testCName;\n"
+ "Issued by: e=aeei,c=adb,o=testOName,ou=testUName,cn=testCName;\n";
assertEquals(EXPECTED, ssl.toString());
+ assertNull(ssl.getX509Certificate());
}
+ public void testGetX509Certificate() {
+ final String TO = "c=ccc,o=testOName,ou=testUName,cn=testCName";
+ final String BY = "e=aeei,c=adb,o=testOName,ou=testUName,cn=testCName";
+ Date validNotBefore = new Date(System.currentTimeMillis() - 1000);
+ Date validNotAfter = new Date(System.currentTimeMillis());
+ SslCertificate ssl = new SslCertificate(TO, BY, validNotBefore, validNotAfter);
+ assertNull(ssl.getX509Certificate());
+
+ X509Certificate cert = new MockX509Certificate();
+ ssl = new SslCertificate(cert);
+ assertSame(cert, ssl.getX509Certificate());
+ }
}