Use handler thread to retrieve carrier config directly

Binder calls to the `CarrierConfigManager` API have a P99 latency of 25ms.
This latency is acceptable for direct execution on the handler thread,
eliminating the need for a separate background thread.

This change reduces complexity and improves code readability.

Flag: EXEMPT mainline
Bug: 422063047
Test: atest ConnectivityCoverageTests:android.net.connectivity.com.android.server.connectivity.MultinetworkPolicyTrackerTest
Change-Id: Id163adb51e9d8db00d1412815852ff0da830789b
This commit is contained in:
Jimi Chen 2025-06-13 10:56:09 +00:00
commit fbdc438e7a
3 changed files with 24 additions and 51 deletions

View file

@ -52,7 +52,6 @@ import android.util.Log;
import com.android.connectivity.resources.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.modules.utils.BackgroundThread;
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.DeviceConfigUtils;
import com.android.net.module.util.HandlerUtils;
@ -91,7 +90,7 @@ public class MultinetworkPolicyTracker {
@Override
public void onCarrierConfigChanged(
int slotIndex, int subId, int carrierId, int specificCarrierId) {
updateAvoidBadWifiFromCarrierConfigBackground(subId);
updateAvoidBadWifiFromCarrierConfigOnHandler(subId);
}
}
@ -212,10 +211,6 @@ public class MultinetworkPolicyTracker {
return Flags.avoidBadWifiFromCarrierConfig();
}
protected Handler getBackgroundThreadHandler() {
return BackgroundThread.getHandler();
}
}
private final Dependencies mDeps;
@ -324,13 +319,12 @@ public class MultinetworkPolicyTracker {
if (mCarrierConfigManager != null) {
mCarrierConfigManager.registerCarrierConfigChangeListener(
BackgroundThread.getExecutor(), mCarrierConfigChangeListener
handlerExecutor, mCarrierConfigChangeListener
);
// This ensures the latest carrier configuration is read.
final int subId = mActiveSubId;
mDeps.getBackgroundThreadHandler().post(() ->
updateAvoidBadWifiFromCarrierConfigBackground(subId));
mHandler.post(() -> updateAvoidBadWifiFromCarrierConfigOnHandler(subId));
} else {
mDeps.addOnDevicePropertiesChangedListener(handlerExecutor,
properties -> reevaluateInternal());
@ -499,8 +493,8 @@ public class MultinetworkPolicyTracker {
* Must be called on the background thread, because it makes an IPC to the phone process.
* It must not be called on the CS handler thread.
*/
private void updateAvoidBadWifiFromCarrierConfigBackground(int subId) {
HandlerUtils.ensureRunningOnHandlerThread(mDeps.getBackgroundThreadHandler());
private void updateAvoidBadWifiFromCarrierConfigOnHandler(int subId) {
HandlerUtils.ensureRunningOnHandlerThread(mHandler);
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
return;
@ -510,7 +504,7 @@ public class MultinetworkPolicyTracker {
// only when system has FEATURE_TELEPHONY_SUBSCRIPTION
final boolean config =
mDeps.readAvoidBadWifiFromCarrierConfig(mCarrierConfigManager, subId);
mHandler.post(() -> updateAvoidBadWifiFromCarrierConfig(subId, config));
updateAvoidBadWifiFromCarrierConfig(subId, config);
}
/**

View file

@ -37,7 +37,6 @@ import android.telephony.TelephonyManager
import android.test.mock.MockContentResolver
import androidx.test.filters.SmallTest
import com.android.connectivity.resources.R
import com.android.internal.os.BackgroundThread
import com.android.internal.util.test.FakeSettingsProvider
import com.android.modules.utils.build.SdkLevel
import com.android.server.connectivity.MultinetworkPolicyTracker.ActiveDataSubscriptionIdListener
@ -45,7 +44,6 @@ import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.com.android.testutils.SetFeatureFlagsRule
import com.android.testutils.com.android.testutils.SetFeatureFlagsRule.FeatureFlag
import com.android.testutils.postAndWait
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
@ -86,27 +84,6 @@ class MultinetworkPolicyTrackerTest(private val supportCarrierConfigManager: Boo
fun data() = listOf(false, true)
}
// This wrapper class prevents JUnit from attempting to load unsupported system classes
// that are present in the System Test (S/T) image, which would otherwise cause test failures.
private class CarrierConfigChangeRunner(
val csLooper: TestLooper,
val bgHandler: Handler,
val listener: CarrierConfigManager.CarrierConfigChangeListener
) {
fun runCarrierConfigChangeOnBackgroundThread(subId: Int) {
bgHandler.postAndWait {
listener.onCarrierConfigChanged(
0, /* logicalSlotIndex */
subId, /* subscriptionId */
0, /* carrierId */
0 /* specificCarrierId */
)
}
csLooper.dispatchNext()
}
}
private val featureFlags = HashSet<String>()
var carrierConfigManager: CarrierConfigManager? = null
@ -157,7 +134,6 @@ class MultinetworkPolicyTrackerTest(private val supportCarrierConfigManager: Boo
}
private val csLooper = TestLooper()
private val handler = Handler(csLooper.looper)
private val bgHandler = BackgroundThread.getHandler()
private val trackerDependencies =
MultinetworkPolicyTrackerTestDependencies(resources)
@ -226,7 +202,6 @@ class MultinetworkPolicyTrackerTest(private val supportCarrierConfigManager: Boo
doReturn(carrierConfigManager).`when`(context)
.getSystemService(CarrierConfigManager::class.java)
trackerDependencies.setBackgroundThreadHandler(bgHandler)
tracker = MultinetworkPolicyTracker(
context,
handler,
@ -416,10 +391,14 @@ class MultinetworkPolicyTrackerTest(private val supportCarrierConfigManager: Boo
// dispatch for the first carrier config initialization on the handler thread
csLooper.dispatchAll()
val runner = CarrierConfigChangeRunner(csLooper, bgHandler, carrierConfiglistener)
// Simulate a carrier configuration change for the initial activeSubId (1000),
// with avoid bad Wi-Fi set to false.
runner.runCarrierConfigChangeOnBackgroundThread(activeSubId)
carrierConfiglistener.onCarrierConfigChanged(
0, /* logicalSlotIndex */
activeSubId, /* subscriptionId */
0, /* carrierId */
0 /* specificCarrierId */
)
// Assert that the tracker's avoidBadWifi flag is false after the carrier config change.
assertFalse(tracker.avoidBadWifi)
@ -429,7 +408,12 @@ class MultinetworkPolicyTrackerTest(private val supportCarrierConfigManager: Boo
trackerDependencies.setAvoidBadWifiCarrierConfigForSubId(activeSubId, true)
// Simulate another carrier configuration change for the same activeSubId (1000),
// now with avoid bad Wi-Fi set to true.
runner.runCarrierConfigChangeOnBackgroundThread(activeSubId)
carrierConfiglistener.onCarrierConfigChanged(
0, /* logicalSlotIndex */
activeSubId, /* subscriptionId */
0, /* carrierId */
0 /* specificCarrierId */
)
// Assert that the tracker's avoidBadWifi flag is now true.
assertTrue(tracker.avoidBadWifi)
@ -439,7 +423,12 @@ class MultinetworkPolicyTrackerTest(private val supportCarrierConfigManager: Boo
// Mock the carrier configuration to return false
trackerDependencies.setAvoidBadWifiCarrierConfigForSubId(changedActiveSubId, false)
// Simulate a carrier configuration change for a different subscription ID.
runner.runCarrierConfigChangeOnBackgroundThread(changedActiveSubId)
carrierConfiglistener.onCarrierConfigChanged(
0, /* logicalSlotIndex */
changedActiveSubId, /* subscriptionId */
0, /* carrierId */
0 /* specificCarrierId */
)
// Assert that the tracker's avoidBadWifi flag remains true,
// because the config change was for a non-active subscription.

View file

@ -1,13 +1,11 @@
package com.android.server.connectivity
import android.content.res.Resources
import android.os.Handler
import android.provider.DeviceConfig
import android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY
import android.provider.DeviceConfig.OnPropertiesChangedListener
import android.telephony.CarrierConfigManager
import com.android.internal.annotations.GuardedBy
import com.android.internal.os.BackgroundThread
import com.android.server.connectivity.MultinetworkPolicyTracker.CONFIG_ACTIVELY_PREFER_BAD_WIFI
import java.util.concurrent.Executor
@ -23,7 +21,6 @@ class MultinetworkPolicyTrackerTestDependencies(
private var avoidBadWifiFromCarrierConfigFeature = false
private val avoidBadWifiCarrierConfigForSubIdMap = HashMap<Int, Boolean>()
private var backgroundThreadHandler = BackgroundThread.getHandler()
fun putConfigActivelyPreferBadWifi(value: Int) {
synchronized(listeners) {
@ -51,10 +48,6 @@ class MultinetworkPolicyTrackerTestDependencies(
avoidBadWifiCarrierConfigForSubIdMap.clear()
}
fun setBackgroundThreadHandler(handler: Handler) {
backgroundThreadHandler = handler
}
override fun getConfigActivelyPreferBadWifi(): Int {
return synchronized(listeners) { configActivelyPreferBadWifi }
}
@ -79,7 +72,4 @@ class MultinetworkPolicyTrackerTestDependencies(
public override fun getAvoidBadWifiFromCarrierConfigFeature(): Boolean =
avoidBadWifiFromCarrierConfigFeature
public override fun getBackgroundThreadHandler(): Handler =
backgroundThreadHandler
}