Merge "[CS] Support "instant failure" from factories"
This commit is contained in:
@@ -3286,9 +3286,9 @@ public class ConnectivityManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called if no network is found in the timeout time specified in
|
* Called if no network is found in the timeout time specified in
|
||||||
* {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} call. This callback is not
|
* {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} call or if the
|
||||||
* called for the version of {@link #requestNetwork(NetworkRequest, NetworkCallback)}
|
* requested network request cannot be fulfilled (whether or not a timeout was
|
||||||
* without timeout. When this callback is invoked the associated
|
* specified). When this callback is invoked the associated
|
||||||
* {@link NetworkRequest} will have already been removed and released, as if
|
* {@link NetworkRequest} will have already been removed and released, as if
|
||||||
* {@link #unregisterNetworkCallback(NetworkCallback)} had been called.
|
* {@link #unregisterNetworkCallback(NetworkCallback)} had been called.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1073,7 +1073,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
handleRegisterNetworkRequest(new NetworkRequestInfo(
|
handleRegisterNetworkRequest(new NetworkRequestInfo(
|
||||||
null, networkRequest, new Binder()));
|
null, networkRequest, new Binder()));
|
||||||
} else {
|
} else {
|
||||||
handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID);
|
handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID,
|
||||||
|
/* callOnUnavailable */ false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2701,11 +2702,25 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean maybeHandleNetworkFactoryMessage(Message msg) {
|
||||||
|
switch (msg.what) {
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
case android.net.NetworkFactory.EVENT_UNFULFILLABLE_REQUEST: {
|
||||||
|
handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.sendingUid,
|
||||||
|
/* callOnUnavailable */ true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
if (!maybeHandleAsyncChannelMessage(msg) &&
|
if (!maybeHandleAsyncChannelMessage(msg)
|
||||||
!maybeHandleNetworkMonitorMessage(msg) &&
|
&& !maybeHandleNetworkMonitorMessage(msg)
|
||||||
!maybeHandleNetworkAgentInfoMessage(msg)) {
|
&& !maybeHandleNetworkAgentInfoMessage(msg)
|
||||||
|
&& !maybeHandleNetworkFactoryMessage(msg)) {
|
||||||
maybeHandleNetworkAgentMessage(msg);
|
maybeHandleNetworkAgentMessage(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2870,6 +2885,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
|
if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
|
||||||
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
|
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
|
||||||
if (VDBG) log("NetworkFactory connected");
|
if (VDBG) log("NetworkFactory connected");
|
||||||
|
// Finish setting up the full connection
|
||||||
|
mNetworkFactoryInfos.get(msg.replyTo).asyncChannel.sendMessage(
|
||||||
|
AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
|
||||||
// A network factory has connected. Send it all current NetworkRequests.
|
// A network factory has connected. Send it all current NetworkRequests.
|
||||||
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
|
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
|
||||||
if (nri.request.isListen()) continue;
|
if (nri.request.isListen()) continue;
|
||||||
@@ -3031,7 +3049,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
if (existingRequest != null) { // remove the existing request.
|
if (existingRequest != null) { // remove the existing request.
|
||||||
if (DBG) log("Replacing " + existingRequest.request + " with "
|
if (DBG) log("Replacing " + existingRequest.request + " with "
|
||||||
+ nri.request + " because their intents matched.");
|
+ nri.request + " because their intents matched.");
|
||||||
handleReleaseNetworkRequest(existingRequest.request, getCallingUid());
|
handleReleaseNetworkRequest(existingRequest.request, getCallingUid(),
|
||||||
|
/* callOnUnavailable */ false);
|
||||||
}
|
}
|
||||||
handleRegisterNetworkRequest(nri);
|
handleRegisterNetworkRequest(nri);
|
||||||
}
|
}
|
||||||
@@ -3057,7 +3076,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
int callingUid) {
|
int callingUid) {
|
||||||
NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
|
NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
|
||||||
if (nri != null) {
|
if (nri != null) {
|
||||||
handleReleaseNetworkRequest(nri.request, callingUid);
|
handleReleaseNetworkRequest(nri.request, callingUid, /* callOnUnavailable */ false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3140,7 +3159,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
|
callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
|
private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid,
|
||||||
|
boolean callOnUnavailable) {
|
||||||
final NetworkRequestInfo nri =
|
final NetworkRequestInfo nri =
|
||||||
getNriForAppRequest(request, callingUid, "release NetworkRequest");
|
getNriForAppRequest(request, callingUid, "release NetworkRequest");
|
||||||
if (nri == null) {
|
if (nri == null) {
|
||||||
@@ -3150,6 +3170,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
log("releasing " + nri.request + " (release request)");
|
log("releasing " + nri.request + " (release request)");
|
||||||
}
|
}
|
||||||
handleRemoveNetworkRequest(nri);
|
handleRemoveNetworkRequest(nri);
|
||||||
|
if (callOnUnavailable) {
|
||||||
|
callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleRemoveNetworkRequest(final NetworkRequestInfo nri) {
|
private void handleRemoveNetworkRequest(final NetworkRequestInfo nri) {
|
||||||
@@ -3651,7 +3674,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EVENT_RELEASE_NETWORK_REQUEST: {
|
case EVENT_RELEASE_NETWORK_REQUEST: {
|
||||||
handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1);
|
handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1,
|
||||||
|
/* callOnUnavailable */ false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EVENT_SET_ACCEPT_UNVALIDATED: {
|
case EVENT_SET_ACCEPT_UNVALIDATED: {
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ import android.test.mock.MockContentResolver;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.InstrumentationRegistry;
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
@@ -761,6 +762,10 @@ public class ConnectivityServiceTest {
|
|||||||
// mExpectations is non-null.
|
// mExpectations is non-null.
|
||||||
private boolean mExpectingAdditions;
|
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,
|
public MockNetworkFactory(Looper looper, Context context, String logTag,
|
||||||
NetworkCapabilities filter) {
|
NetworkCapabilities filter) {
|
||||||
super(looper, context, logTag, filter);
|
super(looper, context, logTag, filter);
|
||||||
@@ -802,6 +807,7 @@ public class ConnectivityServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the request.
|
// Add the request.
|
||||||
|
mNetworkRequests.put(request.requestId, request);
|
||||||
super.handleAddRequest(request, score);
|
super.handleAddRequest(request, score);
|
||||||
|
|
||||||
// Reduce the number of request additions we're waiting for.
|
// Reduce the number of request additions we're waiting for.
|
||||||
@@ -819,6 +825,7 @@ public class ConnectivityServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove the request.
|
// Remove the request.
|
||||||
|
mNetworkRequests.remove(request.requestId);
|
||||||
super.handleRemoveRequest(request);
|
super.handleRemoveRequest(request);
|
||||||
|
|
||||||
// Reduce the number of request removals we're waiting for.
|
// Reduce the number of request removals we're waiting for.
|
||||||
@@ -828,6 +835,11 @@ public class ConnectivityServiceTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trigger releasing the request as unfulfillable
|
||||||
|
public void triggerUnfulfillable(NetworkRequest r) {
|
||||||
|
super.releaseRequestAsUnfulfillableByAnyFactory(r);
|
||||||
|
}
|
||||||
|
|
||||||
private void assertNoExpectations() {
|
private void assertNoExpectations() {
|
||||||
if (mExpectations != null) {
|
if (mExpectations != null) {
|
||||||
fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
|
fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
|
||||||
@@ -860,9 +872,11 @@ public class ConnectivityServiceTest {
|
|||||||
mExpectations = null;
|
mExpectations = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForNetworkRequests(final int count) throws InterruptedException {
|
public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
|
||||||
|
throws InterruptedException {
|
||||||
waitForRequests();
|
waitForRequests();
|
||||||
assertEquals(count, getMyRequestCount());
|
assertEquals(count, getMyRequestCount());
|
||||||
|
return mNetworkRequests;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3636,6 +3650,55 @@ public class ConnectivityServiceTest {
|
|||||||
networkCallback.assertNoCallback();
|
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 {
|
private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
|
||||||
|
|
||||||
public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
|
public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
|
||||||
|
|||||||
Reference in New Issue
Block a user