157a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass/* 257a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * Copyright (C) 2017 The Android Open Source Project 357a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * 457a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * Licensed under the Apache License, Version 2.0 (the "License"); 557a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * you may not use this file except in compliance with the License. 657a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * You may obtain a copy of the License at 757a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * 857a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * http://www.apache.org/licenses/LICENSE-2.0 957a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * 1057a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * Unless required by applicable law or agreed to in writing, software 1157a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * distributed under the License is distributed on an "AS IS" BASIS, 1257a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1357a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * See the License for the specific language governing permissions and 1457a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * limitations under the License. 1557a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass */ 1657a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 1757a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plasspackage com.android.server.wifi; 1857a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 1957a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plassimport static org.junit.Assert.assertTrue; 2057a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plassimport static org.mockito.Mockito.doReturn; 2157a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plassimport static org.mockito.Mockito.when; 2257a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 2357a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plassimport android.content.Context; 2457a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plassimport android.content.res.Resources; 2557a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plassimport android.net.wifi.WifiInfo; 2657a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 2757a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plassimport com.android.internal.R; 2857a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 2957a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plassimport org.junit.Before; 3057a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plassimport org.junit.Test; 3157a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plassimport org.mockito.Mock; 3257a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plassimport org.mockito.MockitoAnnotations; 3357a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plassimport org.mockito.Spy; 3457a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 3557a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass/** 3657a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * Unit tests for {@link com.android.server.wifi.VelocityBasedConnectedScore}. 3757a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass */ 3857a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plasspublic class VelocityBasedConnectedScoreTest { 3957a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 4057a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 4157a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass class FakeClock extends Clock { 4257a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass long mWallClockMillis = 1500000000000L; 4357a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass int mStepMillis = 3001; 4457a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 4557a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass @Override 4657a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass public long getWallClockMillis() { 4757a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mWallClockMillis += mStepMillis; 4857a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass return mWallClockMillis; 4957a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass } 5057a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass } 5157a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 5257a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass FakeClock mClock; 5357a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass VelocityBasedConnectedScore mVelocityBasedConnectedScore; 5457a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass ScanDetailCache mScanDetailCache; 5557a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass WifiInfo mWifiInfo; 5657a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass int mRssiExitThreshold2GHz; 5757a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass int mRssiExitThreshold5GHz; 5857a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass @Mock Context mContext; 5957a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass @Spy private MockResources mResources = new MockResources(); 6057a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 6157a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass private int setupIntegerResource(int resourceName, int value) { 6257a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass doReturn(value).when(mResources).getInteger(resourceName); 6357a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass return value; 6457a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass } 6557a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 6657a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass /** 6757a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * Sets up resource values for testing 6857a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * 6957a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * See frameworks/base/core/res/res/values/config.xml 7057a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass */ 7157a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass private void setUpResources(Resources resources) { 7257a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mRssiExitThreshold2GHz = setupIntegerResource( 7357a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz, -83); 7457a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mRssiExitThreshold5GHz = setupIntegerResource( 7557a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz, -80); 7657a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass } 7757a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 7857a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass /** 7957a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * Sets up for unit test 8057a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass */ 8157a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass @Before 8257a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass public void setUp() throws Exception { 8357a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass MockitoAnnotations.initMocks(this); 8457a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass setUpResources(mResources); 8557a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mWifiInfo = new WifiInfo(); 8657a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mWifiInfo.setFrequency(2412); 8757a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass when(mContext.getResources()).thenReturn(mResources); 8857a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mClock = new FakeClock(); 8979545bef4e8d6c1d891f7396665b5c457bc31617Michael Plass mVelocityBasedConnectedScore = new VelocityBasedConnectedScore( 9079545bef4e8d6c1d891f7396665b5c457bc31617Michael Plass new ScoringParams(mContext), mClock); 9157a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass } 9257a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 9357a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass /** 941a0ff86a3520e9b79ded4746171a883a7f72fcdfMichael Plass * Generate a score with no updates 951a0ff86a3520e9b79ded4746171a883a7f72fcdfMichael Plass * 961a0ff86a3520e9b79ded4746171a883a7f72fcdfMichael Plass * Expect no crash, passing score 971a0ff86a3520e9b79ded4746171a883a7f72fcdfMichael Plass */ 981a0ff86a3520e9b79ded4746171a883a7f72fcdfMichael Plass @Test 991a0ff86a3520e9b79ded4746171a883a7f72fcdfMichael Plass public void noCrashWhenNoData() throws Exception { 1001a0ff86a3520e9b79ded4746171a883a7f72fcdfMichael Plass int score = mVelocityBasedConnectedScore.generateScore(); 1011a0ff86a3520e9b79ded4746171a883a7f72fcdfMichael Plass assertTrue(score > ConnectedScore.WIFI_TRANSITION_SCORE); 1021a0ff86a3520e9b79ded4746171a883a7f72fcdfMichael Plass } 1031a0ff86a3520e9b79ded4746171a883a7f72fcdfMichael Plass 1041a0ff86a3520e9b79ded4746171a883a7f72fcdfMichael Plass /** 10557a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * 10657a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * Low RSSI, but some data is moving and error rate is low. 10757a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * 10857a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * Expect a score above threshold. 10957a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass */ 11057a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass @Test 11157a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass public void allowLowRssiIfErrorRateIsLowAndSomeDataIsMoving() throws Exception { 11257a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mWifiInfo.setRssi(mRssiExitThreshold2GHz - 2); 11357a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mWifiInfo.setLinkSpeed(6); // Mbps 114442a0afdad6b7eb32a9098d927ecd65aa64df6eaMichael Plass mWifiInfo.txSuccessRate = 2.1; // proportional to pps 11557a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mWifiInfo.txBadRate = .5; 116442a0afdad6b7eb32a9098d927ecd65aa64df6eaMichael Plass mWifiInfo.rxSuccessRate = 2.1; 11757a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass for (int i = 0; i < 10; i++) { 11857a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mVelocityBasedConnectedScore.updateUsingWifiInfo(mWifiInfo, 11957a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mClock.getWallClockMillis()); 12057a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass } 12157a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass int score = mVelocityBasedConnectedScore.generateScore(); 122b865ae432e451bedf561619ce50ff4430447046bMichael Plass assertTrue(score > ConnectedScore.WIFI_TRANSITION_SCORE); 12366e108c8bcc57ac1b9eef2a165907b7444c2065aMichael Plass // If we reset, should be below threshold after the first input 12466e108c8bcc57ac1b9eef2a165907b7444c2065aMichael Plass mVelocityBasedConnectedScore.reset(); 12566e108c8bcc57ac1b9eef2a165907b7444c2065aMichael Plass mVelocityBasedConnectedScore.updateUsingWifiInfo(mWifiInfo, mClock.getWallClockMillis()); 12666e108c8bcc57ac1b9eef2a165907b7444c2065aMichael Plass score = mVelocityBasedConnectedScore.generateScore(); 12766e108c8bcc57ac1b9eef2a165907b7444c2065aMichael Plass assertTrue(score < ConnectedScore.WIFI_TRANSITION_SCORE); 12857a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass } 12957a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass 13057a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass /** 13157a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * 13257a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * Low RSSI, and almost no data is moving. 13357a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * 13457a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass * Expect a score below threshold. 13557a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass */ 13657a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass @Test 13757a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass public void disallowLowRssiIfDataIsNotMoving() throws Exception { 13857a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mWifiInfo.setRssi(mRssiExitThreshold2GHz - 1); 13957a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mWifiInfo.setLinkSpeed(6); // Mbps 14057a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mWifiInfo.txSuccessRate = .1; // proportional to pps 14157a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mWifiInfo.txBadRate = 0; 14257a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mWifiInfo.rxSuccessRate = .1; 14357a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass for (int i = 0; i < 10; i++) { 14457a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mVelocityBasedConnectedScore.updateUsingWifiInfo(mWifiInfo, 14557a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass mClock.getWallClockMillis()); 14657a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass } 14757a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass int score = mVelocityBasedConnectedScore.generateScore(); 148b865ae432e451bedf561619ce50ff4430447046bMichael Plass assertTrue(score < ConnectedScore.WIFI_TRANSITION_SCORE); 14957a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass } 15057a1fc416cf86d489693e0c02eb8c684f98b4cdbMichael Plass} 151