blob: 6d55b19f4cdfbc6a50beb33eeb290d52ea43b6de [file] [log] [blame]
/*
* 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.Mockito.anyInt;
import static org.mockito.Mockito.atLeast;
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.NetworkAgent;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import com.android.internal.R;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
/**
* Unit tests for {@link com.android.server.wifi.WifiScoreReport}.
*/
public class WifiScoreReportTest {
private static final int CELLULAR_THRESHOLD_SCORE = 50;
WifiConfiguration mWifiConfiguration;
WifiScoreReport mWifiScoreReport;
ScanDetailCache mScanDetailCache;
@Mock Context mContext;
@Mock NetworkAgent mNetworkAgent;
@Mock Resources mResources;
@Mock WifiConfigManager mWifiConfigManager;
@Mock WifiInfo mWifiInfo;
@Mock WifiMetrics mWifiMetrics;
/**
* 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_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_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_wifi_framework_wifi_score_bad_link_speed_24))
.thenReturn(6); // Mbps
when(resources.getInteger(
R.integer.config_wifi_framework_wifi_score_bad_link_speed_5))
.thenReturn(12);
when(resources.getInteger(
R.integer.config_wifi_framework_wifi_score_good_link_speed_24))
.thenReturn(24);
when(resources.getInteger(
R.integer.config_wifi_framework_wifi_score_good_link_speed_5))
.thenReturn(36);
when(resources.getBoolean(
R.bool.config_wifi_framework_cellular_handover_enable_user_triggered_adjustment))
.thenReturn(true);
}
/**
* Pulls the final score from a report string
*
* The report string is essentially free-form, intended for debugging,
* but we would like to know that the score is in there somewhere.
*
* Currently, the score is found as the last value in a comma-separated
* list enclosed in square brackets.
*/
private int fishScoreFromReportString(String report) {
int score = 0;
if (report != null) {
String[] f = report.split("]");
assertTrue(f.length > 1);
f = f[f.length - 2].split(",");
score = Integer.parseInt(f[f.length - 1]);
// clipping happens after stashing in report string, so do that here.
score = Integer.min(score, NetworkAgent.WIFI_BASE_SCORE);
}
return score;
}
/**
* Sets up for unit test
*/
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
setUpResources(mResources);
WifiConfiguration config = new WifiConfiguration();
config.SSID = "nooooooooooo";
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
config.hiddenSSID = false;
when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(config));
when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
mWifiConfiguration = config;
int maxSize = 10;
int trimSize = 5;
mScanDetailCache = new ScanDetailCache(config, maxSize, trimSize);
// TODO: populate the cache, but probably in the test cases, not here.
when(mWifiConfigManager.getScanDetailCacheForNetwork(anyInt()))
.thenReturn(mScanDetailCache);
when(mContext.getResources()).thenReturn(mResources);
mWifiScoreReport = new WifiScoreReport(mContext, mWifiConfigManager);
}
/**
* Cleans up after test
*/
@After
public void tearDown() throws Exception {
mResources = null;
mWifiScoreReport = null;
mWifiConfigManager = 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 {
when(mWifiInfo.getRssi()).thenReturn(-77);
int aggressiveHandover = 0;
mWifiScoreReport.calculateAndReportScore(mWifiInfo,
mNetworkAgent, aggressiveHandover, mWifiMetrics);
verify(mNetworkAgent).sendNetworkScore(anyInt());
verify(mWifiMetrics).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 {
when(mWifiInfo.getRssi()).thenReturn(-33);
mWifiScoreReport.enableVerboseLogging(true);
mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
verify(mWifiMetrics).incrementWifiScoreCount(anyInt());
}
/**
* Test operation of saved last report
*
* One score is calculated
* Expect: last report is not valid before any score is calculated
* Expect: last report is valid after a score is calculated
* Expect: the score in the last report string matches the reported score
* Expect: reset makes the last report invalid again
*/
@Test
public void makeSureLastReportWorks() throws Exception {
when(mWifiInfo.getRssi()).thenReturn(-33);
assertFalse(mWifiScoreReport.isLastReportValid());
mWifiScoreReport.enableVerboseLogging(true);
mWifiScoreReport.calculateAndReportScore(mWifiInfo, mNetworkAgent, 0, mWifiMetrics);
assertTrue(mWifiScoreReport.isLastReportValid());
String report = mWifiScoreReport.getLastReport();
int score = fishScoreFromReportString(report);
verify(mWifiMetrics).incrementWifiScoreCount(score);
verify(mNetworkAgent).sendNetworkScore(score);
mWifiScoreReport.reset();
assertFalse(mWifiScoreReport.isLastReportValid());
assertTrue(mWifiScoreReport.getLastReport().equals(""));
}
/**
* Test bad linkspeed counter
*
* Expect badLinkspeed count to be incemented based on bad link speed.
* Expect counter to be pinned at a maximum value.
* Expect counter to be cleared by reset.
*/
@Test
public void badLinkspeedCounter() throws Exception {
when(mWifiInfo.getRssi()).thenReturn(-123);
when(mWifiInfo.getLinkSpeed()).thenReturn(1);
when(mWifiInfo.is24GHz()).thenReturn(true);
assertFalse(mWifiScoreReport.isLastReportValid());
mWifiScoreReport.enableVerboseLogging(true);
assertEquals(0, mWifiScoreReport.getLastBadLinkspeedcount());
mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
assertEquals(1, mWifiScoreReport.getLastBadLinkspeedcount());
mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
assertEquals(2, mWifiScoreReport.getLastBadLinkspeedcount());
mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
assertEquals(3, mWifiScoreReport.getLastBadLinkspeedcount());
mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 1, mWifiMetrics);
mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 1, mWifiMetrics);
mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
assertEquals(6, mWifiScoreReport.getLastBadLinkspeedcount()); // pinned at limit
verify(mWifiMetrics, times(9)).incrementWifiScoreCount(anyInt());
verify(mWifiInfo, atLeast(9)).is24GHz();
assertTrue(mWifiScoreReport.isLastReportValid());
mWifiScoreReport.reset();
assertEquals(0, mWifiScoreReport.getLastBadLinkspeedcount());
}
/**
* 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 {
when(mWifiInfo.getRssi()).thenReturn(-80);
when(mWifiInfo.getLinkSpeed()).thenReturn(6); // Mbps
when(mWifiInfo.is24GHz()).thenReturn(true);
mWifiInfo.txSuccessRate = 5.1; // proportional to pps
mWifiInfo.rxSuccessRate = 5.1;
for (int i = 0; i < 10; i++) {
mWifiScoreReport.calculateAndReportScore(mWifiInfo, mNetworkAgent, 0, mWifiMetrics);
}
assertTrue(mWifiScoreReport.isLastReportValid());
int score = fishScoreFromReportString(mWifiScoreReport.getLastReport());
assertTrue(score > CELLULAR_THRESHOLD_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 {
when(mWifiInfo.getRssi()).thenReturn(-100);
when(mWifiInfo.getLinkSpeed()).thenReturn(6); // Mbps
when(mWifiInfo.is24GHz()).thenReturn(true);
mWifiScoreReport.enableVerboseLogging(true);
mWifiInfo.txSuccessRate = 0.1;
mWifiInfo.rxSuccessRate = 0.1;
for (int i = 0; i < 10; i++) {
mWifiScoreReport.calculateAndReportScore(mWifiInfo, mNetworkAgent, 0, mWifiMetrics);
String report = mWifiScoreReport.getLastReport();
assertTrue(report.contains(" br "));
}
assertTrue(mWifiScoreReport.isLastReportValid());
int score = fishScoreFromReportString(mWifiScoreReport.getLastReport());
assertTrue(score < CELLULAR_THRESHOLD_SCORE);
verify(mNetworkAgent, atLeast(1)).sendNetworkScore(score);
}
}