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:
@@ -18,12 +18,14 @@ package android.net
|
||||
|
||||
import android.app.Instrumentation
|
||||
import android.content.Context
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
|
||||
import android.net.NetworkCapabilities.TRANSPORT_TEST
|
||||
import android.net.NetworkProviderTest.TestNetworkCallback.CallbackEntry.OnUnavailable
|
||||
import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequestWithdrawn
|
||||
import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequested
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
@@ -34,6 +36,7 @@ import com.android.testutils.DevSdkIgnoreRule
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
|
||||
import com.android.testutils.DevSdkIgnoreRunner
|
||||
import com.android.testutils.TestableNetworkOfferCallback
|
||||
import com.android.testutils.isDevSdkInRange
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@@ -44,11 +47,14 @@ import org.mockito.Mockito.doReturn
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.verifyNoMoreInteractions
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.Executor
|
||||
import java.util.concurrent.RejectedExecutionException
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotEquals
|
||||
import kotlin.test.fail
|
||||
|
||||
private const val DEFAULT_TIMEOUT_MS = 5000L
|
||||
private const val DEFAULT_NO_CALLBACK_TIMEOUT_MS = 200L
|
||||
private val instrumentation: Instrumentation
|
||||
get() = InstrumentationRegistry.getInstrumentation()
|
||||
private val context: Context get() = InstrumentationRegistry.getContext()
|
||||
@@ -102,12 +108,24 @@ class NetworkProviderTest {
|
||||
crossinline predicate: (T) -> Boolean
|
||||
) = seenEvents.poll(DEFAULT_TIMEOUT_MS) { it is T && predicate(it) }
|
||||
?: 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 {
|
||||
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
|
||||
// onNetworkRequested for every request. Instead, provider needs to
|
||||
// call {@code registerNetworkOffer} with the description of networks they
|
||||
@@ -115,10 +133,7 @@ class NetworkProviderTest {
|
||||
@IgnoreAfter(Build.VERSION_CODES.R)
|
||||
@Test
|
||||
fun testOnNetworkRequested() {
|
||||
val provider = createNetworkProvider()
|
||||
assertEquals(provider.getProviderId(), NetworkProvider.ID_NONE)
|
||||
mCm.registerNetworkProvider(provider)
|
||||
assertNotEquals(provider.getProviderId(), NetworkProvider.ID_NONE)
|
||||
val provider = createAndRegisterNetworkProvider()
|
||||
|
||||
val specifier = CompatUtil.makeTestNetworkSpecifier(
|
||||
UUID.randomUUID().toString())
|
||||
@@ -179,6 +194,167 @@ class NetworkProviderTest {
|
||||
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 val seenEvents = ArrayTrackRecord<CallbackEntry>().newReadHead()
|
||||
sealed class CallbackEntry {
|
||||
|
||||
Reference in New Issue
Block a user