Loading common/moduleutils/src/android/net/util/FdEventsReader.java +9 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.system.OsConstants; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import java.io.FileDescriptor; import java.io.IOException; Loading Loading @@ -92,6 +93,12 @@ public abstract class FdEventsReader<BufferType> { mBuffer = buffer; } @VisibleForTesting @NonNull protected MessageQueue getMessageQueue() { return mQueue; } /** Start this FdEventsReader. */ public boolean start() { if (!onCorrectThread()) { Loading Loading @@ -185,7 +192,7 @@ public abstract class FdEventsReader<BufferType> { if (mFd == null) return false; mQueue.addOnFileDescriptorEventListener( getMessageQueue().addOnFileDescriptorEventListener( mFd, FD_EVENTS, (fd, events) -> { Loading Loading @@ -247,7 +254,7 @@ public abstract class FdEventsReader<BufferType> { private void unregisterAndDestroyFd() { if (mFd == null) return; mQueue.removeOnFileDescriptorEventListener(mFd); getMessageQueue().removeOnFileDescriptorEventListener(mFd); closeFd(mFd); mFd = null; onStop(); Loading src/android/net/ip/IpClient.java +11 −8 Original line number Diff line number Diff line Loading @@ -772,14 +772,6 @@ public class IpClient extends StateMachine { return; } mInterfaceParams = mDependencies.getInterfaceParams(mInterfaceName); if (mInterfaceParams == null) { logError("Failed to find InterfaceParams for " + mInterfaceName); doImmediateProvisioningFailure(IpManagerEvent.ERROR_INTERFACE_NOT_FOUND); return; } mCallback.setNeighborDiscoveryOffload(true); sendMessage(CMD_START, new android.net.shared.ProvisioningConfiguration(req)); } Loading Loading @@ -1650,6 +1642,17 @@ public class IpClient extends StateMachine { // tethering or during an IpClient restart. stopAllIP(); } // Ensure that interface parameters are fetched on the handler thread so they are // properly ordered with other events, such as restoring the interface MTU on teardown. mInterfaceParams = mDependencies.getInterfaceParams(mInterfaceName); if (mInterfaceParams == null) { logError("Failed to find InterfaceParams for " + mInterfaceName); doImmediateProvisioningFailure(IpManagerEvent.ERROR_INTERFACE_NOT_FOUND); transitionTo(mStoppedState); return; } mCallback.setNeighborDiscoveryOffload(true); } @Override Loading src/android/net/ip/IpReachabilityMonitor.java +9 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.net.INetd; import android.net.LinkProperties; import android.net.RouteInfo; import android.net.ip.IpNeighborMonitor.NeighborEvent; import android.net.ip.IpNeighborMonitor.NeighborEventConsumer; import android.net.metrics.IpConnectivityLog; import android.net.metrics.IpReachabilityEvent; import android.net.netlink.StructNdMsg; Loading Loading @@ -154,11 +155,12 @@ public class IpReachabilityMonitor { } /** * Encapsulates IpReachabilityMonitor depencencies on systems that hinder unit testing. * Encapsulates IpReachabilityMonitor dependencies on systems that hinder unit testing. * TODO: consider also wrapping MultinetworkPolicyTracker in this interface. */ interface Dependencies { void acquireWakeLock(long durationMs); IpNeighborMonitor makeIpNeighborMonitor(Handler h, SharedLog log, NeighborEventConsumer cb); static Dependencies makeDefault(Context context, String iface) { final String lockName = TAG + "." + iface; Loading @@ -169,6 +171,11 @@ public class IpReachabilityMonitor { public void acquireWakeLock(long durationMs) { lock.acquire(durationMs); } public IpNeighborMonitor makeIpNeighborMonitor(Handler h, SharedLog log, NeighborEventConsumer cb) { return new IpNeighborMonitor(h, log, cb); } }; } } Loading Loading @@ -223,7 +230,7 @@ public class IpReachabilityMonitor { } setNeighbourParametersForSteadyState(); mIpNeighborMonitor = new IpNeighborMonitor(h, mLog, mIpNeighborMonitor = mDependencies.makeIpNeighborMonitor(h, mLog, (NeighborEvent event) -> { if (mInterfaceParams.index != event.ifindex) return; if (!mNeighborWatchList.containsKey(event.ip)) return; Loading src/com/android/server/connectivity/NetworkMonitor.java +1 −1 Original line number Diff line number Diff line Loading @@ -621,7 +621,7 @@ public class NetworkMonitor extends StateMachine { private void notifyNetworkTested( int result, @Nullable String redirectUrl, PersistableBundle extras) { try { if (mCallbackVersion <= 4) { if (mCallbackVersion <= 5) { mCallback.notifyNetworkTested(result, redirectUrl); } else { mCallback.notifyNetworkTestedWithExtras( Loading tests/integration/src/android/net/ip/IpClientIntegrationTest.java +49 −3 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ import com.android.networkstack.arp.ArpPacket; import com.android.server.NetworkObserverRegistry; import com.android.server.NetworkStackService.NetworkStackServiceManager; import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService; import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import com.android.testutils.HandlerUtilsKt; import com.android.testutils.TapPacketReader; Loading Loading @@ -524,7 +525,6 @@ public class IpClientIntegrationTest { mDependencies.setHostnameConfiguration(isHostnameConfigurationEnabled, hostname); mIpc.setL2KeyAndGroupHint(TEST_L2KEY, TEST_GROUPHINT); mIpc.startProvisioning(builder.build()); verify(mCb).setNeighborDiscoveryOffload(true); if (!isPreconnectionEnabled) { verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(false); } Loading Loading @@ -642,7 +642,6 @@ public class IpClientIntegrationTest { ArgumentCaptor.forClass(LinkProperties.class); verifyProvisioningSuccess(captor, Collections.singletonList(CLIENT_ADDR)); } return packetList; } } Loading @@ -660,6 +659,12 @@ public class IpClientIntegrationTest { null /* captivePortalApiUrl */, null /* displayName */, null /* scanResultInfo */); } private List<DhcpPacket> performDhcpHandshake() throws Exception { return performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S, false /* isDhcpLeaseCacheEnabled */, false /* shouldReplyRapidCommitAck */, TEST_DEFAULT_MTU, false /* isDhcpIpConflictDetectEnabled */); } private DhcpPacket getNextDhcpPacket() throws ParseException { byte[] packet; while ((packet = mPacketReader.popPacket(PACKET_TIMEOUT_MS)) != null) { Loading Loading @@ -725,6 +730,12 @@ public class IpClientIntegrationTest { assertEquals(NetworkInterface.getByName(mIfaceName).getMTU(), mtu); } // Sometimes, IpClient receives an update with an empty LinkProperties during startup, // when the link-local address is deleted after interface bringup. Reset expectations // here to ensure that verifyAfterIpClientShutdown does not fail because it sees two // empty LinkProperties changes instead of one. reset(mCb); if (shouldRemoveTapInterface) removeTapInterface(mTapFd); try { mIpc.shutdown(); Loading Loading @@ -1047,6 +1058,14 @@ public class IpClientIntegrationTest { assertTrue(packet instanceof DhcpDiscoverPacket); } @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testDhcpServerInLinkProperties() throws Exception { performDhcpHandshake(); ArgumentCaptor<LinkProperties> captor = ArgumentCaptor.forClass(LinkProperties.class); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningSuccess(captor.capture()); assertEquals(SERVER_ADDR, captor.getValue().getDhcpServerAddress()); } @Test public void testRestoreInitialInterfaceMtu() throws Exception { doRestoreInitialMtuTest(true /* shouldChangeMtu */, false /* shouldRemoveTapInterface */); Loading Loading @@ -1081,10 +1100,37 @@ public class IpClientIntegrationTest { .build(); mIpc.startProvisioning(config); verify(mCb).onProvisioningFailure(any()); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningFailure(any()); verify(mCb, never()).setNeighborDiscoveryOffload(true); } @Test public void testRestoreInitialInterfaceMtu_stopIpClientAndRestart() throws Exception { long currentTime = System.currentTimeMillis(); performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S, true /* isDhcpLeaseCacheEnabled */, false /* shouldReplyRapidCommitAck */, TEST_MIN_MTU, false /* isDhcpIpConflictDetectEnabled */); assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime, TEST_MIN_MTU); // Pretend that ConnectivityService set the MTU. mNetd.interfaceSetMtu(mIfaceName, TEST_MIN_MTU); assertEquals(NetworkInterface.getByName(mIfaceName).getMTU(), TEST_MIN_MTU); reset(mCb); reset(mIpMemoryStore); // Stop IpClient and then restart provisioning immediately. mIpc.stop(); currentTime = System.currentTimeMillis(); // Intend to set mtu option to 0, then verify that won't influence interface mtu restore. performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S, true /* isDhcpLeaseCacheEnabled */, false /* shouldReplyRapidCommitAck */, 0 /* mtu */, false /* isDhcpIpConflictDetectEnabled */); assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime, 0 /* mtu */); assertEquals(NetworkInterface.getByName(mIfaceName).getMTU(), TEST_DEFAULT_MTU); } private boolean isRouterSolicitation(final byte[] packetBytes) { ByteBuffer packet = ByteBuffer.wrap(packetBytes); return packet.getShort(ETHER_TYPE_OFFSET) == (short) ETH_P_IPV6 Loading Loading
common/moduleutils/src/android/net/util/FdEventsReader.java +9 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.system.OsConstants; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import java.io.FileDescriptor; import java.io.IOException; Loading Loading @@ -92,6 +93,12 @@ public abstract class FdEventsReader<BufferType> { mBuffer = buffer; } @VisibleForTesting @NonNull protected MessageQueue getMessageQueue() { return mQueue; } /** Start this FdEventsReader. */ public boolean start() { if (!onCorrectThread()) { Loading Loading @@ -185,7 +192,7 @@ public abstract class FdEventsReader<BufferType> { if (mFd == null) return false; mQueue.addOnFileDescriptorEventListener( getMessageQueue().addOnFileDescriptorEventListener( mFd, FD_EVENTS, (fd, events) -> { Loading Loading @@ -247,7 +254,7 @@ public abstract class FdEventsReader<BufferType> { private void unregisterAndDestroyFd() { if (mFd == null) return; mQueue.removeOnFileDescriptorEventListener(mFd); getMessageQueue().removeOnFileDescriptorEventListener(mFd); closeFd(mFd); mFd = null; onStop(); Loading
src/android/net/ip/IpClient.java +11 −8 Original line number Diff line number Diff line Loading @@ -772,14 +772,6 @@ public class IpClient extends StateMachine { return; } mInterfaceParams = mDependencies.getInterfaceParams(mInterfaceName); if (mInterfaceParams == null) { logError("Failed to find InterfaceParams for " + mInterfaceName); doImmediateProvisioningFailure(IpManagerEvent.ERROR_INTERFACE_NOT_FOUND); return; } mCallback.setNeighborDiscoveryOffload(true); sendMessage(CMD_START, new android.net.shared.ProvisioningConfiguration(req)); } Loading Loading @@ -1650,6 +1642,17 @@ public class IpClient extends StateMachine { // tethering or during an IpClient restart. stopAllIP(); } // Ensure that interface parameters are fetched on the handler thread so they are // properly ordered with other events, such as restoring the interface MTU on teardown. mInterfaceParams = mDependencies.getInterfaceParams(mInterfaceName); if (mInterfaceParams == null) { logError("Failed to find InterfaceParams for " + mInterfaceName); doImmediateProvisioningFailure(IpManagerEvent.ERROR_INTERFACE_NOT_FOUND); transitionTo(mStoppedState); return; } mCallback.setNeighborDiscoveryOffload(true); } @Override Loading
src/android/net/ip/IpReachabilityMonitor.java +9 −2 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.net.INetd; import android.net.LinkProperties; import android.net.RouteInfo; import android.net.ip.IpNeighborMonitor.NeighborEvent; import android.net.ip.IpNeighborMonitor.NeighborEventConsumer; import android.net.metrics.IpConnectivityLog; import android.net.metrics.IpReachabilityEvent; import android.net.netlink.StructNdMsg; Loading Loading @@ -154,11 +155,12 @@ public class IpReachabilityMonitor { } /** * Encapsulates IpReachabilityMonitor depencencies on systems that hinder unit testing. * Encapsulates IpReachabilityMonitor dependencies on systems that hinder unit testing. * TODO: consider also wrapping MultinetworkPolicyTracker in this interface. */ interface Dependencies { void acquireWakeLock(long durationMs); IpNeighborMonitor makeIpNeighborMonitor(Handler h, SharedLog log, NeighborEventConsumer cb); static Dependencies makeDefault(Context context, String iface) { final String lockName = TAG + "." + iface; Loading @@ -169,6 +171,11 @@ public class IpReachabilityMonitor { public void acquireWakeLock(long durationMs) { lock.acquire(durationMs); } public IpNeighborMonitor makeIpNeighborMonitor(Handler h, SharedLog log, NeighborEventConsumer cb) { return new IpNeighborMonitor(h, log, cb); } }; } } Loading Loading @@ -223,7 +230,7 @@ public class IpReachabilityMonitor { } setNeighbourParametersForSteadyState(); mIpNeighborMonitor = new IpNeighborMonitor(h, mLog, mIpNeighborMonitor = mDependencies.makeIpNeighborMonitor(h, mLog, (NeighborEvent event) -> { if (mInterfaceParams.index != event.ifindex) return; if (!mNeighborWatchList.containsKey(event.ip)) return; Loading
src/com/android/server/connectivity/NetworkMonitor.java +1 −1 Original line number Diff line number Diff line Loading @@ -621,7 +621,7 @@ public class NetworkMonitor extends StateMachine { private void notifyNetworkTested( int result, @Nullable String redirectUrl, PersistableBundle extras) { try { if (mCallbackVersion <= 4) { if (mCallbackVersion <= 5) { mCallback.notifyNetworkTested(result, redirectUrl); } else { mCallback.notifyNetworkTestedWithExtras( Loading
tests/integration/src/android/net/ip/IpClientIntegrationTest.java +49 −3 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ import com.android.networkstack.arp.ArpPacket; import com.android.server.NetworkObserverRegistry; import com.android.server.NetworkStackService.NetworkStackServiceManager; import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService; import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import com.android.testutils.HandlerUtilsKt; import com.android.testutils.TapPacketReader; Loading Loading @@ -524,7 +525,6 @@ public class IpClientIntegrationTest { mDependencies.setHostnameConfiguration(isHostnameConfigurationEnabled, hostname); mIpc.setL2KeyAndGroupHint(TEST_L2KEY, TEST_GROUPHINT); mIpc.startProvisioning(builder.build()); verify(mCb).setNeighborDiscoveryOffload(true); if (!isPreconnectionEnabled) { verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(false); } Loading Loading @@ -642,7 +642,6 @@ public class IpClientIntegrationTest { ArgumentCaptor.forClass(LinkProperties.class); verifyProvisioningSuccess(captor, Collections.singletonList(CLIENT_ADDR)); } return packetList; } } Loading @@ -660,6 +659,12 @@ public class IpClientIntegrationTest { null /* captivePortalApiUrl */, null /* displayName */, null /* scanResultInfo */); } private List<DhcpPacket> performDhcpHandshake() throws Exception { return performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S, false /* isDhcpLeaseCacheEnabled */, false /* shouldReplyRapidCommitAck */, TEST_DEFAULT_MTU, false /* isDhcpIpConflictDetectEnabled */); } private DhcpPacket getNextDhcpPacket() throws ParseException { byte[] packet; while ((packet = mPacketReader.popPacket(PACKET_TIMEOUT_MS)) != null) { Loading Loading @@ -725,6 +730,12 @@ public class IpClientIntegrationTest { assertEquals(NetworkInterface.getByName(mIfaceName).getMTU(), mtu); } // Sometimes, IpClient receives an update with an empty LinkProperties during startup, // when the link-local address is deleted after interface bringup. Reset expectations // here to ensure that verifyAfterIpClientShutdown does not fail because it sees two // empty LinkProperties changes instead of one. reset(mCb); if (shouldRemoveTapInterface) removeTapInterface(mTapFd); try { mIpc.shutdown(); Loading Loading @@ -1047,6 +1058,14 @@ public class IpClientIntegrationTest { assertTrue(packet instanceof DhcpDiscoverPacket); } @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testDhcpServerInLinkProperties() throws Exception { performDhcpHandshake(); ArgumentCaptor<LinkProperties> captor = ArgumentCaptor.forClass(LinkProperties.class); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningSuccess(captor.capture()); assertEquals(SERVER_ADDR, captor.getValue().getDhcpServerAddress()); } @Test public void testRestoreInitialInterfaceMtu() throws Exception { doRestoreInitialMtuTest(true /* shouldChangeMtu */, false /* shouldRemoveTapInterface */); Loading Loading @@ -1081,10 +1100,37 @@ public class IpClientIntegrationTest { .build(); mIpc.startProvisioning(config); verify(mCb).onProvisioningFailure(any()); verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningFailure(any()); verify(mCb, never()).setNeighborDiscoveryOffload(true); } @Test public void testRestoreInitialInterfaceMtu_stopIpClientAndRestart() throws Exception { long currentTime = System.currentTimeMillis(); performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S, true /* isDhcpLeaseCacheEnabled */, false /* shouldReplyRapidCommitAck */, TEST_MIN_MTU, false /* isDhcpIpConflictDetectEnabled */); assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime, TEST_MIN_MTU); // Pretend that ConnectivityService set the MTU. mNetd.interfaceSetMtu(mIfaceName, TEST_MIN_MTU); assertEquals(NetworkInterface.getByName(mIfaceName).getMTU(), TEST_MIN_MTU); reset(mCb); reset(mIpMemoryStore); // Stop IpClient and then restart provisioning immediately. mIpc.stop(); currentTime = System.currentTimeMillis(); // Intend to set mtu option to 0, then verify that won't influence interface mtu restore. performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S, true /* isDhcpLeaseCacheEnabled */, false /* shouldReplyRapidCommitAck */, 0 /* mtu */, false /* isDhcpIpConflictDetectEnabled */); assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime, 0 /* mtu */); assertEquals(NetworkInterface.getByName(mIfaceName).getMTU(), TEST_DEFAULT_MTU); } private boolean isRouterSolicitation(final byte[] packetBytes) { ByteBuffer packet = ByteBuffer.wrap(packetBytes); return packet.getShort(ETHER_TYPE_OFFSET) == (short) ETH_P_IPV6 Loading