Transmitting multiple default networks to netd

Updating ConnectivityService to transmit network information to netd as
part of supporting multiple default networks.

Bug: 176191930
Bug: 172347841
Test: atest FrameworksNetTests
atest NetworkStackTests
atest FrameworksNetIntegrationTests
atest NetworkStackIntegrationTests
atest CtsNetTestCasesLatestSdk

Change-Id: I5851a36e3c3ccb45f4cb3ff85e0fc1352f64dc70
This commit is contained in:
James Mattis 2020-12-23 16:37:26 -08:00
commit d31bdfaa0c

View file

@ -1227,6 +1227,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
mDnsManager = new DnsManager(mContext, mDnsResolver);
registerPrivateDnsSettingsCallbacks();
mNoServiceNetwork = new NetworkAgentInfo(null,
new Network(NO_SERVICE_NET_ID),
new NetworkInfo(TYPE_NONE, 0, "", ""),
new LinkProperties(), new NetworkCapabilities(), 0, mContext,
null, new NetworkAgentConfig(), this, null,
null, null, 0, INVALID_UID,
mQosCallbackTracker);
}
private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
@ -3446,13 +3454,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
propagateUnderlyingNetworkCapabilities(nai.network);
// Remove all previously satisfied requests.
for (int i = 0; i < nai.numNetworkRequests(); i++) {
NetworkRequest request = nai.requestAt(i);
final NetworkRequest request = nai.requestAt(i);
final NetworkRequestInfo nri = mNetworkRequests.get(request);
final NetworkAgentInfo currentNetwork = nri.getSatisfier();
if (currentNetwork != null
&& currentNetwork.network.getNetId() == nai.network.getNetId()) {
// uid rules for this network will be removed in destroyNativeNetwork(nai).
nri.setSatisfier(null, null);
sendUpdatedScoreToFactories(request, null);
if (request.isRequest()) {
sendUpdatedScoreToFactories(request, null);
}
if (mDefaultRequest == nri) {
// TODO : make battery stats aware that since 2013 multiple interfaces may be
@ -3709,7 +3720,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (mNetworkRequests.get(nri.mRequests.get(0)) == null) {
return;
}
if (nri.getSatisfier() != null) {
if (nri.getActiveRequest() != null) {
return;
}
if (VDBG || (DBG && nri.mRequests.get(0).isRequest())) {
@ -4951,6 +4962,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
// TODO This needs to be the default network that applies to the NAI.
private Network[] underlyingNetworksOrDefault(Network[] underlyingNetworks) {
final Network defaultNetwork = getNetwork(getDefaultNetwork());
if (underlyingNetworks == null && defaultNetwork != null) {
@ -5521,9 +5533,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
mActiveRequest = activeRequest;
}
// The network currently satisfying this request, or null if none. Must only be touched
// on the handler thread. This only makes sense for network requests and not for listens,
// as defined by NetworkRequest#isRequest(). For listens, this is always null.
// The network currently satisfying this NRI. Only one request in an NRI can have a
// satisfier. For non-multilayer requests, only REQUEST-type requests can have a satisfier.
@Nullable
private NetworkAgentInfo mSatisfier;
NetworkAgentInfo getSatisfier() {
@ -5546,6 +5557,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
final int mUid;
final Messenger messenger;
/**
* Get the list of UIDs this nri applies to.
*/
@NonNull
private Set<UidRange> getUids() {
// networkCapabilities.getUids() returns a defensive copy.
// multilayer requests will all have the same uids so return the first one.
final Set<UidRange> uids = null == mRequests.get(0).networkCapabilities.getUids()
? new ArraySet<>() : mRequests.get(0).networkCapabilities.getUids();
return uids;
}
NetworkRequestInfo(NetworkRequest r, PendingIntent pi) {
mRequests = initializeRequests(r);
ensureAllNetworkRequestsHaveType(mRequests);
@ -5604,7 +5627,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Override
public String toString() {
return "uid/pid:" + mUid + "/" + mPid + " " + mRequests
return "uid/pid:" + mUid + "/" + mPid + " active request Id: "
+ (mActiveRequest == null ? null : mActiveRequest.requestId)
+ " " + mRequests
+ (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
}
}
@ -6064,6 +6089,26 @@ public class ConnectivityService extends IConnectivityManager.Stub
@NonNull
private final ArraySet<NetworkRequestInfo> mDefaultNetworkRequests = new ArraySet<>();
private boolean isPerAppDefaultRequest(@NonNull final NetworkRequestInfo nri) {
return (mDefaultNetworkRequests.contains(nri) && mDefaultRequest != nri);
}
/**
* Determine if an nri is a managed default request that disallows default networking.
* @param nri the request to evaluate
* @return true if device-default networking is disallowed
*/
private boolean isDefaultBlocked(@NonNull final NetworkRequestInfo nri) {
// Check if this nri is a managed default that supports the default network at its
// lowest priority request.
final NetworkRequest defaultNetworkRequest = mDefaultRequest.mRequests.get(0);
final NetworkCapabilities lowestPriorityNetCap =
nri.mRequests.get(nri.mRequests.size() - 1).networkCapabilities;
return isPerAppDefaultRequest(nri)
&& !(defaultNetworkRequest.networkCapabilities.equalRequestableCapabilities(
lowestPriorityNetCap));
}
// Request used to optionally keep mobile data active even when higher
// priority networks like Wi-Fi are active.
private final NetworkRequest mDefaultMobileDataRequest;
@ -6075,6 +6120,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Request used to optionally keep vehicle internal network always active
private final NetworkRequest mDefaultVehicleRequest;
// TODO replace with INetd.DUMMY_NET_ID when available.
private static final int NO_SERVICE_NET_ID = 51;
// Sentinel NAI used to direct apps with default networks that should have no connectivity to a
// network with no service. This NAI should never be matched against, nor should any public API
// ever return the associated network. For this reason, this NAI is not in the list of available
// NAIs. It is used in computeNetworkReassignment() to be set as the satisfier for non-device
// default requests that don't support using the device default network which will ultimately
// allow ConnectivityService to use this no-service network when calling makeDefaultForApps().
@VisibleForTesting
final NetworkAgentInfo mNoServiceNetwork;
// TODO: b/178729499 update this in favor of a method taking in a UID.
// The NetworkAgentInfo currently satisfying the default request, if any.
private NetworkAgentInfo getDefaultNetwork() {
@ -6165,8 +6221,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
LinkProperties lp = new LinkProperties(linkProperties);
// TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
// satisfies mDefaultRequest.
final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
final NetworkAgentInfo nai = new NetworkAgentInfo(na,
new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
@ -7233,21 +7287,20 @@ public class ConnectivityService extends IConnectivityManager.Stub
log("Switching to new default network for: " + nri + " using " + newDefaultNetwork);
}
try {
// TODO http://b/176191930 update netd calls in follow-up CL for multinetwork changes.
if (mDefaultRequest != nri) {
return;
}
if (null != newDefaultNetwork) {
mNetd.networkSetDefault(newDefaultNetwork.network.getNetId());
} else {
mNetd.networkClearDefault();
}
} catch (RemoteException | ServiceSpecificException e) {
loge("Exception setting default network :" + e);
// Fix up the NetworkCapabilities of any networks that have this network as underlying.
if (newDefaultNetwork != null) {
propagateUnderlyingNetworkCapabilities(newDefaultNetwork.network);
}
// Set an app level managed default and return since further processing only applies to the
// default network.
if (mDefaultRequest != nri) {
makeDefaultForApps(nri, oldDefaultNetwork, newDefaultNetwork);
return;
}
makeDefaultNetwork(newDefaultNetwork);
if (oldDefaultNetwork != null) {
mLingerMonitor.noteLingerDefaultNetwork(oldDefaultNetwork, newDefaultNetwork);
}
@ -7258,10 +7311,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
updateTcpBufferSizes(null != newDefaultNetwork
? newDefaultNetwork.linkProperties.getTcpBufferSizes() : null);
notifyIfacesChangedForNetworkStats();
// Fix up the NetworkCapabilities of any networks that have this network as underlying.
if (newDefaultNetwork != null) {
propagateUnderlyingNetworkCapabilities(newDefaultNetwork.network);
}
// Log 0 -> X and Y -> X default network transitions, where X is the new default.
final Network network = (newDefaultNetwork != null) ? newDefaultNetwork.network : null;
@ -7285,6 +7334,49 @@ public class ConnectivityService extends IConnectivityManager.Stub
prevNetwork, prevScore, prevLp, prevNc);
}
private void makeDefaultForApps(@NonNull final NetworkRequestInfo nri,
@Nullable final NetworkAgentInfo oldDefaultNetwork,
@Nullable final NetworkAgentInfo newDefaultNetwork) {
try {
if (VDBG) {
log("Setting default network for " + nri
+ " using UIDs " + nri.getUids()
+ " with old network " + (oldDefaultNetwork != null
? oldDefaultNetwork.network().getNetId() : "null")
+ " and new network " + (newDefaultNetwork != null
? newDefaultNetwork.network().getNetId() : "null"));
}
if (nri.getUids().isEmpty()) {
throw new IllegalStateException("makeDefaultForApps called without specifying"
+ " any applications to set as the default." + nri);
}
if (null != newDefaultNetwork) {
mNetd.networkAddUidRanges(
newDefaultNetwork.network.getNetId(),
toUidRangeStableParcels(nri.getUids()));
}
if (null != oldDefaultNetwork) {
mNetd.networkRemoveUidRanges(
oldDefaultNetwork.network.getNetId(),
toUidRangeStableParcels(nri.getUids()));
}
} catch (RemoteException | ServiceSpecificException e) {
loge("Exception setting OEM network preference default network :" + e);
}
}
private void makeDefaultNetwork(@Nullable final NetworkAgentInfo newDefaultNetwork) {
try {
if (null != newDefaultNetwork) {
mNetd.networkSetDefault(newDefaultNetwork.network.getNetId());
} else {
mNetd.networkClearDefault();
}
} catch (RemoteException | ServiceSpecificException e) {
loge("Exception setting default network :" + e);
}
}
private void processListenRequests(@NonNull final NetworkAgentInfo nai) {
// For consistency with previous behaviour, send onLost callbacks before onAvailable.
processNewlyLostListenRequests(nai);
@ -7406,9 +7498,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Nullable final NetworkAgentInfo previousSatisfier,
@Nullable final NetworkAgentInfo newSatisfier,
final long now) {
if (newSatisfier != null) {
if (null != newSatisfier && mNoServiceNetwork != newSatisfier) {
if (VDBG) log("rematch for " + newSatisfier.toShortString());
if (previousSatisfier != null) {
if (null != previousSatisfier && mNoServiceNetwork != previousSatisfier) {
if (VDBG || DDBG) {
log(" accepting network in place of " + previousSatisfier.toShortString());
}
@ -7422,7 +7514,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
Log.wtf(TAG, "BUG: " + newSatisfier.toShortString() + " already has "
+ newRequest);
}
} else {
} else if (null != previousSatisfier) {
if (DBG) {
log("Network " + previousSatisfier.toShortString() + " stopped satisfying"
+ " request " + previousRequest.requestId);
@ -7473,7 +7565,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
break;
}
}
if (bestNetwork != nri.mSatisfier) {
if (null == bestNetwork && isDefaultBlocked(nri)) {
// Remove default networking if disallowed for managed default requests.
bestNetwork = mNoServiceNetwork;
}
if (nri.getSatisfier() != bestNetwork) {
// bestNetwork may be null if no network can satisfy this request.
changes.addRequestReassignment(new NetworkReassignment.RequestReassignment(
nri, nri.mActiveRequest, bestRequest, nri.getSatisfier(), bestNetwork));