SavedNetworkEvaluatorTest.java revision 13fb8e99c1a793c42e102e4f16f63de02f6eeed3
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 com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_NONE;
20import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_PSK;
21
22import static org.junit.Assert.*;
23import static org.mockito.Mockito.*;
24
25import android.content.ContentResolver;
26import android.content.Context;
27import android.content.res.Resources;
28import android.database.ContentObserver;
29import android.net.Uri;
30import android.net.wifi.ScanResult;
31import android.net.wifi.WifiConfiguration;
32import android.os.Looper;
33import android.os.SystemClock;
34import android.provider.Settings;
35import android.test.suitebuilder.annotation.SmallTest;
36import android.util.LocalLog;
37
38import com.android.internal.R;
39import com.android.server.wifi.WifiNetworkSelectorTestUtil.ScanDetailsAndWifiConfigs;
40
41import org.junit.After;
42import org.junit.Before;
43import org.junit.Test;
44import org.mockito.ArgumentCaptor;
45import org.mockito.Mock;
46import org.mockito.MockitoAnnotations;
47
48import java.util.List;
49
50/**
51 * Unit tests for {@link com.android.server.wifi.SavedNetworkEvaluator}.
52 */
53@SmallTest
54public class SavedNetworkEvaluatorTest {
55
56    /** Sets up test. */
57    @Before
58    public void setUp() throws Exception {
59        MockitoAnnotations.initMocks(this);
60        setupContext();
61        setupResource();
62        setupWifiConfigManager();
63        mLocalLog = new LocalLog(512);
64
65        when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(false);
66        when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime());
67        when(mFrameworkFacade.getIntegerSetting(mContext,
68                Settings.Global.CURATE_SAVED_OPEN_NETWORKS, 0)).thenReturn(0);
69        when(mFrameworkFacade.getIntegerSetting(mContext,
70                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0)).thenReturn(0);
71
72        mThresholdMinimumRssi2G = mResource.getInteger(
73                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz);
74        mThresholdMinimumRssi5G = mResource.getInteger(
75                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz);
76        mThresholdQualifiedRssi2G = mResource.getInteger(
77                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz);
78        mThresholdQualifiedRssi5G = mResource.getInteger(
79                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz);
80        mThresholdSaturatedRssi2G = mResource.getInteger(
81                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz);
82        mThresholdSaturatedRssi5G = mResource.getInteger(
83                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz);
84
85        ArgumentCaptor<ContentObserver> observerCaptor =
86                ArgumentCaptor.forClass(ContentObserver.class);
87
88        mSavedNetworkEvaluator = new SavedNetworkEvaluator(mContext, mWifiConfigManager,
89                mClock, mLocalLog, Looper.getMainLooper(), mFrameworkFacade,
90                mWifiConnectivityHelper);
91        verify(mFrameworkFacade, times(2)).registerContentObserver(eq(mContext), any(Uri.class),
92                eq(false), observerCaptor.capture());
93        // SavedNetworkEvaluator uses a single ContentObserver for two registrations, we only need
94        // to get this object once.
95        mContentObserver = observerCaptor.getValue();
96    }
97
98    /** Cleans up test. */
99    @After
100    public void cleanup() {
101        validateMockitoUsage();
102    }
103
104    private SavedNetworkEvaluator mSavedNetworkEvaluator;
105    @Mock private WifiConfigManager mWifiConfigManager;
106    @Mock private WifiConnectivityHelper mWifiConnectivityHelper;
107    @Mock private Context mContext;
108    @Mock private ContentResolver mContentResolver;
109    @Mock private FrameworkFacade mFrameworkFacade;
110    @Mock private Resources mResource;
111    @Mock private Clock mClock;
112    private LocalLog mLocalLog;
113    private int mThresholdMinimumRssi2G;
114    private int mThresholdMinimumRssi5G;
115    private int mThresholdQualifiedRssi2G;
116    private int mThresholdQualifiedRssi5G;
117    private int mThresholdSaturatedRssi2G;
118    private int mThresholdSaturatedRssi5G;
119    private ContentObserver mContentObserver;
120
121    private void setupContext() {
122        when(mContext.getResources()).thenReturn(mResource);
123        when(mContext.getContentResolver()).thenReturn(mContentResolver);
124    }
125
126    private void setupResource() {
127        when(mResource.getInteger(
128                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz))
129                .thenReturn(-57);
130        when(mResource.getInteger(
131                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz))
132                .thenReturn(-60);
133        when(mResource.getInteger(
134                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz))
135                .thenReturn(-70);
136        when(mResource.getInteger(
137                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz))
138                .thenReturn(-73);
139        when(mResource.getInteger(
140                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz))
141                .thenReturn(-82);
142        when(mResource.getInteger(
143                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz))
144                .thenReturn(-85);
145        when(mResource.getInteger(
146                R.integer.config_wifi_framework_RSSI_SCORE_SLOPE))
147                .thenReturn(4);
148        when(mResource.getInteger(
149                R.integer.config_wifi_framework_RSSI_SCORE_OFFSET))
150                .thenReturn(85);
151        when(mResource.getInteger(
152                R.integer.config_wifi_framework_SAME_BSSID_AWARD))
153                .thenReturn(24);
154        when(mResource.getInteger(
155                R.integer.config_wifi_framework_SECURITY_AWARD))
156                .thenReturn(80);
157        when(mResource.getInteger(
158                R.integer.config_wifi_framework_5GHz_preference_boost_factor))
159                .thenReturn(16);
160        when(mResource.getInteger(
161                R.integer.config_wifi_framework_current_network_boost))
162                .thenReturn(16);
163    }
164
165    private void setupWifiConfigManager() {
166        when(mWifiConfigManager.getLastSelectedNetwork())
167                .thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
168    }
169
170    /**
171     * Do not evaluate networks that {@link WifiConfiguration#useExternalScores}.
172     */
173    @Test
174    public void ignoreNetworksIfUseExternalScores() {
175        String[] ssids = {"\"test1\"", "\"test2\""};
176        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
177        int[] freqs = {2470, 2437};
178        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
179        int[] levels = {mThresholdQualifiedRssi2G + 8, mThresholdQualifiedRssi2G + 10};
180        int[] securities = {SECURITY_PSK, SECURITY_PSK};
181
182        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
183                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
184                        freqs, caps, levels, securities, mWifiConfigManager, mClock);
185        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
186        WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
187        for (WifiConfiguration wifiConfiguration : savedConfigs) {
188            wifiConfiguration.useExternalScores = true;
189        }
190
191        WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails,
192                null, null, true, false, null);
193
194        assertNull(candidate);
195    }
196
197    /**
198     * Do not evaluate open networks when {@link Settings.Global.CURATE_SAVED_OPEN_NETWORKS} and
199     * {@link Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED} are enabled.
200     */
201    @Test
202    public void ignoreOpensNetworksIfCurateSavedNetworksEnabled() {
203        String[] ssids = {"\"test1\"", "\"test2\""};
204        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
205        int[] freqs = {5200, 5240};
206        String[] caps = {"[ESS]", "[ESS]"};
207        int[] levels = {mThresholdQualifiedRssi5G, mThresholdQualifiedRssi5G};
208        int[] securities = {SECURITY_NONE, SECURITY_NONE};
209
210        when(mFrameworkFacade.getIntegerSetting(mContext,
211                Settings.Global.CURATE_SAVED_OPEN_NETWORKS, 0)).thenReturn(1);
212        when(mFrameworkFacade.getIntegerSetting(mContext,
213                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0)).thenReturn(1);
214        mContentObserver.onChange(false);
215
216        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
217                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
218                        freqs, caps, levels, securities, mWifiConfigManager, mClock);
219        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
220
221        WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails,
222                null, null, true, false, null);
223
224        assertNull(candidate);
225    }
226
227    /**
228     * Set the candidate {@link ScanResult} for all {@link WifiConfiguration}s even if they have
229     * useExternalScores set or are open networks with
230     * {@link Settings.Global.CURATE_SAVED_OPEN_NETWORKS} and
231     * {@link Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED} enabled.
232     */
233    @Test
234    public void setCandidateScanResultsForAllSavedNetworks() {
235        String[] ssids = {"\"test1\"", "\"test2\""};
236        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
237        int[] freqs = {5200, 5240};
238        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[ESS]"};
239        int[] levels = {mThresholdQualifiedRssi5G, mThresholdQualifiedRssi5G};
240        int[] securities = {SECURITY_PSK, SECURITY_NONE};
241
242        when(mFrameworkFacade.getIntegerSetting(mContext,
243                Settings.Global.CURATE_SAVED_OPEN_NETWORKS, 0)).thenReturn(1);
244        when(mFrameworkFacade.getIntegerSetting(mContext,
245                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0)).thenReturn(1);
246        mContentObserver.onChange(false);
247
248        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
249                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
250                        freqs, caps, levels, securities, mWifiConfigManager, mClock);
251        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
252        WifiConfiguration useExternalScoresConfig = scanDetailsAndConfigs.getWifiConfigs()[0];
253        useExternalScoresConfig.useExternalScores = true;
254        WifiConfiguration openNetworkConfig = scanDetailsAndConfigs.getWifiConfigs()[1];
255
256        WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails,
257                null, null, true, false, null);
258
259        assertNull(candidate);
260
261        verify(mWifiConfigManager).setNetworkCandidateScanResult(
262                eq(useExternalScoresConfig.networkId),
263                eq(scanDetails.get(0).getScanResult()),
264                anyInt());
265        verify(mWifiConfigManager).setNetworkCandidateScanResult(
266                eq(openNetworkConfig.networkId),
267                eq(scanDetails.get(1).getScanResult()),
268                anyInt());
269    }
270
271    /**
272     * Between two 2G networks, choose the one with stronger RSSI value if other conditions
273     * are the same and the RSSI values are not satuarted.
274     */
275    @Test
276    public void chooseStrongerRssi2GNetwork() {
277        String[] ssids = {"\"test1\"", "\"test2\""};
278        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
279        int[] freqs = {2470, 2437};
280        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
281        int[] levels = {mThresholdQualifiedRssi2G + 8, mThresholdQualifiedRssi2G + 10};
282        int[] securities = {SECURITY_PSK, SECURITY_PSK};
283
284        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
285                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
286                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
287        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
288        WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
289
290        WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails,
291                null, null, true, false, null);
292
293        ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
294        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[1], candidate);
295        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
296                chosenScanResult, candidate);
297    }
298
299    /**
300     * Between two 5G networks, choose the one with stronger RSSI value if other conditions
301     * are the same and the RSSI values are not saturated.
302     * {@link Settings.Global.CURATE_SAVED_OPEN_NETWORKS} and
303     * {@link Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED} will no affect on the outcome
304     * because both networks are secure.
305     */
306    @Test
307    public void chooseStrongerRssi5GNetwork() {
308        String[] ssids = {"\"test1\"", "\"test2\""};
309        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
310        int[] freqs = {5200, 5240};
311        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
312        int[] levels = {mThresholdQualifiedRssi5G + 8, mThresholdQualifiedRssi5G + 10};
313        int[] securities = {SECURITY_PSK, SECURITY_PSK};
314
315        when(mFrameworkFacade.getIntegerSetting(mContext,
316                Settings.Global.CURATE_SAVED_OPEN_NETWORKS, 0)).thenReturn(1);
317        when(mFrameworkFacade.getIntegerSetting(mContext,
318                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0)).thenReturn(1);
319        mContentObserver.onChange(false);
320
321        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
322                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
323                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
324        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
325        WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
326
327        WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails,
328                null, null, true, false, null);
329
330        ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
331        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[1], candidate);
332        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
333                chosenScanResult, candidate);
334    }
335
336    /**
337     * Choose secure network over open network if other conditions are the same.
338     */
339    @Test
340    public void chooseSecureNetworkOverOpenNetwork() {
341        String[] ssids = {"\"test1\"", "\"test2\""};
342        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
343        int[] freqs = {5200, 5240};
344        String[] caps = {"[ESS]", "[WPA2-EAP-CCMP][ESS]"};
345        int[] levels = {mThresholdQualifiedRssi5G, mThresholdQualifiedRssi5G};
346        int[] securities = {SECURITY_NONE, SECURITY_PSK};
347
348        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
349                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
350                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
351        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
352        WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
353
354        WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails,
355                null, null, true, false, null);
356
357        ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
358        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[1], candidate);
359        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
360                chosenScanResult, candidate);
361    }
362
363    /**
364     * Choose 5G network over 2G network if other conditions are the same.
365     */
366    @Test
367    public void choose5GNetworkOver2GNetwork() {
368        String[] ssids = {"\"test1\"", "\"test2\""};
369        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
370        int[] freqs = {2437, 5240};
371        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
372        int[] levels = {mThresholdQualifiedRssi2G, mThresholdQualifiedRssi5G};
373        int[] securities = {SECURITY_PSK, SECURITY_PSK};
374
375        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
376                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
377                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
378        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
379        WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
380
381        WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails,
382                null, null, true, false, null);
383
384        ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
385        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[1], candidate);
386        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
387                chosenScanResult, candidate);
388    }
389
390    /**
391     * Verify that we stick to the currently connected network if the other one is
392     * just slightly better scored.
393     */
394    @Test
395    public void stickToCurrentNetwork() {
396        String[] ssids = {"\"test1\"", "\"test2\""};
397        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
398        int[] freqs = {5200, 5240};
399        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
400        // test2 has slightly stronger RSSI value than test1
401        int[] levels = {mThresholdMinimumRssi5G + 2, mThresholdMinimumRssi5G + 4};
402        int[] securities = {SECURITY_PSK, SECURITY_PSK};
403
404        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
405                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
406                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
407        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
408        WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
409
410        // Simuluate we are connected to SSID test1 already.
411        WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails,
412                savedConfigs[0], null, true, false, null);
413
414        // Even though test2 has higher RSSI value, test1 is chosen because of the
415        // currently connected network bonus.
416        ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
417        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate);
418        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
419                chosenScanResult, candidate);
420    }
421
422    /**
423     * Verify that we stick to the currently connected BSSID if the other one is
424     * just slightly better scored.
425     */
426    @Test
427    public void stickToCurrentBSSID() {
428        // Same SSID
429        String[] ssids = {"\"test1\"", "\"test1\""};
430        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
431        int[] freqs = {5200, 5240};
432        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
433        // test2 has slightly stronger RSSI value than test1
434        int[] levels = {mThresholdMinimumRssi5G + 2, mThresholdMinimumRssi5G + 6};
435        int[] securities = {SECURITY_PSK, SECURITY_PSK};
436
437        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
438                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
439                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
440        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
441        WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
442
443        // Simuluate we are connected to BSSID "6c:f3:7f:ae:8c:f3" already
444        WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails,
445                null, bssids[0], true, false, null);
446
447        // Even though test2 has higher RSSI value, test1 is chosen because of the
448        // currently connected BSSID bonus.
449        ScanResult chosenScanResult = scanDetails.get(0).getScanResult();
450        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate);
451    }
452
453    /**
454     * Verify that the same BSSID award is applied to all the BSSIDs which are under the same
455     * network as the currently connected BSSID.
456     */
457    @Test
458    public void currentBssidAwardForAllBssidsWithinTheSameNetworkWhenFirmwareRoamingSupported() {
459        // Three BSSIDs are carefully setup there:
460        // BSSID_0 and BSSID_1 have the same SSID and security type, so they are considered under
461        // the same 2.4 GHz network. BSSID_1 RSSI is stronger than BSSID_0.
462        // BSSID_2 is under a 5GHz network different from BSSID_0 and BSSID_1. Its RSSI is
463        // slightly stronger than BSSID_1.
464        //
465        // When firmware roaming is not supported, BSSID_2 has higher score than BSSID_0 and
466        // BSSID_1.
467        // When firmware roaming is suported, BSSID_1 has higher score than BSSID_2 because the
468        // same BSSID award is now applied to both BSSID_0 and BSSID_1.
469        String[] ssids = {"\"test1\"", "\"test1\"", "\"test2\""};
470        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4", "6c:f3:7f:ae:8c:f5"};
471        int[] freqs = {2470, 2437, 5200};
472        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
473        int[] levels = {mThresholdMinimumRssi2G + 2, mThresholdMinimumRssi2G + 5,
474                mThresholdMinimumRssi5G + 7};
475        int[] securities = {SECURITY_PSK, SECURITY_PSK, SECURITY_PSK};
476
477        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
478                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
479                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
480        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
481        WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
482
483        // Firmware roaming is not supported.
484        when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(false);
485        // Simuluate we are connected to BSSID_0 already.
486        WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails,
487                savedConfigs[0], bssids[0], true, false, null);
488        // Verify that BSSID_2 is chosen.
489        ScanResult chosenScanResult = scanDetails.get(2).getScanResult();
490        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[2], candidate);
491        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
492                chosenScanResult, candidate);
493
494        // Firmware roaming is supported.
495        when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
496        // Simuluate we are connected to BSSID_0 already.
497        candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails,
498                savedConfigs[0], bssids[0], true, false, null);
499        // Verify that BSSID_1 is chosen.
500        chosenScanResult = scanDetails.get(1).getScanResult();
501        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[1], candidate);
502        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
503                chosenScanResult, candidate);
504    }
505
506    /**
507     * One 2.4GHz network and one 5GHz network have the same security type. Perform
508     * the following tests to verify that once across the RSSI saturation threshold
509     * stronger RSSI value doesn't increase network score.
510     *
511     * 1) Both 2.4GHz network and 5GHz network have the same RSSI value,
512     *    mThresholdQualifiedRssi2G, which is below the saturation threshold. 5GHz
513     *    network is chosen because of the 5G band award.
514     * 2) Bump up 2.4GHz network RSSI 20dBm higher. Verify that it helps the 2.4GHz network
515     *    score and it gets chosen over the 5GHz network.
516     * 3) Bring both 2.4GHz network and 5GHz network RSSI value to mThresholdSaturatedRssi2G.
517     *    Verify that 5GHz network is chosen because of the 5G band award.
518     * 4) Bump up 2.4GHz network RSSI to be 20dBm higher than mThresholdSaturatedRssi2G.
519     *    Verify that the incresed RSSI doesn't help 2.4GHz network score and 5GHz network
520     *    is still chosen.
521     */
522    @Test
523    public void saturatedRssiAddsNoWeightToNetwork() {
524        String[] ssids = {"\"test1\"", "\"test2\""};
525        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
526        int[] freqs = {2437, 5400};
527        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-EAP-CCMP][ESS]"};
528        int[] securities = {SECURITY_PSK, SECURITY_PSK};
529
530        // 1) The RSSI of both networks is mThresholdQualifiedRssi2G
531        int[] levels = {mThresholdQualifiedRssi2G, mThresholdQualifiedRssi2G};
532        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
533                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
534                    freqs, caps, levels, securities, mWifiConfigManager, mClock);
535        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
536        WifiConfiguration[] savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
537        WifiConfiguration candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails,
538                null, null, false, false, null);
539        // Verify that 5GHz network is chosen because of 5G band award
540        ScanResult chosenScanResult = scanDetails.get(1).getScanResult();
541        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[1], candidate);
542        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
543                chosenScanResult, candidate);
544
545        // 2) Bump up 2.4GHz network RSSI by 20dBm.
546        levels[0] = mThresholdQualifiedRssi2G + 20;
547        scanDetailsAndConfigs = WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids,
548                bssids, freqs, caps, levels, securities, mWifiConfigManager, mClock);
549        scanDetails = scanDetailsAndConfigs.getScanDetails();
550        savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
551        candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails, null, null, false,
552                false, null);
553        // Verify that 2.4GHz network is chosen because of much higher RSSI value
554        chosenScanResult = scanDetails.get(0).getScanResult();
555        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[0], candidate);
556        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
557                chosenScanResult, candidate);
558
559        // 3) Bring both 2.4GHz network and 5GHz network RSSI to mThresholdSaturatedRssi2G
560        levels[0] = levels[1] = mThresholdSaturatedRssi2G;
561        scanDetailsAndConfigs = WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids,
562                bssids, freqs, caps, levels, securities, mWifiConfigManager, mClock);
563        scanDetails = scanDetailsAndConfigs.getScanDetails();
564        savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
565        candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails, null, null, false,
566                false, null);
567        // Verify that 5GHz network is chosen because of 5G band award
568        chosenScanResult = scanDetails.get(1).getScanResult();
569        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[1], candidate);
570        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
571                chosenScanResult, candidate);
572
573        // 4) Bump 2.4GHz network RSSI to be 20dBm higher than mThresholdSaturatedRssi2G
574        levels[0] = mThresholdSaturatedRssi2G + 20;
575        scanDetailsAndConfigs = WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids,
576                bssids, freqs, caps, levels, securities, mWifiConfigManager, mClock);
577        scanDetails = scanDetailsAndConfigs.getScanDetails();
578        savedConfigs = scanDetailsAndConfigs.getWifiConfigs();
579        candidate = mSavedNetworkEvaluator.evaluateNetworks(scanDetails, null, null, false,
580                false, null);
581        // Verify that the increased RSSI doesn't help 2.4GHz network and 5GHz network
582        // is still chosen
583        chosenScanResult = scanDetails.get(1).getScanResult();
584        WifiConfigurationTestUtil.assertConfigurationEqual(savedConfigs[1], candidate);
585        WifiNetworkSelectorTestUtil.verifySelectedScanResult(mWifiConfigManager,
586                chosenScanResult, candidate);
587    }
588}
589