Merge "WifiManagerTest: allow NetworkStack to grant network permissions"
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index ec5a877..c6e80a2 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -92,7 +92,8 @@
private static final String NETWORK_STATUS_SEPARATOR = "\\|";
private static final int SECOND_IN_MS = 1000;
static final int NETWORK_TIMEOUT_MS = 15 * SECOND_IN_MS;
- private static final int PROCESS_STATE_FOREGROUND_SERVICE = 3;
+ private static int PROCESS_STATE_FOREGROUND_SERVICE;
+
private static final int PROCESS_STATE_TOP = 2;
private static final String KEY_NETWORK_STATE_OBSERVER = TEST_PKG + ".observer";
@@ -131,6 +132,8 @@
protected void setUp() throws Exception {
super.setUp();
+ PROCESS_STATE_FOREGROUND_SERVICE = (Integer) ActivityManager.class
+ .getDeclaredField("PROCESS_STATE_FOREGROUND_SERVICE").get(null);
mInstrumentation = getInstrumentation();
mContext = mInstrumentation.getContext();
mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyVpnService.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyVpnService.java
index 90a3ce4..7d91574 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyVpnService.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/MyVpnService.java
@@ -17,6 +17,7 @@
package com.android.cts.net.hostside;
import android.content.Intent;
+import android.net.ProxyInfo;
import android.net.VpnService;
import android.os.ParcelFileDescriptor;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -32,6 +33,10 @@
private static String TAG = "MyVpnService";
private static int MTU = 1799;
+ public static final String ACTION_ESTABLISHED = "com.android.cts.net.hostside.ESTABNLISHED";
+ public static final String EXTRA_ALWAYS_ON = "is-always-on";
+ public static final String EXTRA_LOCKDOWN_ENABLED = "is-lockdown-enabled";
+
private ParcelFileDescriptor mFd = null;
private PacketReflector mPacketReflector = null;
@@ -113,6 +118,8 @@
}
}
+ ProxyInfo vpnProxy = intent.getParcelableExtra(packageName + ".httpProxy");
+ builder.setHttpProxy(vpnProxy);
builder.setMtu(MTU);
builder.setBlocking(true);
builder.setSession("MyVpnService");
@@ -126,10 +133,19 @@
mFd = builder.establish();
Log.i(TAG, "Established, fd=" + (mFd == null ? "null" : mFd.getFd()));
+ broadcastEstablished();
+
mPacketReflector = new PacketReflector(mFd.getFileDescriptor(), MTU);
mPacketReflector.start();
}
+ private void broadcastEstablished() {
+ final Intent bcIntent = new Intent(ACTION_ESTABLISHED);
+ bcIntent.putExtra(EXTRA_ALWAYS_ON, isAlwaysOn());
+ bcIntent.putExtra(EXTRA_LOCKDOWN_ENABLED, isLockdownEnabled());
+ sendBroadcast(bcIntent);
+ }
+
private void stop() {
if (mPacketReflector != null) {
mPacketReflector.interrupt();
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 48f0afb..f58fa7b 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
@@ -19,6 +19,7 @@
import static android.os.Process.INVALID_UID;
import static android.system.OsConstants.*;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
@@ -27,14 +28,14 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
+import android.net.Proxy;
+import android.net.ProxyInfo;
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;
-import android.support.test.uiautomator.UiScrollable;
import android.support.test.uiautomator.UiSelector;
import android.system.ErrnoException;
import android.system.Os;
@@ -45,18 +46,13 @@
import android.text.TextUtils;
import android.util.Log;
-import com.android.cts.net.hostside.IRemoteSocketFactory;
+import com.android.compatibility.common.util.BlockingBroadcastReceiver;
-import java.io.BufferedReader;
import java.io.Closeable;
import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.FileInputStream;
-import java.io.InputStreamReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.PrintWriter;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet6Address;
@@ -64,9 +60,9 @@
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
-import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.util.Random;
+import java.util.concurrent.TimeUnit;
/**
* Tests for the VpnService API.
@@ -197,9 +193,8 @@
}
private void startVpn(
- String[] addresses, String[] routes,
- String allowedApplications, String disallowedApplications) throws Exception {
-
+ String[] addresses, String[] routes, String allowedApplications,
+ String disallowedApplications, ProxyInfo proxyInfo) throws Exception {
prepareVpn();
// Register a callback so we will be notified when our VPN comes up.
@@ -225,7 +220,9 @@
.putExtra(mPackageName + ".addresses", TextUtils.join(",", addresses))
.putExtra(mPackageName + ".routes", TextUtils.join(",", routes))
.putExtra(mPackageName + ".allowedapplications", allowedApplications)
- .putExtra(mPackageName + ".disallowedapplications", disallowedApplications);
+ .putExtra(mPackageName + ".disallowedapplications", disallowedApplications)
+ .putExtra(mPackageName + ".httpProxy", proxyInfo);
+
mActivity.startService(intent);
synchronized (mLock) {
if (mNetwork == null) {
@@ -569,15 +566,27 @@
return;
}
+ final BlockingBroadcastReceiver receiver = new BlockingBroadcastReceiver(
+ getInstrumentation().getTargetContext(), MyVpnService.ACTION_ESTABLISHED);
+ receiver.register();
+
FileDescriptor fd = openSocketFdInOtherApp(TEST_HOST, 80, TIMEOUT_MS);
startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
new String[] {"0.0.0.0/0", "::/0"},
- "", "");
+ "", "", null);
+
+ final Intent intent = receiver.awaitForBroadcast(TimeUnit.MINUTES.toMillis(1));
+ assertNotNull("Failed to receive broadcast from VPN service", intent);
+ assertFalse("Wrong VpnService#isAlwaysOn",
+ intent.getBooleanExtra(MyVpnService.EXTRA_ALWAYS_ON, true));
+ assertFalse("Wrong VpnService#isLockdownEnabled",
+ intent.getBooleanExtra(MyVpnService.EXTRA_LOCKDOWN_ENABLED, true));
assertSocketClosed(fd, TEST_HOST);
checkTrafficOnVpn();
+ receiver.unregisterQuietly();
}
public void testAppAllowed() throws Exception {
@@ -589,7 +598,7 @@
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"},
- allowedApps, "");
+ allowedApps, "", null);
assertSocketClosed(fd, TEST_HOST);
@@ -611,7 +620,7 @@
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);
+ "", disallowedApps, null);
assertSocketStillOpen(localFd, TEST_HOST);
assertSocketStillOpen(remoteFd, TEST_HOST);
@@ -620,7 +629,6 @@
}
public void testGetConnectionOwnerUidSecurity() throws Exception {
-
if (!supportedHardware()) return;
DatagramSocket s;
@@ -637,4 +645,166 @@
return;
}
}
+
+ public void testSetProxy() throws Exception {
+ if (!supportedHardware()) return;
+ ProxyInfo initialProxy = mCM.getDefaultProxy();
+ // Receiver for the proxy change broadcast.
+ BlockingBroadcastReceiver proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver();
+ proxyBroadcastReceiver.register();
+
+ String allowedApps = mPackageName;
+ ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("10.0.0.1", 8888);
+ startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
+ new String[] {"0.0.0.0/0", "::/0"}, allowedApps, "",
+ testProxyInfo);
+
+ // Check that the proxy change broadcast is received
+ try {
+ assertNotNull("No proxy change was broadcast when VPN is connected.",
+ proxyBroadcastReceiver.awaitForBroadcast());
+ } finally {
+ proxyBroadcastReceiver.unregisterQuietly();
+ }
+
+ // Proxy is set correctly in network and in link properties.
+ assertNetworkHasExpectedProxy(testProxyInfo, mNetwork);
+ assertDefaultProxy(testProxyInfo);
+
+ proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver();
+ proxyBroadcastReceiver.register();
+ stopVpn();
+ try {
+ assertNotNull("No proxy change was broadcast when VPN was disconnected.",
+ proxyBroadcastReceiver.awaitForBroadcast());
+ } finally {
+ proxyBroadcastReceiver.unregisterQuietly();
+ }
+
+ // After disconnecting from VPN, the proxy settings are the ones of the initial network.
+ assertDefaultProxy(initialProxy);
+ }
+
+ public void testSetProxyDisallowedApps() throws Exception {
+ if (!supportedHardware()) return;
+ ProxyInfo initialProxy = mCM.getDefaultProxy();
+
+ // 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
+ String disallowedApps = mPackageName + ",com.android.shell";
+ ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("10.0.0.1", 8888);
+ startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
+ new String[] {"0.0.0.0/0", "::/0"}, "", disallowedApps,
+ testProxyInfo);
+
+ // The disallowed app does has the proxy configs of the default network.
+ assertNetworkHasExpectedProxy(initialProxy, mCM.getActiveNetwork());
+ assertDefaultProxy(initialProxy);
+ }
+
+ public void testNoProxy() throws Exception {
+ if (!supportedHardware()) return;
+ ProxyInfo initialProxy = mCM.getDefaultProxy();
+ BlockingBroadcastReceiver proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver();
+ proxyBroadcastReceiver.register();
+ String allowedApps = mPackageName;
+ startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
+ new String[] {"0.0.0.0/0", "::/0"}, allowedApps, "", null);
+
+ try {
+ assertNotNull("No proxy change was broadcast.",
+ proxyBroadcastReceiver.awaitForBroadcast());
+ } finally {
+ proxyBroadcastReceiver.unregisterQuietly();
+ }
+
+ // The VPN network has no proxy set.
+ assertNetworkHasExpectedProxy(null, mNetwork);
+
+ proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver();
+ proxyBroadcastReceiver.register();
+ stopVpn();
+ try {
+ assertNotNull("No proxy change was broadcast.",
+ proxyBroadcastReceiver.awaitForBroadcast());
+ } finally {
+ proxyBroadcastReceiver.unregisterQuietly();
+ }
+ // After disconnecting from VPN, the proxy settings are the ones of the initial network.
+ assertDefaultProxy(initialProxy);
+ assertNetworkHasExpectedProxy(initialProxy, mCM.getActiveNetwork());
+ }
+
+ public void testBindToNetworkWithProxy() throws Exception {
+ if (!supportedHardware()) return;
+ String allowedApps = mPackageName;
+ Network initialNetwork = mCM.getActiveNetwork();
+ ProxyInfo initialProxy = mCM.getDefaultProxy();
+ ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("10.0.0.1", 8888);
+ // Receiver for the proxy change broadcast.
+ BlockingBroadcastReceiver proxyBroadcastReceiver = new ProxyChangeBroadcastReceiver();
+ proxyBroadcastReceiver.register();
+ startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
+ new String[] {"0.0.0.0/0", "::/0"}, allowedApps, "",
+ testProxyInfo);
+
+ assertDefaultProxy(testProxyInfo);
+ mCM.bindProcessToNetwork(initialNetwork);
+ try {
+ assertNotNull("No proxy change was broadcast.",
+ proxyBroadcastReceiver.awaitForBroadcast());
+ } finally {
+ proxyBroadcastReceiver.unregisterQuietly();
+ }
+ assertDefaultProxy(initialProxy);
+ }
+
+ private void assertDefaultProxy(ProxyInfo expected) {
+ assertEquals("Incorrect proxy config.", expected, mCM.getDefaultProxy());
+ String expectedHost = expected == null ? null : expected.getHost();
+ String expectedPort = expected == null ? null : String.valueOf(expected.getPort());
+ assertEquals("Incorrect proxy host system property.", expectedHost,
+ System.getProperty("http.proxyHost"));
+ assertEquals("Incorrect proxy port system property.", expectedPort,
+ System.getProperty("http.proxyPort"));
+ }
+
+ private void assertNetworkHasExpectedProxy(ProxyInfo expected, Network network) {
+ LinkProperties lp = mCM.getLinkProperties(network);
+ assertNotNull("The network link properties object is null.", lp);
+ assertEquals("Incorrect proxy config.", expected, lp.getHttpProxy());
+
+ assertEquals(expected, mCM.getProxyForNetwork(network));
+ }
+
+// public void testIsAlwaysOnIsLockdownNotAlwaysOn() throws Exception {
+// if (!supportedHardware()) return;
+//
+// // This package is the VPN app, so we can call the APIs directly.
+//
+// startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
+// new String[] {"0.0.0.0/0", "::/0"},
+// mPackageName /* allowedApps */, "",
+// null /* proxyInfo */);
+// }
+
+ class ProxyChangeBroadcastReceiver extends BlockingBroadcastReceiver {
+ private boolean received;
+
+ public ProxyChangeBroadcastReceiver() {
+ super(VpnTest.this.getInstrumentation().getContext(), Proxy.PROXY_CHANGE_ACTION);
+ received = false;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!received) {
+ // Do not call onReceive() more than once.
+ super.onReceive(context, intent);
+ }
+ received = true;
+ }
+ }
}
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 853668c..e34ee89 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
@@ -48,4 +48,20 @@
public void testGetConnectionOwnerUidSecurity() throws Exception {
runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testGetConnectionOwnerUidSecurity");
}
+
+ public void testSetProxy() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testSetProxy");
+ }
+
+ public void testSetProxyDisallowedApps() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testSetProxyDisallowedApps");
+ }
+
+ public void testNoProxy() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testNoProxy");
+ }
+
+ public void testBindToNetworkWithProxy() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testBindToNetworkWithProxy");
+ }
}