Fix a tethering crash when a 464xlat upstream disconnects.

When a 464xlat upstream disconnects, onLinkPropertiesChanged is
called after onLost. This breaks an UpstreamNetworkMonitor
assumption that no callback will ever arrive after onLost.

Bug: 173068192
Fix: 185117377
Test: new unit test
Change-Id: I4ff1eca6d5ed1680ff716c71b683891c8a0e5a77
This commit is contained in:
Lorenzo Colitti
2021-04-12 16:53:12 +09:00
parent 65bba3f6bc
commit a329e8c984
2 changed files with 23 additions and 6 deletions

View File

@@ -43,6 +43,7 @@ import android.util.Log;
import android.util.SparseIntArray;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.StateMachine;
@@ -402,13 +403,20 @@ public class UpstreamNetworkMonitor {
notifyTarget(EVENT_ON_CAPABILITIES, network);
}
private void updateLinkProperties(Network network, LinkProperties newLp) {
private @Nullable UpstreamNetworkState updateLinkProperties(@NonNull Network network,
LinkProperties newLp) {
final UpstreamNetworkState prev = mNetworkMap.get(network);
if (prev == null || newLp.equals(prev.linkProperties)) {
// Ignore notifications about networks for which we have not yet
// received onAvailable() (should never happen) and any duplicate
// notifications (e.g. matching more than one of our callbacks).
return;
//
// Also, it can happen that onLinkPropertiesChanged is called after
// onLost removed the state from mNetworkMap. This appears to be due
// to a bug in disconnectAndDestroyNetwork, which calls
// nai.clatd.update() after the onLost callbacks.
// TODO: fix the bug and make this method void.
return null;
}
if (VDBG) {
@@ -416,13 +424,17 @@ public class UpstreamNetworkMonitor {
network, newLp));
}
mNetworkMap.put(network, new UpstreamNetworkState(
newLp, prev.networkCapabilities, network));
final UpstreamNetworkState ns = new UpstreamNetworkState(newLp, prev.networkCapabilities,
network);
mNetworkMap.put(network, ns);
return ns;
}
private void handleLinkProp(Network network, LinkProperties newLp) {
updateLinkProperties(network, newLp);
notifyTarget(EVENT_ON_LINKPROPERTIES, network);
final UpstreamNetworkState ns = updateLinkProperties(network, newLp);
if (ns != null) {
notifyTarget(EVENT_ON_LINKPROPERTIES, ns);
}
}
private void handleLost(Network network) {

View File

@@ -1184,6 +1184,11 @@ public class TetheringTest {
assertTrue(mUpstreamNetworkMonitor.getCurrentPreferredUpstream().linkProperties
.hasIPv4Address());
// Check that the code does not crash if onLinkPropertiesChanged is received after onLost.
mobile.fakeDisconnect();
mobile.sendLinkProperties();
mLooper.dispatchAll();
}
private void runNcmTethering() {