diff --git a/service/src/com/android/server/connectivity/MultinetworkPolicyTracker.java b/service/src/com/android/server/connectivity/MultinetworkPolicyTracker.java index 561a7934aa..fc96b65645 100644 --- a/service/src/com/android/server/connectivity/MultinetworkPolicyTracker.java +++ b/service/src/com/android/server/connectivity/MultinetworkPolicyTracker.java @@ -20,6 +20,10 @@ import static android.content.pm.PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION; import static android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI; import static android.net.ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE; +import static com.android.net.module.util.ConnectivitySettingsUtils.convertCarrierAwareSettingsStringToMap; +import static com.android.net.module.util.ConnectivitySettingsUtils.getNetworkAvoidBadWifiSetting; +import static com.android.net.module.util.ConnectivitySettingsUtils.getNetworkLegacyGlobalAvoidBadWifiSetting; + import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -57,6 +61,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; @@ -508,6 +513,54 @@ public class MultinetworkPolicyTracker { mHandler.post(() -> updateAvoidBadWifiFromCarrierConfig(subId, config)); } + /** + * Determines whether the device should avoid bad Wi-Fi connections based on a hierarchical + * preference for settings. + * + * This method checks for the "avoid bad Wi-Fi" setting by first looking for a + * **carrier-aware setting** via {@code NETWORK_CARRIER_AWARE_AVOID_BAD_WIFI}. + * If this setting is present and contains a value for the {@code mActiveSubId}, + * that value is used. + * If {@code mActiveSubId} isn't explicitly found in the map, then fall back to the + * **legacy global setting** {@code NETWORK_AVOID_BAD_WIFI}. + * + * If the carrier-aware setting isn't available (i.e., it's {@code null}), the method then + * falls back to the **legacy global setting** {@code NETWORK_AVOID_BAD_WIFI}. + * This setting is considered {@code true} if its value is anything other than "0", + * and {@code false} if it is "0". + * + * Finally, if neither of the above settings is available (meaning both are {@code null}), + * the method retrieves the setting from a **local cache** using + * {@code readAvoidBadWifiFromCache(mActiveSubId)}. + * This is done to avoid potential IPC issues or blocking. + * + * @return {@code true} if the device should avoid bad Wi-Fi based on the highest priority + * available setting, {@code false} otherwise. + */ + private boolean getAvoidBadWifiInternal() { + final String carrierAwareSetting = + getNetworkAvoidBadWifiSetting(mContext); + if (carrierAwareSetting != null) { + final Map settingMap = + convertCarrierAwareSettingsStringToMap(carrierAwareSetting); + if (settingMap.containsKey(mActiveSubId)) { + return settingMap.get(mActiveSubId); + } + } + + // if NETWORK_CARRIER_AWARE_AVOID_BAD_WIFI is not set, + // check NETWORK_AVOID_BAD_WIFI setting for backward compatible + final String setting = + getNetworkLegacyGlobalAvoidBadWifiSetting(mContext); + if (setting != null) { + return !setting.equals("0"); + } + + // Retrieve the avoid bad Wi-Fi setting from the local cache to avoid potential + // issues or blocking from the IPC call getAvoidBadWifiCarrierConfigForSubId(). + return readAvoidBadWifiFromCache(mActiveSubId); + } + /** * Updates the "avoid bad Wi-Fi" setting. * Depending on whether the carrier config feature is enabled, this method uses different logic: @@ -535,14 +588,7 @@ public class MultinetworkPolicyTracker { // and mAvoidBadWifiFromCarrierConfigFeature is a trunk stable flag // that only exists in 25Q4+ mActivelyPreferBadWifi = true; - final String settingAvoidBadWifiStr = readAvoidBadWifiFromSettings(); - if (settingAvoidBadWifiStr != null) { - mAvoidBadWifi = "1".equals(settingAvoidBadWifiStr); - } else { - // Retrieve the avoid bad Wi-Fi setting from the local cache to avoid potential - // issues or blocking from the IPC call getAvoidBadWifiCarrierConfigForSubId(). - mAvoidBadWifi = readAvoidBadWifiFromCache(mActiveSubId); - } + mAvoidBadWifi = getAvoidBadWifiInternal(); return mAvoidBadWifi != prevAvoid; case FROM_RESOURCE: final boolean settingAvoidBadWifi = "1".equals(readAvoidBadWifiFromSettings()); diff --git a/tests/unit/java/com/android/server/connectivity/MultinetworkPolicyTrackerTest.kt b/tests/unit/java/com/android/server/connectivity/MultinetworkPolicyTrackerTest.kt index fd75f8ef72..b5c24b9526 100644 --- a/tests/unit/java/com/android/server/connectivity/MultinetworkPolicyTrackerTest.kt +++ b/tests/unit/java/com/android/server/connectivity/MultinetworkPolicyTrackerTest.kt @@ -23,6 +23,7 @@ import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY import android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI +import android.net.ConnectivitySettingsManager.NETWORK_CARRIER_AWARE_AVOID_BAD_WIFI import android.net.ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE import android.net.platform.flags.Flags.FLAG_AVOID_BAD_WIFI_FROM_CARRIER_CONFIG import android.os.Build @@ -310,8 +311,8 @@ class MultinetworkPolicyTrackerTest(private val supportCarrierConfigManager: Boo @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.BAKLAVA) fun testAvoidBadWifiWithGlobalSetting() { val activeSubId = 1000 - // Mock the initial global setting to false - Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "0") + // Mock the initial NETWORK_CARRIER_AWARE_AVOID_BAD_WIFI setting to false + Settings.Global.putString(resolver, NETWORK_CARRIER_AWARE_AVOID_BAD_WIFI, "$activeSubId,0") // Mock the initial carrier configuration to return true trackerDependencies.setAvoidBadWifiCarrierConfigForSubId(activeSubId, true) @@ -330,12 +331,51 @@ class MultinetworkPolicyTrackerTest(private val supportCarrierConfigManager: Boo assertFalse(tracker.avoidBadWifi) assertTrue(tracker.activelyPreferBadWifi) - // Mock the initial global setting to true - Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "1") + // Mock the NETWORK_CARRIER_AWARE_AVOID_BAD_WIFI setting to true + Settings.Global.putString(resolver, NETWORK_CARRIER_AWARE_AVOID_BAD_WIFI, "$activeSubId,1") // Mock the initial carrier configuration to return false trackerDependencies.setAvoidBadWifiCarrierConfigForSubId(activeSubId, false) - // Assert that the tracker's avoidBadWifi flag is true based on global setting + // Assert that the tracker's avoidBadWifi flag is true based on carrier aware setting + assertTrue(tracker.updateAvoidBadWifi()) + assertTrue(tracker.avoidBadWifi) + assertTrue(tracker.activelyPreferBadWifi) + + val testSubId = 1001 + // Mock the NETWORK_CARRIER_AWARE_AVOID_BAD_WIFI setting to multiple carrier setting + Settings.Global.putString( + resolver, + NETWORK_CARRIER_AWARE_AVOID_BAD_WIFI, + "$activeSubId, 0;$testSubId, 1" + ) + + // Assert that the tracker's avoidBadWifi flag is false based on carrier aware setting + assertTrue(tracker.updateAvoidBadWifi()) + assertFalse(tracker.avoidBadWifi) + assertTrue(tracker.activelyPreferBadWifi) + + // Simulate a change in the active data subscription ID to testSubId. + listener.onActiveDataSubscriptionIdChanged(testSubId) + + // Assert that the tracker's avoidBadWifi flag is true based on carrier aware setting + assertTrue(tracker.avoidBadWifi) + assertTrue(tracker.activelyPreferBadWifi) + + // Unset NETWORK_CARRIER_AWARE_AVOID_BAD_WIFI setting, + // it check NETWORK_AVOID_BAD_WIFI setting for backward compatible + Settings.Global.putString(resolver, NETWORK_CARRIER_AWARE_AVOID_BAD_WIFI, null) + // Mock the NETWORK_AVOID_BAD_WIFI setting to setting + Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "0") + + // Assert that the tracker's avoidBadWifi flag is true based on setting + assertTrue(tracker.updateAvoidBadWifi()) + assertFalse(tracker.avoidBadWifi) + assertTrue(tracker.activelyPreferBadWifi) + + // Mock the NETWORK_AVOID_BAD_WIFI setting to setting + Settings.Global.putString(resolver, NETWORK_AVOID_BAD_WIFI, "1") + + // Assert that the tracker's avoidBadWifi flag is true based on setting assertTrue(tracker.updateAvoidBadWifi()) assertTrue(tracker.avoidBadWifi) assertTrue(tracker.activelyPreferBadWifi)