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.assertTrue;
20import static org.mockito.Mockito.anyInt;
21import static org.mockito.Mockito.atLeast;
22import static org.mockito.Mockito.verify;
23import static org.mockito.Mockito.when;
24
25import android.content.Context;
26import android.content.res.Resources;
27import android.net.NetworkAgent;
28import android.net.wifi.WifiConfiguration;
29import android.net.wifi.WifiInfo;
30
31import com.android.internal.R;
32
33import org.junit.After;
34import org.junit.Before;
35import org.junit.Test;
36import org.mockito.Mock;
37import org.mockito.MockitoAnnotations;
38
39import java.util.Arrays;
40
41/**
42 * Unit tests for {@link com.android.server.wifi.WifiScoreReport}.
43 */
44public class WifiScoreReportTest {
45
46    private static final int CELLULAR_THRESHOLD_SCORE = 50;
47
48    WifiConfiguration mWifiConfiguration;
49    WifiScoreReport mWifiScoreReport;
50    ScanDetailCache mScanDetailCache;
51    WifiInfo mWifiInfo;
52    @Mock Context mContext;
53    @Mock NetworkAgent mNetworkAgent;
54    @Mock Resources mResources;
55    @Mock WifiConfigManager mWifiConfigManager;
56    @Mock WifiMetrics mWifiMetrics;
57
58    /**
59     * Sets up resource values for testing
60     *
61     * See frameworks/base/core/res/res/values/config.xml
62     */
63    private void setUpResources(Resources resources) {
64        when(resources.getInteger(
65                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz))
66            .thenReturn(-82);
67        when(resources.getInteger(
68                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz))
69            .thenReturn(-70);
70        when(resources.getInteger(
71                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz))
72            .thenReturn(-57);
73        when(resources.getInteger(
74                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz))
75            .thenReturn(-85);
76        when(resources.getInteger(
77                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz))
78            .thenReturn(-73);
79        when(resources.getInteger(
80                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz))
81            .thenReturn(-60);
82        when(resources.getInteger(
83                R.integer.config_wifi_framework_wifi_score_bad_link_speed_24))
84            .thenReturn(6); // Mbps
85        when(resources.getInteger(
86                R.integer.config_wifi_framework_wifi_score_bad_link_speed_5))
87            .thenReturn(12);
88        when(resources.getInteger(
89                R.integer.config_wifi_framework_wifi_score_good_link_speed_24))
90            .thenReturn(24);
91        when(resources.getInteger(
92                R.integer.config_wifi_framework_wifi_score_good_link_speed_5))
93            .thenReturn(36);
94    }
95
96    /**
97     * Sets up for unit test
98     */
99    @Before
100    public void setUp() throws Exception {
101        MockitoAnnotations.initMocks(this);
102        setUpResources(mResources);
103        WifiConfiguration config = new WifiConfiguration();
104        config.SSID = "nooooooooooo";
105        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
106        config.hiddenSSID = false;
107        mWifiInfo = new WifiInfo();
108        mWifiInfo.setFrequency(2412);
109        when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(config));
110        when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);
111        mWifiConfiguration = config;
112        int maxSize = 10;
113        int trimSize = 5;
114        mScanDetailCache = new ScanDetailCache(config, maxSize, trimSize);
115        // TODO: populate the cache, but probably in the test cases, not here.
116        when(mWifiConfigManager.getScanDetailCacheForNetwork(anyInt()))
117                .thenReturn(mScanDetailCache);
118        when(mContext.getResources()).thenReturn(mResources);
119        mWifiScoreReport = new WifiScoreReport(mContext, mWifiConfigManager);
120    }
121
122    /**
123     * Cleans up after test
124     */
125    @After
126    public void tearDown() throws Exception {
127        mResources = null;
128        mWifiScoreReport = null;
129        mWifiConfigManager = null;
130        mWifiMetrics = null;
131    }
132
133    /**
134     * Test for score reporting
135     *
136     * The score should be sent to both the NetworkAgent and the
137     * WifiMetrics
138     */
139    @Test
140    public void calculateAndReportScoreSucceeds() throws Exception {
141        int aggressiveHandover = 0;
142        mWifiInfo.setRssi(-77);
143        mWifiScoreReport.calculateAndReportScore(mWifiInfo,
144                mNetworkAgent, aggressiveHandover, mWifiMetrics);
145        verify(mNetworkAgent).sendNetworkScore(anyInt());
146        verify(mWifiMetrics).incrementWifiScoreCount(anyInt());
147    }
148
149    /**
150     * Test for operation with null NetworkAgent
151     *
152     * Expect to not die, and to calculate the score and report to metrics.
153     */
154    @Test
155    public void networkAgentMayBeNull() throws Exception {
156        mWifiInfo.setRssi(-33);
157        mWifiScoreReport.enableVerboseLogging(true);
158        mWifiScoreReport.calculateAndReportScore(mWifiInfo, null, 0, mWifiMetrics);
159        verify(mWifiMetrics).incrementWifiScoreCount(anyInt());
160    }
161
162    /**
163     * Exercise the rates with low RSSI
164     *
165     * The setup has a low (not bad) RSSI, and data movement (txSuccessRate) above
166     * the threshold.
167     *
168     * Expect a score above threshold.
169     */
170    @Test
171    public void allowLowRssiIfDataIsMoving() throws Exception {
172        mWifiInfo.setRssi(-80);
173        mWifiInfo.setLinkSpeed(6); // Mbps
174        mWifiInfo.txSuccessRate = 5.1; // proportional to pps
175        mWifiInfo.rxSuccessRate = 5.1;
176        for (int i = 0; i < 10; i++) {
177            mWifiScoreReport.calculateAndReportScore(mWifiInfo, mNetworkAgent, 0, mWifiMetrics);
178        }
179        int score = mWifiInfo.score;
180        assertTrue(score > CELLULAR_THRESHOLD_SCORE);
181    }
182
183    /**
184     * Bad RSSI without data moving should allow handoff
185     *
186     * The setup has a bad RSSI, and the txSuccessRate is below threshold; several
187     * scoring iterations are performed.
188     *
189     * Expect the score to drop below the handoff threshold.
190     */
191    @Test
192    public void giveUpOnBadRssiWhenDataIsNotMoving() throws Exception {
193        mWifiInfo.setRssi(-100);
194        mWifiInfo.setLinkSpeed(6); // Mbps
195        mWifiInfo.setFrequency(5220);
196        mWifiScoreReport.enableVerboseLogging(true);
197        mWifiInfo.txSuccessRate = 0.1;
198        mWifiInfo.rxSuccessRate = 0.1;
199        for (int i = 0; i < 10; i++) {
200            mWifiScoreReport.calculateAndReportScore(mWifiInfo, mNetworkAgent, 0, mWifiMetrics);
201        }
202        int score = mWifiInfo.score;
203        assertTrue(score < CELLULAR_THRESHOLD_SCORE);
204        verify(mNetworkAgent, atLeast(1)).sendNetworkScore(score);
205    }
206}
207