[CS] Support "instant failure" from factories

Add a mechanism by which a factory can declare "instant failure" for
a request - which would result in it getting an OnUnavailable()
(even without a timeout).

Factories may only do this iff:
1. They know they are the only factory which may fulfill this
   request (common for transport-specific requests).
2. The know that the request can definitely not be
   fulfilled at any point in the future.

Bug: 31382922
Test: atest ConnectivityServiceTest
Merged-In: I9bce0f4d85fa8cad7f8a9998819f945b778c5ac5
Change-Id: I9bce0f4d85fa8cad7f8a9998819f945b778c5ac5
This commit is contained in:
Etan Cohen
2019-01-08 12:09:18 -08:00
parent 80c8a33c95
commit fbfdd84e7c
3 changed files with 99 additions and 12 deletions

View File

@@ -152,6 +152,7 @@ import android.test.mock.MockContentResolver;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -748,6 +749,10 @@ public class ConnectivityServiceTest {
// mExpectations is non-null.
private boolean mExpectingAdditions;
// Used to collect the networks requests managed by this factory. This is a duplicate of
// the internal information stored in the NetworkFactory (which is private).
private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
public MockNetworkFactory(Looper looper, Context context, String logTag,
NetworkCapabilities filter) {
super(looper, context, logTag, filter);
@@ -789,6 +794,7 @@ public class ConnectivityServiceTest {
}
// Add the request.
mNetworkRequests.put(request.requestId, request);
super.handleAddRequest(request, score);
// Reduce the number of request additions we're waiting for.
@@ -806,6 +812,7 @@ public class ConnectivityServiceTest {
}
// Remove the request.
mNetworkRequests.remove(request.requestId);
super.handleRemoveRequest(request);
// Reduce the number of request removals we're waiting for.
@@ -815,6 +822,11 @@ public class ConnectivityServiceTest {
}
}
// Trigger releasing the request as unfulfillable
public void triggerUnfulfillable(NetworkRequest r) {
super.releaseRequestAsUnfulfillableByAnyFactory(r);
}
private void assertNoExpectations() {
if (mExpectations != null) {
fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
@@ -847,9 +859,11 @@ public class ConnectivityServiceTest {
mExpectations = null;
}
public void waitForNetworkRequests(final int count) throws InterruptedException {
public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
throws InterruptedException {
waitForRequests();
assertEquals(count, getMyRequestCount());
return mNetworkRequests;
}
}
@@ -3523,6 +3537,55 @@ public class ConnectivityServiceTest {
networkCallback.assertNoCallback();
}
/**
* Validate the callback flow for a factory releasing a request as unfulfillable.
*/
@Test
public void testUnfulfillableNetworkRequest() throws Exception {
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
NetworkCapabilities.TRANSPORT_WIFI).build();
final TestNetworkCallback networkCallback = new TestNetworkCallback();
final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
handlerThread.start();
NetworkCapabilities filter = new NetworkCapabilities()
.addTransportType(TRANSPORT_WIFI)
.addCapability(NET_CAPABILITY_INTERNET);
final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
mServiceContext, "testFactory", filter);
testFactory.setScoreFilter(40);
// Register the factory and expect it to receive the default request.
testFactory.expectAddRequests(1);
testFactory.register();
SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
assertEquals(1, requests.size()); // have 1 request at this point
int origRequestId = requests.valueAt(0).requestId;
// Now file the test request and expect it.
testFactory.expectAddRequests(1);
mCm.requestNetwork(nr, networkCallback);
requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
int newRequestId = 0;
for (int i = 0; i < requests.size(); ++i) {
if (requests.valueAt(i).requestId != origRequestId) {
newRequestId = requests.valueAt(i).requestId;
break;
}
}
// Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
testFactory.expectRemoveRequests(1);
testFactory.triggerUnfulfillable(requests.get(newRequestId));
networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
testFactory.waitForRequests();
testFactory.unregister();
handlerThread.quit();
}
private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };