From b9ac4c8fe270002a3362d361ef7748b88013d89e Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Wed, 5 Feb 2025 15:29:02 +0900 Subject: [PATCH] Wait for carrier config to apply in tests TetheringManagerTest#testRequestLatestEntitlementResult in particular set carrier config overrides without waiting for the override to be applied, which caused flakes. Wait for the override to be applied when adding and clearing them. This makes the logic to wait for the update in NetworkAgentTest unnecessary. Bug: 391966043 Test: atest Change-Id: I371ff5742627ca0b1b6eb6be5f0fd19a0487ae83 --- .../android/testutils/CarrierConfigRule.kt | 47 ++++++++++++++++--- .../src/android/net/cts/NetworkAgentTest.kt | 2 - 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/staticlibs/testutils/devicetests/com/android/testutils/CarrierConfigRule.kt b/staticlibs/testutils/devicetests/com/android/testutils/CarrierConfigRule.kt index a93ae3e1e6..ae0de794b9 100644 --- a/staticlibs/testutils/devicetests/com/android/testutils/CarrierConfigRule.kt +++ b/staticlibs/testutils/devicetests/com/android/testutils/CarrierConfigRule.kt @@ -18,28 +18,36 @@ package com.android.testutils.com.android.testutils import android.Manifest.permission.MODIFY_PHONE_STATE import android.Manifest.permission.READ_PHONE_STATE +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.os.ConditionVariable import android.os.PersistableBundle import android.telephony.CarrierConfigManager +import android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED +import android.telephony.SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX import android.util.Log import androidx.test.platform.app.InstrumentationRegistry import com.android.modules.utils.build.SdkLevel.isAtLeastU import com.android.testutils.runAsShell import com.android.testutils.tryTest import kotlin.test.assertNotNull +import kotlin.test.assertTrue import org.junit.rules.TestRule import org.junit.runner.Description import org.junit.runners.model.Statement private val TAG = CarrierConfigRule::class.simpleName +private const val CARRIER_CONFIG_CHANGE_TIMEOUT_MS = 10_000L /** * A [TestRule] that helps set [CarrierConfigManager] overrides for tests and clean up the test * configuration automatically on teardown. */ class CarrierConfigRule : TestRule { - private val ccm by lazy { InstrumentationRegistry.getInstrumentation().context.getSystemService( - CarrierConfigManager::class.java - ) } + private val context by lazy { InstrumentationRegistry.getInstrumentation().context } + private val ccm by lazy { context.getSystemService(CarrierConfigManager::class.java) } // Map of (subId) -> (original values of overridden settings) private val originalConfigs = mutableMapOf() @@ -61,6 +69,33 @@ class CarrierConfigRule : TestRule { } } + private class ConfigChangeReceiver(private val subId: Int) : BroadcastReceiver() { + val cv = ConditionVariable() + override fun onReceive(context: Context, intent: Intent) { + if (intent.action != ACTION_CARRIER_CONFIG_CHANGED || + intent.getIntExtra(EXTRA_SUBSCRIPTION_INDEX, -1) != subId) { + return + } + // This may race with other config changes for the same subId, but there is no way to + // know which update is being reported, and querying the override would return the + // latest values even before the config is applied. Config changes should be rare, so it + // is unlikely they would happen exactly after the override applied here and cause + // flakes. + cv.open() + } + } + + private fun overrideConfigAndWait(subId: Int, config: PersistableBundle) { + val changeReceiver = ConfigChangeReceiver(subId) + context.registerReceiver(changeReceiver, IntentFilter(ACTION_CARRIER_CONFIG_CHANGED)) + ccm.overrideConfig(subId, config) + assertTrue( + changeReceiver.cv.block(CARRIER_CONFIG_CHANGE_TIMEOUT_MS), + "Timed out waiting for config change for subId $subId" + ) + context.unregisterReceiver(changeReceiver) + } + /** * Add carrier config overrides with the specified configuration. * @@ -79,7 +114,7 @@ class CarrierConfigRule : TestRule { originalConfig.putAll(previousValues) runAsShell(MODIFY_PHONE_STATE) { - ccm.overrideConfig(subId, config) + overrideConfigAndWait(subId, config) } } @@ -93,10 +128,10 @@ class CarrierConfigRule : TestRule { runAsShell(MODIFY_PHONE_STATE) { originalConfigs.forEach { (subId, config) -> try { - // Do not use overrideConfig with null, as it would reset configs that may + // Do not use null as the config to reset, as it would reset configs that may // have been set by target preparers such as // ConnectivityTestTargetPreparer / CarrierConfigSetupTest. - ccm.overrideConfig(subId, config) + overrideConfigAndWait(subId, config) } catch (e: Throwable) { Log.e(TAG, "Error resetting carrier config for subId $subId") } diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt index 4ba41cdef6..8fcc703c0a 100644 --- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt +++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt @@ -743,7 +743,6 @@ class NetworkAgentTest { } return@tryTest } - cv.close() if (hold) { carrierConfigRule.addConfigOverrides(subId, PersistableBundle().also { it.putStringArray(CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY, @@ -752,7 +751,6 @@ class NetworkAgentTest { } else { carrierConfigRule.cleanUpNow() } - assertTrue(cv.block(DEFAULT_TIMEOUT_MS), "Can't change carrier privilege") } cleanup @JvmSerializableLambda { runAsShell(READ_PRIVILEGED_PHONE_STATE) @JvmSerializableLambda { tm.unregisterCarrierPrivilegesCallback(cpb)