| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.server.wifi; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assume.assumeFalse; |
| import static org.junit.Assume.assumeTrue; |
| import static org.mockito.AdditionalAnswers.answerVoid; |
| 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.argThat; |
| import static org.mockito.Mockito.atMost; |
| import static org.mockito.Mockito.doAnswer; |
| import static org.mockito.Mockito.doThrow; |
| import static org.mockito.Mockito.never; |
| import static org.mockito.Mockito.reset; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.when; |
| |
| import android.content.Context; |
| import android.content.res.Resources; |
| import android.net.Network; |
| import android.net.NetworkCapabilities; |
| import android.net.NetworkScore; |
| import android.net.wifi.IScoreUpdateObserver; |
| import android.net.wifi.IWifiConnectedNetworkScorer; |
| import android.net.wifi.WifiConnectedSessionInfo; |
| import android.net.wifi.WifiInfo; |
| import android.net.wifi.WifiManager; |
| import android.os.Handler; |
| import android.os.IBinder; |
| import android.os.RemoteException; |
| import android.os.test.TestLooper; |
| |
| import androidx.test.filters.SmallTest; |
| |
| import com.android.modules.utils.build.SdkLevel; |
| 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.ArgumentMatcher; |
| import org.mockito.Captor; |
| import org.mockito.Mock; |
| import org.mockito.MockitoAnnotations; |
| import org.mockito.verification.VerificationMode; |
| |
| import java.io.PrintWriter; |
| |
| /** |
| * Unit tests for {@link com.android.server.wifi.WifiScoreReport}. |
| */ |
| @SmallTest |
| public class WifiScoreReportTest extends WifiBaseTest { |
| class FakeClock extends Clock { |
| long mWallClockMillis = 1500000000000L; |
| int mStepMillis = 1001; |
| |
| @Override |
| public long getWallClockMillis() { |
| mWallClockMillis += mStepMillis; |
| return mWallClockMillis; |
| } |
| } |
| |
| private static final int TEST_NETWORK_ID = 860370; |
| private static final int TEST_SESSION_ID = 8603703; // last digit is a check digit |
| private static final String TEST_IFACE_NAME = "wlan0"; |
| public static final String TEST_BSSID = "00:00:00:00:00:00"; |
| public static final boolean TEST_USER_SELECTED = true; |
| |
| FakeClock mClock; |
| WifiScoreReport mWifiScoreReport; |
| ExtendedWifiInfo mWifiInfo; |
| ScoringParams mScoringParams; |
| @Mock WifiNetworkAgent mNetworkAgent; |
| WifiThreadRunner mWifiThreadRunner; |
| @Mock Context mContext; |
| @Mock Resources mResources; |
| @Mock WifiMetrics mWifiMetrics; |
| @Mock PrintWriter mPrintWriter; |
| @Mock IBinder mAppBinder; |
| @Mock IWifiConnectedNetworkScorer mWifiConnectedNetworkScorer; |
| @Mock WifiNative mWifiNative; |
| @Mock WifiBlocklistMonitor mWifiBlocklistMonitor; |
| @Mock Network mNetwork; |
| @Mock WifiScoreCard mWifiScoreCard; |
| @Mock WifiScoreCard.PerNetwork mPerNetwork; |
| @Mock DeviceConfigFacade mDeviceConfigFacade; |
| @Mock AdaptiveConnectivityEnabledSettingObserver mAdaptiveConnectivityEnabledSettingObserver; |
| @Mock ExternalScoreUpdateObserverProxy mExternalScoreUpdateObserverProxy; |
| @Mock WifiSettingsStore mWifiSettingsStore; |
| @Mock WifiGlobals mWifiGlobals; |
| @Captor ArgumentCaptor<WifiManager.ScoreUpdateObserver> mExternalScoreUpdateObserverCbCaptor; |
| private TestLooper mLooper; |
| |
| public class WifiConnectedNetworkScorerImpl extends IWifiConnectedNetworkScorer.Stub { |
| public int mSessionId = -1; |
| |
| @Override |
| public void onStart(WifiConnectedSessionInfo sessionInfo) { |
| mSessionId = sessionInfo.getSessionId(); |
| } |
| @Override |
| public void onStop(int sessionId) { |
| } |
| @Override |
| public void onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl) { |
| } |
| } |
| |
| /** |
| * Sets up resource values for testing |
| * |
| * See frameworks/base/core/res/res/values/config.xml |
| */ |
| private void setUpResources(Resources resources) { |
| when(resources.getInteger( |
| R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz)) |
| .thenReturn(-82); |
| when(resources.getInteger( |
| R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_5GHz)) |
| .thenReturn(-77); |
| when(resources.getInteger( |
| R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz)) |
| .thenReturn(-70); |
| when(resources.getInteger( |
| R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz)) |
| .thenReturn(-57); |
| when(resources.getInteger( |
| R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz)) |
| .thenReturn(-85); |
| when(resources.getInteger( |
| R.integer.config_wifi_framework_wifi_score_entry_rssi_threshold_24GHz)) |
| .thenReturn(-80); |
| when(resources.getInteger( |
| R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz)) |
| .thenReturn(-73); |
| when(resources.getInteger( |
| R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz)) |
| .thenReturn(-60); |
| when(resources.getInteger( |
| R.integer.config_wifiFrameworkScoreBadRssiThreshold6ghz)) |
| .thenReturn(-82); |
| when(resources.getInteger( |
| R.integer.config_wifiFrameworkScoreEntryRssiThreshold6ghz)) |
| .thenReturn(-77); |
| when(resources.getInteger( |
| R.integer.config_wifiFrameworkScoreLowRssiThreshold6ghz)) |
| .thenReturn(-70); |
| when(resources.getInteger( |
| R.integer.config_wifiFrameworkScoreGoodRssiThreshold6ghz)) |
| .thenReturn(-57); |
| when(resources.getInteger( |
| R.integer.config_wifiFrameworkMinPacketPerSecondHighTraffic)) |
| .thenReturn(100); |
| when(resources.getBoolean( |
| R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)) |
| .thenReturn(false); |
| } |
| |
| /** |
| * Sets up for unit test |
| */ |
| @Before |
| public void setUp() throws Exception { |
| MockitoAnnotations.initMocks(this); |
| setUpResources(mResources); |
| mWifiInfo = new ExtendedWifiInfo(mWifiGlobals); |
| mWifiInfo.setFrequency(2412); |
| mWifiInfo.setBSSID(TEST_BSSID); |
| mLooper = new TestLooper(); |
| when(mContext.getResources()).thenReturn(mResources); |
| when(mNetwork.getNetId()).thenReturn(0); |
| when(mNetworkAgent.getNetwork()).thenReturn(mNetwork); |
| when(mNetworkAgent.getCurrentNetworkCapabilities()).thenReturn( |
| new NetworkCapabilities.Builder() |
| .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) |
| .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) |
| .build()); |
| mClock = new FakeClock(); |
| mScoringParams = new ScoringParams(); |
| mWifiThreadRunner = new WifiThreadRunner(new Handler(mLooper.getLooper())); |
| when(mAdaptiveConnectivityEnabledSettingObserver.get()).thenReturn(true); |
| mWifiScoreReport = new WifiScoreReport(mScoringParams, mClock, mWifiMetrics, mWifiInfo, |
| mWifiNative, mWifiBlocklistMonitor, mWifiThreadRunner, mWifiScoreCard, |
| mDeviceConfigFacade, mContext, |
| mAdaptiveConnectivityEnabledSettingObserver, TEST_IFACE_NAME, |
| mExternalScoreUpdateObserverProxy, mWifiSettingsStore); |
| mWifiScoreReport.onRoleChanged(ActiveModeManager.ROLE_CLIENT_PRIMARY); |
| mWifiScoreReport.setNetworkAgent(mNetworkAgent); |
| when(mDeviceConfigFacade.getMinConfirmationDurationSendLowScoreMs()).thenReturn( |
| DeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS); |
| when(mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()).thenReturn( |
| DeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_HIGH_SCORE_MS); |
| when(mDeviceConfigFacade.getRssiThresholdNotSendLowScoreToCsDbm()).thenReturn( |
| DeviceConfigFacade.DEFAULT_RSSI_THRESHOLD_NOT_SEND_LOW_SCORE_TO_CS_DBM); |
| when(mWifiSettingsStore.isWifiScoringEnabled()).thenReturn(true); |
| when(mPerNetwork.getTxLinkBandwidthKbps()).thenReturn(40_000); |
| when(mPerNetwork.getRxLinkBandwidthKbps()).thenReturn(50_000); |
| when(mWifiScoreCard.lookupNetwork(any())).thenReturn(mPerNetwork); |
| } |
| |
| /** |
| * Cleans up after test |
| */ |
| @After |
| public void tearDown() throws Exception { |
| mResources = null; |
| mWifiScoreReport = null; |
| mWifiMetrics = null; |
| } |
| |
| /** |
| * Assert a certain score was sent. Works on all SDK levels. |
| * @param score expected score |
| * @param mode times(n), never(), atLeastOnce(), etc. |
| */ |
| private void verifySentNetworkScore(int score, VerificationMode mode) { |
| if (SdkLevel.isAtLeastS()) { |
| verify(mNetworkAgent, mode).sendNetworkScore(argThat( |
| // note that a lambda doesn't work here, will cause a crash due to missing |
| // class `NetworkScore` on R even though this code path is never reached on R. |
| // Maybe lambdas are eagerly loaded by the classloader, while inner classes |
| // aren't? |
| new ArgumentMatcher<NetworkScore>() { |
| @Override |
| public boolean matches(NetworkScore networkScore) { |
| return networkScore.getLegacyInt() == score; |
| } |
| })); |
| } else { |
| verify(mNetworkAgent, mode).sendNetworkScore(score); |
| } |
| } |
| |
| private void verifySentNetworkScore(int score) { |
| verifySentNetworkScore(score, times(1)); |
| } |
| |
| private void verifySentAnyNetworkScore(VerificationMode mode) { |
| if (SdkLevel.isAtLeastS()) { |
| verify(mNetworkAgent, mode).sendNetworkScore(any(NetworkScore.class)); |
| } else { |
| verify(mNetworkAgent, mode).sendNetworkScore(anyInt()); |
| } |
| } |
| |
| private void verifySentAnyNetworkScore() { |
| verifySentAnyNetworkScore(times(1)); |
| } |
| |
| /** |
| * Test for score reporting |
| * |
| * The score should be sent to both NetworkAgent and WifiMetrics |
| */ |
| @Test |
| public void calculateAndReportScoreSucceeds() throws Exception { |
| // initially called once |
| verifySentAnyNetworkScore(); |
| |
| mWifiInfo.setRssi(-77); |
| mWifiScoreReport.calculateAndReportScore(); |
| // called again after calculateAndReportScore() |
| verifySentAnyNetworkScore(times(2)); |
| verify(mWifiMetrics).incrementWifiScoreCount(eq(TEST_IFACE_NAME), anyInt()); |
| } |
| |
| @Test |
| public void mbbNetworkForceKeepUp() throws Exception { |
| assumeTrue(SdkLevel.isAtLeastS()); |
| reset(mNetworkAgent); |
| |
| ArgumentCaptor<NetworkScore> networkScoreCaptor = |
| ArgumentCaptor.forClass(NetworkScore.class); |
| |
| // start as SECONDARY_TRANSIENT |
| mWifiScoreReport.onRoleChanged(ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT); |
| |
| verify(mNetworkAgent).sendNetworkScore(networkScoreCaptor.capture()); |
| { |
| NetworkScore networkScore = networkScoreCaptor.getValue(); |
| assertNotEquals(WifiScoreReport.LINGERING_SCORE, networkScore.getLegacyInt()); |
| assertFalse(networkScore.isExiting()); |
| assertFalse(networkScore.isTransportPrimary()); |
| // force keep up network |
| assertEquals(NetworkScore.KEEP_CONNECTED_FOR_HANDOVER, |
| networkScore.getKeepConnectedReason()); |
| } |
| |
| // network validated, becomes primary |
| mWifiScoreReport.onRoleChanged(ActiveModeManager.ROLE_CLIENT_PRIMARY); |
| verify(mNetworkAgent, times(2)).sendNetworkScore(networkScoreCaptor.capture()); |
| { |
| NetworkScore networkScore = networkScoreCaptor.getValue(); |
| assertNotEquals(WifiScoreReport.LINGERING_SCORE, networkScore.getLegacyInt()); |
| assertFalse(networkScore.isExiting()); |
| assertTrue(networkScore.isTransportPrimary()); |
| // no longer need to force keep up network |
| assertEquals(NetworkScore.KEEP_CONNECTED_NONE, networkScore.getKeepConnectedReason()); |
| } |
| } |
| |
| @Test |
| public void calculateAndReportScoreWhileLingering_sendLingeringScore() throws Exception { |
| assumeTrue(SdkLevel.isAtLeastS()); |
| reset(mNetworkAgent); |
| |
| ArgumentCaptor<NetworkScore> networkScoreCaptor = |
| ArgumentCaptor.forClass(NetworkScore.class); |
| |
| // start as primary |
| mWifiScoreReport.onRoleChanged(ActiveModeManager.ROLE_CLIENT_PRIMARY); |
| |
| verify(mNetworkAgent).sendNetworkScore(networkScoreCaptor.capture()); |
| { |
| NetworkScore networkScore = networkScoreCaptor.getValue(); |
| assertNotEquals(WifiScoreReport.LINGERING_SCORE, networkScore.getLegacyInt()); |
| assertFalse(networkScore.isExiting()); |
| assertTrue(networkScore.isTransportPrimary()); |
| assertEquals(NetworkScore.KEEP_CONNECTED_NONE, networkScore.getKeepConnectedReason()); |
| } |
| |
| // then, role changed to SECONDARY_TRANSIENT and started lingering |
| mWifiScoreReport.onRoleChanged(ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT); |
| mWifiScoreReport.setShouldReduceNetworkScore(true); |
| // upon lingering, immediately send LINGERING_SCORE |
| // capture most recent invocation |
| verify(mNetworkAgent, times(3)).sendNetworkScore(networkScoreCaptor.capture()); |
| { |
| NetworkScore networkScore = networkScoreCaptor.getValue(); |
| assertEquals(WifiScoreReport.LINGERING_SCORE, networkScore.getLegacyInt()); |
| assertFalse(networkScore.isExiting()); |
| assertFalse(networkScore.isTransportPrimary()); |
| assertEquals(NetworkScore.KEEP_CONNECTED_NONE, networkScore.getKeepConnectedReason()); |
| } |
| |
| mWifiInfo.setRssi(-77); |
| mWifiScoreReport.calculateAndReportScore(); |
| // score not sent again while lingering |
| verify(mNetworkAgent, times(3)).sendNetworkScore(any()); |
| |
| // disable lingering |
| mWifiScoreReport.onRoleChanged(ActiveModeManager.ROLE_CLIENT_PRIMARY); |
| mWifiScoreReport.setShouldReduceNetworkScore(false); |
| // report score again |
| mWifiInfo.setRssi(-60); |
| mWifiScoreReport.calculateAndReportScore(); |
| // Some non-lingering score is sent |
| // capture most recent invocation |
| verify(mNetworkAgent, times(6)).sendNetworkScore(networkScoreCaptor.capture()); |
| { |
| NetworkScore networkScore = networkScoreCaptor.getValue(); |
| assertNotEquals(WifiScoreReport.LINGERING_SCORE, networkScore.getLegacyInt()); |
| assertFalse(networkScore.isExiting()); |
| assertTrue(networkScore.isTransportPrimary()); |
| assertEquals(NetworkScore.KEEP_CONNECTED_NONE, networkScore.getKeepConnectedReason()); |
| } |
| } |
| |
| @Test |
| public void testExternalScorerWhileLingering_sendLingeringScore() throws Exception { |
| assumeTrue(SdkLevel.isAtLeastS()); |
| |
| mWifiScoreReport.onRoleChanged(ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED); |
| |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| verify(mWifiConnectedNetworkScorer).onStart( |
| argThat(sessionInfo -> sessionInfo.getSessionId() == TEST_SESSION_ID |
| && sessionInfo.isUserSelected() == TEST_USER_SELECTED)); |
| |
| reset(mNetworkAgent); |
| |
| ArgumentCaptor<NetworkScore> networkScoreCaptor = |
| ArgumentCaptor.forClass(NetworkScore.class); |
| mWifiScoreReport.setShouldReduceNetworkScore(true); |
| // upon lingering, immediately send LINGERING_SCORE |
| // capture most recent invocation |
| verify(mNetworkAgent).sendNetworkScore(networkScoreCaptor.capture()); |
| { |
| NetworkScore networkScore = networkScoreCaptor.getValue(); |
| assertEquals(WifiScoreReport.LINGERING_SCORE, networkScore.getLegacyInt()); |
| assertFalse(networkScore.isExiting()); |
| assertFalse(networkScore.isTransportPrimary()); |
| } |
| // upon lingering, send session end to client. |
| verify(mWifiConnectedNetworkScorer).onStop(TEST_SESSION_ID); |
| |
| // send score after session has ended |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyStatusUpdate(TEST_SESSION_ID, false); |
| mLooper.dispatchAll(); |
| // score not sent since session ended |
| verify(mNetworkAgent, never()).sendNetworkScore(argThat( |
| new ArgumentMatcher<NetworkScore>() { |
| @Override |
| public boolean matches(NetworkScore ns) { |
| return ns.getLegacyInt() == 49 && ns.isExiting() && ns.isTransportPrimary(); |
| } |
| })); |
| } |
| |
| /** |
| * Test for no score report if rssi is invalid |
| * |
| * The score should be sent to neither the NetworkAgent nor the |
| * WifiMetrics |
| */ |
| @Test |
| public void calculateAndReportScoreDoesNotReportWhenRssiIsNotValid() throws Exception { |
| // initially called once |
| verifySentAnyNetworkScore(); |
| |
| mWifiInfo.setRssi(WifiInfo.INVALID_RSSI); |
| mWifiScoreReport.calculateAndReportScore(); |
| // still only called once |
| verifySentAnyNetworkScore(); |
| verify(mWifiMetrics, never()).incrementWifiScoreCount(any(), anyInt()); |
| } |
| |
| /** |
| * Test for operation with null NetworkAgent |
| * |
| * Expect to not die, and to calculate the score and report to metrics. |
| */ |
| @Test |
| public void networkAgentMayBeNull() throws Exception { |
| mWifiInfo.setRssi(-33); |
| mWifiScoreReport.enableVerboseLogging(true); |
| mWifiScoreReport.setNetworkAgent(null); |
| mWifiScoreReport.calculateAndReportScore(); |
| verify(mWifiMetrics).incrementWifiScoreCount(eq(TEST_IFACE_NAME), anyInt()); |
| } |
| |
| /** |
| * Exercise the rates with low RSSI |
| * |
| * The setup has a low (not bad) RSSI, and data movement (txSuccessRate) above |
| * the threshold. |
| * |
| * Expect a score above threshold. |
| */ |
| @Test |
| public void allowLowRssiIfDataIsMoving() throws Exception { |
| mWifiInfo.setRssi(-80); |
| mWifiInfo.setLinkSpeed(6); // Mbps |
| mWifiInfo.setSuccessfulTxPacketsPerSecond(5.1); // proportional to pps |
| mWifiInfo.setSuccessfulRxPacketsPerSecond(5.1); |
| for (int i = 0; i < 10; i++) { |
| mWifiScoreReport.calculateAndReportScore(); |
| } |
| int score = mWifiInfo.getScore(); |
| assertTrue(score > ConnectedScore.WIFI_TRANSITION_SCORE); |
| } |
| |
| /** |
| * Bad RSSI without data moving should allow handoff |
| * |
| * The setup has a bad RSSI, and the txSuccessRate is below threshold; several |
| * scoring iterations are performed. |
| * |
| * Expect the score to drop below the handoff threshold. |
| */ |
| @Test |
| public void giveUpOnBadRssiWhenDataIsNotMoving() throws Exception { |
| // initially called once |
| verifySentAnyNetworkScore(); |
| |
| mWifiInfo.setRssi(-100); |
| mWifiInfo.setLinkSpeed(6); // Mbps |
| mWifiInfo.setFrequency(5220); |
| mWifiScoreReport.enableVerboseLogging(true); |
| mWifiInfo.setSuccessfulTxPacketsPerSecond(0.1); |
| mWifiInfo.setSuccessfulRxPacketsPerSecond(0.1); |
| for (int i = 0; i < 10; i++) { |
| mWifiScoreReport.calculateAndReportScore(); |
| } |
| int score = mWifiInfo.getScore(); |
| assertTrue(score < ConnectedScore.WIFI_TRANSITION_SCORE); |
| if (SdkLevel.isAtLeastS()) { |
| ArgumentCaptor<NetworkScore> scoreCaptor = ArgumentCaptor.forClass(NetworkScore.class); |
| verify(mNetworkAgent, times(2)).sendNetworkScore(scoreCaptor.capture()); |
| NetworkScore ns = scoreCaptor.getValue(); |
| assertEquals(score, ns.getLegacyInt()); |
| assertTrue(ns.isExiting()); |
| assertTrue(ns.isTransportPrimary()); |
| } else { |
| verify(mNetworkAgent).sendNetworkScore(score); |
| } |
| } |
| |
| /** |
| * When the score ramps down to the exit theshold, let go. |
| */ |
| @Test |
| public void giveUpOnBadRssiAggressively() throws Exception { |
| String oops = "giveUpOnBadRssiAggressively"; |
| mWifiInfo.setFrequency(5220); |
| for (int rssi = -60; rssi >= -83; rssi -= 1) { |
| mWifiInfo.setRssi(rssi); |
| oops += " " + mClock.mWallClockMillis + "," + rssi; |
| mWifiScoreReport.calculateAndReportScore(); |
| oops += ":" + mWifiInfo.getScore(); |
| } |
| int score = mWifiInfo.getScore(); |
| verifySentNetworkScore(score); |
| assertTrue(oops, score < ConnectedScore.WIFI_TRANSITION_SCORE); |
| } |
| |
| /** |
| * RSSI that falls rapidly but does not cross entry threshold should not cause handoff |
| * |
| * Expect the score to not drop below the handoff threshold. |
| */ |
| @Test |
| public void stayOnIfRssiDoesNotGetBelowEntryThreshold() throws Exception { |
| String oops = "didNotStickLanding"; |
| int minScore = 100; |
| mWifiInfo.setLinkSpeed(6); // Mbps |
| mWifiInfo.setFrequency(5220); |
| mWifiScoreReport.enableVerboseLogging(true); |
| mWifiInfo.setSuccessfulTxPacketsPerSecond(0.1); |
| mWifiInfo.setSuccessfulRxPacketsPerSecond(0.1); |
| assertTrue(mScoringParams.update("rssi5=-83:-80:-66:-55")); |
| for (int r = -30; r >= -100; r -= 1) { |
| int rssi = Math.max(r, -80); |
| mWifiInfo.setRssi(rssi); |
| oops += " " + mClock.mWallClockMillis + "," + rssi; |
| mWifiScoreReport.calculateAndReportScore(); |
| oops += ":" + mWifiInfo.getScore(); |
| if (mWifiInfo.getScore() < minScore) minScore = mWifiInfo.getScore(); |
| } |
| assertTrue(oops, minScore > ConnectedScore.WIFI_TRANSITION_SCORE); |
| } |
| |
| /** |
| * Don't breach if the success rates are great |
| * |
| * Ramp the RSSI down, but maintain a high packet throughput |
| * |
| * Expect score to stay above above threshold. |
| */ |
| @Test |
| public void allowTerribleRssiIfDataIsMovingWell() throws Exception { |
| mWifiInfo.setSuccessfulTxPacketsPerSecond( |
| mScoringParams.getYippeeSkippyPacketsPerSecond() + 0.1); |
| mWifiInfo.setSuccessfulRxPacketsPerSecond( |
| mScoringParams.getYippeeSkippyPacketsPerSecond() + 0.1); |
| assertTrue(mWifiInfo.getSuccessfulTxPacketsPerSecond() > 10); |
| mWifiInfo.setFrequency(5220); |
| for (int r = -30; r >= -120; r -= 2) { |
| mWifiInfo.setRssi(r); |
| mWifiScoreReport.calculateAndReportScore(); |
| assertTrue(mWifiInfo.getScore() > ConnectedScore.WIFI_TRANSITION_SCORE); |
| } |
| // If the throughput dips, we should let go |
| mWifiInfo.setSuccessfulRxPacketsPerSecond( |
| mScoringParams.getYippeeSkippyPacketsPerSecond() - 0.1); |
| mWifiScoreReport.calculateAndReportScore(); |
| assertTrue(mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE); |
| // And even if throughput improves again, once we have decided to let go, disregard |
| // the good rates. |
| mWifiInfo.setSuccessfulRxPacketsPerSecond( |
| mScoringParams.getYippeeSkippyPacketsPerSecond() + 0.1); |
| mWifiScoreReport.calculateAndReportScore(); |
| assertTrue(mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE); |
| } |
| |
| /** |
| * Never ask for nud check when nud=0 |
| */ |
| @Test |
| public void neverAskForNudCheckWhenNudKnobIsZero() throws Exception { |
| assertTrue(mScoringParams.update("nud=0")); |
| assertEquals(0, mScoringParams.getNudKnob()); |
| mWifiInfo.setFrequency(5220); |
| for (int rssi = -30; rssi >= -120; rssi -= 1) { |
| mWifiInfo.setRssi(rssi); |
| mWifiScoreReport.calculateAndReportScore(); |
| assertFalse(mWifiScoreReport.shouldCheckIpLayer()); |
| } |
| } |
| |
| /** |
| * Eventually ask for nud check when nud=1 |
| */ |
| @Test |
| public void eventuallyAskForNudCheckWhenNudKnobIsOne() throws Exception { |
| String oops = "nud=1"; |
| long lastAskedMillis = 0; // Check that we don't send too soon |
| int asks = 0; // Keep track of how many time we asked |
| assertTrue(mScoringParams.update("nud=1")); |
| assertEquals(1, mScoringParams.getNudKnob()); |
| mWifiInfo.setFrequency(5220); |
| for (int rssi = -40; rssi >= -120; rssi -= 1) { |
| mWifiInfo.setRssi(rssi); |
| mWifiScoreReport.calculateAndReportScore(); |
| boolean ask = mWifiScoreReport.shouldCheckIpLayer(); |
| if (ask) { |
| assertTrue(mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE); |
| assertTrue(oops, mClock.mWallClockMillis >= lastAskedMillis + 5000); |
| lastAskedMillis = mClock.mWallClockMillis; |
| oops += " " + lastAskedMillis + ":" + mWifiInfo.getScore(); |
| mWifiScoreReport.noteIpCheck(); |
| asks++; |
| } |
| } |
| assertTrue(oops + " asks:" + asks, asks > 5 && asks < 15); |
| } |
| |
| |
| /** |
| * Ask for more nud checks when nud=10 |
| */ |
| @Test |
| public void askForMoreNudChecksWhenNudKnobIsBigger() throws Exception { |
| String oops = "nud=10"; |
| long lastAskedMillis = 0; // Check that we don't send too soon |
| int asks = 0; // Keep track of how many time we asked |
| assertTrue(mScoringParams.update("nud=10")); |
| assertEquals(10, mScoringParams.getNudKnob()); |
| mWifiInfo.setFrequency(5220); |
| for (int rssi = -40; rssi >= -120; rssi -= 1) { |
| mWifiInfo.setRssi(rssi); |
| mWifiScoreReport.calculateAndReportScore(); |
| boolean ask = mWifiScoreReport.shouldCheckIpLayer(); |
| if (ask) { |
| assertTrue(mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE); |
| assertTrue(oops, mClock.mWallClockMillis >= lastAskedMillis + 5000); |
| lastAskedMillis = mClock.mWallClockMillis; |
| oops += " " + lastAskedMillis + ":" + mWifiInfo.getScore(); |
| mWifiScoreReport.noteIpCheck(); |
| asks++; |
| } |
| } |
| assertTrue(oops + " asks:" + asks, asks > 12 && asks < 80); |
| } |
| |
| /** |
| * Test initial conditions, and after reset() |
| */ |
| @Test |
| public void exerciseReset() throws Exception { |
| assertFalse(mWifiScoreReport.shouldCheckIpLayer()); |
| mWifiScoreReport.reset(); |
| assertFalse(mWifiScoreReport.shouldCheckIpLayer()); |
| } |
| |
| /** |
| * This setup causes some reports to be generated when println |
| * methods are called, to check for "concurrent" modification |
| * errors. |
| */ |
| private void setupToGenerateAReportWhenPrintlnIsCalled() { |
| int[] counter = new int[1]; |
| doAnswer(answerVoid((String line) -> { |
| if (counter[0]++ < 3) { |
| mWifiScoreReport.calculateAndReportScore(); |
| } |
| })).when(mPrintWriter).println(anyString()); |
| } |
| |
| /** |
| * Test data logging |
| */ |
| @Test |
| public void testDataLogging() throws Exception { |
| for (int i = 0; i < 10; i++) { |
| mWifiInfo.setRssi(-65 + i); |
| mWifiInfo.setLinkSpeed(300); |
| mWifiInfo.setFrequency(5220); |
| mWifiInfo.setSuccessfulTxPacketsPerSecond(0.1 + i); |
| mWifiInfo.setRetriedTxPacketsRate(0.2 + i); |
| mWifiInfo.setLostTxPacketsPerSecond(0.01 * i); |
| mWifiInfo.setSuccessfulRxPacketsPerSecond(0.3 + i); |
| mWifiScoreReport.calculateAndReportScore(); |
| } |
| setupToGenerateAReportWhenPrintlnIsCalled(); |
| mWifiScoreReport.dump(null, mPrintWriter, null); |
| verify(mPrintWriter, times(13)).println(anyString()); |
| } |
| |
| /** |
| * Test data logging limit |
| * <p> |
| * Check that only a bounded amount of data is collected for dumpsys report |
| */ |
| @Test |
| public void testDataLoggingLimit() throws Exception { |
| for (int i = 0; i < 3620; i++) { |
| mWifiInfo.setRssi(-65 + i % 20); |
| mWifiInfo.setLinkSpeed(300); |
| mWifiInfo.setFrequency(5220); |
| mWifiInfo.setSuccessfulTxPacketsPerSecond(0.1 + i % 100); |
| mWifiInfo.setRetriedTxPacketsRate(0.2 + i % 100); |
| mWifiInfo.setLostTxPacketsPerSecond(0.0001 * i); |
| mWifiInfo.setSuccessfulRxPacketsPerSecond(0.3 + i % 200); |
| mWifiScoreReport.calculateAndReportScore(); |
| } |
| mWifiScoreReport.dump(null, mPrintWriter, null); |
| verify(mPrintWriter, atMost(3603)).println(anyString()); |
| } |
| |
| /** |
| * Test for staying at below transition score for a certain period of time. |
| */ |
| @Test |
| public void stayAtBelowTransitionScoreForCertainPeriodOfTime() throws Exception { |
| mWifiScoreReport.enableVerboseLogging(true); |
| mWifiInfo.setFrequency(5220); |
| |
| // Reduce RSSI value to fall below the transition score |
| for (int rssi = -60; rssi >= -83; rssi -= 1) { |
| mWifiInfo.setRssi(rssi); |
| mWifiScoreReport.calculateAndReportScore(); |
| } |
| assertTrue(mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE); |
| |
| // Then, set high RSSI value to exceed the transition score |
| mWifiInfo.setRssi(-50); |
| // 8 seconds elapse |
| for (int i = 0; i < 8; i++) { |
| mWifiScoreReport.calculateAndReportScore(); |
| } |
| assertTrue(mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE); |
| |
| // 9 seconds elapse |
| mWifiScoreReport.calculateAndReportScore(); |
| assertTrue(mWifiInfo.getScore() > ConnectedScore.WIFI_TRANSITION_SCORE); |
| } |
| |
| /** |
| * Test for resetting the internal timer which is used to keep staying at |
| * below transition score for a certain period of time. |
| */ |
| @Test |
| public void stayAtBelowTransitionScoreWithReset() throws Exception { |
| mWifiScoreReport.enableVerboseLogging(true); |
| mWifiInfo.setFrequency(5220); |
| |
| // Reduce RSSI value to fall below the transition score |
| for (int rssi = -60; rssi >= -83; rssi -= 1) { |
| mWifiInfo.setRssi(rssi); |
| mWifiScoreReport.calculateAndReportScore(); |
| } |
| assertTrue(mWifiInfo.getScore() < ConnectedScore.WIFI_TRANSITION_SCORE); |
| |
| // Then, set high RSSI value to exceed the transition score |
| mWifiInfo.setRssi(-50); |
| // Reset the internal timer so that no need to wait for 9 seconds |
| mWifiScoreReport.reset(); |
| mWifiScoreReport.calculateAndReportScore(); |
| assertTrue(mWifiInfo.getScore() > ConnectedScore.WIFI_TRANSITION_SCORE); |
| } |
| |
| /** |
| * Verify that client gets ScoreChangeCallback object when client sets its scorer. |
| */ |
| @Test |
| public void testClientNotification() throws RemoteException { |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); |
| // Client should get ScoreChangeCallback. |
| verify(mExternalScoreUpdateObserverProxy).registerCallback(any()); |
| } |
| |
| /** |
| * Verify that clear client should be handled. |
| */ |
| @Test |
| public void testClearClient() throws RemoteException { |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback(any()); |
| mWifiScoreReport.clearWifiConnectedNetworkScorer(); |
| verify(mAppBinder).unlinkToDeath(any(), anyInt()); |
| verify(mExternalScoreUpdateObserverProxy).unregisterCallback(any()); |
| |
| mWifiScoreReport.startConnectedNetworkScorer(10, true); |
| verify(mWifiConnectedNetworkScorer, never()).onStart(any()); |
| } |
| |
| /** |
| * Verify that WifiScoreReport adds for death notification on setting client. |
| */ |
| @Test |
| public void testAddsForBinderDeathOnSetClient() throws Exception { |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback(any()); |
| verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); |
| } |
| |
| /** |
| * Verify that client fails to get message when scorer add failed. |
| */ |
| @Test |
| public void testAddsScorerFailureOnLinkToDeath() throws Exception { |
| doThrow(new RemoteException()) |
| .when(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); |
| verify(mExternalScoreUpdateObserverProxy, never()).registerCallback(any()); |
| verify(mAppBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); |
| |
| // Client should not get any message when scorer add failed. |
| verify(mWifiConnectedNetworkScorer, never()).onSetScoreUpdateObserver(any()); |
| } |
| |
| /** |
| * Verify netId to sessionId conversion. |
| */ |
| @Test |
| public void testSessionId() throws Exception { |
| assertEquals(-1, WifiScoreReport.sessionIdFromNetId(Integer.MIN_VALUE)); |
| assertEquals(-1, WifiScoreReport.sessionIdFromNetId(-42)); |
| assertEquals(-1, WifiScoreReport.sessionIdFromNetId(-1)); |
| assertEquals(-1, WifiScoreReport.sessionIdFromNetId(0)); |
| assertEquals(18, WifiScoreReport.sessionIdFromNetId(1)); |
| assertEquals(3339, WifiScoreReport.sessionIdFromNetId(333)); |
| assertEquals(TEST_SESSION_ID, WifiScoreReport.sessionIdFromNetId(TEST_NETWORK_ID)); |
| int dangerOfOverflow = Integer.MAX_VALUE / 10; |
| assertEquals(214748364, dangerOfOverflow); |
| assertEquals(2147483646, WifiScoreReport.sessionIdFromNetId(dangerOfOverflow)); |
| assertEquals(8, WifiScoreReport.sessionIdFromNetId(dangerOfOverflow + 1)); |
| assertEquals(8, WifiScoreReport.sessionIdFromNetId(Integer.MAX_VALUE)); |
| } |
| |
| /** |
| * Verify that client gets session ID when onStart() method is called. |
| */ |
| @Test |
| public void testClientGetSessionIdOnStart() throws Exception { |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback(any()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| verify(mWifiConnectedNetworkScorer).onStart( |
| argThat(sessionInfo -> sessionInfo.getSessionId() == TEST_SESSION_ID |
| && sessionInfo.isUserSelected() == TEST_USER_SELECTED)); |
| } |
| |
| /** |
| * Verify that onStart is called if there is already an active network when registered. |
| */ |
| @Test |
| public void testClientStartOnRegWhileActive() throws Exception { |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback(any()); |
| verify(mWifiConnectedNetworkScorer).onStart( |
| argThat(sessionInfo -> sessionInfo.getSessionId() == TEST_SESSION_ID |
| && sessionInfo.isUserSelected() == TEST_USER_SELECTED)); |
| } |
| |
| /** |
| * Verify that client gets session ID when onStop() method is called. |
| */ |
| @Test |
| public void testClientGetSessionIdOnStop() throws Exception { |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback(any()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| verify(mWifiConnectedNetworkScorer).onStart( |
| argThat(sessionInfo -> sessionInfo.getSessionId() == TEST_SESSION_ID |
| && sessionInfo.isUserSelected() == TEST_USER_SELECTED)); |
| mWifiScoreReport.stopConnectedNetworkScorer(); |
| verify(mWifiConnectedNetworkScorer).onStop(TEST_SESSION_ID); |
| // After the session stops, it should not start again (without a new NetworkAgent) |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| verify(mWifiConnectedNetworkScorer).onStart( |
| argThat(sessionInfo -> sessionInfo.getSessionId() == TEST_SESSION_ID |
| && sessionInfo.isUserSelected() == TEST_USER_SELECTED)); |
| } |
| |
| /** |
| * Verify that only a single Wi-Fi connected network scorer can be registered successfully. |
| */ |
| @Test |
| public void verifyOnlyASingleScorerCanBeRegisteredSuccessively() throws Exception { |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| assertEquals(true, mWifiScoreReport.setWifiConnectedNetworkScorer( |
| mAppBinder, scorerImpl)); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback(any()); |
| assertEquals(false, mWifiScoreReport.setWifiConnectedNetworkScorer( |
| mAppBinder, scorerImpl)); |
| } |
| |
| /** |
| * Verify that WifiScoreReport gets updated score when notifyScoreUpdate() is called by apps. |
| */ |
| @Test |
| public void testFrameworkGetsUpdatesScore() throws Exception { |
| assumeFalse(SdkLevel.isAtLeastS()); |
| // initially called once |
| verifySentNetworkScore(60); |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| |
| assertEquals(TEST_SESSION_ID, scorerImpl.mSessionId); |
| |
| // Invalid session ID |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate(-1, 49); |
| if (SdkLevel.isAtLeastS()) { |
| NetworkScore score = mWifiScoreReport.getScore(); |
| assertEquals(ConnectedScore.WIFI_MAX_SCORE, score.getLegacyInt()); |
| assertTrue(score.isTransportPrimary()); |
| assertFalse(score.isExiting()); |
| } else { |
| assertEquals(ConnectedScore.WIFI_MAX_SCORE, mWifiScoreReport.getLegacyIntScore()); |
| } |
| |
| // Incorrect session ID |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId + 10, 49); |
| if (SdkLevel.isAtLeastS()) { |
| NetworkScore score = mWifiScoreReport.getScore(); |
| assertEquals(ConnectedScore.WIFI_MAX_SCORE, score.getLegacyInt()); |
| assertTrue(score.isTransportPrimary()); |
| assertFalse(score.isExiting()); |
| } else { |
| assertEquals(ConnectedScore.WIFI_MAX_SCORE, mWifiScoreReport.getLegacyIntScore()); |
| } |
| |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| verifySentNetworkScore(49); |
| if (SdkLevel.isAtLeastS()) { |
| NetworkScore score = mWifiScoreReport.getScore(); |
| assertEquals(score.getLegacyInt(), 49); |
| assertTrue(score.isTransportPrimary()); |
| assertTrue(score.isExiting()); |
| } else { |
| assertEquals(49, mWifiScoreReport.getLegacyIntScore()); |
| } |
| |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 59); |
| mLooper.dispatchAll(); |
| verifySentNetworkScore(59); |
| if (SdkLevel.isAtLeastS()) { |
| NetworkScore score = mWifiScoreReport.getScore(); |
| assertEquals(score.getLegacyInt(), 59); |
| assertTrue(score.isTransportPrimary()); |
| assertFalse(score.isExiting()); |
| } else { |
| assertEquals(59, mWifiScoreReport.getLegacyIntScore()); |
| } |
| } |
| |
| /** |
| * Verify that WifiScoreReport triggers an update of WifiUsabilityStatsEntry. |
| */ |
| @Test |
| public void testFrameworkTriggersUpdateOfWifiUsabilityStats() throws Exception { |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| |
| mExternalScoreUpdateObserverCbCaptor.getValue().triggerUpdateOfWifiUsabilityStats( |
| scorerImpl.mSessionId); |
| mLooper.dispatchAll(); |
| verify(mWifiNative).getWifiLinkLayerStats(TEST_IFACE_NAME); |
| verify(mWifiNative).signalPoll(TEST_IFACE_NAME); |
| } |
| |
| /** |
| * Ask for nud when score from external scorer breaches |
| */ |
| @Test |
| public void askForNudCheckWhenExternalScoreBreaches() throws Exception { |
| assumeFalse(SdkLevel.isAtLeastS()); |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| mClock.mStepMillis = 0; |
| |
| mClock.mWallClockMillis = 5001; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| assertTrue(mWifiScoreReport.shouldCheckIpLayer()); |
| mWifiScoreReport.noteIpCheck(); |
| |
| mClock.mWallClockMillis = 10000; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| assertFalse(mWifiScoreReport.shouldCheckIpLayer()); |
| |
| mClock.mWallClockMillis = 10001; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| assertTrue(mWifiScoreReport.shouldCheckIpLayer()); |
| } |
| |
| /** |
| * Verify BSSID blocklist does not happen when score stays below threshold for less than the |
| * minimum duration |
| */ |
| @Test |
| public void bssidBlockListDoesnotHappenWhenExitingIsLessThanMinDuration() throws Exception { |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| mClock.mStepMillis = 0; |
| |
| mClock.mWallClockMillis = 10; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| mClock.mWallClockMillis = 29009; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| mWifiScoreReport.stopConnectedNetworkScorer(); |
| mLooper.dispatchAll(); |
| verify(mWifiBlocklistMonitor, never()).handleBssidConnectionFailure(any(), any(), |
| anyInt(), anyInt()); |
| } |
| |
| /** |
| * Verify BSSID blocklist happens when score stays below threshold for longer than the |
| * minimum duration |
| */ |
| @Test |
| public void bssidBlockListHappensWhenExitingIsLongerThanMinDuration() throws Exception { |
| assumeFalse(SdkLevel.isAtLeastS()); |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| mClock.mStepMillis = 0; |
| |
| mClock.mWallClockMillis = 10; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| mClock.mWallClockMillis = 29011; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| mWifiScoreReport.stopConnectedNetworkScorer(); |
| mLooper.dispatchAll(); |
| verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(any(), any(), |
| eq(WifiBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE), anyInt()); |
| } |
| |
| /** |
| * Verify BSSID blocklist does not happen when there is score flip flop |
| */ |
| @Test |
| public void bssidBlockListDoesnotHappenWhenExitingIsReset() throws Exception { |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| mClock.mStepMillis = 0; |
| |
| mClock.mWallClockMillis = 10; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| mClock.mWallClockMillis = 15000; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 51); |
| mLooper.dispatchAll(); |
| mClock.mWallClockMillis = 29011; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| mWifiScoreReport.stopConnectedNetworkScorer(); |
| mLooper.dispatchAll(); |
| verify(mWifiBlocklistMonitor, never()).handleBssidConnectionFailure(any(), any(), |
| anyInt(), anyInt()); |
| } |
| |
| /** |
| * Verify that the initial score value in WifiInfo is the max when onStart is called. |
| */ |
| @Test |
| public void testOnStartInitialScoreInWifiInfoIsMaxScore() throws Exception { |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); |
| assertEquals(ConnectedScore.WIFI_MAX_SCORE, mWifiInfo.getScore()); |
| } |
| |
| /** |
| * Verify confirmation duration is not added when it is not enabled in config overlay by default |
| */ |
| @Test |
| public void confirmationDurationIsNotAddedWhenItIsNotEnabledInConfigOverlay() throws Exception { |
| assumeFalse(SdkLevel.isAtLeastS()); |
| verifySentAnyNetworkScore(); |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| mClock.mStepMillis = 0; |
| |
| mClock.mWallClockMillis = 10; |
| mWifiInfo.setRssi(-65); |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| verifySentAnyNetworkScore(times(2)); |
| } |
| |
| /** |
| * Verify confirmation duration is not added when there is no score breach |
| */ |
| @Test |
| public void confirmationDurationIsNotAddedWhenThereIsNoScoreBreach() throws Exception { |
| assumeFalse(SdkLevel.isAtLeastS()); |
| // initially sent score = 60 |
| verifySentNetworkScore(60); |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| mClock.mStepMillis = 0; |
| when(mContext.getResources().getBoolean( |
| R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true); |
| |
| mClock.mWallClockMillis = 10; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 60); |
| mWifiInfo.setRssi(-70); |
| mLooper.dispatchAll(); |
| verifySentNetworkScore(60, times(2)); |
| mClock.mWallClockMillis = 3010; |
| mWifiInfo.setRssi(-65); |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 59); |
| mLooper.dispatchAll(); |
| verifySentNetworkScore(59); |
| mClock.mWallClockMillis = 6010; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 58); |
| mLooper.dispatchAll(); |
| verifySentNetworkScore(58); |
| } |
| |
| /** |
| * Verify confirmation duration and RSSI check is added for reporting low score when it is |
| * enabled in config overlay |
| */ |
| @Test |
| public void confirmationDurationAndRssiCheckIsAddedForSendingLowScore() throws Exception { |
| assumeFalse(SdkLevel.isAtLeastS()); |
| // initially called once |
| verifySentAnyNetworkScore(); |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| mClock.mStepMillis = 0; |
| when(mContext.getResources().getBoolean( |
| R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true); |
| |
| mClock.mWallClockMillis = 10; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| // still only called once |
| verifySentAnyNetworkScore(); |
| mClock.mWallClockMillis = 10 |
| + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS - 1; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 48); |
| mLooper.dispatchAll(); |
| // still only called once |
| verifySentAnyNetworkScore(); |
| mClock.mWallClockMillis = 10 |
| + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS; |
| mWifiInfo.setRssi(-65); |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 47); |
| mLooper.dispatchAll(); |
| verifySentNetworkScore(47, never()); |
| mClock.mWallClockMillis = 10 |
| + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS + 3000; |
| mWifiInfo.setRssi(-68); |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 46); |
| mLooper.dispatchAll(); |
| verifySentNetworkScore(46); |
| } |
| |
| /** |
| * Verify confirmation duration is not added for reporting high score with default zero value |
| */ |
| @Test |
| public void confirmationDurationIsNotAddedForSendingHighScore() throws Exception { |
| assumeFalse(SdkLevel.isAtLeastS()); |
| // initially called once |
| verifySentAnyNetworkScore(); |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| mClock.mStepMillis = 0; |
| when(mContext.getResources().getBoolean( |
| R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true); |
| |
| mClock.mWallClockMillis = 10; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| // still only called once |
| verifySentAnyNetworkScore(); |
| mClock.mWallClockMillis = 3000; |
| mWifiInfo.setRssi(-70); |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 51); |
| mLooper.dispatchAll(); |
| verifySentNetworkScore(51); |
| mClock.mWallClockMillis = 6000; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 52); |
| mLooper.dispatchAll(); |
| verifySentNetworkScore(52); |
| |
| } |
| |
| /** |
| * Verify confirmation duration is added for reporting high score with non-zero value |
| */ |
| @Test |
| public void confirmationDurationIsAddedForSendingHighScore() throws Exception { |
| assumeFalse(SdkLevel.isAtLeastS()); |
| // initially called once |
| verifySentAnyNetworkScore(); |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| mClock.mStepMillis = 0; |
| when(mContext.getResources().getBoolean( |
| R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true); |
| when(mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()).thenReturn(4000); |
| |
| mClock.mWallClockMillis = 10; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| // still only called once |
| verifySentAnyNetworkScore(); |
| mClock.mWallClockMillis = 3000; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 51); |
| mLooper.dispatchAll(); |
| // still only called once |
| verifySentAnyNetworkScore(); |
| mClock.mWallClockMillis = 6999; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 52); |
| mLooper.dispatchAll(); |
| // still only called once |
| verifySentAnyNetworkScore(); |
| mClock.mWallClockMillis = 7000; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 53); |
| mLooper.dispatchAll(); |
| verifySentNetworkScore(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 { |
| // initially called once |
| verifySentAnyNetworkScore(); |
| |
| mWifiInfo.setFrequency(5220); |
| mWifiInfo.setRssi(-85); |
| when(mAdaptiveConnectivityEnabledSettingObserver.get()).thenReturn(false); |
| mWifiScoreReport.calculateAndReportScore(); |
| assertFalse(mWifiScoreReport.shouldCheckIpLayer()); |
| |
| if (SdkLevel.isAtLeastS()) { |
| ArgumentCaptor<NetworkScore> scoreCaptor = ArgumentCaptor.forClass(NetworkScore.class); |
| verify(mNetworkAgent, times(2)).sendNetworkScore(scoreCaptor.capture()); |
| NetworkScore ns = scoreCaptor.getValue(); |
| assertEquals(51, ns.getLegacyInt()); |
| assertFalse(ns.isExiting()); |
| assertTrue(ns.isTransportPrimary()); |
| } else { |
| verify(mNetworkAgent).sendNetworkScore(51); |
| } |
| } |
| |
| /** |
| * Verify NUD check is not recommended and the score of 51 is sent to connectivity service |
| * when Wifi scoring is disabled. |
| */ |
| @Test |
| public void verifyNudCheckAndScoreIfScoringDisabledForAospScorer() throws Exception { |
| // initially called once |
| verifySentAnyNetworkScore(); |
| mWifiInfo.setFrequency(5220); |
| mWifiInfo.setRssi(-85); |
| when(mWifiSettingsStore.isWifiScoringEnabled()).thenReturn(false); |
| mWifiScoreReport.calculateAndReportScore(); |
| assertFalse(mWifiScoreReport.shouldCheckIpLayer()); |
| |
| if (SdkLevel.isAtLeastS()) { |
| ArgumentCaptor<NetworkScore> scoreCaptor = ArgumentCaptor.forClass(NetworkScore.class); |
| verify(mNetworkAgent, times(2)).sendNetworkScore(scoreCaptor.capture()); |
| NetworkScore ns = scoreCaptor.getValue(); |
| assertEquals(51, ns.getLegacyInt()); |
| assertFalse(ns.isExiting()); |
| assertTrue(ns.isTransportPrimary()); |
| } else { |
| 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 { |
| assumeFalse(SdkLevel.isAtLeastS()); |
| // initially called once |
| verifySentAnyNetworkScore(); |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| mClock.mStepMillis = 0; |
| when(mContext.getResources().getBoolean( |
| R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true); |
| when(mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()).thenReturn(4000); |
| |
| when(mAdaptiveConnectivityEnabledSettingObserver.get()).thenReturn(false); |
| |
| mClock.mWallClockMillis = 10; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 49); |
| mLooper.dispatchAll(); |
| // still only called once |
| verifySentAnyNetworkScore(); |
| assertFalse(mWifiScoreReport.shouldCheckIpLayer()); |
| |
| mClock.mWallClockMillis = 10 |
| + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS - 1; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 48); |
| mLooper.dispatchAll(); |
| // still only called once |
| verifySentAnyNetworkScore(); |
| mClock.mWallClockMillis = 10 |
| + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS; |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 47); |
| mLooper.dispatchAll(); |
| verifySentNetworkScore(51); |
| } |
| |
| /** |
| * Verify NUD check is not recommended and the score of 51 is sent to connectivity service |
| * when Wifi scoring is disabled for external Wi-Fi scorer. |
| */ |
| @Test |
| public void verifyNudCheckAndScoreIfScoringDisabledForExternalScorer() throws Exception { |
| assumeFalse(SdkLevel.isAtLeastS()); |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| when(mWifiSettingsStore.isWifiScoringEnabled()).thenReturn(false); |
| |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 47); |
| mLooper.dispatchAll(); |
| assertFalse(mWifiScoreReport.shouldCheckIpLayer()); |
| verifySentNetworkScore(51); |
| } |
| |
| /** |
| * Verify that WifiScoreReport gets updated score when notifyStoreUpdate() is called by apps. |
| */ |
| @Test |
| public void testFrameworkGetsNotifiedOfUpdatedScore() throws Exception { |
| assumeTrue(SdkLevel.isAtLeastS()); |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyScoreUpdate( |
| scorerImpl.mSessionId, 59); |
| mLooper.dispatchAll(); |
| verify(mWifiMetrics).incrementWifiScoreCount(eq(TEST_IFACE_NAME), anyInt()); |
| } |
| |
| /** |
| * Verify that WifiScoreReport gets updated status when notifyStatusUpdate() is called by apps. |
| */ |
| @Test |
| public void testFrameworkGetsNotifiedOfUpdatedStatus() throws Exception { |
| assumeTrue(SdkLevel.isAtLeastS()); |
| // initially called once |
| verify(mNetworkAgent).sendNetworkScore(any()); |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyStatusUpdate( |
| scorerImpl.mSessionId, true); |
| mLooper.dispatchAll(); |
| |
| { |
| ArgumentCaptor<NetworkScore> scoreCaptor = ArgumentCaptor.forClass(NetworkScore.class); |
| verify(mNetworkAgent, times(2)).sendNetworkScore(scoreCaptor.capture()); |
| NetworkScore ns = scoreCaptor.getValue(); |
| assertEquals(51, ns.getLegacyInt()); |
| assertFalse(ns.isExiting()); |
| assertTrue(ns.isTransportPrimary()); |
| } |
| |
| mExternalScoreUpdateObserverCbCaptor.getValue().notifyStatusUpdate( |
| scorerImpl.mSessionId, false); |
| mLooper.dispatchAll(); |
| |
| { |
| ArgumentCaptor<NetworkScore> scoreCaptor = ArgumentCaptor.forClass(NetworkScore.class); |
| verify(mNetworkAgent, times(3)).sendNetworkScore(scoreCaptor.capture()); |
| NetworkScore ns = scoreCaptor.getValue(); |
| assertEquals(49, ns.getLegacyInt()); |
| assertTrue(ns.isExiting()); |
| assertTrue(ns.isTransportPrimary()); |
| } |
| } |
| |
| /** |
| * Verify that WifiScoreReport gets NUD request only once when requestNudOperation() is called |
| * by apps. |
| */ |
| @Test |
| public void testFrameworkGetsNotifiedOfRequestedNudOperation() throws Exception { |
| assumeTrue(SdkLevel.isAtLeastS()); |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mClock.mStepMillis = 0; |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| |
| mClock.mWallClockMillis = 5001; |
| mExternalScoreUpdateObserverCbCaptor.getValue().requestNudOperation(scorerImpl.mSessionId); |
| mLooper.dispatchAll(); |
| assertTrue(mWifiScoreReport.shouldCheckIpLayer()); |
| mWifiScoreReport.noteIpCheck(); |
| // Assert NUD is triggered only once by one request. |
| assertFalse(mWifiScoreReport.shouldCheckIpLayer()); |
| |
| mClock.mWallClockMillis = 10000; |
| mExternalScoreUpdateObserverCbCaptor.getValue().requestNudOperation(scorerImpl.mSessionId); |
| mLooper.dispatchAll(); |
| assertFalse(mWifiScoreReport.shouldCheckIpLayer()); |
| } |
| |
| /** |
| * Verify that blocklisting happens when blocklistCurrentBssid() is called by apps. |
| */ |
| @Test |
| public void testFrameworkGetsBlocklistCurrentBssidOperation() throws Exception { |
| WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| |
| mExternalScoreUpdateObserverCbCaptor.getValue().blocklistCurrentBssid( |
| scorerImpl.mSessionId); |
| mLooper.dispatchAll(); |
| verify(mWifiBlocklistMonitor).handleBssidConnectionFailure(any(), any(), |
| eq(WifiBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE), anyInt()); |
| } |
| |
| @Test |
| public void testClientNotNotifiedForLocalOnlyConnection() throws Exception { |
| when(mNetworkAgent.getCurrentNetworkCapabilities()).thenReturn( |
| new NetworkCapabilities.Builder() |
| // no internet |
| .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) |
| .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) |
| .build()); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| verify(mWifiConnectedNetworkScorer, never()).onStart(any()); |
| } |
| |
| @Test |
| public void testClientNotNotifiedForOemPaidConnection() throws Exception { |
| assumeTrue(SdkLevel.isAtLeastS()); |
| when(mNetworkAgent.getCurrentNetworkCapabilities()).thenReturn( |
| new NetworkCapabilities.Builder() |
| .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) |
| // oem paid |
| .addCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID) |
| .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) |
| .build()); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| verify(mWifiConnectedNetworkScorer, never()).onStart(any()); |
| } |
| |
| @Test |
| public void testClientNotNotifiedForOemPrivateConnection() throws Exception { |
| assumeTrue(SdkLevel.isAtLeastS()); |
| when(mNetworkAgent.getCurrentNetworkCapabilities()).thenReturn( |
| new NetworkCapabilities.Builder() |
| .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) |
| // oem private |
| .addCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE) |
| .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) |
| .build()); |
| // Register Client for verification. |
| mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer); |
| verify(mExternalScoreUpdateObserverProxy).registerCallback( |
| mExternalScoreUpdateObserverCbCaptor.capture()); |
| when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); |
| mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID, TEST_USER_SELECTED); |
| verify(mWifiConnectedNetworkScorer, never()).onStart(any()); |
| } |
| } |