diff options
3 files changed, 152 insertions, 3 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java index 95983096a..0b67fa319 100644 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ b/service/java/com/android/server/wifi/ClientModeImpl.java @@ -812,7 +812,7 @@ public class ClientModeImpl extends StateMachine { mWifiScoreReport = new WifiScoreReport(mWifiInjector.getScoringParams(), mClock, mWifiMetrics, mWifiInfo, mWifiNative, mBssidBlocklistMonitor, mWifiInjector.getWifiThreadRunner(), mWifiInjector.getDeviceConfigFacade(), - mContext); + mContext, looper, mFacade); mNetworkCapabilitiesFilter = new NetworkCapabilities.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) @@ -3441,6 +3441,7 @@ public class ClientModeImpl extends StateMachine { break; case CMD_INITIALIZE: mWifiNative.initialize(); + mWifiScoreReport.initialize(); break; case CMD_BOOT_COMPLETED: // get other services that we need to manage diff --git a/service/java/com/android/server/wifi/WifiScoreReport.java b/service/java/com/android/server/wifi/WifiScoreReport.java index 89f0445cb..381be7f2b 100644 --- a/service/java/com/android/server/wifi/WifiScoreReport.java +++ b/service/java/com/android/server/wifi/WifiScoreReport.java @@ -17,16 +17,22 @@ package com.android.server.wifi; import android.content.Context; +import android.database.ContentObserver; import android.net.Network; import android.net.NetworkAgent; +import android.net.Uri; import android.net.wifi.IScoreUpdateObserver; import android.net.wifi.IWifiConnectedNetworkScorer; import android.net.wifi.WifiInfo; import android.net.wifi.nl80211.WifiNl80211Manager; +import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.RemoteException; +import android.provider.Settings; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; import com.android.wifi.resources.R; import java.io.FileDescriptor; @@ -57,6 +63,15 @@ public class WifiScoreReport { private static final long DURATION_TO_BLOCKLIST_BSSID_AFTER_FIRST_EXITING_MILLIS = 30000; private static final long INVALID_WALL_CLOCK_MILLIS = -1; + /** + * Copy of the settings string. Can't directly use the constant because it is @hide. + * See {@link android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED}. + * TODO(b/167709538) remove this hardcoded string and create new API in Wifi mainline. + */ + @VisibleForTesting + public static final String SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED = + "adaptive_connectivity_enabled"; + // Cache of the last score private int mScore = ConnectedScore.WIFI_MAX_SCORE; @@ -78,6 +93,8 @@ public class WifiScoreReport { WifiNative mWifiNative; WifiThreadRunner mWifiThreadRunner; DeviceConfigFacade mDeviceConfigFacade; + Handler mHandler; + FrameworkFacade mFrameworkFacade; /** * Callback proxy. See {@link android.net.wifi.WifiManager.ScoreUpdateObserver}. @@ -200,6 +217,10 @@ public class WifiScoreReport { return; } } + // Stay a notch above the transition score if adaptive connectivity is disabled. + if (!mAdaptiveConnectivityEnabled) { + score = ConnectedScore.WIFI_TRANSITION_SCORE + 1; + } mNetworkAgent.sendNetworkScore(score); } @@ -286,10 +307,50 @@ public class WifiScoreReport { private WifiConnectedNetworkScorerHolder mWifiConnectedNetworkScorerHolder; + /** + * Observer for adaptive connectivity enable settings changes. + * This is enabled by default. Will be toggled off via adb command or a settings + * toggle by the user to disable adaptive connectivity. + */ + private class AdaptiveConnectivityEnabledSettingObserver extends ContentObserver { + AdaptiveConnectivityEnabledSettingObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + mAdaptiveConnectivityEnabled = getValue(); + Log.d(TAG, "Adaptive connectivity status changed: " + mAdaptiveConnectivityEnabled); + } + + /** + * Register settings change observer. + */ + public void initialize() { + Uri uri = Settings.Secure.getUriFor(SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED); + if (uri == null) { + Log.e(TAG, "Adaptive connectivity user toggle does not exist in Settings"); + return; + } + mFrameworkFacade.registerContentObserver(mContext, uri, true, this); + mAdaptiveConnectivityEnabled = mAdaptiveConnectivityEnabledSettingObserver.getValue(); + } + + public boolean getValue() { + return mFrameworkFacade.getIntegerSetting( + mContext, SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED, 1) == 1; + } + } + + private final AdaptiveConnectivityEnabledSettingObserver + mAdaptiveConnectivityEnabledSettingObserver; + private boolean mAdaptiveConnectivityEnabled = true; + WifiScoreReport(ScoringParams scoringParams, Clock clock, WifiMetrics wifiMetrics, WifiInfo wifiInfo, WifiNative wifiNative, BssidBlocklistMonitor bssidBlocklistMonitor, WifiThreadRunner wifiThreadRunner, DeviceConfigFacade deviceConfigFacade, - Context context) { + Context context, Looper looper, FrameworkFacade frameworkFacade) { mScoringParams = scoringParams; mClock = clock; mAggressiveConnectedScore = new AggressiveConnectedScore(scoringParams, clock); @@ -301,6 +362,10 @@ public class WifiScoreReport { mWifiThreadRunner = wifiThreadRunner; mDeviceConfigFacade = deviceConfigFacade; mContext = context; + mFrameworkFacade = frameworkFacade; + mHandler = new Handler(looper); + mAdaptiveConnectivityEnabledSettingObserver = + new AdaptiveConnectivityEnabledSettingObserver(mHandler); } /** @@ -463,6 +528,10 @@ public class WifiScoreReport { * @return true to indicate that an IP reachability check is recommended */ public boolean shouldCheckIpLayer() { + // Don't recommend if adaptive connectivity is disabled. + if (!mAdaptiveConnectivityEnabled) { + return false; + } int nud = mScoringParams.getNudKnob(); if (nud == 0) { return false; @@ -703,4 +772,11 @@ public class WifiScoreReport { mWifiConnectedNetworkScorerHolder = null; mWifiMetrics.setIsExternalWifiScorerOn(false); } + + /** + * Initialize WifiScoreReport + */ + public void initialize() { + mAdaptiveConnectivityEnabledSettingObserver.initialize(); + } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java b/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java index 82dbbe941..cf83fbee3 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.AdditionalAnswers.answerVoid; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyLong; @@ -38,6 +39,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; +import android.database.ContentObserver; import android.net.ConnectivityManager; import android.net.LinkProperties; import android.net.Network; @@ -50,6 +52,7 @@ import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.RemoteException; import android.os.test.TestLooper; @@ -60,6 +63,7 @@ import com.android.wifi.resources.R; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -102,6 +106,8 @@ public class WifiScoreReportTest extends WifiBaseTest { @Mock BssidBlocklistMonitor mBssidBlocklistMonitor; @Mock Network mNetwork; @Mock DeviceConfigFacade mDeviceConfigFacade; + @Mock Looper mWifiLooper; + @Mock FrameworkFacade mFrameworkFacade; private TestLooper mLooper; public class WifiConnectedNetworkScorerImpl extends IWifiConnectedNetworkScorer.Stub { @@ -200,10 +206,14 @@ public class WifiScoreReportTest extends WifiBaseTest { mClock = new FakeClock(); mScoringParams = new ScoringParams(); mWifiThreadRunner = new WifiThreadRunner(new Handler(mLooper.getLooper())); + when(mFrameworkFacade.getIntegerSetting(any(Context.class), + eq(WifiScoreReport.SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED), eq(1))) + .thenReturn(1); mWifiScoreReport = new WifiScoreReport(mScoringParams, mClock, mWifiMetrics, mWifiInfo, mWifiNative, mBssidBlocklistMonitor, mWifiThreadRunner, - mDeviceConfigFacade, mContext); + mDeviceConfigFacade, mContext, mWifiLooper, mFrameworkFacade); mWifiScoreReport.setNetworkAgent(mNetworkAgent); + mWifiScoreReport.initialize(); when(mDeviceConfigFacade.getMinConfirmationDurationSendLowScoreMs()).thenReturn( DeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS); when(mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()).thenReturn( @@ -999,4 +1009,66 @@ public class WifiScoreReportTest extends WifiBaseTest { mLooper.dispatchAll(); verify(mNetworkAgent).sendNetworkScore(53); } + + /** + * Verify NUD check is not recommended and the score of 51 is sent to connectivity service + * when adaptive connectivity is disabled for AOSP scorer. + */ + @Test + public void verifyNudCheckAndScoreIfToggleOffForAospScorer() throws Exception { + mWifiInfo.setFrequency(5220); + mWifiInfo.setRssi(-85); + ArgumentCaptor<ContentObserver> observer = ArgumentCaptor.forClass(ContentObserver.class); + verify(mFrameworkFacade).registerContentObserver( + any(), any(), eq(true), observer.capture()); + when(mFrameworkFacade.getIntegerSetting(any(Context.class), + eq(WifiScoreReport.SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED), eq(1))) + .thenReturn(0); + observer.getValue().onChange(true); + mWifiScoreReport.calculateAndReportScore(); + assertFalse(mWifiScoreReport.shouldCheckIpLayer()); + verify(mNetworkAgent).sendNetworkScore(51); + } + + /** + * Verify NUD check is not recommended and the score of 51 is sent to connectivity service + * when adaptive connectivity is disabled for external Wi-Fi scorer. + */ + @Test + public void verifyNudCheckAndScoreIfToggleOffForExternalScorer() throws Exception { + WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); + // Register Client for verification. + mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); + when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); + mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); + mClock.mStepMillis = 0; + when(mContext.getResources().getBoolean( + R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true); + when(mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()).thenReturn(4000); + + ArgumentCaptor<ContentObserver> observer = ArgumentCaptor.forClass(ContentObserver.class); + verify(mFrameworkFacade).registerContentObserver( + any(), any(), eq(true), observer.capture()); + when(mFrameworkFacade.getIntegerSetting(any(Context.class), + eq(WifiScoreReport.SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED), eq(1))) + .thenReturn(0); + observer.getValue().onChange(true); + + mClock.mWallClockMillis = 10; + scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); + mLooper.dispatchAll(); + verify(mNetworkAgent, never()).sendNetworkScore(anyInt()); + assertFalse(mWifiScoreReport.shouldCheckIpLayer()); + + mClock.mWallClockMillis = 10 + + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS - 1; + scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 48); + mLooper.dispatchAll(); + verify(mNetworkAgent, never()).sendNetworkScore(anyInt()); + mClock.mWallClockMillis = 10 + + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS; + scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 47); + mLooper.dispatchAll(); + verify(mNetworkAgent).sendNetworkScore(51); + } } |