Always stop dhcp server even it is obsolete

If dhcp server is obsolete, explicitly stop it to shut down its thread.

Bug: 161418295
Test: atest CtsTetheringTest
Change-Id: Ic5b876bd23711ec8d832879a7baee0495246b218
This commit is contained in:
markchien
2020-07-22 21:28:48 +08:00
parent af9ec640c9
commit af2670f427
2 changed files with 50 additions and 14 deletions

View File

@@ -422,9 +422,13 @@ public class IpServer extends StateMachine {
getHandler().post(() -> {
// We are on the handler thread: mDhcpServerStartIndex can be read safely.
if (mStartIndex != mDhcpServerStartIndex) {
// This start request is obsolete. When the |server| binder token goes out of
// scope, the garbage collector will finalize it, which causes the network stack
// process garbage collector to collect the server itself.
// This start request is obsolete. Explicitly stop the DHCP server to shut
// down its thread. When the |server| binder token goes out of scope, the
// garbage collector will finalize it, which causes the network stack process
// garbage collector to collect the server itself.
try {
server.stop(null);
} catch (RemoteException e) { }
return;
}

View File

@@ -49,6 +49,7 @@ import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
@@ -72,6 +73,7 @@ import android.net.MacAddress;
import android.net.RouteInfo;
import android.net.TetherOffloadRuleParcel;
import android.net.TetherStatsParcel;
import android.net.dhcp.DhcpServerCallbacks;
import android.net.dhcp.DhcpServingParamsParcel;
import android.net.dhcp.IDhcpEventCallbacks;
import android.net.dhcp.IDhcpServer;
@@ -162,17 +164,6 @@ public class IpServerTest {
private void initStateMachine(int interfaceType, boolean usingLegacyDhcp,
boolean usingBpfOffload) throws Exception {
doAnswer(inv -> {
final IDhcpServerCallbacks cb = inv.getArgument(2);
new Thread(() -> {
try {
cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
} catch (RemoteException e) {
fail(e.getMessage());
}
}).run();
return null;
}).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any());
when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
@@ -224,6 +215,20 @@ public class IpServerTest {
when(mAddressCoordinator.requestDownstreamAddress(any())).thenReturn(mTestAddress);
}
private void setUpDhcpServer() throws Exception {
doAnswer(inv -> {
final IDhcpServerCallbacks cb = inv.getArgument(2);
new Thread(() -> {
try {
cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
} catch (RemoteException e) {
fail(e.getMessage());
}
}).run();
return null;
}).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any());
}
@Before public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog);
@@ -257,6 +262,8 @@ public class IpServerTest {
return mTetherConfig;
}
}));
setUpDhcpServer();
}
@Test
@@ -964,6 +971,31 @@ public class IpServerTest {
reset(mRaDaemon);
}
@Test
public void testStopObsoleteDhcpServer() throws Exception {
final ArgumentCaptor<DhcpServerCallbacks> cbCaptor =
ArgumentCaptor.forClass(DhcpServerCallbacks.class);
doNothing().when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(),
cbCaptor.capture());
initStateMachine(TETHERING_WIFI);
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
verify(mDhcpServer, never()).startWithCallbacks(any(), any());
// No stop dhcp server because dhcp server is not created yet.
dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
verify(mDhcpServer, never()).stop(any());
// Stop obsolete dhcp server.
try {
final DhcpServerCallbacks cb = cbCaptor.getValue();
cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
mLooper.dispatchAll();
} catch (RemoteException e) {
fail(e.getMessage());
}
verify(mDhcpServer).stop(any());
}
private void assertDhcpServingParams(final DhcpServingParamsParcel params,
final IpPrefix prefix) {
// Last address byte is random