/*
 * 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.assertTrue;
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.atLeast;
import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
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.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.wifi.IScoreUpdateObserver;
import android.net.wifi.IWifiConnectedNetworkScorer;
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;

import androidx.test.filters.SmallTest;

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;

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

    FakeClock mClock;
    WifiConfiguration mWifiConfiguration;
    WifiScoreReport mWifiScoreReport;
    ScanDetailCache mScanDetailCache;
    WifiInfo mWifiInfo;
    ScoringParams mScoringParams;
    NetworkAgent 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 BssidBlocklistMonitor mBssidBlocklistMonitor;
    @Mock Network mNetwork;
    @Mock DeviceConfigFacade mDeviceConfigFacade;
    @Mock Looper mWifiLooper;
    @Mock FrameworkFacade mFrameworkFacade;
    private TestLooper mLooper;

    public class WifiConnectedNetworkScorerImpl extends IWifiConnectedNetworkScorer.Stub {
        public IScoreUpdateObserver mScoreUpdateObserver;
        public int mSessionId = -1;

        @Override
        public void onStart(int sessionId) {
            mSessionId = sessionId;
        }
        @Override
        public void onStop(int sessionId) {
        }
        @Override
        public void onSetScoreUpdateObserver(IScoreUpdateObserver observerImpl) {
            mScoreUpdateObserver = observerImpl;
        }
    }

    // NetworkAgent is abstract, so a subclass is necessary
    private static class TestNetworkAgent extends NetworkAgent {
        TestNetworkAgent(Context context) {
            super(new TestLooper().getLooper(), context, "TestNetworkAgent",
                    mock(NetworkInfo.class), new NetworkCapabilities(), new LinkProperties(), 0);
        }
        @Override protected void unwanted() { }
    }

    /**
     * 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 WifiInfo();
        mWifiInfo.setFrequency(2412);
        mLooper = new TestLooper();
        when(mContext.getResources()).thenReturn(mResources);
        final ConnectivityManager cm = mock(ConnectivityManager.class);
        when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(cm);
        when(cm.registerNetworkAgent(any(), any(), any(), any(), anyInt(), any(), anyInt()))
                .thenReturn(mNetwork);
        when(mNetwork.getNetId()).thenReturn(0);
        mNetworkAgent = spy(new TestNetworkAgent(mContext));
        mClock = new FakeClock();
        mScoringParams = new ScoringParams();
        mWifiThreadRunner = new WifiThreadRunner(new Handler(mLooper.getLooper()));
        when(mFrameworkFacade.getSecureIntegerSetting(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, mWifiLooper, mFrameworkFacade);
        mWifiScoreReport.setNetworkAgent(mNetworkAgent);
        mWifiScoreReport.initialize();
        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);
    }

    /**
     * Cleans up after test
     */
    @After
    public void tearDown() throws Exception {
        mResources = null;
        mWifiScoreReport = null;
        mWifiMetrics = null;
    }

    /**
     * Test for score reporting
     *
     * The score should be sent to both the NetworkAgent and the
     * WifiMetrics
     */
    @Test
    public void calculateAndReportScoreSucceeds() throws Exception {
        mWifiInfo.setRssi(-77);
        mWifiScoreReport.calculateAndReportScore();
        verify(mNetworkAgent).sendNetworkScore(anyInt());
        verify(mWifiMetrics).incrementWifiScoreCount(anyInt());
    }

    /**
     * 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 {
        mWifiInfo.setRssi(WifiInfo.INVALID_RSSI);
        mWifiScoreReport.calculateAndReportScore();
        verify(mNetworkAgent, never()).sendNetworkScore(anyInt());
        verify(mWifiMetrics, never()).incrementWifiScoreCount(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(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 {
        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);
        verify(mNetworkAgent, atLeast(1)).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();
        verify(mNetworkAgent, atLeast(1)).sendNetworkScore(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(11)).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(3601)).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(mWifiConnectedNetworkScorer).onSetScoreUpdateObserver(any());
    }

    /**
     * Verify that clear client should be handled.
     */
    @Test
    public void testClearClient() throws RemoteException {
        // Register Client for verification.
        mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer);
        mWifiScoreReport.clearWifiConnectedNetworkScorer();
        verify(mAppBinder).unlinkToDeath(any(), anyInt());

        mWifiScoreReport.startConnectedNetworkScorer(10);
        verify(mWifiConnectedNetworkScorer, never()).onStart(anyInt());
    }

    /**
     * Verify that WifiScoreReport adds for death notification on setting client.
     */
    @Test
    public void testAddsForBinderDeathOnSetClient() throws Exception {
        mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer);
        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(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);
        when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID);
        mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID);
        verify(mWifiConnectedNetworkScorer).onStart(TEST_SESSION_ID);
    }

    /**
     * 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);
        mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer);
        verify(mWifiConnectedNetworkScorer).onStart(TEST_SESSION_ID);
    }

    /**
     * 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);
        when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID);
        mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID);
        verify(mWifiConnectedNetworkScorer).onStart(TEST_SESSION_ID);
        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);
        verify(mWifiConnectedNetworkScorer).onStart(anyInt());
    }

    /**
     * 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));
        assertEquals(false, mWifiScoreReport.setWifiConnectedNetworkScorer(
                mAppBinder, scorerImpl));
    }

    /**
     * Verify that WifiScoreReport gets updated score when notifyScoreUpdate() is called by apps.
     */
    @Test
    public void testFrameworkGetsUpdatesScore() 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);

        assertEquals(TEST_SESSION_ID, scorerImpl.mSessionId);

        // Invalid session ID
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(-1, 49);
        assertEquals(mWifiScoreReport.getScore(), ConnectedScore.WIFI_MAX_SCORE);

        // Incorrect session ID
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId + 10, 49);
        assertEquals(mWifiScoreReport.getScore(), ConnectedScore.WIFI_MAX_SCORE);

        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
        mLooper.dispatchAll();
        verify(mNetworkAgent).sendNetworkScore(49);
        assertEquals(mWifiScoreReport.getScore(), 49);

        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 59);
        mLooper.dispatchAll();
        verify(mNetworkAgent).sendNetworkScore(59);
        assertEquals(mWifiScoreReport.getScore(), 59);
    }

    /**
     * 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);
        mWifiScoreReport.setInterfaceName("wlan0");
        when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID);
        mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID);

        scorerImpl.mScoreUpdateObserver.triggerUpdateOfWifiUsabilityStats(scorerImpl.mSessionId);
        mLooper.dispatchAll();
        verify(mWifiNative).getWifiLinkLayerStats("wlan0");
        verify(mWifiNative).signalPoll("wlan0");
    }

    /**
     * Ask for nud when score from external scorer breaches
     */
    @Test
    public void askForNudCheckWhenExternalScoreBreaches() 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;

        mClock.mWallClockMillis = 5001;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
        mLooper.dispatchAll();
        assertTrue(mWifiScoreReport.shouldCheckIpLayer());
        mWifiScoreReport.noteIpCheck();

        mClock.mWallClockMillis = 10000;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
        mLooper.dispatchAll();
        assertFalse(mWifiScoreReport.shouldCheckIpLayer());

        mClock.mWallClockMillis = 10001;
        scorerImpl.mScoreUpdateObserver.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);
        when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID);
        mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID);
        mClock.mStepMillis = 0;

        mClock.mWallClockMillis = 10;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
        mLooper.dispatchAll();
        mClock.mWallClockMillis = 29009;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
        mLooper.dispatchAll();
        mWifiScoreReport.stopConnectedNetworkScorer();
        mLooper.dispatchAll();
        verify(mBssidBlocklistMonitor, 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 {
        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;

        mClock.mWallClockMillis = 10;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
        mLooper.dispatchAll();
        mClock.mWallClockMillis = 29011;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
        mLooper.dispatchAll();
        mWifiScoreReport.stopConnectedNetworkScorer();
        mLooper.dispatchAll();
        verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(any(), any(),
                eq(BssidBlocklistMonitor.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);
        when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID);
        mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID);
        mClock.mStepMillis = 0;

        mClock.mWallClockMillis = 10;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
        mLooper.dispatchAll();
        mClock.mWallClockMillis = 15000;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 51);
        mLooper.dispatchAll();
        mClock.mWallClockMillis = 29011;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
        mLooper.dispatchAll();
        mWifiScoreReport.stopConnectedNetworkScorer();
        mLooper.dispatchAll();
        verify(mBssidBlocklistMonitor, 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);
        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 {
        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;

        mClock.mWallClockMillis = 10;
        mWifiInfo.setRssi(-65);
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
        mLooper.dispatchAll();
        verify(mNetworkAgent).sendNetworkScore(anyInt());
    }

    /**
     * Verify confirmation duration is not added when there is no score breacht
     */
    @Test
    public void confirmationDurationIsNotAddedWhenThereIsNoScoreBreach() 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);

        mClock.mWallClockMillis = 10;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 60);
        mWifiInfo.setRssi(-70);
        mLooper.dispatchAll();
        verify(mNetworkAgent).sendNetworkScore(60);
        mClock.mWallClockMillis = 3010;
        mWifiInfo.setRssi(-65);
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 59);
        mLooper.dispatchAll();
        verify(mNetworkAgent).sendNetworkScore(59);
        mClock.mWallClockMillis = 6010;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 58);
        mLooper.dispatchAll();
        verify(mNetworkAgent).sendNetworkScore(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 {
        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);

        mClock.mWallClockMillis = 10;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
        mLooper.dispatchAll();
        verify(mNetworkAgent, never()).sendNetworkScore(anyInt());
        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;
        mWifiInfo.setRssi(-65);
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 47);
        mLooper.dispatchAll();
        verify(mNetworkAgent, never()).sendNetworkScore(47);
        mClock.mWallClockMillis = 10
                + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS + 3000;
        mWifiInfo.setRssi(-68);
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 46);
        mLooper.dispatchAll();
        verify(mNetworkAgent).sendNetworkScore(46);
    }

    /**
     * Verify confirmation duration is not added for reporting high score with default zero value
     */
    @Test
    public void confirmationDurationIsNotAddedForSendingHighScore() 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);

        mClock.mWallClockMillis = 10;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
        mLooper.dispatchAll();
        verify(mNetworkAgent, never()).sendNetworkScore(anyInt());
        mClock.mWallClockMillis = 3000;
        mWifiInfo.setRssi(-70);
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 51);
        mLooper.dispatchAll();
        verify(mNetworkAgent).sendNetworkScore(51);
        mClock.mWallClockMillis = 6000;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 52);
        mLooper.dispatchAll();
        verify(mNetworkAgent).sendNetworkScore(52);
    }

    /**
     * Verify confirmation duration is added for reporting high score with non-zero value
     */
    @Test
    public void confirmationDurationIsAddedForSendingHighScore() 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);

        mClock.mWallClockMillis = 10;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
        mLooper.dispatchAll();
        verify(mNetworkAgent, never()).sendNetworkScore(anyInt());
        mClock.mWallClockMillis = 3000;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 51);
        mLooper.dispatchAll();
        verify(mNetworkAgent, never()).sendNetworkScore(anyInt());
        mClock.mWallClockMillis = 6999;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 52);
        mLooper.dispatchAll();
        verify(mNetworkAgent, never()).sendNetworkScore(anyInt());
        mClock.mWallClockMillis = 7000;
        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 53);
        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.getSecureIntegerSetting(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.getSecureIntegerSetting(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);
    }
}
