Immediately create native networks when NetworkAgents register.
Currently, native networks for non-VPN networks are created only when the NetworkAgent goes into the CONNECTED state. This is not ideal, because until the network is connected: - Nothing routes to the network, so no IP packets can be sent on it (except via packet sockets). - Many network configuration changes (e.g., routes and DNS servers) fail to apply because the network does not exist yet. These cause ENONET errors in the logs. Fix this starting in U by creating the native network as soon as the agent registers. This should not impact apps because NetworkCallbacks are not sent until networks are connected. Bug: 143158421 Test: new coverage in NetworkAgentTest Change-Id: I26bfa8630c085422175558645c47a6c64be96ae6
This commit is contained in:
@@ -2597,7 +2597,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
final ArrayList<NetworkStateSnapshot> result = new ArrayList<>();
|
||||
for (Network network : getAllNetworks()) {
|
||||
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
|
||||
if (nai != null && nai.everConnected()) {
|
||||
final boolean includeNetwork = (nai != null) && nai.isCreated();
|
||||
if (includeNetwork) {
|
||||
// TODO (b/73321673) : NetworkStateSnapshot contains a copy of the
|
||||
// NetworkCapabilities, which may contain UIDs of apps to which the
|
||||
// network applies. Should the UIDs be cleared so as not to leak or
|
||||
@@ -3799,9 +3800,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
break;
|
||||
}
|
||||
case NetworkAgent.EVENT_UNREGISTER_AFTER_REPLACEMENT: {
|
||||
if (!nai.isCreated()) {
|
||||
Log.d(TAG, "unregisterAfterReplacement on uncreated " + nai.toShortString()
|
||||
+ ", tearing down instead");
|
||||
if (!nai.everConnected()) {
|
||||
Log.d(TAG, "unregisterAfterReplacement on never-connected "
|
||||
+ nai.toShortString() + ", tearing down instead");
|
||||
teardownUnneededNetwork(nai);
|
||||
break;
|
||||
}
|
||||
@@ -4386,6 +4387,25 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected static boolean shouldCreateNetworksImmediately() {
|
||||
// Before U, physical networks are only created when the agent advances to CONNECTED.
|
||||
// In U and above, all networks are immediately created when the agent is registered.
|
||||
return SdkLevel.isAtLeastU();
|
||||
}
|
||||
|
||||
private static boolean shouldCreateNativeNetwork(@NonNull NetworkAgentInfo nai,
|
||||
@NonNull NetworkInfo.State state) {
|
||||
if (nai.isCreated()) return false;
|
||||
if (state == NetworkInfo.State.CONNECTED) return true;
|
||||
if (state != NetworkInfo.State.CONNECTING) {
|
||||
// TODO: throw if no WTFs are observed in the field.
|
||||
Log.wtf(TAG, "Uncreated network in invalid state: " + state);
|
||||
return false;
|
||||
}
|
||||
return nai.isVPN() || shouldCreateNetworksImmediately();
|
||||
}
|
||||
|
||||
private static boolean shouldDestroyNativeNetwork(@NonNull NetworkAgentInfo nai) {
|
||||
return nai.isCreated() && !nai.isDestroyed();
|
||||
}
|
||||
@@ -7823,7 +7843,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
|
||||
if (isDefaultNetwork(networkAgent)) {
|
||||
handleApplyDefaultProxy(newLp.getHttpProxy());
|
||||
} else {
|
||||
} else if (networkAgent.everConnected()) {
|
||||
updateProxy(newLp, oldLp);
|
||||
}
|
||||
|
||||
@@ -7857,6 +7877,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent);
|
||||
}
|
||||
|
||||
private void applyInitialLinkProperties(@NonNull NetworkAgentInfo nai) {
|
||||
updateLinkProperties(nai, new LinkProperties(nai.linkProperties), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param naData captive portal data from NetworkAgent
|
||||
* @param apiData captive portal data from capport API
|
||||
@@ -9608,21 +9632,32 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
+ oldInfo.getState() + " to " + state);
|
||||
}
|
||||
|
||||
if (!networkAgent.isCreated()
|
||||
&& (state == NetworkInfo.State.CONNECTED
|
||||
|| (state == NetworkInfo.State.CONNECTING && networkAgent.isVPN()))) {
|
||||
|
||||
if (shouldCreateNativeNetwork(networkAgent, state)) {
|
||||
// A network that has just connected has zero requests and is thus a foreground network.
|
||||
networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
|
||||
|
||||
if (!createNativeNetwork(networkAgent)) return;
|
||||
|
||||
networkAgent.setCreated();
|
||||
|
||||
// If the network is created immediately on register, then apply the LinkProperties now.
|
||||
// Otherwise, this is done further down when the network goes into connected state.
|
||||
// Applying the LinkProperties means that the network is ready to carry traffic -
|
||||
// interfaces and routing rules have been added, DNS servers programmed, etc.
|
||||
// For VPNs, this must be done before the capabilities are updated, because as soon as
|
||||
// that happens, UIDs are routed to the network.
|
||||
if (shouldCreateNetworksImmediately()) {
|
||||
applyInitialLinkProperties(networkAgent);
|
||||
}
|
||||
|
||||
// TODO: should this move earlier? It doesn't seem to have anything to do with whether
|
||||
// a network is created or not.
|
||||
if (networkAgent.propagateUnderlyingCapabilities()) {
|
||||
// Initialize the network's capabilities to their starting values according to the
|
||||
// underlying networks. This ensures that the capabilities are correct before
|
||||
// anything happens to the network.
|
||||
updateCapabilitiesForNetwork(networkAgent);
|
||||
}
|
||||
networkAgent.setCreated();
|
||||
networkAgent.onNetworkCreated();
|
||||
updateAllowedUids(networkAgent, null, networkAgent.networkCapabilities);
|
||||
updateProfileAllowedNetworks();
|
||||
@@ -9636,8 +9671,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
networkAgent.getAndSetNetworkCapabilities(networkAgent.networkCapabilities);
|
||||
|
||||
handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
|
||||
updateLinkProperties(networkAgent, new LinkProperties(networkAgent.linkProperties),
|
||||
null);
|
||||
if (!shouldCreateNetworksImmediately()) {
|
||||
applyInitialLinkProperties(networkAgent);
|
||||
} else {
|
||||
// The network was created when the agent registered, and the LinkProperties are
|
||||
// already up-to-date. However, updateLinkProperties also makes some changes only
|
||||
// when the network connects. Apply those changes here. On T and below these are
|
||||
// handled by the applyInitialLinkProperties call just above.
|
||||
// TODO: stop relying on updateLinkProperties(..., null) to do this.
|
||||
// If something depends on both LinkProperties and connected state, it should be in
|
||||
// this method as well.
|
||||
networkAgent.clatd.update();
|
||||
updateProxy(networkAgent.linkProperties, null);
|
||||
}
|
||||
|
||||
// If a rate limit has been configured and is applicable to this network (network
|
||||
// provides internet connectivity), apply it. The tc police filter cannot be attached
|
||||
|
||||
Reference in New Issue
Block a user