WifiScoreReportTest.java revision 9b256a5cb87062b7ae1696324e2bd7c9b1ceca27
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wifi;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertFalse;
21import static org.junit.Assert.assertTrue;
22import static org.mockito.Mockito.anyInt;
23import static org.mockito.Mockito.atLeast;
24import static org.mockito.Mockito.times;
25import static org.mockito.Mockito.verify;
26import static org.mockito.Mockito.when;
27
28import android.content.Context;
29import android.content.res.Resources;
30import android.net.NetworkAgent;
31import android.net.wifi.WifiConfiguration;
32import android.net.wifi.WifiInfo;
33
34import com.android.internal.R;
35
36import org.junit.After;
37import org.junit.Before;
38import org.junit.Test;
39import org.mockito.Mock;
40import org.mockito.MockitoAnnotations;
41
42import java.util.Arrays;
43
44/**
45 * Unit tests for {@link com.android.server.wifi.WifiScoreReport}.
46 */
47public class WifiScoreReportTest {
48
49    private static final int CELLULAR_THRESHOLD_SCORE = 50;
50
51    WifiConfiguration mWifiConfiguration;
52    WifiScoreReport mWifiScoreReport;
53    ScanDetailCache mScanDetailCache;
54    WifiInfo mWifiInfo;
55    @Mock Context mContext;
56    @Mock NetworkAgent mNetworkAgent;
57    @Mock Resources mResources;
58    @Mock WifiConfigManager mWifiConfigManager;
59    @Mock WifiMetrics mWifiMetrics;
60
61    /**
62     * Sets up resource values for testing
63     *
64     * See frameworks/base/core/res/res/values/config.xml
65     */
66    private void setUpResources(Resources resources) {
67        when(resources.getInteger(
68                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz))
69            .thenReturn(-82);
70        when(resources.getInteger(
71                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz))
72            .thenReturn(-70);
73        when(resources.getInteger(
74                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz))
75            .thenReturn(-57);
76        when(resources.getInteger(
77                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz))
78            .thenReturn(-85);
79        when(resources.getInteger(
80                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz))
81            .thenReturn(-73);
82        when(resources.getInteger(
83                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz))
84            .thenReturn(-60);
85        when(resources.getInteger(
86                R.integer.config_wifi_framework_wifi_score_bad_link_speed_24))
87            .thenReturn(6); // Mbps
88        when(resources.getInteger(
89                R.integer.config_wifi_framework_wifi_score_bad_link_speed_5))
90            .thenReturn(12);
91        when(resources.getInteger(
92                R.integer.config_wifi_framework_wifi_score_good_link_speed_24))
93            .thenReturn(24);
94        when(resources.getInteger(
95                R.integer.config_wifi_framework_wifi_score_good_link_speed_5))
96            .thenReturn(36);
97        when(resources.getBoolean(
98                R.bool.config_wifi_framework_cellular_handover_enable_user_triggered_adjustment))
99            .thenReturn(true);
100    }
101
102    /**
103     *  Pulls the final score from a report string
104     *
105     *  The report string is essentially free-form, intended for debugging,
106     *  but we would like to know that the score is in there somewhere.
107     *
108     *  Currently, the score is found as the last value in a comma-separated
109     *  list enclosed in square brackets.
110     */
111    private int fishScoreFromReportString(String report) {
112        int score = 0;
113        if (report != null) {
114            String[] f = report.split("]");
115            assertTrue(f.length > 1);
116            f = f[f.length - 2].split(",");
117            score = Integer.parseInt(f[f.length - 1]);
118            // clipping happens after stashing in report string, so do that here.
119            score = Integer.min(score, NetworkAgent.WIFI_BASE_SCORE);
120        }
121        return score;
122    }
123
124    /**
125     * Sets up for unit test
126     */
127    @Before
128    public void setUp() throws Exception {
129        MockitoAnnotations.initMocks(this);
130        setUpResources(mResources);
131        WifiConfiguration config = new WifiConfiguration();
132        config.SSID = "nooooooooooo";
133        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
134        config.hiddenSSID = false;
135        mWifiInfo = new WifiInfo();
136        mWifiInfo.setFrequency(2410);
137        when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(config));
138        when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
139        mWifiConfiguration = config;
140        int maxSize = 10;
141        int trimSize = 5;
142        mScanDetailCache = new ScanDetailCache(config, maxSize, trimSize);
143        // TODO: populate the cache, but probably in the test cases, not here.
144        when(mWifiConfigManager.getScanDetailCacheForNetwork(anyInt()))
145                .thenReturn(mScanDetailCache);
146        when(mContext.getResources()).thenReturn(mResources);
147        mWifiScoreReport = new WifiScoreReport(mContext, mWifiConfigManager);
148    }
149
150    /**
151     * Cleans up after test
152     */
153    @After
154    public void tearDown() throws Exception {
155        mResources = null;
156        mWifiScoreReport = null;
157        mWifiConfigManager = null;
158        mWifiMetrics = null;
159    }
160
161    /**
162     * Test for score reporting
163     *
164     * The score should be sent to both the NetworkAgent and the
165     * WifiMetrics
166     */
167    @Test
168    public void calculateAndReportScoreSucceeds() throws Exception {
169        int aggressiveHandover = 0;
170        mWifiInfo.setRssi(-77);
171        mWifiScoreReport.calculateAndReportScore(mWifiInfo,
172                mNetworkAgent, aggressiveHandover, mWifiMetrics);
173        verify(mNetworkAgent).sendNetworkScore(anyInt());
174        verify(mWifiMetrics).incrementWifiScoreCount(anyInt());
175    }
176
177    /**
178     * Test for operation with null NetworkAgent
179     *
180     * Expect to not die, and to calculate the score and report to metrics.
181     */
182    @Test
183    public void networkAgentMayBeNull() throws Exception {
184        mWifiInfo.setRssi(-33);
185        mWifiScoreReport.enableVerboseLogging(true);
186        mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
187        verify(mWifiMetrics).incrementWifiScoreCount(anyInt());
188    }
189
190    /**
191     * Test operation of saved last report
192     *
193     * One score is calculated
194     * Expect: last report is not valid before any score is calculated
195     * Expect: last report is valid after a score is calculated
196     * Expect: the score in the last report string matches the reported score
197     * Expect: reset makes the last report invalid again
198     */
199    @Test
200    public void makeSureLastReportWorks() throws Exception {
201        mWifiInfo.setRssi(-33);
202        assertFalse(mWifiScoreReport.isLastReportValid());
203        mWifiScoreReport.enableVerboseLogging(true);
204        mWifiScoreReport.calculateAndReportScore(mWifiInfo, mNetworkAgent, 0, mWifiMetrics);
205        assertTrue(mWifiScoreReport.isLastReportValid());
206        String report = mWifiScoreReport.getLastReport();
207        int score = fishScoreFromReportString(report);
208        verify(mWifiMetrics).incrementWifiScoreCount(score);
209        verify(mNetworkAgent).sendNetworkScore(score);
210        mWifiScoreReport.reset();
211        assertFalse(mWifiScoreReport.isLastReportValid());
212        assertTrue(mWifiScoreReport.getLastReport().equals(""));
213    }
214
215    /**
216     * Test bad linkspeed counter
217     *
218     * Expect badLinkspeed count to be incemented based on bad link speed.
219     * Expect counter to be pinned at a maximum value.
220     * Expect counter to be cleared by reset.
221     */
222    @Test
223    public void badLinkspeedCounter() throws Exception {
224        mWifiInfo.setRssi(-123);
225        mWifiInfo.setLinkSpeed(1);
226        mWifiInfo.setFrequency(2410);
227        assertFalse(mWifiScoreReport.isLastReportValid());
228        mWifiScoreReport.enableVerboseLogging(true);
229        assertEquals(0, mWifiScoreReport.getLastBadLinkspeedcount());
230        mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
231        assertEquals(1, mWifiScoreReport.getLastBadLinkspeedcount());
232        mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
233        assertEquals(2, mWifiScoreReport.getLastBadLinkspeedcount());
234        mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
235        assertEquals(3, mWifiScoreReport.getLastBadLinkspeedcount());
236        mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 1, mWifiMetrics);
237        mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
238        mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 1, mWifiMetrics);
239        mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
240        mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
241        mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
242        assertEquals(6, mWifiScoreReport.getLastBadLinkspeedcount()); // pinned at limit
243        verify(mWifiMetrics, times(9)).incrementWifiScoreCount(anyInt());
244        assertTrue(mWifiScoreReport.isLastReportValid());
245        mWifiScoreReport.reset();
246        assertEquals(0, mWifiScoreReport.getLastBadLinkspeedcount());
247    }
248
249    /**
250     * Exercise the rates with low RSSI
251     *
252     * The setup has a low (not bad) RSSI, and data movement (txSuccessRate) above
253     * the threshold.
254     *
255     * Expect a score above threshold.
256     */
257    @Test
258    public void allowLowRssiIfDataIsMoving() throws Exception {
259        mWifiInfo.setRssi(-80);
260        mWifiInfo.setLinkSpeed(6); // Mbps
261        mWifiInfo.txSuccessRate = 5.1; // proportional to pps
262        mWifiInfo.rxSuccessRate = 5.1;
263        for (int i = 0; i < 10; i++) {
264            mWifiScoreReport.calculateAndReportScore(mWifiInfo, mNetworkAgent, 0, mWifiMetrics);
265        }
266        assertTrue(mWifiScoreReport.isLastReportValid());
267        int score = fishScoreFromReportString(mWifiScoreReport.getLastReport());
268        assertTrue(score > CELLULAR_THRESHOLD_SCORE);
269    }
270
271    /**
272     * Bad RSSI without data moving should allow handoff
273     *
274     * The setup has a bad RSSI, and the txSuccessRate is below threshold; several
275     * scoring iterations are performed.
276     *
277     * Expect the score to drop below the handoff threshold.
278     */
279    @Test
280    public void giveUpOnBadRssiWhenDataIsNotMoving() throws Exception {
281        mWifiInfo.setRssi(-100);
282        mWifiInfo.setLinkSpeed(6); // Mbps
283        mWifiInfo.setFrequency(5010);
284        mWifiScoreReport.enableVerboseLogging(true);
285        mWifiInfo.txSuccessRate = 0.1;
286        mWifiInfo.rxSuccessRate = 0.1;
287        for (int i = 0; i < 10; i++) {
288            mWifiScoreReport.calculateAndReportScore(mWifiInfo, mNetworkAgent, 0, mWifiMetrics);
289            String report = mWifiScoreReport.getLastReport();
290            assertTrue(report.contains(" br "));
291        }
292        assertTrue(mWifiScoreReport.isLastReportValid());
293        int score = fishScoreFromReportString(mWifiScoreReport.getLastReport());
294        assertTrue(score < CELLULAR_THRESHOLD_SCORE);
295        verify(mNetworkAgent, atLeast(1)).sendNetworkScore(score);
296    }
297}
298