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
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/CarrierConfigRule.kt b/staticlibs/testutils/devicetests/com/android/testutils/CarrierConfigRule.kt
index a93ae3e..ae0de79 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/CarrierConfigRule.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/CarrierConfigRule.kt
@@ -18,28 +18,36 @@
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<Int, PersistableBundle>()
@@ -61,6 +69,33 @@
}
}
+ 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 @@
originalConfig.putAll(previousValues)
runAsShell(MODIFY_PHONE_STATE) {
- ccm.overrideConfig(subId, config)
+ overrideConfigAndWait(subId, config)
}
}
@@ -93,10 +128,10 @@
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 4ba41cd..8fcc703 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 @@
}
return@tryTest
}
- cv.close()
if (hold) {
carrierConfigRule.addConfigOverrides(subId, PersistableBundle().also {
it.putStringArray(CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY,
@@ -752,7 +751,6 @@
} 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)