Updates to handler logic for multilayer requests

Updates to ConnectivityService network request handler's logic to support
(or disallow support of) multilayer network requests.

Bug: 175239920
Bug: 171991028
Test: atest FrameworksNetTests
atest NetworkStackTests
atest FrameworksNetIntegrationTests
atest NetworkStackIntegrationTests
atest CtsNetTestCasesLatestSdk

Change-Id: Ic67cff950d72745d6508a0a037bd33f932d5132c
This commit is contained in:
James Mattis
2020-12-13 16:28:14 -08:00
parent f8b661d084
commit f7027321e0

View File

@@ -3513,42 +3513,63 @@ public class ConnectivityService extends IConnectivityManager.Stub
return null; return null;
} }
private void handleRegisterNetworkRequestWithIntent(Message msg) { private void handleRegisterNetworkRequestWithIntent(@NonNull final Message msg) {
final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj); final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj);
// handleRegisterNetworkRequestWithIntent() doesn't apply to multilayer requests.
NetworkRequestInfo existingRequest = findExistingNetworkRequestInfo(nri.mPendingIntent); ensureNotMultilayerRequest(nri, "handleRegisterNetworkRequestWithIntent");
final NetworkRequestInfo existingRequest =
findExistingNetworkRequestInfo(nri.mPendingIntent);
if (existingRequest != null) { // remove the existing request. if (existingRequest != null) { // remove the existing request.
if (DBG) log("Replacing " + existingRequest.request + " with " if (DBG) {
+ nri.request + " because their intents matched."); log("Replacing " + existingRequest.mRequests.get(0) + " with "
handleReleaseNetworkRequest(existingRequest.request, getCallingUid(), + nri.mRequests.get(0) + " because their intents matched.");
}
handleReleaseNetworkRequest(existingRequest.mRequests.get(0), getCallingUid(),
/* callOnUnavailable */ false); /* callOnUnavailable */ false);
} }
handleRegisterNetworkRequest(nri); handleRegisterNetworkRequest(nri);
} }
private void handleRegisterNetworkRequest(NetworkRequestInfo nri) { private void handleRegisterNetworkRequest(@NonNull final NetworkRequestInfo nri) {
ensureRunningOnConnectivityServiceThread(); ensureRunningOnConnectivityServiceThread();
mNetworkRequests.put(nri.request, nri);
mNetworkRequestInfoLogs.log("REGISTER " + nri); mNetworkRequestInfoLogs.log("REGISTER " + nri);
if (nri.request.isListen()) { for (final NetworkRequest req : nri.mRequests) {
for (NetworkAgentInfo network : mNetworkAgentInfos) { mNetworkRequests.put(req, nri);
if (nri.request.networkCapabilities.hasSignalStrength() && if (req.isListen()) {
network.satisfiesImmutableCapabilitiesOf(nri.request)) { for (final NetworkAgentInfo network : mNetworkAgentInfos) {
updateSignalStrengthThresholds(network, "REGISTER", nri.request); if (req.networkCapabilities.hasSignalStrength()
&& network.satisfiesImmutableCapabilitiesOf(req)) {
updateSignalStrengthThresholds(network, "REGISTER", req);
}
} }
} }
} }
rematchAllNetworksAndRequests(); rematchAllNetworksAndRequests();
if (nri.request.isRequest() && nri.getSatisfier() == null) { // If an active request exists, return as its score has already been sent if needed.
sendUpdatedScoreToFactories(nri.request, null); if (null != nri.getActiveRequest()) {
return;
}
// As this request was not satisfied on rematch and thus never had any scores sent to the
// factories, send null now for each request of type REQUEST.
for (final NetworkRequest req : nri.mRequests) {
if (!req.isRequest()) {
continue;
}
sendUpdatedScoreToFactories(req, null);
} }
} }
private void handleReleaseNetworkRequestWithIntent(PendingIntent pendingIntent, private void handleReleaseNetworkRequestWithIntent(@NonNull final PendingIntent pendingIntent,
int callingUid) { final int callingUid) {
NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent); final NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
if (nri != null) { if (nri != null) {
handleReleaseNetworkRequest(nri.request, callingUid, /* callOnUnavailable */ false); // handleReleaseNetworkRequestWithIntent() paths don't apply to multilayer requests.
ensureNotMultilayerRequest(nri, "handleReleaseNetworkRequestWithIntent");
handleReleaseNetworkRequest(
nri.mRequests.get(0),
callingUid,
/* callOnUnavailable */ false);
} }
} }
@@ -3652,30 +3673,45 @@ public class ConnectivityService extends IConnectivityManager.Stub
return nri; return nri;
} }
private void handleTimedOutNetworkRequest(final NetworkRequestInfo nri) { private void ensureNotMultilayerRequest(@NonNull final NetworkRequestInfo nri,
final String callingMethod) {
if (nri.isMultilayerRequest()) {
throw new IllegalStateException(
callingMethod + " does not support multilayer requests.");
}
}
private void handleTimedOutNetworkRequest(@NonNull final NetworkRequestInfo nri) {
ensureRunningOnConnectivityServiceThread(); ensureRunningOnConnectivityServiceThread();
if (mNetworkRequests.get(nri.request) == null) { // handleTimedOutNetworkRequest() is part of the requestNetwork() flow which works off of a
// single NetworkRequest and thus does not apply to multilayer requests.
ensureNotMultilayerRequest(nri, "handleTimedOutNetworkRequest");
if (mNetworkRequests.get(nri.mRequests.get(0)) == null) {
return; return;
} }
if (nri.getSatisfier() != null) { if (nri.getSatisfier() != null) {
return; return;
} }
if (VDBG || (DBG && nri.request.isRequest())) { if (VDBG || (DBG && nri.mRequests.get(0).isRequest())) {
log("releasing " + nri.request + " (timeout)"); log("releasing " + nri.mRequests.get(0) + " (timeout)");
} }
handleRemoveNetworkRequest(nri); handleRemoveNetworkRequest(nri);
callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0); callCallbackForRequest(
nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
} }
private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid, private void handleReleaseNetworkRequest(@NonNull final NetworkRequest request,
boolean callOnUnavailable) { final int callingUid,
final boolean callOnUnavailable) {
final NetworkRequestInfo nri = final NetworkRequestInfo nri =
getNriForAppRequest(request, callingUid, "release NetworkRequest"); getNriForAppRequest(request, callingUid, "release NetworkRequest");
if (nri == null) { if (nri == null) {
return; return;
} }
if (VDBG || (DBG && nri.request.isRequest())) { // handleReleaseNetworkRequest() paths don't apply to multilayer requests.
log("releasing " + nri.request + " (release request)"); ensureNotMultilayerRequest(nri, "handleReleaseNetworkRequest");
if (VDBG || (DBG && request.isRequest())) {
log("releasing " + request + " (release request)");
} }
handleRemoveNetworkRequest(nri); handleRemoveNetworkRequest(nri);
if (callOnUnavailable) { if (callOnUnavailable) {
@@ -5451,12 +5487,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
/** /**
* Tracks info about the requester. * Tracks info about the requester.
* Also used to notice when the calling process dies so we can self-expire * Also used to notice when the calling process dies so as to self-expire
*/ */
@VisibleForTesting @VisibleForTesting
protected class NetworkRequestInfo implements IBinder.DeathRecipient { protected class NetworkRequestInfo implements IBinder.DeathRecipient {
final List<NetworkRequest> mRequests; final List<NetworkRequest> mRequests;
final NetworkRequest request;
// mSatisfier and mActiveRequest rely on one another therefore set them together. // mSatisfier and mActiveRequest rely on one another therefore set them together.
void setSatisfier( void setSatisfier(
@@ -5492,7 +5527,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
final Messenger messenger; final Messenger messenger;
NetworkRequestInfo(NetworkRequest r, PendingIntent pi) { NetworkRequestInfo(NetworkRequest r, PendingIntent pi) {
request = r;
mRequests = initializeRequests(r); mRequests = initializeRequests(r);
ensureAllNetworkRequestsHaveType(mRequests); ensureAllNetworkRequestsHaveType(mRequests);
mPendingIntent = pi; mPendingIntent = pi;
@@ -5506,7 +5540,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder) { NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder) {
super(); super();
messenger = m; messenger = m;
request = r;
mRequests = initializeRequests(r); mRequests = initializeRequests(r);
ensureAllNetworkRequestsHaveType(mRequests); ensureAllNetworkRequestsHaveType(mRequests);
mBinder = binder; mBinder = binder;
@@ -5961,13 +5994,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
} }
@Override @Override
public void declareNetworkRequestUnfulfillable(NetworkRequest request) { public void declareNetworkRequestUnfulfillable(@NonNull final NetworkRequest request) {
if (request.hasTransport(TRANSPORT_TEST)) { if (request.hasTransport(TRANSPORT_TEST)) {
enforceNetworkFactoryOrTestNetworksPermission(); enforceNetworkFactoryOrTestNetworksPermission();
} else { } else {
enforceNetworkFactoryPermission(); enforceNetworkFactoryPermission();
} }
mHandler.post(() -> handleReleaseNetworkRequest(request, mDeps.getCallingUid(), true)); final NetworkRequestInfo nri = mNetworkRequests.get(request);
if (nri != null) {
// declareNetworkRequestUnfulfillable() paths don't apply to multilayer requests.
ensureNotMultilayerRequest(nri, "declareNetworkRequestUnfulfillable");
mHandler.post(() -> handleReleaseNetworkRequest(
nri.mRequests.get(0), mDeps.getCallingUid(), true));
}
} }
// NOTE: Accessed on multiple threads, must be synchronized on itself. // NOTE: Accessed on multiple threads, must be synchronized on itself.