Merge "Fix and deflake ConnectivityManagerTest" am: 591263914c

Change-Id: I8caf45c73d7fb9a44251d0403734c675064e0335
This commit is contained in:
Remi NGUYEN VAN
2020-05-26 00:25:56 +00:00
committed by Automerger Merge Worker

View File

@@ -40,6 +40,16 @@ import static android.system.OsConstants.AF_INET6;
import static android.system.OsConstants.AF_UNSPEC; import static android.system.OsConstants.AF_UNSPEC;
import static com.android.compatibility.common.util.SystemUtil.runShellCommand; import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.app.Instrumentation; import android.app.Instrumentation;
@@ -78,17 +88,22 @@ import android.os.SystemProperties;
import android.os.VintfRuntimeInfo; import android.os.VintfRuntimeInfo;
import android.platform.test.annotations.AppModeFull; import android.platform.test.annotations.AppModeFull;
import android.provider.Settings; import android.provider.Settings;
import android.test.AndroidTestCase;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.util.Pair; import android.util.Pair;
import androidx.test.InstrumentationRegistry; import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.util.ArrayUtils; import com.android.internal.util.ArrayUtils;
import libcore.io.Streams; import libcore.io.Streams;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -114,7 +129,8 @@ import java.util.function.Supplier;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class ConnectivityManagerTest extends AndroidTestCase { @RunWith(AndroidJUnit4.class)
public class ConnectivityManagerTest {
private static final String TAG = ConnectivityManagerTest.class.getSimpleName(); private static final String TAG = ConnectivityManagerTest.class.getSimpleName();
@@ -126,7 +142,10 @@ public class ConnectivityManagerTest extends AndroidTestCase {
private static final int INTERVAL_KEEPALIVE_RETRY_MS = 500; private static final int INTERVAL_KEEPALIVE_RETRY_MS = 500;
private static final int MAX_KEEPALIVE_RETRY_COUNT = 3; private static final int MAX_KEEPALIVE_RETRY_COUNT = 3;
private static final int MIN_KEEPALIVE_INTERVAL = 10; private static final int MIN_KEEPALIVE_INTERVAL = 10;
private static final int NETWORK_CHANGE_METEREDNESS_TIMEOUT = 5000;
// Changing meteredness on wifi involves reconnecting, which can take several seconds (involves
// re-associating, DHCP...)
private static final int NETWORK_CHANGE_METEREDNESS_TIMEOUT = 30_000;
private static final int NUM_TRIES_MULTIPATH_PREF_CHECK = 20; private static final int NUM_TRIES_MULTIPATH_PREF_CHECK = 20;
private static final long INTERVAL_MULTIPATH_PREF_CHECK_MS = 500; private static final long INTERVAL_MULTIPATH_PREF_CHECK_MS = 500;
// device could have only one interface: data, wifi. // device could have only one interface: data, wifi.
@@ -150,22 +169,19 @@ public class ConnectivityManagerTest extends AndroidTestCase {
private PackageManager mPackageManager; private PackageManager mPackageManager;
private final HashMap<Integer, NetworkConfig> mNetworks = private final HashMap<Integer, NetworkConfig> mNetworks =
new HashMap<Integer, NetworkConfig>(); new HashMap<Integer, NetworkConfig>();
boolean mWifiConnectAttempted; boolean mWifiWasDisabled;
private UiAutomation mUiAutomation; private UiAutomation mUiAutomation;
private CtsNetUtils mCtsNetUtils; private CtsNetUtils mCtsNetUtils;
private boolean mShellPermissionIdentityAdopted;
@Override @Before
protected void setUp() throws Exception { public void setUp() throws Exception {
super.setUp();
Looper.prepare();
mContext = getContext();
mInstrumentation = InstrumentationRegistry.getInstrumentation(); mInstrumentation = InstrumentationRegistry.getInstrumentation();
mContext = mInstrumentation.getContext();
mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
mPackageManager = mContext.getPackageManager(); mPackageManager = mContext.getPackageManager();
mCtsNetUtils = new CtsNetUtils(mContext); mCtsNetUtils = new CtsNetUtils(mContext);
mWifiConnectAttempted = false; mWifiWasDisabled = false;
// Get com.android.internal.R.array.networkAttributes // Get com.android.internal.R.array.networkAttributes
int resId = mContext.getResources().getIdentifier("networkAttributes", "array", "android"); int resId = mContext.getResources().getIdentifier("networkAttributes", "array", "android");
@@ -182,20 +198,17 @@ public class ConnectivityManagerTest extends AndroidTestCase {
} catch (Exception e) {} } catch (Exception e) {}
} }
mUiAutomation = mInstrumentation.getUiAutomation(); mUiAutomation = mInstrumentation.getUiAutomation();
mShellPermissionIdentityAdopted = false;
} }
@Override @After
protected void tearDown() throws Exception { public void tearDown() throws Exception {
// Return WiFi to its original disabled state after tests that explicitly connect. // Return WiFi to its original disabled state after tests that explicitly connect.
if (mWifiConnectAttempted) { if (mWifiWasDisabled) {
mCtsNetUtils.disconnectFromWifi(null); mCtsNetUtils.disconnectFromWifi(null);
} }
if (mCtsNetUtils.cellConnectAttempted()) { if (mCtsNetUtils.cellConnectAttempted()) {
mCtsNetUtils.disconnectFromCell(); mCtsNetUtils.disconnectFromCell();
} }
dropShellPermissionIdentity();
super.tearDown();
} }
/** /**
@@ -204,13 +217,12 @@ public class ConnectivityManagerTest extends AndroidTestCase {
* automatically in tearDown(). * automatically in tearDown().
*/ */
private Network ensureWifiConnected() { private Network ensureWifiConnected() {
if (mWifiManager.isWifiEnabled()) { mWifiWasDisabled = !mWifiManager.isWifiEnabled();
return mCtsNetUtils.getWifiNetwork(); // Even if wifi is enabled, the network may not be connected or ready yet
}
mWifiConnectAttempted = true;
return mCtsNetUtils.connectToWifi(); return mCtsNetUtils.connectToWifi();
} }
@Test
public void testIsNetworkTypeValid() { public void testIsNetworkTypeValid() {
assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE)); assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE));
assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_WIFI)); assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_WIFI));
@@ -240,12 +252,14 @@ public class ConnectivityManagerTest extends AndroidTestCase {
} }
@Test
public void testSetNetworkPreference() { public void testSetNetworkPreference() {
// getNetworkPreference() and setNetworkPreference() are both deprecated so they do // getNetworkPreference() and setNetworkPreference() are both deprecated so they do
// not preform any action. Verify they are at least still callable. // not preform any action. Verify they are at least still callable.
mCm.setNetworkPreference(mCm.getNetworkPreference()); mCm.setNetworkPreference(mCm.getNetworkPreference());
} }
@Test
public void testGetActiveNetworkInfo() { public void testGetActiveNetworkInfo() {
NetworkInfo ni = mCm.getActiveNetworkInfo(); NetworkInfo ni = mCm.getActiveNetworkInfo();
@@ -254,6 +268,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
assertTrue(ni.getState() == State.CONNECTED); assertTrue(ni.getState() == State.CONNECTED);
} }
@Test
public void testGetActiveNetwork() { public void testGetActiveNetwork() {
Network network = mCm.getActiveNetwork(); Network network = mCm.getActiveNetwork();
assertNotNull("You must have an active network connection to complete CTS", network); assertNotNull("You must have an active network connection to complete CTS", network);
@@ -266,6 +281,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
assertTrue(ni.getState() == State.CONNECTED); assertTrue(ni.getState() == State.CONNECTED);
} }
@Test
public void testGetNetworkInfo() { public void testGetNetworkInfo() {
for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE+1; type++) { for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE+1; type++) {
if (shouldBeSupported(type)) { if (shouldBeSupported(type)) {
@@ -284,6 +300,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
} }
} }
@Test
public void testGetAllNetworkInfo() { public void testGetAllNetworkInfo() {
NetworkInfo[] ni = mCm.getAllNetworkInfo(); NetworkInfo[] ni = mCm.getAllNetworkInfo();
assertTrue(ni.length >= MIN_NUM_NETWORK_TYPES); assertTrue(ni.length >= MIN_NUM_NETWORK_TYPES);
@@ -307,6 +324,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
* and that they are made from different IP addresses. * and that they are made from different IP addresses.
*/ */
@AppModeFull(reason = "Cannot get WifiManager in instant app mode") @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testOpenConnection() throws Exception { public void testOpenConnection() throws Exception {
boolean canRunTest = mPackageManager.hasSystemFeature(FEATURE_WIFI) boolean canRunTest = mPackageManager.hasSystemFeature(FEATURE_WIFI)
&& mPackageManager.hasSystemFeature(FEATURE_TELEPHONY); && mPackageManager.hasSystemFeature(FEATURE_TELEPHONY);
@@ -386,6 +404,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
} catch (UnsupportedOperationException expected) {} } catch (UnsupportedOperationException expected) {}
} }
@Test
public void testStartUsingNetworkFeature() { public void testStartUsingNetworkFeature() {
final String invalidateFeature = "invalidateFeature"; final String invalidateFeature = "invalidateFeature";
@@ -415,6 +434,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
(networkType == ConnectivityManager.TYPE_ETHERNET && shouldEthernetBeSupported()); (networkType == ConnectivityManager.TYPE_ETHERNET && shouldEthernetBeSupported());
} }
@Test
public void testIsNetworkSupported() { public void testIsNetworkSupported() {
for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) { for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
boolean supported = mCm.isNetworkSupported(type); boolean supported = mCm.isNetworkSupported(type);
@@ -426,12 +446,14 @@ public class ConnectivityManagerTest extends AndroidTestCase {
} }
} }
@Test
public void testRequestRouteToHost() { public void testRequestRouteToHost() {
for (int type = -1 ; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) { for (int type = -1 ; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
assertRequestRouteToHostUnsupported(type, HOST_ADDRESS); assertRequestRouteToHostUnsupported(type, HOST_ADDRESS);
} }
} }
@Test
public void testTest() { public void testTest() {
mCm.getBackgroundDataSetting(); mCm.getBackgroundDataSetting();
} }
@@ -452,6 +474,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
* that it would increase test coverage by much (how many devices have 3G radio but not Wifi?). * that it would increase test coverage by much (how many devices have 3G radio but not Wifi?).
*/ */
@AppModeFull(reason = "Cannot get WifiManager in instant app mode") @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testRegisterNetworkCallback() { public void testRegisterNetworkCallback() {
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
Log.i(TAG, "testRegisterNetworkCallback cannot execute unless device supports WiFi"); Log.i(TAG, "testRegisterNetworkCallback cannot execute unless device supports WiFi");
@@ -493,6 +516,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
* of a {@code NetworkCallback}. * of a {@code NetworkCallback}.
*/ */
@AppModeFull(reason = "Cannot get WifiManager in instant app mode") @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testRegisterNetworkCallback_withPendingIntent() { public void testRegisterNetworkCallback_withPendingIntent() {
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
Log.i(TAG, "testRegisterNetworkCallback cannot execute unless device supports WiFi"); Log.i(TAG, "testRegisterNetworkCallback cannot execute unless device supports WiFi");
@@ -538,6 +562,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
* see if we get a callback for an INTERNET request. * see if we get a callback for an INTERNET request.
*/ */
@AppModeFull(reason = "CHANGE_NETWORK_STATE permission can't be granted to instant apps") @AppModeFull(reason = "CHANGE_NETWORK_STATE permission can't be granted to instant apps")
@Test
public void testRequestNetworkCallback() { public void testRequestNetworkCallback() {
final TestNetworkCallback callback = new TestNetworkCallback(); final TestNetworkCallback callback = new TestNetworkCallback();
mCm.requestNetwork(new NetworkRequest.Builder() mCm.requestNetwork(new NetworkRequest.Builder()
@@ -561,6 +586,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
* fail. Use WIFI and switch Wi-Fi off. * fail. Use WIFI and switch Wi-Fi off.
*/ */
@AppModeFull(reason = "Cannot get WifiManager in instant app mode") @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testRequestNetworkCallback_onUnavailable() { public void testRequestNetworkCallback_onUnavailable() {
final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled(); final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
if (previousWifiEnabledState) { if (previousWifiEnabledState) {
@@ -598,6 +624,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
/** Verify restricted networks cannot be requested. */ /** Verify restricted networks cannot be requested. */
@AppModeFull(reason = "CHANGE_NETWORK_STATE permission can't be granted to instant apps") @AppModeFull(reason = "CHANGE_NETWORK_STATE permission can't be granted to instant apps")
@Test
public void testRestrictedNetworks() { public void testRestrictedNetworks() {
// Verify we can request unrestricted networks: // Verify we can request unrestricted networks:
NetworkRequest request = new NetworkRequest.Builder() NetworkRequest request = new NetworkRequest.Builder()
@@ -719,6 +746,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
* for metered and unmetered networks. * for metered and unmetered networks.
*/ */
@AppModeFull(reason = "Cannot get WifiManager in instant app mode") @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testGetMultipathPreference() throws Exception { public void testGetMultipathPreference() throws Exception {
final ContentResolver resolver = mContext.getContentResolver(); final ContentResolver resolver = mContext.getContentResolver();
ensureWifiConnected(); ensureWifiConnected();
@@ -887,18 +915,6 @@ public class ConnectivityManagerTest extends AndroidTestCase {
keepalivesPerTransport, nc); keepalivesPerTransport, nc);
} }
private void adoptShellPermissionIdentity() {
mUiAutomation.adoptShellPermissionIdentity();
mShellPermissionIdentityAdopted = true;
}
private void dropShellPermissionIdentity() {
if (mShellPermissionIdentityAdopted) {
mUiAutomation.dropShellPermissionIdentity();
mShellPermissionIdentityAdopted = false;
}
}
private static boolean isTcpKeepaliveSupportedByKernel() { private static boolean isTcpKeepaliveSupportedByKernel() {
final String kVersionString = VintfRuntimeInfo.getKernelVersion(); final String kVersionString = VintfRuntimeInfo.getKernelVersion();
return compareMajorMinorVersion(kVersionString, "4.8") >= 0; return compareMajorMinorVersion(kVersionString, "4.8") >= 0;
@@ -933,6 +949,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
* Verifies that version string compare logic returns expected result for various cases. * Verifies that version string compare logic returns expected result for various cases.
* Note that only major and minor number are compared. * Note that only major and minor number are compared.
*/ */
@Test
public void testMajorMinorVersionCompare() { public void testMajorMinorVersionCompare() {
assertEquals(0, compareMajorMinorVersion("4.8.1", "4.8")); assertEquals(0, compareMajorMinorVersion("4.8.1", "4.8"));
assertEquals(1, compareMajorMinorVersion("4.9", "4.8.1")); assertEquals(1, compareMajorMinorVersion("4.9", "4.8.1"));
@@ -952,6 +969,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
* keepalives is set to 0. * keepalives is set to 0.
*/ */
@AppModeFull(reason = "Cannot get WifiManager in instant app mode") @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testKeepaliveWifiUnsupported() throws Exception { public void testKeepaliveWifiUnsupported() throws Exception {
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
Log.i(TAG, "testKeepaliveUnsupported cannot execute unless device" Log.i(TAG, "testKeepaliveUnsupported cannot execute unless device"
@@ -961,32 +979,36 @@ public class ConnectivityManagerTest extends AndroidTestCase {
final Network network = ensureWifiConnected(); final Network network = ensureWifiConnected();
if (getSupportedKeepalivesForNet(network) != 0) return; if (getSupportedKeepalivesForNet(network) != 0) return;
final InetAddress srcAddr = getFirstV4Address(network);
assumeTrue("This test requires native IPv4", srcAddr != null);
adoptShellPermissionIdentity(); runWithShellPermissionIdentity(() -> {
assertEquals(0, createConcurrentSocketKeepalives(network, srcAddr, 1, 0));
assertEquals(0, createConcurrentSocketKeepalives(network, 1, 0)); assertEquals(0, createConcurrentSocketKeepalives(network, srcAddr, 0, 1));
assertEquals(0, createConcurrentSocketKeepalives(network, 0, 1)); });
dropShellPermissionIdentity();
} }
@AppModeFull(reason = "Cannot get WifiManager in instant app mode") @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testCreateTcpKeepalive() throws Exception { public void testCreateTcpKeepalive() throws Exception {
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
Log.i(TAG, "testCreateTcpKeepalive cannot execute unless device supports WiFi"); Log.i(TAG, "testCreateTcpKeepalive cannot execute unless device supports WiFi");
return; return;
} }
adoptShellPermissionIdentity();
final Network network = ensureWifiConnected(); final Network network = ensureWifiConnected();
if (getSupportedKeepalivesForNet(network) == 0) return; if (getSupportedKeepalivesForNet(network) == 0) return;
final InetAddress srcAddr = getFirstV4Address(network);
assumeTrue("This test requires native IPv4", srcAddr != null);
// If kernel < 4.8 then it doesn't support TCP keepalive, but it might still support // If kernel < 4.8 then it doesn't support TCP keepalive, but it might still support
// NAT-T keepalive. If keepalive limits from resource overlay is not zero, TCP keepalive // NAT-T keepalive. If keepalive limits from resource overlay is not zero, TCP keepalive
// needs to be supported except if the kernel doesn't support it. // needs to be supported except if the kernel doesn't support it.
if (!isTcpKeepaliveSupportedByKernel()) { if (!isTcpKeepaliveSupportedByKernel()) {
// Sanity check to ensure the callback result is expected. // Sanity check to ensure the callback result is expected.
assertEquals(0, createConcurrentSocketKeepalives(network, 0, 1)); runWithShellPermissionIdentity(() -> {
assertEquals(0, createConcurrentSocketKeepalives(network, srcAddr, 0, 1));
});
Log.i(TAG, "testCreateTcpKeepalive is skipped for kernel " Log.i(TAG, "testCreateTcpKeepalive is skipped for kernel "
+ VintfRuntimeInfo.getKernelVersion()); + VintfRuntimeInfo.getKernelVersion());
return; return;
@@ -1000,6 +1022,8 @@ public class ConnectivityManagerTest extends AndroidTestCase {
// Should able to start keep alive offload when socket is idle. // Should able to start keep alive offload when socket is idle.
final Executor executor = mContext.getMainExecutor(); final Executor executor = mContext.getMainExecutor();
final TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(); final TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
mUiAutomation.adoptShellPermissionIdentity();
try (SocketKeepalive sk = mCm.createSocketKeepalive(network, s, executor, callback)) { try (SocketKeepalive sk = mCm.createSocketKeepalive(network, s, executor, callback)) {
sk.start(MIN_KEEPALIVE_INTERVAL); sk.start(MIN_KEEPALIVE_INTERVAL);
callback.expectStarted(); callback.expectStarted();
@@ -1021,6 +1045,8 @@ public class ConnectivityManagerTest extends AndroidTestCase {
// Stop. // Stop.
sk.stop(); sk.stop();
callback.expectStopped(); callback.expectStopped();
} finally {
mUiAutomation.dropShellPermissionIdentity();
} }
// Ensure socket is still connected. // Ensure socket is still connected.
@@ -1049,9 +1075,12 @@ public class ConnectivityManagerTest extends AndroidTestCase {
// Should get ERROR_SOCKET_NOT_IDLE because there is still data in the receive queue // Should get ERROR_SOCKET_NOT_IDLE because there is still data in the receive queue
// that has not been read. // that has not been read.
mUiAutomation.adoptShellPermissionIdentity();
try (SocketKeepalive sk = mCm.createSocketKeepalive(network, s, executor, callback)) { try (SocketKeepalive sk = mCm.createSocketKeepalive(network, s, executor, callback)) {
sk.start(MIN_KEEPALIVE_INTERVAL); sk.start(MIN_KEEPALIVE_INTERVAL);
callback.expectError(SocketKeepalive.ERROR_SOCKET_NOT_IDLE); callback.expectError(SocketKeepalive.ERROR_SOCKET_NOT_IDLE);
} finally {
mUiAutomation.dropShellPermissionIdentity();
} }
} }
} }
@@ -1096,7 +1125,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
} }
private @NonNull ArrayList<SocketKeepalive> createConcurrentNattSocketKeepalives( private @NonNull ArrayList<SocketKeepalive> createConcurrentNattSocketKeepalives(
@NonNull Network network, int requestCount, @NonNull Network network, @NonNull InetAddress srcAddr, int requestCount,
@NonNull TestSocketKeepaliveCallback callback) throws Exception { @NonNull TestSocketKeepaliveCallback callback) throws Exception {
final Executor executor = mContext.getMainExecutor(); final Executor executor = mContext.getMainExecutor();
@@ -1104,7 +1133,6 @@ public class ConnectivityManagerTest extends AndroidTestCase {
// Initialize a real NaT-T socket. // Initialize a real NaT-T socket.
final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE); final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
final UdpEncapsulationSocket nattSocket = mIpSec.openUdpEncapsulationSocket(); final UdpEncapsulationSocket nattSocket = mIpSec.openUdpEncapsulationSocket();
final InetAddress srcAddr = getFirstV4Address(network);
final InetAddress dstAddr = getAddrByName(TEST_HOST, AF_INET); final InetAddress dstAddr = getAddrByName(TEST_HOST, AF_INET);
assertNotNull(srcAddr); assertNotNull(srcAddr);
assertNotNull(dstAddr); assertNotNull(dstAddr);
@@ -1145,11 +1173,12 @@ public class ConnectivityManagerTest extends AndroidTestCase {
* @return the total number of keepalives created. * @return the total number of keepalives created.
*/ */
private int createConcurrentSocketKeepalives( private int createConcurrentSocketKeepalives(
@NonNull Network network, int nattCount, int tcpCount) throws Exception { @NonNull Network network, @NonNull InetAddress srcAddr, int nattCount, int tcpCount)
throws Exception {
final ArrayList<SocketKeepalive> kalist = new ArrayList<>(); final ArrayList<SocketKeepalive> kalist = new ArrayList<>();
final TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback(); final TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
kalist.addAll(createConcurrentNattSocketKeepalives(network, nattCount, callback)); kalist.addAll(createConcurrentNattSocketKeepalives(network, srcAddr, nattCount, callback));
kalist.addAll(createConcurrentTcpSocketKeepalives(network, tcpCount, callback)); kalist.addAll(createConcurrentTcpSocketKeepalives(network, tcpCount, callback));
final int ret = kalist.size(); final int ret = kalist.size();
@@ -1169,6 +1198,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
* get leaked after iterations. * get leaked after iterations.
*/ */
@AppModeFull(reason = "Cannot get WifiManager in instant app mode") @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testSocketKeepaliveLimitWifi() throws Exception { public void testSocketKeepaliveLimitWifi() throws Exception {
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
Log.i(TAG, "testSocketKeepaliveLimitWifi cannot execute unless device" Log.i(TAG, "testSocketKeepaliveLimitWifi cannot execute unless device"
@@ -1181,33 +1211,39 @@ public class ConnectivityManagerTest extends AndroidTestCase {
if (supported == 0) { if (supported == 0) {
return; return;
} }
final InetAddress srcAddr = getFirstV4Address(network);
assumeTrue("This test requires native IPv4", srcAddr != null);
adoptShellPermissionIdentity(); runWithShellPermissionIdentity(() -> {
// Verifies that the supported keepalive slots meet MIN_SUPPORTED_KEEPALIVE_COUNT.
assertGreaterOrEqual(supported, MIN_SUPPORTED_WIFI_KEEPALIVE_COUNT);
// Verifies that the supported keepalive slots meet MIN_SUPPORTED_KEEPALIVE_COUNT. // Verifies that Nat-T keepalives can be established.
assertGreaterOrEqual(supported, MIN_SUPPORTED_WIFI_KEEPALIVE_COUNT); assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr,
supported + 1, 0));
// Verifies that Nat-T keepalives can be established. // Verifies that keepalives don't get leaked in second round.
assertEquals(supported, createConcurrentSocketKeepalives(network, supported + 1, 0)); assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, supported,
// Verifies that keepalives don't get leaked in second round. 0));
assertEquals(supported, createConcurrentSocketKeepalives(network, supported, 0)); });
// If kernel < 4.8 then it doesn't support TCP keepalive, but it might still support // If kernel < 4.8 then it doesn't support TCP keepalive, but it might still support
// NAT-T keepalive. Test below cases only if TCP keepalive is supported by kernel. // NAT-T keepalive. Test below cases only if TCP keepalive is supported by kernel.
if (isTcpKeepaliveSupportedByKernel()) { if (!isTcpKeepaliveSupportedByKernel()) return;
assertEquals(supported, createConcurrentSocketKeepalives(network, 0, supported + 1));
runWithShellPermissionIdentity(() -> {
assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, 0,
supported + 1));
// Verifies that different types can be established at the same time. // Verifies that different types can be established at the same time.
assertEquals(supported, createConcurrentSocketKeepalives(network, assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr,
supported / 2, supported - supported / 2)); supported / 2, supported - supported / 2));
// Verifies that keepalives don't get leaked in second round. // Verifies that keepalives don't get leaked in second round.
assertEquals(supported, createConcurrentSocketKeepalives(network, 0, supported)); assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, 0,
assertEquals(supported, createConcurrentSocketKeepalives(network, supported));
assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr,
supported / 2, supported - supported / 2)); supported / 2, supported - supported / 2));
} });
dropShellPermissionIdentity();
} }
/** /**
@@ -1215,6 +1251,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
* don't get leaked after iterations. * don't get leaked after iterations.
*/ */
@AppModeFull(reason = "Cannot request network in instant app mode") @AppModeFull(reason = "Cannot request network in instant app mode")
@Test
public void testSocketKeepaliveLimitTelephony() throws Exception { public void testSocketKeepaliveLimitTelephony() throws Exception {
if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY)) { if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY)) {
Log.i(TAG, "testSocketKeepaliveLimitTelephony cannot execute unless device" Log.i(TAG, "testSocketKeepaliveLimitTelephony cannot execute unless device"
@@ -1231,18 +1268,19 @@ public class ConnectivityManagerTest extends AndroidTestCase {
final Network network = mCtsNetUtils.connectToCell(); final Network network = mCtsNetUtils.connectToCell();
final int supported = getSupportedKeepalivesForNet(network); final int supported = getSupportedKeepalivesForNet(network);
final InetAddress srcAddr = getFirstV4Address(network);
assumeTrue("This test requires native IPv4", srcAddr != null);
adoptShellPermissionIdentity(); runWithShellPermissionIdentity(() -> {
// Verifies that the supported keepalive slots meet minimum requirement.
// Verifies that the supported keepalive slots meet minimum requirement. assertGreaterOrEqual(supported, MIN_SUPPORTED_CELLULAR_KEEPALIVE_COUNT);
assertGreaterOrEqual(supported, MIN_SUPPORTED_CELLULAR_KEEPALIVE_COUNT); // Verifies that Nat-T keepalives can be established.
assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr,
// Verifies that Nat-T keepalives can be established. supported + 1, 0));
assertEquals(supported, createConcurrentSocketKeepalives(network, supported + 1, 0)); // Verifies that keepalives don't get leaked in second round.
// Verifies that keepalives don't get leaked in second round. assertEquals(supported, createConcurrentSocketKeepalives(network, srcAddr, supported,
assertEquals(supported, createConcurrentSocketKeepalives(network, supported, 0)); 0));
});
dropShellPermissionIdentity();
} }
private int getIntResourceForName(@NonNull String resName) { private int getIntResourceForName(@NonNull String resName) {
@@ -1255,6 +1293,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
* Verifies that the keepalive slots are limited as customized for unprivileged requests. * Verifies that the keepalive slots are limited as customized for unprivileged requests.
*/ */
@AppModeFull(reason = "Cannot get WifiManager in instant app mode") @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testSocketKeepaliveUnprivileged() throws Exception { public void testSocketKeepaliveUnprivileged() throws Exception {
if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) { if (!mPackageManager.hasSystemFeature(FEATURE_WIFI)) {
Log.i(TAG, "testSocketKeepaliveUnprivileged cannot execute unless device" Log.i(TAG, "testSocketKeepaliveUnprivileged cannot execute unless device"
@@ -1267,6 +1306,8 @@ public class ConnectivityManagerTest extends AndroidTestCase {
if (supported == 0) { if (supported == 0) {
return; return;
} }
final InetAddress srcAddr = getFirstV4Address(network);
assumeTrue("This test requires native IPv4", srcAddr != null);
// Resource ID might be shifted on devices that compiled with different symbols. // Resource ID might be shifted on devices that compiled with different symbols.
// Thus, resolve ID at runtime is needed. // Thus, resolve ID at runtime is needed.
@@ -1282,7 +1323,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
final int expectedUnprivileged = final int expectedUnprivileged =
Math.min(allowedUnprivilegedPerUid, supported - reservedPrivilegedSlots); Math.min(allowedUnprivilegedPerUid, supported - reservedPrivilegedSlots);
assertEquals(expectedUnprivileged, assertEquals(expectedUnprivileged,
createConcurrentSocketKeepalives(network, supported + 1, 0)); createConcurrentSocketKeepalives(network, srcAddr, supported + 1, 0));
} }
private static void assertGreaterOrEqual(long greater, long lesser) { private static void assertGreaterOrEqual(long greater, long lesser) {
@@ -1296,6 +1337,7 @@ public class ConnectivityManagerTest extends AndroidTestCase {
* See. b/144679405. * See. b/144679405.
*/ */
@AppModeFull(reason = "Cannot get WifiManager in instant app mode") @AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
public void testRestrictedNetworkPermission() throws Exception { public void testRestrictedNetworkPermission() throws Exception {
// Ensure that CONNECTIVITY_USE_RESTRICTED_NETWORKS isn't granted to this package. // Ensure that CONNECTIVITY_USE_RESTRICTED_NETWORKS isn't granted to this package.
final PackageInfo app = mPackageManager.getPackageInfo(mContext.getPackageName(), final PackageInfo app = mPackageManager.getPackageInfo(mContext.getPackageName(),