Merge "Add CTS for registerNetworkOffer" am: f92979bd5b

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/1731451

Change-Id: I3fccedc04f86a24573222e76cbcf44cb313fe569
This commit is contained in:
Junyu Lai
2021-06-21 13:54:13 +00:00
committed by Automerger Merge Worker

View File

@@ -18,12 +18,14 @@ package android.net
import android.app.Instrumentation import android.app.Instrumentation
import android.content.Context import android.content.Context
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
import android.net.NetworkCapabilities.TRANSPORT_TEST import android.net.NetworkCapabilities.TRANSPORT_TEST
import android.net.NetworkProviderTest.TestNetworkCallback.CallbackEntry.OnUnavailable import android.net.NetworkProviderTest.TestNetworkCallback.CallbackEntry.OnUnavailable
import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequestWithdrawn import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequestWithdrawn
import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequested import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequested
import android.os.Build import android.os.Build
import android.os.Handler
import android.os.HandlerThread import android.os.HandlerThread
import android.os.Looper import android.os.Looper
import android.util.Log import android.util.Log
@@ -34,6 +36,7 @@ import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.TestableNetworkOfferCallback
import com.android.testutils.isDevSdkInRange import com.android.testutils.isDevSdkInRange
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
@@ -44,11 +47,14 @@ import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock import org.mockito.Mockito.mock
import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.Mockito.verifyNoMoreInteractions
import java.util.UUID import java.util.UUID
import java.util.concurrent.Executor
import java.util.concurrent.RejectedExecutionException
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotEquals import kotlin.test.assertNotEquals
import kotlin.test.fail import kotlin.test.fail
private const val DEFAULT_TIMEOUT_MS = 5000L private const val DEFAULT_TIMEOUT_MS = 5000L
private const val DEFAULT_NO_CALLBACK_TIMEOUT_MS = 200L
private val instrumentation: Instrumentation private val instrumentation: Instrumentation
get() = InstrumentationRegistry.getInstrumentation() get() = InstrumentationRegistry.getInstrumentation()
private val context: Context get() = InstrumentationRegistry.getContext() private val context: Context get() = InstrumentationRegistry.getContext()
@@ -102,12 +108,24 @@ class NetworkProviderTest {
crossinline predicate: (T) -> Boolean crossinline predicate: (T) -> Boolean
) = seenEvents.poll(DEFAULT_TIMEOUT_MS) { it is T && predicate(it) } ) = seenEvents.poll(DEFAULT_TIMEOUT_MS) { it is T && predicate(it) }
?: fail("Did not receive callback after ${DEFAULT_TIMEOUT_MS}ms") ?: fail("Did not receive callback after ${DEFAULT_TIMEOUT_MS}ms")
fun assertNoCallback() {
val cb = seenEvents.poll(DEFAULT_NO_CALLBACK_TIMEOUT_MS)
if (null != cb) fail("Expected no callback but got $cb")
}
} }
private fun createNetworkProvider(ctx: Context = context): TestNetworkProvider { private fun createNetworkProvider(ctx: Context = context): TestNetworkProvider {
return TestNetworkProvider(ctx, mHandlerThread.looper) return TestNetworkProvider(ctx, mHandlerThread.looper)
} }
private fun createAndRegisterNetworkProvider(ctx: Context = context) =
createNetworkProvider(ctx).also {
assertEquals(it.getProviderId(), NetworkProvider.ID_NONE)
mCm.registerNetworkProvider(it)
assertNotEquals(it.getProviderId(), NetworkProvider.ID_NONE)
}
// In S+ framework, do not run this test, since the provider will no longer receive // In S+ framework, do not run this test, since the provider will no longer receive
// onNetworkRequested for every request. Instead, provider needs to // onNetworkRequested for every request. Instead, provider needs to
// call {@code registerNetworkOffer} with the description of networks they // call {@code registerNetworkOffer} with the description of networks they
@@ -115,10 +133,7 @@ class NetworkProviderTest {
@IgnoreAfter(Build.VERSION_CODES.R) @IgnoreAfter(Build.VERSION_CODES.R)
@Test @Test
fun testOnNetworkRequested() { fun testOnNetworkRequested() {
val provider = createNetworkProvider() val provider = createAndRegisterNetworkProvider()
assertEquals(provider.getProviderId(), NetworkProvider.ID_NONE)
mCm.registerNetworkProvider(provider)
assertNotEquals(provider.getProviderId(), NetworkProvider.ID_NONE)
val specifier = CompatUtil.makeTestNetworkSpecifier( val specifier = CompatUtil.makeTestNetworkSpecifier(
UUID.randomUUID().toString()) UUID.randomUUID().toString())
@@ -179,6 +194,167 @@ class NetworkProviderTest {
mCm.unregisterNetworkProvider(provider) mCm.unregisterNetworkProvider(provider)
} }
// Mainline module can't use internal HandlerExecutor, so add an identical executor here.
// TODO: Refactor with the one in MultiNetworkPolicyTracker.
private class HandlerExecutor(private val handler: Handler) : Executor {
public override fun execute(command: Runnable) {
if (!handler.post(command)) {
throw RejectedExecutionException(handler.toString() + " is shutting down")
}
}
}
@IgnoreUpTo(Build.VERSION_CODES.R)
@Test
fun testRegisterNetworkOffer() {
val provider = createAndRegisterNetworkProvider()
val provider2 = createAndRegisterNetworkProvider()
// Prepare the materials which will be used to create different offers.
val specifier1 = CompatUtil.makeTestNetworkSpecifier("TEST-SPECIFIER-1")
val specifier2 = CompatUtil.makeTestNetworkSpecifier("TEST-SPECIFIER-2")
val scoreWeaker = NetworkScore.Builder().build()
val scoreStronger = NetworkScore.Builder().setTransportPrimary(true).build()
val ncFilter1 = NetworkCapabilities.Builder().addTransportType(TRANSPORT_TEST)
.setNetworkSpecifier(specifier1).build()
val ncFilter2 = NetworkCapabilities.Builder().addTransportType(TRANSPORT_TEST)
.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
.setNetworkSpecifier(specifier1).build()
val ncFilter3 = NetworkCapabilities.Builder().addTransportType(TRANSPORT_TEST)
.setNetworkSpecifier(specifier2).build()
val ncFilter4 = NetworkCapabilities.Builder().addTransportType(TRANSPORT_TEST)
.setNetworkSpecifier(specifier2).build()
// Make 4 offers, where 1 doesn't have NOT_VCN, 2 has NOT_VCN, 3 is similar to 1 but with
// different specifier, and 4 is also similar to 1 but with different provider.
val offerCallback1 = TestableNetworkOfferCallback(
DEFAULT_TIMEOUT_MS, DEFAULT_NO_CALLBACK_TIMEOUT_MS)
val offerCallback2 = TestableNetworkOfferCallback(
DEFAULT_TIMEOUT_MS, DEFAULT_NO_CALLBACK_TIMEOUT_MS)
val offerCallback3 = TestableNetworkOfferCallback(
DEFAULT_TIMEOUT_MS, DEFAULT_NO_CALLBACK_TIMEOUT_MS)
val offerCallback4 = TestableNetworkOfferCallback(
DEFAULT_TIMEOUT_MS, DEFAULT_NO_CALLBACK_TIMEOUT_MS)
provider.registerNetworkOffer(scoreWeaker, ncFilter1,
HandlerExecutor(mHandlerThread.threadHandler), offerCallback1)
provider.registerNetworkOffer(scoreStronger, ncFilter2,
HandlerExecutor(mHandlerThread.threadHandler), offerCallback2)
provider.registerNetworkOffer(scoreWeaker, ncFilter3,
HandlerExecutor(mHandlerThread.threadHandler), offerCallback3)
provider2.registerNetworkOffer(scoreWeaker, ncFilter4,
HandlerExecutor(mHandlerThread.threadHandler), offerCallback4)
// Unlike Android R, Android S+ provider will only receive interested requests via offer
// callback. Verify that the callbacks do not see any existing request such as default
// requests.
offerCallback1.assertNoCallback()
offerCallback2.assertNoCallback()
offerCallback3.assertNoCallback()
offerCallback4.assertNoCallback()
// File a request with specifier but without NOT_VCN, verify network is needed for callback
// with the same specifier.
val nrNoNotVcn: NetworkRequest = NetworkRequest.Builder()
.addTransportType(TRANSPORT_TEST)
// Test network is not allowed to be trusted.
.removeCapability(NET_CAPABILITY_TRUSTED)
.setNetworkSpecifier(specifier1)
.build()
val cb1 = ConnectivityManager.NetworkCallback()
mCm.requestNetwork(nrNoNotVcn, cb1)
offerCallback1.expectOnNetworkNeeded(ncFilter1)
offerCallback2.expectOnNetworkNeeded(ncFilter2)
offerCallback3.assertNoCallback()
offerCallback4.assertNoCallback()
mCm.unregisterNetworkCallback(cb1)
offerCallback1.expectOnNetworkUnneeded(ncFilter1)
offerCallback2.expectOnNetworkUnneeded(ncFilter2)
offerCallback3.assertNoCallback()
offerCallback4.assertNoCallback()
// File a request without specifier but with NOT_VCN, verify network is needed for offer
// with NOT_VCN.
val nrNotVcn: NetworkRequest = NetworkRequest.Builder()
.addTransportType(TRANSPORT_TEST)
.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
// Test network is not allowed to be trusted.
.removeCapability(NET_CAPABILITY_TRUSTED)
.build()
val cb2 = ConnectivityManager.NetworkCallback()
mCm.requestNetwork(nrNotVcn, cb2)
offerCallback1.assertNoCallback()
offerCallback2.expectOnNetworkNeeded(ncFilter2)
offerCallback3.assertNoCallback()
offerCallback4.assertNoCallback()
// Upgrade offer 3 & 4 to satisfy previous request and then verify they are also needed.
ncFilter3.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
provider.registerNetworkOffer(scoreWeaker, ncFilter3,
HandlerExecutor(mHandlerThread.threadHandler), offerCallback3)
ncFilter4.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
provider2.registerNetworkOffer(scoreWeaker, ncFilter4,
HandlerExecutor(mHandlerThread.threadHandler), offerCallback4)
offerCallback1.assertNoCallback()
offerCallback2.assertNoCallback()
offerCallback3.expectOnNetworkNeeded(ncFilter3)
offerCallback4.expectOnNetworkNeeded(ncFilter4)
// Connect an agent to fulfill the request, verify offer 4 is not needed since it is not
// from currently serving provider nor can beat the current satisfier.
val nc = NetworkCapabilities().apply {
addTransportType(NetworkCapabilities.TRANSPORT_TEST)
removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
setNetworkSpecifier(specifier1)
}
val config = NetworkAgentConfig.Builder().build()
val agent = object : NetworkAgent(context, mHandlerThread.looper, "TestAgent", nc,
LinkProperties(), scoreWeaker, config, provider) {}
agent.register()
agent.markConnected()
// TODO: The request is satisying by offer 2 instead of offer 1, thus it should not be
// considered as needed.
offerCallback1.expectOnNetworkNeeded(ncFilter2)
offerCallback2.assertNoCallback() // Still needed.
offerCallback3.assertNoCallback() // Still needed.
offerCallback4.expectOnNetworkUnneeded(ncFilter4)
// Upgrade the agent, verify no change since the framework will treat the offer as needed
// if a request is currently satisfied by the network provided by the same provider.
// TODO: Consider offers with weaker score are unneeded.
agent.sendNetworkScore(scoreStronger)
offerCallback1.assertNoCallback()
offerCallback2.assertNoCallback() // Still needed.
offerCallback3.assertNoCallback() // Still needed.
offerCallback4.assertNoCallback() // Still unneeded.
// Verify that offer callbacks cannot receive any event if offer is unregistered.
provider2.unregisterNetworkOffer(offerCallback4)
agent.unregister()
offerCallback1.assertNoCallback() // Still needed.
offerCallback2.assertNoCallback() // Still needed.
offerCallback3.assertNoCallback() // Still needed.
// Since the agent is unregistered, and the offer has chance to satisfy the request,
// this callback should receive needed if it is not unregistered.
offerCallback4.assertNoCallback()
// Verify that offer callbacks cannot receive any event if provider is unregistered.
mCm.unregisterNetworkProvider(provider)
mCm.unregisterNetworkCallback(cb2)
offerCallback1.assertNoCallback() // Should be unneeded if not unregistered.
offerCallback2.assertNoCallback() // Should be unneeded if not unregistered.
offerCallback3.assertNoCallback() // Should be unneeded if not unregistered.
offerCallback4.assertNoCallback() // Already unregistered.
// Clean up and Verify providers did not receive any callback during the entire test.
mCm.unregisterNetworkProvider(provider2)
provider.assertNoCallback()
provider2.assertNoCallback()
}
private class TestNetworkCallback : ConnectivityManager.NetworkCallback() { private class TestNetworkCallback : ConnectivityManager.NetworkCallback() {
private val seenEvents = ArrayTrackRecord<CallbackEntry>().newReadHead() private val seenEvents = ArrayTrackRecord<CallbackEntry>().newReadHead()
sealed class CallbackEntry { sealed class CallbackEntry {