Loading src/android/net/dhcp/DhcpClient.java +18 −5 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ import android.net.util.InterfaceParams; import android.net.util.NetworkStackUtils; import android.net.util.PacketReader; import android.net.util.SocketUtils; import android.os.Build; import android.os.Handler; import android.os.Message; import android.os.PowerManager; Loading @@ -98,6 +99,7 @@ import com.android.internal.util.WakeupMessage; import com.android.networkstack.R; import com.android.networkstack.apishim.CaptivePortalDataShimImpl; import com.android.networkstack.apishim.SocketUtilsShimImpl; import com.android.networkstack.apishim.common.ShimUtils; import com.android.networkstack.arp.ArpPacket; import java.io.FileDescriptor; Loading Loading @@ -407,8 +409,10 @@ public class DhcpClient extends StateMachine { * Return whether a feature guarded by a feature flag is enabled. * @see NetworkStackUtils#isFeatureEnabled(Context, String, String) */ public boolean isFeatureEnabled(final Context context, final String name) { return NetworkStackUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY, name); public boolean isFeatureEnabled(final Context context, final String name, boolean defaultEnabled) { return NetworkStackUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY, name, defaultEnabled); } /** Loading Loading @@ -496,23 +500,32 @@ public class DhcpClient extends StateMachine { /** * check whether or not to support caching the last lease info and INIT-REBOOT state. * * INIT-REBOOT state is supported on Android R by default if there is no experiment flag set to * disable this feature explicitly, meanwhile we still hope to be able to control this feature * on/off by pushing experiment flag for A/B testing and metrics collection on both of Android * Q and R version, however it's disbled on Android Q by default. */ public boolean isDhcpLeaseCacheEnabled() { return mDependencies.isFeatureEnabled(mContext, DHCP_INIT_REBOOT_VERSION); final boolean defaultEnabled = ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q); return mDependencies.isFeatureEnabled(mContext, DHCP_INIT_REBOOT_VERSION, defaultEnabled); } /** * check whether or not to support DHCP Rapid Commit option. */ public boolean isDhcpRapidCommitEnabled() { return mDependencies.isFeatureEnabled(mContext, DHCP_RAPID_COMMIT_VERSION); return mDependencies.isFeatureEnabled(mContext, DHCP_RAPID_COMMIT_VERSION, false /* defaultEnabled */); } /** * check whether or not to support IP address conflict detection and DHCPDECLINE. */ public boolean isDhcpIpConflictDetectEnabled() { return mDependencies.isFeatureEnabled(mContext, DHCP_IP_CONFLICT_DETECT_VERSION); return mDependencies.isFeatureEnabled(mContext, DHCP_IP_CONFLICT_DETECT_VERSION, false /* defaultEnabled */); } private void confirmDhcpLease(DhcpPacket packet, DhcpResults results) { Loading src/android/net/ip/IpClient.java +9 −1 Original line number Diff line number Diff line Loading @@ -458,7 +458,7 @@ public class IpClient extends StateMachine { private final SharedLog mLog; private final LocalLog mConnectivityPacketLog; private final MessageHandlingLogger mMsgStateLogger; private final IpConnectivityLog mMetricsLog = new IpConnectivityLog(); private final IpConnectivityLog mMetricsLog; private final InterfaceController mInterfaceCtrl; // Ignore nonzero RDNSS option lifetimes below this value. 0 = disabled. Loading Loading @@ -537,6 +537,13 @@ public class IpClient extends StateMachine { return NetworkStackUtils.getDeviceConfigPropertyInt(NAMESPACE_CONNECTIVITY, name, defaultValue); } /** * Get a IpConnectivityLog instance. */ public IpConnectivityLog getIpConnectivityLog() { return new IpConnectivityLog(); } } public IpClient(Context context, String ifName, IIpClientCallbacks callback, Loading @@ -558,6 +565,7 @@ public class IpClient extends StateMachine { mInterfaceName = ifName; mClatInterfaceName = CLAT_PREFIX + ifName; mDependencies = deps; mMetricsLog = deps.getIpConnectivityLog(); mShutdownLatch = new CountDownLatch(1); mCm = mContext.getSystemService(ConnectivityManager.class); mObserverRegistry = observerRegistry; Loading src/android/net/util/NetworkStackUtils.java +1 −3 Original line number Diff line number Diff line Loading @@ -355,9 +355,7 @@ public class NetworkStackUtils { */ public static boolean isFeatureEnabled(@NonNull Context context, @NonNull String namespace, @NonNull String name) { final int propertyVersion = getDeviceConfigPropertyInt(namespace, name, 0 /* default value */); return isFeatureEnabled(context, namespace, name, false); return isFeatureEnabled(context, namespace, name, false /* defaultEnabled */); } /** Loading tests/integration/src/android/net/ip/IpClientIntegrationTest.java +4 −2 Original line number Diff line number Diff line Loading @@ -141,6 +141,7 @@ import com.android.server.NetworkObserverRegistry; import com.android.server.NetworkStackService.NetworkStackServiceManager; import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService; import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import com.android.testutils.HandlerUtilsKt; import com.android.testutils.TapPacketReader; Loading Loading @@ -319,7 +320,8 @@ public class IpClientIntegrationTest { NetworkStackIpMemoryStore ipMemoryStore) { return new DhcpClient.Dependencies(ipMemoryStore) { @Override public boolean isFeatureEnabled(final Context context, final String name) { public boolean isFeatureEnabled(final Context context, final String name, final boolean defaultEnabled) { switch (name) { case NetworkStackUtils.DHCP_RAPID_COMMIT_VERSION: return mIsDhcpRapidCommitEnabled; Loading Loading @@ -1066,7 +1068,7 @@ public class IpClientIntegrationTest { assertIpMemoryStoreNetworkAttributes(null, currentTime, TEST_DEFAULT_MTU); } @Test @Test @IgnoreAfter(Build.VERSION_CODES.Q) // INIT-REBOOT is enabled on R. public void testHandleDisableInitRebootState() throws Exception { performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S, false /* isDhcpLeaseCacheEnabled */, false /* shouldReplyRapidCommitAck */, Loading tests/integration/src/android/net/netlink/InetDiagSocketIntegrationTest.java 0 → 100644 +223 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.netlink; import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.AF_INET6; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; import static android.system.OsConstants.SOCK_STREAM; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assume.assumeTrue; import android.app.Instrumentation; import android.content.Context; import android.net.ConnectivityManager; import android.os.Process; import android.system.Os; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.networkstack.apishim.common.ShimUtils; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.io.FileDescriptor; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; @RunWith(AndroidJUnit4.class) @SmallTest public class InetDiagSocketIntegrationTest { private ConnectivityManager mCm; private Context mContext; @Before public void setUp() throws Exception { Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); mContext = instrumentation.getTargetContext(); mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); } private class Connection { public int socketDomain; public int socketType; public InetAddress localAddress; public InetAddress remoteAddress; public InetAddress localhostAddress; public InetSocketAddress local; public InetSocketAddress remote; public int protocol; public FileDescriptor localFd; public FileDescriptor remoteFd; public FileDescriptor createSocket() throws Exception { return Os.socket(socketDomain, socketType, protocol); } Connection(String to, String from) throws Exception { remoteAddress = InetAddress.getByName(to); if (from != null) { localAddress = InetAddress.getByName(from); } else { localAddress = (remoteAddress instanceof Inet4Address) ? Inet4Address.getByName("localhost") : Inet6Address.getByName("::"); } if ((localAddress instanceof Inet4Address) && (remoteAddress instanceof Inet4Address)) { socketDomain = AF_INET; localhostAddress = Inet4Address.getByName("localhost"); } else { socketDomain = AF_INET6; localhostAddress = Inet6Address.getByName("::"); } } public void close() throws Exception { Os.close(localFd); } } private class TcpConnection extends Connection { TcpConnection(String to, String from) throws Exception { super(to, from); protocol = IPPROTO_TCP; socketType = SOCK_STREAM; remoteFd = createSocket(); Os.bind(remoteFd, remoteAddress, 0); Os.listen(remoteFd, 10); int remotePort = ((InetSocketAddress) Os.getsockname(remoteFd)).getPort(); localFd = createSocket(); Os.bind(localFd, localAddress, 0); Os.connect(localFd, remoteAddress, remotePort); local = (InetSocketAddress) Os.getsockname(localFd); remote = (InetSocketAddress) Os.getpeername(localFd); } public void close() throws Exception { super.close(); Os.close(remoteFd); } } private class UdpConnection extends Connection { UdpConnection(String to, String from) throws Exception { super(to, from); protocol = IPPROTO_UDP; socketType = SOCK_DGRAM; remoteFd = null; localFd = createSocket(); Os.bind(localFd, localAddress, 0); Os.connect(localFd, remoteAddress, 7); local = (InetSocketAddress) Os.getsockname(localFd); remote = new InetSocketAddress(remoteAddress, 7); } } private void checkConnectionOwnerUid(int protocol, InetSocketAddress local, InetSocketAddress remote, boolean expectSuccess) { final int uid = mCm.getConnectionOwnerUid(protocol, local, remote); if (expectSuccess) { assertEquals(Process.myUid(), uid); } else { assertNotEquals(Process.myUid(), uid); } } private int findLikelyFreeUdpPort(UdpConnection conn) throws Exception { UdpConnection udp = new UdpConnection(conn.remoteAddress.getHostAddress(), conn.localAddress.getHostAddress()); final int localPort = udp.local.getPort(); udp.close(); return localPort; } /** * Create a test connection for UDP and TCP sockets and verify that this * {protocol, local, remote} socket result in receiving a valid UID. */ public void checkGetConnectionOwnerUid(String to, String from) throws Exception { TcpConnection tcp = new TcpConnection(to, from); checkConnectionOwnerUid(tcp.protocol, tcp.local, tcp.remote, true); checkConnectionOwnerUid(IPPROTO_UDP, tcp.local, tcp.remote, false); checkConnectionOwnerUid(tcp.protocol, new InetSocketAddress(0), tcp.remote, false); checkConnectionOwnerUid(tcp.protocol, tcp.local, new InetSocketAddress(0), false); tcp.close(); UdpConnection udp = new UdpConnection(to, from); checkConnectionOwnerUid(udp.protocol, udp.local, udp.remote, true); checkConnectionOwnerUid(IPPROTO_TCP, udp.local, udp.remote, false); checkConnectionOwnerUid(udp.protocol, new InetSocketAddress(findLikelyFreeUdpPort(udp)), udp.remote, false); udp.close(); } @Test public void testGetConnectionOwnerUid() throws Exception { // Skip the test for API <= Q, as b/141603906 this was only fixed in Q-QPR2 assumeTrue(ShimUtils.isAtLeastR()); checkGetConnectionOwnerUid("::", null); checkGetConnectionOwnerUid("::", "::"); checkGetConnectionOwnerUid("0.0.0.0", null); checkGetConnectionOwnerUid("0.0.0.0", "0.0.0.0"); checkGetConnectionOwnerUid("127.0.0.1", null); checkGetConnectionOwnerUid("127.0.0.1", "127.0.0.2"); checkGetConnectionOwnerUid("::1", null); checkGetConnectionOwnerUid("::1", "::1"); } /* Verify fix for b/141603906 */ @Test public void testB141603906() throws Exception { // Skip the test for API <= Q, as b/141603906 this was only fixed in Q-QPR2 assumeTrue(ShimUtils.isAtLeastR()); final InetSocketAddress src = new InetSocketAddress(0); final InetSocketAddress dst = new InetSocketAddress(0); final int numThreads = 8; final int numSockets = 5000; final Thread[] threads = new Thread[numThreads]; for (int i = 0; i < numThreads; i++) { threads[i] = new Thread(() -> { for (int j = 0; j < numSockets; j++) { mCm.getConnectionOwnerUid(IPPROTO_TCP, src, dst); } }); } for (Thread thread : threads) { thread.start(); } for (Thread thread : threads) { thread.join(); } } } Loading
src/android/net/dhcp/DhcpClient.java +18 −5 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ import android.net.util.InterfaceParams; import android.net.util.NetworkStackUtils; import android.net.util.PacketReader; import android.net.util.SocketUtils; import android.os.Build; import android.os.Handler; import android.os.Message; import android.os.PowerManager; Loading @@ -98,6 +99,7 @@ import com.android.internal.util.WakeupMessage; import com.android.networkstack.R; import com.android.networkstack.apishim.CaptivePortalDataShimImpl; import com.android.networkstack.apishim.SocketUtilsShimImpl; import com.android.networkstack.apishim.common.ShimUtils; import com.android.networkstack.arp.ArpPacket; import java.io.FileDescriptor; Loading Loading @@ -407,8 +409,10 @@ public class DhcpClient extends StateMachine { * Return whether a feature guarded by a feature flag is enabled. * @see NetworkStackUtils#isFeatureEnabled(Context, String, String) */ public boolean isFeatureEnabled(final Context context, final String name) { return NetworkStackUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY, name); public boolean isFeatureEnabled(final Context context, final String name, boolean defaultEnabled) { return NetworkStackUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY, name, defaultEnabled); } /** Loading Loading @@ -496,23 +500,32 @@ public class DhcpClient extends StateMachine { /** * check whether or not to support caching the last lease info and INIT-REBOOT state. * * INIT-REBOOT state is supported on Android R by default if there is no experiment flag set to * disable this feature explicitly, meanwhile we still hope to be able to control this feature * on/off by pushing experiment flag for A/B testing and metrics collection on both of Android * Q and R version, however it's disbled on Android Q by default. */ public boolean isDhcpLeaseCacheEnabled() { return mDependencies.isFeatureEnabled(mContext, DHCP_INIT_REBOOT_VERSION); final boolean defaultEnabled = ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q); return mDependencies.isFeatureEnabled(mContext, DHCP_INIT_REBOOT_VERSION, defaultEnabled); } /** * check whether or not to support DHCP Rapid Commit option. */ public boolean isDhcpRapidCommitEnabled() { return mDependencies.isFeatureEnabled(mContext, DHCP_RAPID_COMMIT_VERSION); return mDependencies.isFeatureEnabled(mContext, DHCP_RAPID_COMMIT_VERSION, false /* defaultEnabled */); } /** * check whether or not to support IP address conflict detection and DHCPDECLINE. */ public boolean isDhcpIpConflictDetectEnabled() { return mDependencies.isFeatureEnabled(mContext, DHCP_IP_CONFLICT_DETECT_VERSION); return mDependencies.isFeatureEnabled(mContext, DHCP_IP_CONFLICT_DETECT_VERSION, false /* defaultEnabled */); } private void confirmDhcpLease(DhcpPacket packet, DhcpResults results) { Loading
src/android/net/ip/IpClient.java +9 −1 Original line number Diff line number Diff line Loading @@ -458,7 +458,7 @@ public class IpClient extends StateMachine { private final SharedLog mLog; private final LocalLog mConnectivityPacketLog; private final MessageHandlingLogger mMsgStateLogger; private final IpConnectivityLog mMetricsLog = new IpConnectivityLog(); private final IpConnectivityLog mMetricsLog; private final InterfaceController mInterfaceCtrl; // Ignore nonzero RDNSS option lifetimes below this value. 0 = disabled. Loading Loading @@ -537,6 +537,13 @@ public class IpClient extends StateMachine { return NetworkStackUtils.getDeviceConfigPropertyInt(NAMESPACE_CONNECTIVITY, name, defaultValue); } /** * Get a IpConnectivityLog instance. */ public IpConnectivityLog getIpConnectivityLog() { return new IpConnectivityLog(); } } public IpClient(Context context, String ifName, IIpClientCallbacks callback, Loading @@ -558,6 +565,7 @@ public class IpClient extends StateMachine { mInterfaceName = ifName; mClatInterfaceName = CLAT_PREFIX + ifName; mDependencies = deps; mMetricsLog = deps.getIpConnectivityLog(); mShutdownLatch = new CountDownLatch(1); mCm = mContext.getSystemService(ConnectivityManager.class); mObserverRegistry = observerRegistry; Loading
src/android/net/util/NetworkStackUtils.java +1 −3 Original line number Diff line number Diff line Loading @@ -355,9 +355,7 @@ public class NetworkStackUtils { */ public static boolean isFeatureEnabled(@NonNull Context context, @NonNull String namespace, @NonNull String name) { final int propertyVersion = getDeviceConfigPropertyInt(namespace, name, 0 /* default value */); return isFeatureEnabled(context, namespace, name, false); return isFeatureEnabled(context, namespace, name, false /* defaultEnabled */); } /** Loading
tests/integration/src/android/net/ip/IpClientIntegrationTest.java +4 −2 Original line number Diff line number Diff line Loading @@ -141,6 +141,7 @@ import com.android.server.NetworkObserverRegistry; import com.android.server.NetworkStackService.NetworkStackServiceManager; import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService; import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import com.android.testutils.HandlerUtilsKt; import com.android.testutils.TapPacketReader; Loading Loading @@ -319,7 +320,8 @@ public class IpClientIntegrationTest { NetworkStackIpMemoryStore ipMemoryStore) { return new DhcpClient.Dependencies(ipMemoryStore) { @Override public boolean isFeatureEnabled(final Context context, final String name) { public boolean isFeatureEnabled(final Context context, final String name, final boolean defaultEnabled) { switch (name) { case NetworkStackUtils.DHCP_RAPID_COMMIT_VERSION: return mIsDhcpRapidCommitEnabled; Loading Loading @@ -1066,7 +1068,7 @@ public class IpClientIntegrationTest { assertIpMemoryStoreNetworkAttributes(null, currentTime, TEST_DEFAULT_MTU); } @Test @Test @IgnoreAfter(Build.VERSION_CODES.Q) // INIT-REBOOT is enabled on R. public void testHandleDisableInitRebootState() throws Exception { performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S, false /* isDhcpLeaseCacheEnabled */, false /* shouldReplyRapidCommitAck */, Loading
tests/integration/src/android/net/netlink/InetDiagSocketIntegrationTest.java 0 → 100644 +223 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.netlink; import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.AF_INET6; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; import static android.system.OsConstants.SOCK_STREAM; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assume.assumeTrue; import android.app.Instrumentation; import android.content.Context; import android.net.ConnectivityManager; import android.os.Process; import android.system.Os; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.networkstack.apishim.common.ShimUtils; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.io.FileDescriptor; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; @RunWith(AndroidJUnit4.class) @SmallTest public class InetDiagSocketIntegrationTest { private ConnectivityManager mCm; private Context mContext; @Before public void setUp() throws Exception { Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); mContext = instrumentation.getTargetContext(); mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); } private class Connection { public int socketDomain; public int socketType; public InetAddress localAddress; public InetAddress remoteAddress; public InetAddress localhostAddress; public InetSocketAddress local; public InetSocketAddress remote; public int protocol; public FileDescriptor localFd; public FileDescriptor remoteFd; public FileDescriptor createSocket() throws Exception { return Os.socket(socketDomain, socketType, protocol); } Connection(String to, String from) throws Exception { remoteAddress = InetAddress.getByName(to); if (from != null) { localAddress = InetAddress.getByName(from); } else { localAddress = (remoteAddress instanceof Inet4Address) ? Inet4Address.getByName("localhost") : Inet6Address.getByName("::"); } if ((localAddress instanceof Inet4Address) && (remoteAddress instanceof Inet4Address)) { socketDomain = AF_INET; localhostAddress = Inet4Address.getByName("localhost"); } else { socketDomain = AF_INET6; localhostAddress = Inet6Address.getByName("::"); } } public void close() throws Exception { Os.close(localFd); } } private class TcpConnection extends Connection { TcpConnection(String to, String from) throws Exception { super(to, from); protocol = IPPROTO_TCP; socketType = SOCK_STREAM; remoteFd = createSocket(); Os.bind(remoteFd, remoteAddress, 0); Os.listen(remoteFd, 10); int remotePort = ((InetSocketAddress) Os.getsockname(remoteFd)).getPort(); localFd = createSocket(); Os.bind(localFd, localAddress, 0); Os.connect(localFd, remoteAddress, remotePort); local = (InetSocketAddress) Os.getsockname(localFd); remote = (InetSocketAddress) Os.getpeername(localFd); } public void close() throws Exception { super.close(); Os.close(remoteFd); } } private class UdpConnection extends Connection { UdpConnection(String to, String from) throws Exception { super(to, from); protocol = IPPROTO_UDP; socketType = SOCK_DGRAM; remoteFd = null; localFd = createSocket(); Os.bind(localFd, localAddress, 0); Os.connect(localFd, remoteAddress, 7); local = (InetSocketAddress) Os.getsockname(localFd); remote = new InetSocketAddress(remoteAddress, 7); } } private void checkConnectionOwnerUid(int protocol, InetSocketAddress local, InetSocketAddress remote, boolean expectSuccess) { final int uid = mCm.getConnectionOwnerUid(protocol, local, remote); if (expectSuccess) { assertEquals(Process.myUid(), uid); } else { assertNotEquals(Process.myUid(), uid); } } private int findLikelyFreeUdpPort(UdpConnection conn) throws Exception { UdpConnection udp = new UdpConnection(conn.remoteAddress.getHostAddress(), conn.localAddress.getHostAddress()); final int localPort = udp.local.getPort(); udp.close(); return localPort; } /** * Create a test connection for UDP and TCP sockets and verify that this * {protocol, local, remote} socket result in receiving a valid UID. */ public void checkGetConnectionOwnerUid(String to, String from) throws Exception { TcpConnection tcp = new TcpConnection(to, from); checkConnectionOwnerUid(tcp.protocol, tcp.local, tcp.remote, true); checkConnectionOwnerUid(IPPROTO_UDP, tcp.local, tcp.remote, false); checkConnectionOwnerUid(tcp.protocol, new InetSocketAddress(0), tcp.remote, false); checkConnectionOwnerUid(tcp.protocol, tcp.local, new InetSocketAddress(0), false); tcp.close(); UdpConnection udp = new UdpConnection(to, from); checkConnectionOwnerUid(udp.protocol, udp.local, udp.remote, true); checkConnectionOwnerUid(IPPROTO_TCP, udp.local, udp.remote, false); checkConnectionOwnerUid(udp.protocol, new InetSocketAddress(findLikelyFreeUdpPort(udp)), udp.remote, false); udp.close(); } @Test public void testGetConnectionOwnerUid() throws Exception { // Skip the test for API <= Q, as b/141603906 this was only fixed in Q-QPR2 assumeTrue(ShimUtils.isAtLeastR()); checkGetConnectionOwnerUid("::", null); checkGetConnectionOwnerUid("::", "::"); checkGetConnectionOwnerUid("0.0.0.0", null); checkGetConnectionOwnerUid("0.0.0.0", "0.0.0.0"); checkGetConnectionOwnerUid("127.0.0.1", null); checkGetConnectionOwnerUid("127.0.0.1", "127.0.0.2"); checkGetConnectionOwnerUid("::1", null); checkGetConnectionOwnerUid("::1", "::1"); } /* Verify fix for b/141603906 */ @Test public void testB141603906() throws Exception { // Skip the test for API <= Q, as b/141603906 this was only fixed in Q-QPR2 assumeTrue(ShimUtils.isAtLeastR()); final InetSocketAddress src = new InetSocketAddress(0); final InetSocketAddress dst = new InetSocketAddress(0); final int numThreads = 8; final int numSockets = 5000; final Thread[] threads = new Thread[numThreads]; for (int i = 0; i < numThreads; i++) { threads[i] = new Thread(() -> { for (int j = 0; j < numSockets; j++) { mCm.getConnectionOwnerUid(IPPROTO_TCP, src, dst); } }); } for (Thread thread : threads) { thread.start(); } for (Thread thread : threads) { thread.join(); } } }