Merge "[VCN13] Implement tracking best matching network" am: f98037abb3 am: 4377c5d40c
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1633519 Change-Id: I49f94fb997e770874e851afaa5266c6fd2ba1396
This commit is contained in:
@@ -18,8 +18,8 @@ package android.net;
|
||||
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
|
||||
import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST;
|
||||
import static android.net.NetworkRequest.Type.LISTEN;
|
||||
import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST;
|
||||
import static android.net.NetworkRequest.Type.REQUEST;
|
||||
import static android.net.NetworkRequest.Type.TRACK_BEST;
|
||||
import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
|
||||
import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT;
|
||||
import static android.net.QosCallback.QosCallbackRegistrationException;
|
||||
@@ -4249,7 +4249,7 @@ public class ConnectivityManager {
|
||||
@NonNull NetworkCallback networkCallback, @NonNull Handler handler) {
|
||||
final NetworkCapabilities nc = request.networkCapabilities;
|
||||
final CallbackHandler cbHandler = new CallbackHandler(handler);
|
||||
sendRequestForNetwork(nc, networkCallback, 0, TRACK_BEST, TYPE_NONE, cbHandler);
|
||||
sendRequestForNetwork(nc, networkCallback, 0, LISTEN_FOR_BEST, TYPE_NONE, cbHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -140,7 +140,7 @@ public class NetworkRequest implements Parcelable {
|
||||
REQUEST,
|
||||
BACKGROUND_REQUEST,
|
||||
TRACK_SYSTEM_DEFAULT,
|
||||
TRACK_BEST,
|
||||
LISTEN_FOR_BEST,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -513,6 +513,15 @@ public class NetworkRequest implements Parcelable {
|
||||
return type == Type.LISTEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff. this NetworkRequest is of type LISTEN_FOR_BEST.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public boolean isListenForBest() {
|
||||
return type == Type.LISTEN_FOR_BEST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff. the contained NetworkRequest is one that:
|
||||
*
|
||||
|
||||
@@ -55,6 +55,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_TEST;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
|
||||
import static android.net.NetworkPolicyManager.RULE_NONE;
|
||||
import static android.net.NetworkPolicyManager.uidRulesToString;
|
||||
import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST;
|
||||
import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequired;
|
||||
import static android.os.Process.INVALID_UID;
|
||||
import static android.os.Process.VPN_UID;
|
||||
@@ -3663,6 +3664,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
mNetworkRequestInfoLogs.log("REGISTER " + nri);
|
||||
for (final NetworkRequest req : nri.mRequests) {
|
||||
mNetworkRequests.put(req, nri);
|
||||
// TODO: Consider update signal strength for other types.
|
||||
if (req.isListen()) {
|
||||
for (final NetworkAgentInfo network : mNetworkAgentInfos) {
|
||||
if (req.networkCapabilities.hasSignalStrength()
|
||||
@@ -3755,18 +3757,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// listen requests won't keep up a network satisfying it. If this is not a multilayer
|
||||
// request, return immediately. For multilayer requests, check to see if any of the
|
||||
// multilayer requests may have a potential satisfier.
|
||||
if (!nri.isMultilayerRequest() && nri.mRequests.get(0).isListen()) {
|
||||
if (!nri.isMultilayerRequest() && (nri.mRequests.get(0).isListen()
|
||||
|| nri.mRequests.get(0).isListenForBest())) {
|
||||
return false;
|
||||
}
|
||||
for (final NetworkRequest req : nri.mRequests) {
|
||||
// This multilayer listen request is satisfied therefore no further requests need to be
|
||||
// evaluated deeming this network not a potential satisfier.
|
||||
if (req.isListen() && nri.getActiveRequest() == req) {
|
||||
if ((req.isListen() || req.isListenForBest()) && nri.getActiveRequest() == req) {
|
||||
return false;
|
||||
}
|
||||
// As non-multilayer listen requests have already returned, the below would only happen
|
||||
// for a multilayer request therefore continue to the next request if available.
|
||||
if (req.isListen()) {
|
||||
if (req.isListen() || req.isListenForBest()) {
|
||||
continue;
|
||||
}
|
||||
// If this Network is already the highest scoring Network for a request, or if
|
||||
@@ -5549,8 +5552,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// request if the app changes network state. http://b/29964605
|
||||
enforceMeteredApnPolicy(networkCapabilities);
|
||||
break;
|
||||
case TRACK_BEST:
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
case LISTEN_FOR_BEST:
|
||||
enforceAccessPermission();
|
||||
networkCapabilities = new NetworkCapabilities(networkCapabilities);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported request type " + reqType);
|
||||
}
|
||||
@@ -5558,11 +5563,17 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
ensureSufficientPermissionsForRequest(networkCapabilities,
|
||||
Binder.getCallingPid(), callingUid, callingPackageName);
|
||||
|
||||
// Set the UID range for this request to the single UID of the requester, or to an empty
|
||||
// set of UIDs if the caller has the appropriate permission and UIDs have not been set.
|
||||
// Enforce FOREGROUND if the caller does not have permission to use background network.
|
||||
if (reqType == LISTEN_FOR_BEST) {
|
||||
restrictBackgroundRequestForCaller(networkCapabilities);
|
||||
}
|
||||
|
||||
// Set the UID range for this request to the single UID of the requester, unless the
|
||||
// requester has the permission to specify other UIDs.
|
||||
// This will overwrite any allowed UIDs in the requested capabilities. Though there
|
||||
// are no visible methods to set the UIDs, an app could use reflection to try and get
|
||||
// networks for other apps so it's essential that the UIDs are overwritten.
|
||||
// Also set the requester UID and package name in the request.
|
||||
restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities,
|
||||
callingUid, callingPackageName);
|
||||
|
||||
|
||||
@@ -719,6 +719,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
|
||||
break;
|
||||
|
||||
case LISTEN:
|
||||
case LISTEN_FOR_BEST:
|
||||
case TRACK_DEFAULT:
|
||||
case TRACK_SYSTEM_DEFAULT:
|
||||
break;
|
||||
|
||||
@@ -1079,6 +1079,10 @@ public class ConnectivityServiceTest {
|
||||
public void triggerUnfulfillable(NetworkRequest r) {
|
||||
super.releaseRequestAsUnfulfillableByAnyFactory(r);
|
||||
}
|
||||
|
||||
public void assertNoRequestChanged() {
|
||||
assertNull(mRequestHistory.poll(0, r -> true));
|
||||
}
|
||||
}
|
||||
|
||||
private Set<UidRange> uidRangesForUids(int... uids) {
|
||||
@@ -11121,11 +11125,99 @@ public class ConnectivityServiceTest {
|
||||
mCm.unregisterNetworkCallback(cellCb);
|
||||
}
|
||||
|
||||
// Cannot be part of MockNetworkFactory since it requires method of the test.
|
||||
private void expectNoRequestChanged(@NonNull MockNetworkFactory factory) {
|
||||
waitForIdle();
|
||||
factory.assertNoRequestChanged();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterBestMatchingNetworkCallback() throws Exception {
|
||||
final NetworkRequest request = new NetworkRequest.Builder().build();
|
||||
assertThrows(UnsupportedOperationException.class,
|
||||
() -> mCm.registerBestMatchingNetworkCallback(request, new NetworkCallback(),
|
||||
mCsHandlerThread.getThreadHandler()));
|
||||
public void testRegisterBestMatchingNetworkCallback_noIssueToFactory() throws Exception {
|
||||
// Prepare mock mms factory.
|
||||
final HandlerThread handlerThread = new HandlerThread("MockCellularFactory");
|
||||
handlerThread.start();
|
||||
NetworkCapabilities filter = new NetworkCapabilities()
|
||||
.addTransportType(TRANSPORT_CELLULAR)
|
||||
.addCapability(NET_CAPABILITY_MMS);
|
||||
final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
|
||||
mServiceContext, "testFactory", filter, mCsHandlerThread);
|
||||
testFactory.setScoreFilter(40);
|
||||
|
||||
try {
|
||||
// Register the factory and expect it will see default request, because all requests
|
||||
// are sent to all factories.
|
||||
testFactory.register();
|
||||
testFactory.expectRequestAdd();
|
||||
testFactory.assertRequestCountEquals(1);
|
||||
// The factory won't try to start the network since the default request doesn't
|
||||
// match the filter (no INTERNET capability).
|
||||
assertFalse(testFactory.getMyStartRequested());
|
||||
|
||||
// Register callback for listening best matching network. Verify that the request won't
|
||||
// be sent to factory.
|
||||
final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
|
||||
mCm.registerBestMatchingNetworkCallback(
|
||||
new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
|
||||
bestMatchingCb, mCsHandlerThread.getThreadHandler());
|
||||
bestMatchingCb.assertNoCallback();
|
||||
expectNoRequestChanged(testFactory);
|
||||
testFactory.assertRequestCountEquals(1);
|
||||
assertFalse(testFactory.getMyStartRequested());
|
||||
|
||||
// Fire a normal mms request, verify the factory will only see the request.
|
||||
final TestNetworkCallback mmsNetworkCallback = new TestNetworkCallback();
|
||||
final NetworkRequest mmsRequest = new NetworkRequest.Builder()
|
||||
.addCapability(NET_CAPABILITY_MMS).build();
|
||||
mCm.requestNetwork(mmsRequest, mmsNetworkCallback);
|
||||
testFactory.expectRequestAdd();
|
||||
testFactory.assertRequestCountEquals(2);
|
||||
assertTrue(testFactory.getMyStartRequested());
|
||||
|
||||
// Unregister best matching callback, verify factory see no change.
|
||||
mCm.unregisterNetworkCallback(bestMatchingCb);
|
||||
expectNoRequestChanged(testFactory);
|
||||
testFactory.assertRequestCountEquals(2);
|
||||
assertTrue(testFactory.getMyStartRequested());
|
||||
} finally {
|
||||
testFactory.terminate();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterBestMatchingNetworkCallback_trackBestNetwork() throws Exception {
|
||||
final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
|
||||
mCm.registerBestMatchingNetworkCallback(
|
||||
new NetworkRequest.Builder().addCapability(NET_CAPABILITY_TRUSTED).build(),
|
||||
bestMatchingCb, mCsHandlerThread.getThreadHandler());
|
||||
|
||||
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
|
||||
mCellNetworkAgent.connect(true);
|
||||
bestMatchingCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
|
||||
|
||||
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
|
||||
mWiFiNetworkAgent.connect(true);
|
||||
bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
|
||||
|
||||
// Change something on cellular to trigger capabilities changed, since the callback
|
||||
// only cares about the best network, verify it received nothing from cellular.
|
||||
mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
|
||||
bestMatchingCb.assertNoCallback();
|
||||
|
||||
// Make cellular the best network again, verify the callback now tracks cellular.
|
||||
mWiFiNetworkAgent.adjustScore(-50);
|
||||
bestMatchingCb.expectAvailableCallbacksValidated(mCellNetworkAgent);
|
||||
|
||||
// Make cellular temporary non-trusted, which will not satisfying the request.
|
||||
// Verify the callback switch from/to the other network accordingly.
|
||||
mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
|
||||
bestMatchingCb.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
|
||||
mCellNetworkAgent.addCapability(NET_CAPABILITY_TRUSTED);
|
||||
bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mCellNetworkAgent);
|
||||
|
||||
// Verify the callback doesn't care about wifi disconnect.
|
||||
mWiFiNetworkAgent.disconnect();
|
||||
bestMatchingCb.assertNoCallback();
|
||||
mCellNetworkAgent.disconnect();
|
||||
bestMatchingCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user