Make NetworkCapabilities authoritative for suspended state

...instead of NetworkInfo

Bug: 138306002
Test: FrameworksNetTests FrameworksTelephonyTests
Change-Id: I4808fcc0047a926b23ed3d49d979bb7b0371dc69
This commit is contained in:
Chalard Jean
2020-01-14 22:46:36 +09:00
parent db2f8836de
commit 45d4f10c42
3 changed files with 46 additions and 31 deletions

View File

@@ -39,6 +39,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.uidRulesToString;
@@ -5840,11 +5841,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
} else {
newNc.addCapability(NET_CAPABILITY_FOREGROUND);
}
if (nai.isSuspended()) {
newNc.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
} else {
newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
}
if (nai.partialConnectivity) {
newNc.addCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
} else {
@@ -5852,6 +5848,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
newNc.setPrivateDnsBroken(nai.networkCapabilities.isPrivateDnsBroken());
// TODO : remove this once all factories are updated to send NOT_SUSPENDED
if (!newNc.hasTransport(TRANSPORT_CELLULAR)) {
newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
}
return newNc;
}
@@ -5896,6 +5897,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
// on this network. We might have been called by rematchNetworkAndRequests when a
// network changed foreground state.
processListenRequests(nai);
final boolean prevSuspended = !prevNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
final boolean suspended = !newNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
if (prevSuspended != suspended) {
// TODO (b/73132094) : remove this call once the few users of onSuspended and
// onResumed have been removed.
notifyNetworkCallbacks(nai, suspended ? ConnectivityManager.CALLBACK_SUSPENDED
: ConnectivityManager.CALLBACK_RESUMED);
// updateNetworkInfo will mix in the suspended info from the capabilities and
// take appropriate action for the network having possibly changed state.
updateNetworkInfo(nai, nai.networkInfo);
}
} else {
// If the requestable capabilities have changed or the score changed, we can't have been
// called by rematchNetworkAndRequests, so it's safe to start a rematch.
@@ -5903,6 +5915,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
}
// TODO : static analysis indicates that prevNc can't be null here (getAndSetNetworkCaps
// never returns null), so mark the relevant members and functions in nai as @NonNull and
// remove this test
if (prevNc != null) {
final boolean oldMetered = prevNc.isMetered();
final boolean newMetered = newNc.isMetered();
@@ -6597,10 +6612,30 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
@NonNull
private NetworkInfo mixInInfo(@NonNull final NetworkAgentInfo nai, @NonNull NetworkInfo info) {
final NetworkInfo newInfo = new NetworkInfo(info);
// The suspended bit is managed in NetworkCapabilities.
final boolean suspended =
!nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
if (suspended && info.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) {
// Only override the state with SUSPENDED if the network is currently in CONNECTED
// state. This is because the network could have been suspended before connecting,
// or it could be disconnecting while being suspended, and in both these cases
// the state should not be overridden. Note that the only detailed state that
// maps to State.CONNECTED is DetailedState.CONNECTED, so there is also no need to
// worry about multiple different substates of CONNECTED.
newInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, info.getReason(),
info.getExtraInfo());
}
return newInfo;
}
private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo info) {
final NetworkInfo newInfo = mixInInfo(networkAgent, info);
final NetworkInfo.State state = newInfo.getState();
NetworkInfo oldInfo = null;
final int oldScore = networkAgent.getCurrentScore();
synchronized (networkAgent) {
oldInfo = networkAgent.networkInfo;
networkAgent.networkInfo = newInfo;
@@ -6682,17 +6717,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
} else if (networkAgent.created && (oldInfo.getState() == NetworkInfo.State.SUSPENDED ||
state == NetworkInfo.State.SUSPENDED)) {
// going into or coming out of SUSPEND: re-score and notify
if (networkAgent.getCurrentScore() != oldScore) {
rematchAllNetworksAndRequests();
}
updateCapabilities(networkAgent.getCurrentScore(), networkAgent,
networkAgent.networkCapabilities);
// TODO (b/73132094) : remove this call once the few users of onSuspended and
// onResumed have been removed.
notifyNetworkCallbacks(networkAgent, (state == NetworkInfo.State.SUSPENDED ?
ConnectivityManager.CALLBACK_SUSPENDED :
ConnectivityManager.CALLBACK_RESUMED));
mLegacyTypeTracker.update(networkAgent);
}
}

View File

@@ -451,15 +451,6 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
&& !isLingering();
}
/**
* Returns whether this network is currently suspended. A network is suspended if it is still
* connected but data temporarily fails to transfer. See {@link NetworkInfo.State#SUSPENDED}
* and {@link NetworkCapabilities#NET_CAPABILITY_NOT_SUSPENDED}.
*/
public boolean isSuspended() {
return networkInfo.getState() == NetworkInfo.State.SUSPENDED;
}
// Does this network satisfy request?
public boolean satisfies(NetworkRequest request) {
return created &&

View File

@@ -16,6 +16,7 @@
package com.android.server;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
@@ -74,6 +75,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork {
final String typeName = ConnectivityManager.getNetworkTypeName(type);
mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
mNetworkCapabilities = new NetworkCapabilities();
mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
mNetworkCapabilities.addTransportType(transport);
switch (transport) {
case TRANSPORT_ETHERNET:
@@ -206,13 +208,11 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork {
}
public void suspend() {
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, null, null);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
}
public void resume() {
mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
addCapability(NET_CAPABILITY_NOT_SUSPENDED);
}
public void disconnect() {