184d962ec8f487f824214744498bba505a6db0c59Randy Pan/*
284d962ec8f487f824214744498bba505a6db0c59Randy Pan * Copyright (C) 2016 The Android Open Source Project
384d962ec8f487f824214744498bba505a6db0c59Randy Pan *
484d962ec8f487f824214744498bba505a6db0c59Randy Pan * Licensed under the Apache License, Version 2.0 (the "License");
584d962ec8f487f824214744498bba505a6db0c59Randy Pan * you may not use this file except in compliance with the License.
684d962ec8f487f824214744498bba505a6db0c59Randy Pan * You may obtain a copy of the License at
784d962ec8f487f824214744498bba505a6db0c59Randy Pan *
884d962ec8f487f824214744498bba505a6db0c59Randy Pan *      http://www.apache.org/licenses/LICENSE-2.0
984d962ec8f487f824214744498bba505a6db0c59Randy Pan *
1084d962ec8f487f824214744498bba505a6db0c59Randy Pan * Unless required by applicable law or agreed to in writing, software
1184d962ec8f487f824214744498bba505a6db0c59Randy Pan * distributed under the License is distributed on an "AS IS" BASIS,
1284d962ec8f487f824214744498bba505a6db0c59Randy Pan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1384d962ec8f487f824214744498bba505a6db0c59Randy Pan * See the License for the specific language governing permissions and
1484d962ec8f487f824214744498bba505a6db0c59Randy Pan * limitations under the License.
1584d962ec8f487f824214744498bba505a6db0c59Randy Pan */
1684d962ec8f487f824214744498bba505a6db0c59Randy Pan
1784d962ec8f487f824214744498bba505a6db0c59Randy Panpackage com.android.server.wifi;
1884d962ec8f487f824214744498bba505a6db0c59Randy Pan
19095121ada1c9ea6034e86606395de20cddcad9baRoshan Piusimport static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE;
20095121ada1c9ea6034e86606395de20cddcad9baRoshan Piusimport static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY;
21095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius
2284d962ec8f487f824214744498bba505a6db0c59Randy Panimport static com.android.server.wifi.WifiConfigurationTestUtil.generateWifiConfig;
23cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Panimport static com.android.server.wifi.WifiStateMachine.WIFI_WORK_SOURCE;
2484d962ec8f487f824214744498bba505a6db0c59Randy Pan
25fb196453c07daad5e525520cecad84cec5d89fb7Roshan Piusimport static org.junit.Assert.*;
2684d962ec8f487f824214744498bba505a6db0c59Randy Panimport static org.mockito.Mockito.*;
2784d962ec8f487f824214744498bba505a6db0c59Randy Pan
28f4267b6840dbc7f430638c35c5448187b6e83846Christopher Wileyimport android.app.test.MockAnswerUtil.AnswerWithArguments;
29026cb51837e4cf3aea30b903320b992a3f5d0d7bChristopher Wileyimport android.app.test.TestAlarmManager;
3084d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.content.Context;
31adf5ee14bfcdef705684b1c4f12d80fae8433170Peter Qiuimport android.content.pm.PackageManager;
3284d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.content.res.Resources;
33d0258ee4816148ff4ab9ac6b854fc5c51ea53be3Amin Shaikhimport android.net.NetworkScoreManager;
3484d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.ScanResult;
35fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Piusimport android.net.wifi.ScanResult.InformationElement;
3650abba06efa7834b5309df561375e4a2e2df630dRandy Panimport android.net.wifi.SupplicantState;
3784d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiConfiguration;
3884d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiInfo;
39c8701c8ad058ec7fa69a2e3c60495f27708bced5Sundeep Ghumanimport android.net.wifi.WifiNetworkScoreCache;
4084d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiScanner;
41fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Piusimport android.net.wifi.WifiScanner.PnoScanListener;
42fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Piusimport android.net.wifi.WifiScanner.PnoSettings;
43cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Panimport android.net.wifi.WifiScanner.ScanData;
4484d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiScanner.ScanListener;
4584d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiScanner.ScanSettings;
461d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Piusimport android.net.wifi.WifiSsid;
479686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colittiimport android.os.Process;
48ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Piusimport android.os.SystemClock;
49e78a18cf874b4d9bb5db2ef7804b8ac576e56489Mitchell Willsimport android.os.WorkSource;
50f4267b6840dbc7f430638c35c5448187b6e83846Christopher Wileyimport android.os.test.TestLooper;
517f2a1e30dd5d14320ffc7b185ac25fdb79fe52b0Etan Cohenimport android.support.test.filters.SmallTest;
5217c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Panimport android.util.LocalLog;
5384d962ec8f487f824214744498bba505a6db0c59Randy Pan
5484d962ec8f487f824214744498bba505a6db0c59Randy Panimport com.android.internal.R;
5584d962ec8f487f824214744498bba505a6db0c59Randy Pan
5684d962ec8f487f824214744498bba505a6db0c59Randy Panimport org.junit.After;
5784d962ec8f487f824214744498bba505a6db0c59Randy Panimport org.junit.Before;
5884d962ec8f487f824214744498bba505a6db0c59Randy Panimport org.junit.Test;
59cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Panimport org.mockito.ArgumentCaptor;
60a54399f6da655dfbe440333ca3682b9199060a27Randy Panimport org.mockito.Captor;
61b4de842310ca698d59ed5b9117d38362e2945947Rebecca Silbersteinimport org.mockito.Mock;
62b4de842310ca698d59ed5b9117d38362e2945947Rebecca Silbersteinimport org.mockito.MockitoAnnotations;
6384d962ec8f487f824214744498bba505a6db0c59Randy Pan
6417c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Panimport java.io.FileDescriptor;
6517c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Panimport java.io.PrintWriter;
6617c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Panimport java.io.StringWriter;
67fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Piusimport java.nio.charset.StandardCharsets;
68fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Piusimport java.util.ArrayList;
69fb196453c07daad5e525520cecad84cec5d89fb7Roshan Piusimport java.util.HashSet;
703f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chenimport java.util.List;
71652381b37461a4aa793327365e144bb4335cbd27Roshan Piusimport java.util.stream.Collectors;
7284d962ec8f487f824214744498bba505a6db0c59Randy Pan
7384d962ec8f487f824214744498bba505a6db0c59Randy Pan/**
7484d962ec8f487f824214744498bba505a6db0c59Randy Pan * Unit tests for {@link com.android.server.wifi.WifiConnectivityManager}.
7584d962ec8f487f824214744498bba505a6db0c59Randy Pan */
7684d962ec8f487f824214744498bba505a6db0c59Randy Pan@SmallTest
7784d962ec8f487f824214744498bba505a6db0c59Randy Panpublic class WifiConnectivityManagerTest {
7884d962ec8f487f824214744498bba505a6db0c59Randy Pan    /**
7984d962ec8f487f824214744498bba505a6db0c59Randy Pan     * Called before each test
8084d962ec8f487f824214744498bba505a6db0c59Randy Pan     */
8184d962ec8f487f824214744498bba505a6db0c59Randy Pan    @Before
8284d962ec8f487f824214744498bba505a6db0c59Randy Pan    public void setUp() throws Exception {
83b4de842310ca698d59ed5b9117d38362e2945947Rebecca Silberstein        MockitoAnnotations.initMocks(this);
8409abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne        mResource = mockResource();
85f4267b6840dbc7f430638c35c5448187b6e83846Christopher Wiley        mAlarmManager = new TestAlarmManager();
8609abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne        mContext = mockContext();
8717c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan        mLocalLog = new LocalLog(512);
8809abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne        mWifiStateMachine = mockWifiStateMachine();
8909abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne        mWifiConfigManager = mockWifiConfigManager();
90fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        mWifiInfo = getWifiInfo();
91cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        mScanData = mockScanData();
9209abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne        mWifiScanner = mockWifiScanner();
93a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityHelper = mockWifiConnectivityHelper();
94220d198691d07506137b6af0bae810ed47ac4ed6Randy Pan        mWifiNS = mockWifiNetworkSelector();
9594eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius        mWifiConnectivityManager = createConnectivityManager();
965d0addadb370bcbb8900414fb9597bd415e6fea0Randy Pan        verify(mWifiConfigManager).setOnSavedNetworkUpdateListener(anyObject());
9784d962ec8f487f824214744498bba505a6db0c59Randy Pan        mWifiConnectivityManager.setWifiEnabled(true);
985de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime());
99e4606e0f9532d250a1e06e8aba5fb48556225773Randy Pan        mFullScanMaxTxPacketRate = mResource.getInteger(
100e4606e0f9532d250a1e06e8aba5fb48556225773Randy Pan                R.integer.config_wifi_framework_max_tx_rate_for_full_scan);
101e4606e0f9532d250a1e06e8aba5fb48556225773Randy Pan        mFullScanMaxRxPacketRate = mResource.getInteger(
102e4606e0f9532d250a1e06e8aba5fb48556225773Randy Pan                R.integer.config_wifi_framework_max_rx_rate_for_full_scan);
10384f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh        when(mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()).thenReturn(true);
10484d962ec8f487f824214744498bba505a6db0c59Randy Pan    }
10584d962ec8f487f824214744498bba505a6db0c59Randy Pan
10684d962ec8f487f824214744498bba505a6db0c59Randy Pan    /**
10784d962ec8f487f824214744498bba505a6db0c59Randy Pan     * Called after each test
10884d962ec8f487f824214744498bba505a6db0c59Randy Pan     */
10984d962ec8f487f824214744498bba505a6db0c59Randy Pan    @After
11084d962ec8f487f824214744498bba505a6db0c59Randy Pan    public void cleanup() {
11184d962ec8f487f824214744498bba505a6db0c59Randy Pan        validateMockitoUsage();
11284d962ec8f487f824214744498bba505a6db0c59Randy Pan    }
11384d962ec8f487f824214744498bba505a6db0c59Randy Pan
11484d962ec8f487f824214744498bba505a6db0c59Randy Pan    private Resources mResource;
115d0258ee4816148ff4ab9ac6b854fc5c51ea53be3Amin Shaikh
11684d962ec8f487f824214744498bba505a6db0c59Randy Pan    private Context mContext;
117f4267b6840dbc7f430638c35c5448187b6e83846Christopher Wiley    private TestAlarmManager mAlarmManager;
118f4267b6840dbc7f430638c35c5448187b6e83846Christopher Wiley    private TestLooper mLooper = new TestLooper();
11984d962ec8f487f824214744498bba505a6db0c59Randy Pan    private WifiConnectivityManager mWifiConnectivityManager;
120220d198691d07506137b6af0bae810ed47ac4ed6Randy Pan    private WifiNetworkSelector mWifiNS;
12184d962ec8f487f824214744498bba505a6db0c59Randy Pan    private WifiStateMachine mWifiStateMachine;
12284d962ec8f487f824214744498bba505a6db0c59Randy Pan    private WifiScanner mWifiScanner;
123a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    private WifiConnectivityHelper mWifiConnectivityHelper;
124cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan    private ScanData mScanData;
12584d962ec8f487f824214744498bba505a6db0c59Randy Pan    private WifiConfigManager mWifiConfigManager;
12684d962ec8f487f824214744498bba505a6db0c59Randy Pan    private WifiInfo mWifiInfo;
12717c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan    private LocalLog mLocalLog;
128d0258ee4816148ff4ab9ac6b854fc5c51ea53be3Amin Shaikh    @Mock private FrameworkFacade mFrameworkFacade;
129d0258ee4816148ff4ab9ac6b854fc5c51ea53be3Amin Shaikh    @Mock private NetworkScoreManager mNetworkScoreManager;
130b4de842310ca698d59ed5b9117d38362e2945947Rebecca Silberstein    @Mock private Clock mClock;
131b4de842310ca698d59ed5b9117d38362e2945947Rebecca Silberstein    @Mock private WifiLastResortWatchdog mWifiLastResortWatchdog;
132ce76a17ac5010e0b7ff5dcf6d8c9db8b48280f9cStephen Chen    @Mock private OpenNetworkNotifier mOpenNetworkNotifier;
133664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    @Mock private CarrierNetworkNotifier mCarrierNetworkNotifier;
134664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    @Mock private CarrierNetworkConfig mCarrierNetworkConfig;
135b4de842310ca698d59ed5b9117d38362e2945947Rebecca Silberstein    @Mock private WifiMetrics mWifiMetrics;
1360b9616e0e126221238edf5843a01b0cd3ec4daeeStephen Chen    @Mock private WifiNetworkScoreCache mScoreCache;
137a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    @Captor ArgumentCaptor<ScanResult> mCandidateScanResultCaptor;
138ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    @Captor ArgumentCaptor<ArrayList<String>> mBssidBlacklistCaptor;
139ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    @Captor ArgumentCaptor<ArrayList<String>> mSsidWhitelistCaptor;
140095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius    @Captor ArgumentCaptor<WifiConfigManager.OnSavedNetworkUpdateListener>
141095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius            mSavedNetworkUpdateListenerCaptor;
14294eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius    private MockResources mResources;
143e4606e0f9532d250a1e06e8aba5fb48556225773Randy Pan    private int mFullScanMaxTxPacketRate;
144e4606e0f9532d250a1e06e8aba5fb48556225773Randy Pan    private int mFullScanMaxRxPacketRate;
14584d962ec8f487f824214744498bba505a6db0c59Randy Pan
14684d962ec8f487f824214744498bba505a6db0c59Randy Pan    private static final int CANDIDATE_NETWORK_ID = 0;
14784d962ec8f487f824214744498bba505a6db0c59Randy Pan    private static final String CANDIDATE_SSID = "\"AnSsid\"";
14884d962ec8f487f824214744498bba505a6db0c59Randy Pan    private static final String CANDIDATE_BSSID = "6c:f3:7f:ae:8c:f3";
149b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan    private static final String INVALID_SCAN_RESULT_BSSID = "6c:f3:7f:ae:8c:f4";
150b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan    private static final long CURRENT_SYSTEM_TIME_MS = 1000;
151ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    private static final int MAX_BSSID_BLACKLIST_SIZE = 16;
152ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
15384d962ec8f487f824214744498bba505a6db0c59Randy Pan
15409abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne    Resources mockResource() {
15584d962ec8f487f824214744498bba505a6db0c59Randy Pan        Resources resource = mock(Resources.class);
15684d962ec8f487f824214744498bba505a6db0c59Randy Pan
15784d962ec8f487f824214744498bba505a6db0c59Randy Pan        when(resource.getInteger(R.integer.config_wifi_framework_SECURITY_AWARD)).thenReturn(80);
15884d962ec8f487f824214744498bba505a6db0c59Randy Pan        when(resource.getInteger(R.integer.config_wifi_framework_SAME_BSSID_AWARD)).thenReturn(24);
15994eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius        when(resource.getBoolean(
16094eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius                R.bool.config_wifi_framework_enable_associated_network_selection)).thenReturn(true);
16194eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius        when(resource.getInteger(
16294eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz))
163220d198691d07506137b6af0bae810ed47ac4ed6Randy Pan                .thenReturn(-60);
16494eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius        when(resource.getInteger(
165b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                R.integer.config_wifi_framework_current_network_boost)).thenReturn(16);
166e4606e0f9532d250a1e06e8aba5fb48556225773Randy Pan        when(resource.getInteger(
167e4606e0f9532d250a1e06e8aba5fb48556225773Randy Pan                R.integer.config_wifi_framework_max_tx_rate_for_full_scan)).thenReturn(8);
168e4606e0f9532d250a1e06e8aba5fb48556225773Randy Pan        when(resource.getInteger(
169e4606e0f9532d250a1e06e8aba5fb48556225773Randy Pan                R.integer.config_wifi_framework_max_rx_rate_for_full_scan)).thenReturn(16);
17084d962ec8f487f824214744498bba505a6db0c59Randy Pan        return resource;
17184d962ec8f487f824214744498bba505a6db0c59Randy Pan    }
17284d962ec8f487f824214744498bba505a6db0c59Randy Pan
17309abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne    Context mockContext() {
17484d962ec8f487f824214744498bba505a6db0c59Randy Pan        Context context = mock(Context.class);
17584d962ec8f487f824214744498bba505a6db0c59Randy Pan
17684d962ec8f487f824214744498bba505a6db0c59Randy Pan        when(context.getResources()).thenReturn(mResource);
17784d962ec8f487f824214744498bba505a6db0c59Randy Pan        when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn(
1781d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius                mAlarmManager.getAlarmManager());
179adf5ee14bfcdef705684b1c4f12d80fae8433170Peter Qiu        when(context.getPackageManager()).thenReturn(mock(PackageManager.class));
18084d962ec8f487f824214744498bba505a6db0c59Randy Pan
18184d962ec8f487f824214744498bba505a6db0c59Randy Pan        return context;
18284d962ec8f487f824214744498bba505a6db0c59Randy Pan    }
18384d962ec8f487f824214744498bba505a6db0c59Randy Pan
184cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan    ScanData mockScanData() {
185cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        ScanData scanData = mock(ScanData.class);
186cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan
187cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        when(scanData.isAllChannelsScanned()).thenReturn(true);
188cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan
189cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        return scanData;
190cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan    }
191cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan
19209abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne    WifiScanner mockWifiScanner() {
19384d962ec8f487f824214744498bba505a6db0c59Randy Pan        WifiScanner scanner = mock(WifiScanner.class);
194cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan        ArgumentCaptor<ScanListener> allSingleScanListenerCaptor =
195cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan                ArgumentCaptor.forClass(ScanListener.class);
196cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan
197cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan        doNothing().when(scanner).registerScanListener(allSingleScanListenerCaptor.capture());
19884d962ec8f487f824214744498bba505a6db0c59Randy Pan
199cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        ScanData[] scanDatas = new ScanData[1];
200cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        scanDatas[0] = mScanData;
20184d962ec8f487f824214744498bba505a6db0c59Randy Pan
20284d962ec8f487f824214744498bba505a6db0c59Randy Pan        // do a synchronous answer for the ScanListener callbacks
20384d962ec8f487f824214744498bba505a6db0c59Randy Pan        doAnswer(new AnswerWithArguments() {
204b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan            public void answer(ScanSettings settings, ScanListener listener,
205b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                    WorkSource workSource) throws Exception {
206b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                listener.onResults(scanDatas);
207b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan            }}).when(scanner).startBackgroundScan(anyObject(), anyObject(), anyObject());
20884d962ec8f487f824214744498bba505a6db0c59Randy Pan
20984d962ec8f487f824214744498bba505a6db0c59Randy Pan        doAnswer(new AnswerWithArguments() {
210b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan            public void answer(ScanSettings settings, ScanListener listener,
211b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                    WorkSource workSource) throws Exception {
212b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                listener.onResults(scanDatas);
213652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                // WCM processes scan results received via onFullResult (even though they're the
214652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                // same as onResult for single scans).
215652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                if (mScanData != null && mScanData.getResults() != null) {
216652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                    for (int i = 0; i < mScanData.getResults().length; i++) {
217652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                        allSingleScanListenerCaptor.getValue().onFullResult(
218652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                                mScanData.getResults()[i]);
219652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                    }
220652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                }
221b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                allSingleScanListenerCaptor.getValue().onResults(scanDatas);
222b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan            }}).when(scanner).startScan(anyObject(), anyObject(), anyObject());
22384d962ec8f487f824214744498bba505a6db0c59Randy Pan
224fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // This unfortunately needs to be a somewhat valid scan result, otherwise
225fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // |ScanDetailUtil.toScanDetail| raises exceptions.
226fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        final ScanResult[] scanResults = new ScanResult[1];
227fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        scanResults[0] = new ScanResult(WifiSsid.createFromAsciiEncoded(CANDIDATE_SSID),
228fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius                CANDIDATE_SSID, CANDIDATE_BSSID, 1245, 0, "some caps",
229fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius                -78, 2450, 1025, 22, 33, 20, 0, 0, true);
230fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        scanResults[0].informationElements = new InformationElement[1];
231fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        scanResults[0].informationElements[0] = new InformationElement();
232fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        scanResults[0].informationElements[0].id = InformationElement.EID_SSID;
233fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        scanResults[0].informationElements[0].bytes =
234b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan            CANDIDATE_SSID.getBytes(StandardCharsets.UTF_8);
235fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
236fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        doAnswer(new AnswerWithArguments() {
237fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            public void answer(ScanSettings settings, PnoSettings pnoSettings,
238fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius                    PnoScanListener listener) throws Exception {
239fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius                listener.onPnoNetworkFound(scanResults);
240fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            }}).when(scanner).startDisconnectedPnoScan(anyObject(), anyObject(), anyObject());
241fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
242fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        doAnswer(new AnswerWithArguments() {
243fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            public void answer(ScanSettings settings, PnoSettings pnoSettings,
244fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius                    PnoScanListener listener) throws Exception {
245fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius                listener.onPnoNetworkFound(scanResults);
246fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            }}).when(scanner).startConnectedPnoScan(anyObject(), anyObject(), anyObject());
247fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
24884d962ec8f487f824214744498bba505a6db0c59Randy Pan        return scanner;
24984d962ec8f487f824214744498bba505a6db0c59Randy Pan    }
25084d962ec8f487f824214744498bba505a6db0c59Randy Pan
251a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    WifiConnectivityHelper mockWifiConnectivityHelper() {
252a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        WifiConnectivityHelper connectivityHelper = mock(WifiConnectivityHelper.class);
253a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
254a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        when(connectivityHelper.isFirmwareRoamingSupported()).thenReturn(false);
255ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        when(connectivityHelper.getMaxNumBlacklistBssid()).thenReturn(MAX_BSSID_BLACKLIST_SIZE);
256a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
257a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        return connectivityHelper;
258a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    }
259a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
26009abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne    WifiStateMachine mockWifiStateMachine() {
26184d962ec8f487f824214744498bba505a6db0c59Randy Pan        WifiStateMachine stateMachine = mock(WifiStateMachine.class);
26284d962ec8f487f824214744498bba505a6db0c59Randy Pan
26384d962ec8f487f824214744498bba505a6db0c59Randy Pan        when(stateMachine.isConnected()).thenReturn(false);
26484d962ec8f487f824214744498bba505a6db0c59Randy Pan        when(stateMachine.isDisconnected()).thenReturn(true);
26584d962ec8f487f824214744498bba505a6db0c59Randy Pan        when(stateMachine.isSupplicantTransientState()).thenReturn(false);
26684d962ec8f487f824214744498bba505a6db0c59Randy Pan
26784d962ec8f487f824214744498bba505a6db0c59Randy Pan        return stateMachine;
26884d962ec8f487f824214744498bba505a6db0c59Randy Pan    }
26984d962ec8f487f824214744498bba505a6db0c59Randy Pan
270220d198691d07506137b6af0bae810ed47ac4ed6Randy Pan    WifiNetworkSelector mockWifiNetworkSelector() {
271220d198691d07506137b6af0bae810ed47ac4ed6Randy Pan        WifiNetworkSelector ns = mock(WifiNetworkSelector.class);
27284d962ec8f487f824214744498bba505a6db0c59Randy Pan
27384d962ec8f487f824214744498bba505a6db0c59Randy Pan        WifiConfiguration candidate = generateWifiConfig(
27484d962ec8f487f824214744498bba505a6db0c59Randy Pan                0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null);
275b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        candidate.BSSID = WifiStateMachine.SUPPLICANT_BSSID_ANY;
27684d962ec8f487f824214744498bba505a6db0c59Randy Pan        ScanResult candidateScanResult = new ScanResult();
27784d962ec8f487f824214744498bba505a6db0c59Randy Pan        candidateScanResult.SSID = CANDIDATE_SSID;
27884d962ec8f487f824214744498bba505a6db0c59Randy Pan        candidateScanResult.BSSID = CANDIDATE_BSSID;
27984d962ec8f487f824214744498bba505a6db0c59Randy Pan        candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult);
28084d962ec8f487f824214744498bba505a6db0c59Randy Pan
281167b90b5e002698378728a54a417a08c317d29dcRandy Pan        when(ns.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(),
282b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                anyBoolean(), anyBoolean())).thenReturn(candidate);
283220d198691d07506137b6af0bae810ed47ac4ed6Randy Pan        return ns;
28484d962ec8f487f824214744498bba505a6db0c59Randy Pan    }
28584d962ec8f487f824214744498bba505a6db0c59Randy Pan
286fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius    WifiInfo getWifiInfo() {
287fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        WifiInfo wifiInfo = new WifiInfo();
28884d962ec8f487f824214744498bba505a6db0c59Randy Pan
289fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        wifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
290fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        wifiInfo.setBSSID(null);
291fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        wifiInfo.setSupplicantState(SupplicantState.DISCONNECTED);
29284d962ec8f487f824214744498bba505a6db0c59Randy Pan
29384d962ec8f487f824214744498bba505a6db0c59Randy Pan        return wifiInfo;
29484d962ec8f487f824214744498bba505a6db0c59Randy Pan    }
29584d962ec8f487f824214744498bba505a6db0c59Randy Pan
29609abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne    WifiConfigManager mockWifiConfigManager() {
29784d962ec8f487f824214744498bba505a6db0c59Randy Pan        WifiConfigManager wifiConfigManager = mock(WifiConfigManager.class);
29884d962ec8f487f824214744498bba505a6db0c59Randy Pan
29994eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius        when(wifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(null);
30084d962ec8f487f824214744498bba505a6db0c59Randy Pan
301fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // Pass dummy pno network list, otherwise Pno scan requests will not be triggered.
302fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        PnoSettings.PnoNetwork pnoNetwork = new PnoSettings.PnoNetwork(CANDIDATE_SSID);
303fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        ArrayList<PnoSettings.PnoNetwork> pnoNetworkList = new ArrayList<>();
304fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        pnoNetworkList.add(pnoNetwork);
30594eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius        when(wifiConfigManager.retrievePnoNetworkList()).thenReturn(pnoNetworkList);
30694eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius        when(wifiConfigManager.retrievePnoNetworkList()).thenReturn(pnoNetworkList);
307095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius        doNothing().when(wifiConfigManager).setOnSavedNetworkUpdateListener(
308095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius                mSavedNetworkUpdateListenerCaptor.capture());
309fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
31084d962ec8f487f824214744498bba505a6db0c59Randy Pan        return wifiConfigManager;
31184d962ec8f487f824214744498bba505a6db0c59Randy Pan    }
31284d962ec8f487f824214744498bba505a6db0c59Randy Pan
31394eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius    WifiConnectivityManager createConnectivityManager() {
31479545bef4e8d6c1d891f7396665b5c457bc31617Michael Plass        return new WifiConnectivityManager(mContext,
31579545bef4e8d6c1d891f7396665b5c457bc31617Michael Plass                new ScoringParams(mContext),
31679545bef4e8d6c1d891f7396665b5c457bc31617Michael Plass                mWifiStateMachine, mWifiScanner,
317a54399f6da655dfbe440333ca3682b9199060a27Randy Pan                mWifiConfigManager, mWifiInfo, mWifiNS, mWifiConnectivityHelper,
318664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                mWifiLastResortWatchdog, mOpenNetworkNotifier, mCarrierNetworkNotifier,
319664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                mCarrierNetworkConfig, mWifiMetrics, mLooper.getLooper(), mClock, mLocalLog, true,
320664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                mFrameworkFacade, null, null, null);
32194eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius    }
32294eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius
32384d962ec8f487f824214744498bba505a6db0c59Randy Pan    /**
32484d962ec8f487f824214744498bba505a6db0c59Randy Pan     *  Wifi enters disconnected state while screen is on.
32584d962ec8f487f824214744498bba505a6db0c59Randy Pan     *
32684d962ec8f487f824214744498bba505a6db0c59Randy Pan     * Expected behavior: WifiConnectivityManager calls
327fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius     * WifiStateMachine.startConnectToNetwork() with the
32884d962ec8f487f824214744498bba505a6db0c59Randy Pan     * expected candidate network ID and BSSID.
32984d962ec8f487f824214744498bba505a6db0c59Randy Pan     */
33084d962ec8f487f824214744498bba505a6db0c59Randy Pan    @Test
33184d962ec8f487f824214744498bba505a6db0c59Randy Pan    public void enterWifiDisconnectedStateWhenScreenOn() {
33284d962ec8f487f824214744498bba505a6db0c59Randy Pan        // Set screen to on
33384d962ec8f487f824214744498bba505a6db0c59Randy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
33484d962ec8f487f824214744498bba505a6db0c59Randy Pan
33584d962ec8f487f824214744498bba505a6db0c59Randy Pan        // Set WiFi to disconnected state
33684d962ec8f487f824214744498bba505a6db0c59Randy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
33784d962ec8f487f824214744498bba505a6db0c59Randy Pan                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
33884d962ec8f487f824214744498bba505a6db0c59Randy Pan
3399686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti        verify(mWifiStateMachine).startConnectToNetwork(
3409686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
34184d962ec8f487f824214744498bba505a6db0c59Randy Pan    }
34284d962ec8f487f824214744498bba505a6db0c59Randy Pan
34384d962ec8f487f824214744498bba505a6db0c59Randy Pan    /**
34484d962ec8f487f824214744498bba505a6db0c59Randy Pan     *  Wifi enters connected state while screen is on.
34584d962ec8f487f824214744498bba505a6db0c59Randy Pan     *
34684d962ec8f487f824214744498bba505a6db0c59Randy Pan     * Expected behavior: WifiConnectivityManager calls
347fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius     * WifiStateMachine.startConnectToNetwork() with the
34884d962ec8f487f824214744498bba505a6db0c59Randy Pan     * expected candidate network ID and BSSID.
34984d962ec8f487f824214744498bba505a6db0c59Randy Pan     */
35084d962ec8f487f824214744498bba505a6db0c59Randy Pan    @Test
35184d962ec8f487f824214744498bba505a6db0c59Randy Pan    public void enterWifiConnectedStateWhenScreenOn() {
35284d962ec8f487f824214744498bba505a6db0c59Randy Pan        // Set screen to on
35384d962ec8f487f824214744498bba505a6db0c59Randy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
35484d962ec8f487f824214744498bba505a6db0c59Randy Pan
35584d962ec8f487f824214744498bba505a6db0c59Randy Pan        // Set WiFi to connected state
35684d962ec8f487f824214744498bba505a6db0c59Randy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
35784d962ec8f487f824214744498bba505a6db0c59Randy Pan                WifiConnectivityManager.WIFI_STATE_CONNECTED);
35884d962ec8f487f824214744498bba505a6db0c59Randy Pan
3599686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti        verify(mWifiStateMachine).startConnectToNetwork(
3609686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
36184d962ec8f487f824214744498bba505a6db0c59Randy Pan    }
36284d962ec8f487f824214744498bba505a6db0c59Randy Pan
36384d962ec8f487f824214744498bba505a6db0c59Randy Pan    /**
36484d962ec8f487f824214744498bba505a6db0c59Randy Pan     *  Screen turned on while WiFi in disconnected state.
36584d962ec8f487f824214744498bba505a6db0c59Randy Pan     *
36684d962ec8f487f824214744498bba505a6db0c59Randy Pan     * Expected behavior: WifiConnectivityManager calls
367fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius     * WifiStateMachine.startConnectToNetwork() with the
36884d962ec8f487f824214744498bba505a6db0c59Randy Pan     * expected candidate network ID and BSSID.
36984d962ec8f487f824214744498bba505a6db0c59Randy Pan     */
37084d962ec8f487f824214744498bba505a6db0c59Randy Pan    @Test
37184d962ec8f487f824214744498bba505a6db0c59Randy Pan    public void turnScreenOnWhenWifiInDisconnectedState() {
37284d962ec8f487f824214744498bba505a6db0c59Randy Pan        // Set WiFi to disconnected state
37384d962ec8f487f824214744498bba505a6db0c59Randy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
37484d962ec8f487f824214744498bba505a6db0c59Randy Pan                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
37584d962ec8f487f824214744498bba505a6db0c59Randy Pan
37684d962ec8f487f824214744498bba505a6db0c59Randy Pan        // Set screen to on
37784d962ec8f487f824214744498bba505a6db0c59Randy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
37884d962ec8f487f824214744498bba505a6db0c59Randy Pan
379fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius        verify(mWifiStateMachine, atLeastOnce()).startConnectToNetwork(
3809686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
38184d962ec8f487f824214744498bba505a6db0c59Randy Pan    }
38284d962ec8f487f824214744498bba505a6db0c59Randy Pan
38384d962ec8f487f824214744498bba505a6db0c59Randy Pan    /**
38484d962ec8f487f824214744498bba505a6db0c59Randy Pan     *  Screen turned on while WiFi in connected state.
38584d962ec8f487f824214744498bba505a6db0c59Randy Pan     *
38684d962ec8f487f824214744498bba505a6db0c59Randy Pan     * Expected behavior: WifiConnectivityManager calls
387fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius     * WifiStateMachine.startConnectToNetwork() with the
38884d962ec8f487f824214744498bba505a6db0c59Randy Pan     * expected candidate network ID and BSSID.
38984d962ec8f487f824214744498bba505a6db0c59Randy Pan     */
39084d962ec8f487f824214744498bba505a6db0c59Randy Pan    @Test
39184d962ec8f487f824214744498bba505a6db0c59Randy Pan    public void turnScreenOnWhenWifiInConnectedState() {
39284d962ec8f487f824214744498bba505a6db0c59Randy Pan        // Set WiFi to connected state
39384d962ec8f487f824214744498bba505a6db0c59Randy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
39484d962ec8f487f824214744498bba505a6db0c59Randy Pan                WifiConnectivityManager.WIFI_STATE_CONNECTED);
39584d962ec8f487f824214744498bba505a6db0c59Randy Pan
39684d962ec8f487f824214744498bba505a6db0c59Randy Pan        // Set screen to on
39784d962ec8f487f824214744498bba505a6db0c59Randy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
39884d962ec8f487f824214744498bba505a6db0c59Randy Pan
399fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius        verify(mWifiStateMachine, atLeastOnce()).startConnectToNetwork(
4009686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
401fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius    }
402fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
403fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius    /**
404a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan     *  Screen turned on while WiFi in connected state but
405a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan     *  auto roaming is disabled.
406a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan     *
407a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan     * Expected behavior: WifiConnectivityManager doesn't invoke
408fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius     * WifiStateMachine.startConnectToNetwork() because roaming
409a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan     * is turned off.
410a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan     */
411a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan    @Test
412a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan    public void turnScreenOnWhenWifiInConnectedStateRoamingDisabled() {
41394eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius        // Turn off auto roaming
41494eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius        when(mResource.getBoolean(
41594eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius                R.bool.config_wifi_framework_enable_associated_network_selection))
41694eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius                .thenReturn(false);
41794eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius        mWifiConnectivityManager = createConnectivityManager();
41894eec4ff65e7e4c1c06c3e817655842b46c02b0aRoshan Pius
419a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan        // Set WiFi to connected state
420a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
421a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan                WifiConnectivityManager.WIFI_STATE_CONNECTED);
422a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan
423a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan        // Set screen to on
424a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
425a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan
426fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius        verify(mWifiStateMachine, times(0)).startConnectToNetwork(
4279686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
428a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan    }
429a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan
430a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan    /**
431fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     * Multiple back to back connection attempts within the rate interval should be rate limited.
432fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     *
433fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius     * Expected behavior: WifiConnectivityManager calls WifiStateMachine.startConnectToNetwork()
434fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     * with the expected candidate network ID and BSSID for only the expected number of times within
435fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     * the given interval.
436fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     */
437fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius    @Test
438fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius    public void connectionAttemptRateLimitedWhenScreenOff() {
439fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        int maxAttemptRate = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_RATE;
440fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        int timeInterval = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS;
441fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        int numAttempts = 0;
442fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        int connectionAttemptIntervals = timeInterval / maxAttemptRate;
443fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
444fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        mWifiConnectivityManager.handleScreenStateChanged(false);
445fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
446fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // First attempt the max rate number of connections within the rate interval.
447fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        long currentTimeStamp = 0;
448fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        for (int attempt = 0; attempt < maxAttemptRate; attempt++) {
449fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            currentTimeStamp += connectionAttemptIntervals;
4505de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang            when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
451fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            // Set WiFi to disconnected state to trigger PNO scan
452fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            mWifiConnectivityManager.handleConnectionStateChanged(
453fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius                    WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
454fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            numAttempts++;
455fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        }
456fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // Now trigger another connection attempt before the rate interval, this should be
457fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // skipped because we've crossed rate limit.
4585de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
459fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // Set WiFi to disconnected state to trigger PNO scan
460fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        mWifiConnectivityManager.handleConnectionStateChanged(
461fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
462fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
463fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // Verify that we attempt to connect upto the rate.
464fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius        verify(mWifiStateMachine, times(numAttempts)).startConnectToNetwork(
4659686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
466fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius    }
467fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
468fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius    /**
469fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     * Multiple back to back connection attempts outside the rate interval should not be rate
470fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     * limited.
471fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     *
472fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius     * Expected behavior: WifiConnectivityManager calls WifiStateMachine.startConnectToNetwork()
473fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     * with the expected candidate network ID and BSSID for only the expected number of times within
474fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     * the given interval.
475fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     */
476fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius    @Test
477fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius    public void connectionAttemptNotRateLimitedWhenScreenOff() {
478fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        int maxAttemptRate = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_RATE;
479fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        int timeInterval = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS;
480fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        int numAttempts = 0;
481fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        int connectionAttemptIntervals = timeInterval / maxAttemptRate;
482fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
483fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        mWifiConnectivityManager.handleScreenStateChanged(false);
484fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
485fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // First attempt the max rate number of connections within the rate interval.
486fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        long currentTimeStamp = 0;
487fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        for (int attempt = 0; attempt < maxAttemptRate; attempt++) {
488fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            currentTimeStamp += connectionAttemptIntervals;
4895de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang            when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
490fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            // Set WiFi to disconnected state to trigger PNO scan
491fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            mWifiConnectivityManager.handleConnectionStateChanged(
492fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius                    WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
493fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            numAttempts++;
494fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        }
495fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // Now trigger another connection attempt after the rate interval, this should not be
496fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // skipped because we should've evicted the older attempt.
4975de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(
498fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius                currentTimeStamp + connectionAttemptIntervals * 2);
499fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // Set WiFi to disconnected state to trigger PNO scan
500fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        mWifiConnectivityManager.handleConnectionStateChanged(
501fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
502fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        numAttempts++;
503fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
504fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // Verify that all the connection attempts went through
505fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius        verify(mWifiStateMachine, times(numAttempts)).startConnectToNetwork(
5069686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
507fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius    }
508fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
509fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius    /**
510fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     * Multiple back to back connection attempts after a user selection should not be rate limited.
511fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     *
512fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius     * Expected behavior: WifiConnectivityManager calls WifiStateMachine.startConnectToNetwork()
513fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     * with the expected candidate network ID and BSSID for only the expected number of times within
514fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     * the given interval.
515fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius     */
516fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius    @Test
517fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius    public void connectionAttemptNotRateLimitedWhenScreenOffAfterUserSelection() {
518fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        int maxAttemptRate = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_RATE;
519fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        int timeInterval = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS;
520fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        int numAttempts = 0;
521fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        int connectionAttemptIntervals = timeInterval / maxAttemptRate;
522fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
523fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        mWifiConnectivityManager.handleScreenStateChanged(false);
524fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
525fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // First attempt the max rate number of connections within the rate interval.
526fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        long currentTimeStamp = 0;
527fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        for (int attempt = 0; attempt < maxAttemptRate; attempt++) {
528fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            currentTimeStamp += connectionAttemptIntervals;
5295de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang            when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
530fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            // Set WiFi to disconnected state to trigger PNO scan
531fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            mWifiConnectivityManager.handleConnectionStateChanged(
532fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius                    WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
533fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            numAttempts++;
534fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        }
535fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
536fa25be15a3dab0fda8d041798c4cac531d0d0866Roshan Pius        mWifiConnectivityManager.setUserConnectChoice(CANDIDATE_NETWORK_ID);
537ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        mWifiConnectivityManager.prepareForForcedConnection(CANDIDATE_NETWORK_ID);
538fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
539fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        for (int attempt = 0; attempt < maxAttemptRate; attempt++) {
540fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            currentTimeStamp += connectionAttemptIntervals;
5415de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang            when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
542fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            // Set WiFi to disconnected state to trigger PNO scan
543fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            mWifiConnectivityManager.handleConnectionStateChanged(
544fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius                    WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
545fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius            numAttempts++;
546fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        }
547fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius
548fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius        // Verify that all the connection attempts went through
549fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius        verify(mWifiStateMachine, times(numAttempts)).startConnectToNetwork(
5509686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
55184d962ec8f487f824214744498bba505a6db0c59Randy Pan    }
5523d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan
5533d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan    /**
5543d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan     *  PNO retry for low RSSI networks.
5553d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan     *
5563d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan     * Expected behavior: WifiConnectivityManager doubles the low RSSI
5573d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan     * network retry delay value after QNS skips the PNO scan results
5583d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan     * because of their low RSSI values.
5593d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan     */
5603d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan    @Test
561220d198691d07506137b6af0bae810ed47ac4ed6Randy Pan    public void pnoRetryForLowRssiNetwork() {
562167b90b5e002698378728a54a417a08c317d29dcRandy Pan        when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(),
563b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                anyBoolean(), anyBoolean())).thenReturn(null);
5643d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan
5653d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan        // Set screen to off
5663d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan        mWifiConnectivityManager.handleScreenStateChanged(false);
5673d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan
5683d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan        // Get the current retry delay value
5693d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan        int lowRssiNetworkRetryDelayStartValue = mWifiConnectivityManager
5703d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan                .getLowRssiNetworkRetryDelay();
5713d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan
5723d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan        // Set WiFi to disconnected state to trigger PNO scan
5733d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
5743d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
5753d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan
5763d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan        // Get the retry delay value after QNS didn't select a
5773d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan        // network candicate from the PNO scan results.
5783d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan        int lowRssiNetworkRetryDelayAfterPnoValue = mWifiConnectivityManager
5793d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan                .getLowRssiNetworkRetryDelay();
5803d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan
5813d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan        assertEquals(lowRssiNetworkRetryDelayStartValue * 2,
582220d198691d07506137b6af0bae810ed47ac4ed6Randy Pan                lowRssiNetworkRetryDelayAfterPnoValue);
5833d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan    }
5841d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius
5851d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius    /**
5861d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius     * Ensure that the watchdog bite increments the "Pno bad" metric.
5871d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius     *
5881d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius     * Expected behavior: WifiConnectivityManager detects that the PNO scan failed to find
5891d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius     * a candidate while watchdog single scan did.
5901d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius     */
5911d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius    @Test
5921d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius    public void watchdogBitePnoBadIncrementsMetrics() {
5931d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        // Set screen to off
5941d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        mWifiConnectivityManager.handleScreenStateChanged(false);
5951d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius
5961d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        // Set WiFi to disconnected state to trigger PNO scan
5971d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        mWifiConnectivityManager.handleConnectionStateChanged(
5981d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
5991d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius
6001d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        // Now fire the watchdog alarm and verify the metrics were incremented.
6011d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        mAlarmManager.dispatch(WifiConnectivityManager.WATCHDOG_TIMER_TAG);
6021d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        mLooper.dispatchAll();
6031d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius
6041d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        verify(mWifiMetrics).incrementNumConnectivityWatchdogPnoBad();
6051d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        verify(mWifiMetrics, never()).incrementNumConnectivityWatchdogPnoGood();
6061d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius    }
6071d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius
6081d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius    /**
6091d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius     * Ensure that the watchdog bite increments the "Pno good" metric.
6101d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius     *
6111d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius     * Expected behavior: WifiConnectivityManager detects that the PNO scan failed to find
6121d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius     * a candidate which was the same with watchdog single scan.
6131d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius     */
6141d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius    @Test
6151d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius    public void watchdogBitePnoGoodIncrementsMetrics() {
6161d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        // Qns returns no candidate after watchdog single scan.
617167b90b5e002698378728a54a417a08c317d29dcRandy Pan        when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(),
618b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                anyBoolean(), anyBoolean())).thenReturn(null);
6191d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius
6201d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        // Set screen to off
6211d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        mWifiConnectivityManager.handleScreenStateChanged(false);
6221d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius
6231d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        // Set WiFi to disconnected state to trigger PNO scan
6241d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        mWifiConnectivityManager.handleConnectionStateChanged(
6251d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
6261d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius
6271d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        // Now fire the watchdog alarm and verify the metrics were incremented.
6281d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        mAlarmManager.dispatch(WifiConnectivityManager.WATCHDOG_TIMER_TAG);
6291d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        mLooper.dispatchAll();
6301d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius
6311d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        verify(mWifiMetrics).incrementNumConnectivityWatchdogPnoGood();
6321d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius        verify(mWifiMetrics, never()).incrementNumConnectivityWatchdogPnoBad();
6331d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius    }
634b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
635b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan    /**
636ce76a17ac5010e0b7ff5dcf6d8c9db8b48280f9cStephen Chen     * {@link OpenNetworkNotifier} handles scan results on network selection.
6373f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     *
6383f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     * Expected behavior: ONA handles scan results
6393f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     */
6403f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    @Test
64108ffa580f6756129929667785408da377b363787Stephen Chen    public void wifiDisconnected_noConnectionCandidate_openNetworkNotifierScanResultsHandled() {
6423f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        // no connection candidate selected
6433f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(),
6443f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen                anyBoolean(), anyBoolean())).thenReturn(null);
6453f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen
6463f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        List<ScanDetail> expectedOpenNetworks = new ArrayList<>();
6473f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        expectedOpenNetworks.add(
6483f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen                new ScanDetail(
6493f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen                        new ScanResult(WifiSsid.createFromAsciiEncoded(CANDIDATE_SSID),
6503f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen                                CANDIDATE_SSID, CANDIDATE_BSSID, 1245, 0, "some caps", -78, 2450,
6513f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen                                1025, 22, 33, 20, 0, 0, true), null));
6523f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen
6533f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        when(mWifiNS.getFilteredScanDetailsForOpenUnsavedNetworks())
6543f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen                .thenReturn(expectedOpenNetworks);
6553f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen
6563f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        // Set WiFi to disconnected state to trigger PNO scan
6573f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        mWifiConnectivityManager.handleConnectionStateChanged(
6583f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
6593f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen
660ce76a17ac5010e0b7ff5dcf6d8c9db8b48280f9cStephen Chen        verify(mOpenNetworkNotifier).handleScanResults(expectedOpenNetworks);
6613f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    }
6623f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen
6633f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    /**
664b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen     * When wifi is connected, {@link OpenNetworkNotifier} handles the Wi-Fi connected behavior.
6653f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     *
666b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen     * Expected behavior: ONA handles connected behavior
6673f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     */
6683f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    @Test
669b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen    public void wifiConnected_openNetworkNotifierHandlesConnection() {
6703f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        // Set WiFi to connected state
6713f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        mWifiConnectivityManager.handleConnectionStateChanged(
6723f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen                WifiConnectivityManager.WIFI_STATE_CONNECTED);
6733f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen
674b6103294dc1e6785c8ba236582e53801e1f9f2cdStephen Chen        verify(mOpenNetworkNotifier).handleWifiConnected();
6753f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    }
6763f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen
6773f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    /**
678ce76a17ac5010e0b7ff5dcf6d8c9db8b48280f9cStephen Chen     * When wifi is connected, {@link OpenNetworkNotifier} handles connection state
6793f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     * change.
6803f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     *
6813f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     * Expected behavior: ONA does not clear pending notification.
6823f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     */
6833f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    @Test
68408ffa580f6756129929667785408da377b363787Stephen Chen    public void wifiDisconnected_openNetworkNotifierDoesNotClearPendingNotification() {
6853f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        // Set WiFi to disconnected state
6863f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        mWifiConnectivityManager.handleConnectionStateChanged(
6873f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
6883f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen
689ce76a17ac5010e0b7ff5dcf6d8c9db8b48280f9cStephen Chen        verify(mOpenNetworkNotifier, never()).clearPendingNotification(anyBoolean());
6903f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    }
6913f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen
6923f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    /**
69308ffa580f6756129929667785408da377b363787Stephen Chen     * When a Wi-Fi connection attempt ends, {@link OpenNetworkNotifier} handles the connection
69408ffa580f6756129929667785408da377b363787Stephen Chen     * failure. A failure code that is not {@link WifiMetrics.ConnectionEvent#FAILURE_NONE}
69508ffa580f6756129929667785408da377b363787Stephen Chen     * represents a connection failure.
69608ffa580f6756129929667785408da377b363787Stephen Chen     *
69708ffa580f6756129929667785408da377b363787Stephen Chen     * Expected behavior: ONA handles connection failure.
69808ffa580f6756129929667785408da377b363787Stephen Chen     */
69908ffa580f6756129929667785408da377b363787Stephen Chen    @Test
70008ffa580f6756129929667785408da377b363787Stephen Chen    public void wifiConnectionEndsWithFailure_openNetworkNotifierHandlesConnectionFailure() {
70108ffa580f6756129929667785408da377b363787Stephen Chen        mWifiConnectivityManager.handleConnectionAttemptEnded(
70208ffa580f6756129929667785408da377b363787Stephen Chen                WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED);
70308ffa580f6756129929667785408da377b363787Stephen Chen
70408ffa580f6756129929667785408da377b363787Stephen Chen        verify(mOpenNetworkNotifier).handleConnectionFailure();
70508ffa580f6756129929667785408da377b363787Stephen Chen    }
70608ffa580f6756129929667785408da377b363787Stephen Chen
70708ffa580f6756129929667785408da377b363787Stephen Chen    /**
70808ffa580f6756129929667785408da377b363787Stephen Chen     * When a Wi-Fi connection attempt ends, {@link OpenNetworkNotifier} does not handle connection
70908ffa580f6756129929667785408da377b363787Stephen Chen     * failure after a successful connection. {@link WifiMetrics.ConnectionEvent#FAILURE_NONE}
71008ffa580f6756129929667785408da377b363787Stephen Chen     * represents a successful connection.
71108ffa580f6756129929667785408da377b363787Stephen Chen     *
71208ffa580f6756129929667785408da377b363787Stephen Chen     * Expected behavior: ONA does nothing.
71308ffa580f6756129929667785408da377b363787Stephen Chen     */
71408ffa580f6756129929667785408da377b363787Stephen Chen    @Test
71508ffa580f6756129929667785408da377b363787Stephen Chen    public void wifiConnectionEndsWithSuccess_openNetworkNotifierDoesNotHandleConnectionFailure() {
71608ffa580f6756129929667785408da377b363787Stephen Chen        mWifiConnectivityManager.handleConnectionAttemptEnded(
71708ffa580f6756129929667785408da377b363787Stephen Chen                WifiMetrics.ConnectionEvent.FAILURE_NONE);
71808ffa580f6756129929667785408da377b363787Stephen Chen
71908ffa580f6756129929667785408da377b363787Stephen Chen        verify(mOpenNetworkNotifier, never()).handleConnectionFailure();
72008ffa580f6756129929667785408da377b363787Stephen Chen    }
72108ffa580f6756129929667785408da377b363787Stephen Chen
72208ffa580f6756129929667785408da377b363787Stephen Chen    /**
7233f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     * When Wi-Fi is disabled, clear the pending notification and reset notification repeat delay.
7243f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     *
7253f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     * Expected behavior: clear pending notification and reset notification repeat delay
7263f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     * */
7273f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    @Test
72808ffa580f6756129929667785408da377b363787Stephen Chen    public void openNetworkNotifierClearsPendingNotificationOnWifiDisabled() {
7293f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        mWifiConnectivityManager.setWifiEnabled(false);
7303f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen
73108ffa580f6756129929667785408da377b363787Stephen Chen        verify(mOpenNetworkNotifier).clearPendingNotification(true /* resetRepeatDelay */);
7323f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    }
7333f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen
7343f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    /**
7350f41a6a3df4a2cedcad60324d91e1fffc968cfbbStephen Chen     * Verify that the ONA controller tracks screen state changes.
7360f41a6a3df4a2cedcad60324d91e1fffc968cfbbStephen Chen     */
7370f41a6a3df4a2cedcad60324d91e1fffc968cfbbStephen Chen    @Test
73808ffa580f6756129929667785408da377b363787Stephen Chen    public void openNetworkNotifierTracksScreenStateChanges() {
7390f41a6a3df4a2cedcad60324d91e1fffc968cfbbStephen Chen        mWifiConnectivityManager.handleScreenStateChanged(false);
7400f41a6a3df4a2cedcad60324d91e1fffc968cfbbStephen Chen
741ce76a17ac5010e0b7ff5dcf6d8c9db8b48280f9cStephen Chen        verify(mOpenNetworkNotifier).handleScreenStateChanged(false);
7420f41a6a3df4a2cedcad60324d91e1fffc968cfbbStephen Chen
7430f41a6a3df4a2cedcad60324d91e1fffc968cfbbStephen Chen        mWifiConnectivityManager.handleScreenStateChanged(true);
7440f41a6a3df4a2cedcad60324d91e1fffc968cfbbStephen Chen
745ce76a17ac5010e0b7ff5dcf6d8c9db8b48280f9cStephen Chen        verify(mOpenNetworkNotifier).handleScreenStateChanged(true);
7460f41a6a3df4a2cedcad60324d91e1fffc968cfbbStephen Chen    }
7470f41a6a3df4a2cedcad60324d91e1fffc968cfbbStephen Chen
7480f41a6a3df4a2cedcad60324d91e1fffc968cfbbStephen Chen    /**
749664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * {@link CarrierNetworkNotifier} handles scan results on network selection.
750664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     *
751664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * Expected behavior: CarrierNetworkNotifier handles scan results
752664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     */
753664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    @Test
754664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    public void wifiDisconnected_noConnectionCandidate_CarrierNetworkNotifierScanResultsHandled() {
755664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        // no connection candidate selected
756664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(),
757664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                anyBoolean(), anyBoolean())).thenReturn(null);
758664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
759664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        List<ScanDetail> expectedCarrierNetworks = new ArrayList<>();
760664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        expectedCarrierNetworks.add(
761664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                new ScanDetail(
762664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                        new ScanResult(WifiSsid.createFromAsciiEncoded(CANDIDATE_SSID),
763664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                                CANDIDATE_SSID, CANDIDATE_BSSID, 1245, 0, "[EAP][ESS]", -78, 2450,
764664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                                1025, 22, 33, 20, 0, 0, true), null));
765664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
766664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        when(mWifiNS.getFilteredScanDetailsForCarrierUnsavedNetworks(any()))
767664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                .thenReturn(expectedCarrierNetworks);
768664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
769664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        // Set WiFi to disconnected state to trigger PNO scan
770664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        mWifiConnectivityManager.handleConnectionStateChanged(
771664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
772664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
773664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        verify(mCarrierNetworkNotifier).handleScanResults(expectedCarrierNetworks);
774664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    }
775664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
776664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    /**
77784f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh     * {@link CarrierNetworkNotifier} does not handle scan results on network selection if carrier
77884f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh     * encryption info is not available.
77984f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh     *
78084f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh     * Expected behavior: CarrierNetworkNotifier does not handle scan results
78184f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh     */
78284f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh    @Test
78384f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh    public void whenNoEncryptionInfoAvailable_CarrierNetworkNotifierDoesNotHandleScanResults() {
78484f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh        // no connection candidate selected
78584f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh        when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(),
78684f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh                anyBoolean(), anyBoolean())).thenReturn(null);
78784f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh
78884f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh        List<ScanDetail> expectedCarrierNetworks = new ArrayList<>();
78984f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh        expectedCarrierNetworks.add(
79084f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh                new ScanDetail(
79184f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh                        new ScanResult(WifiSsid.createFromAsciiEncoded(CANDIDATE_SSID),
79284f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh                                CANDIDATE_SSID, CANDIDATE_BSSID, 1245, 0, "[EAP][ESS]", -78, 2450,
79384f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh                                1025, 22, 33, 20, 0, 0, true), null));
79484f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh
79584f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh        when(mWifiNS.getFilteredScanDetailsForCarrierUnsavedNetworks(any()))
79684f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh                .thenReturn(expectedCarrierNetworks);
79784f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh        when(mCarrierNetworkConfig.isCarrierEncryptionInfoAvailable()).thenReturn(false);
79884f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh
79984f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh        // Set WiFi to disconnected state to trigger PNO scan
80084f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh        mWifiConnectivityManager.handleConnectionStateChanged(
80184f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
80284f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh
80384f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh        verify(mCarrierNetworkNotifier, never()).handleScanResults(expectedCarrierNetworks);
80484f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh    }
80584f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh
80684f6d8d25d5982b703a74113083e814c9fe5b28fMehdi Alizadeh    /**
807664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * When wifi is connected, {@link CarrierNetworkNotifier} handles the Wi-Fi connected behavior.
808664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     *
809664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * Expected behavior: CarrierNetworkNotifier handles connected behavior
810664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     */
811664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    @Test
812664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    public void wifiConnected_carrierNetworkNotifierHandlesConnection() {
813664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        // Set WiFi to connected state
814664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        mWifiConnectivityManager.handleConnectionStateChanged(
815664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                WifiConnectivityManager.WIFI_STATE_CONNECTED);
816664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
817664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        verify(mCarrierNetworkNotifier).handleWifiConnected();
818664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    }
819664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
820664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    /**
821664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * When wifi is connected, {@link CarrierNetworkNotifier} handles connection state
822664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * change.
823664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     *
824664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * Expected behavior: CarrierNetworkNotifer does not clear pending notification.
825664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     */
826664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    @Test
827664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    public void wifiDisconnected_carrierNetworkNotifierDoesNotClearPendingNotification() {
828664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        // Set WiFi to disconnected state
829664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        mWifiConnectivityManager.handleConnectionStateChanged(
830664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
831664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
832664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        verify(mCarrierNetworkNotifier, never()).clearPendingNotification(anyBoolean());
833664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    }
834664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
835664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    /**
836664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * When a Wi-Fi connection attempt ends, {@link CarrierNetworkNotifier} handles the connection
837664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * failure. A failure code that is not {@link WifiMetrics.ConnectionEvent#FAILURE_NONE}
838664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * represents a connection failure.
839664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     *
840664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * Expected behavior: CarrierNetworkNotifier handles connection failure.
841664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     */
842664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    @Test
843664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    public void wifiConnectionEndsWithFailure_carrierNetworkNotifierHandlesConnectionFailure() {
844664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        mWifiConnectivityManager.handleConnectionAttemptEnded(
845664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                WifiMetrics.ConnectionEvent.FAILURE_CONNECT_NETWORK_FAILED);
846664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
847664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        verify(mCarrierNetworkNotifier).handleConnectionFailure();
848664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    }
849664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
850664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    /**
851664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * When a Wi-Fi connection attempt ends, {@link CarrierNetworkNotifier} does not handle
852664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * connection failure after a successful connection.
853664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * {@link WifiMetrics.ConnectionEvent#FAILURE_NONE} represents a successful connection.
854664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     *
855664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * Expected behavior: CarrierNetworkNotifier does nothing.
856664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     */
857664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    @Test
858664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    public void
859664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh            wifiConnectionEndsWithSuccess_carrierNetworkNotifierDoesNotHandleConnectionFailure() {
860664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        mWifiConnectivityManager.handleConnectionAttemptEnded(
861664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh                WifiMetrics.ConnectionEvent.FAILURE_NONE);
862664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
863664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        verify(mCarrierNetworkNotifier, never()).handleConnectionFailure();
864664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    }
865664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
866664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    /**
867664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * When Wi-Fi is disabled, clear the pending notification and reset notification repeat delay.
868664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     *
869664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * Expected behavior: clear pending notification and reset notification repeat delay
870664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * */
871664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    @Test
872664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    public void carrierNetworkNotifierClearsPendingNotificationOnWifiDisabled() {
873664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        mWifiConnectivityManager.setWifiEnabled(false);
874664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
875664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        verify(mCarrierNetworkNotifier).clearPendingNotification(true /* resetRepeatDelay */);
876664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    }
877664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
878664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    /**
879664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     * Verify that the CarrierNetworkNotifier tracks screen state changes.
880664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh     */
881664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    @Test
882664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    public void carrierNetworkNotifierTracksScreenStateChanges() {
883664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        mWifiConnectivityManager.handleScreenStateChanged(false);
884664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
885664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        verify(mCarrierNetworkNotifier).handleScreenStateChanged(false);
886664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
887664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        mWifiConnectivityManager.handleScreenStateChanged(true);
888664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
889664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh        verify(mCarrierNetworkNotifier).handleScreenStateChanged(true);
890664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    }
891664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh
892664a859a1cc81f6c679e7da44768238374e102f1Mehdi Alizadeh    /**
893b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     *  Verify that scan interval for screen on and wifi disconnected scenario
894b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     *  is in the exponential backoff fashion.
895b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     *
896b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     * Expected behavior: WifiConnectivityManager doubles periodic
897b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     * scan interval.
898b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     */
899b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan    @Test
900b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan    public void checkPeriodicScanIntervalWhenDisconnected() {
901c2963eb07660a06592c60224279685166390217dRandy Pan        long currentTimeStamp = CURRENT_SYSTEM_TIME_MS;
9025de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
903b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
904b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        // Set screen to ON
905b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
906b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
907c2963eb07660a06592c60224279685166390217dRandy Pan        // Wait for MAX_PERIODIC_SCAN_INTERVAL_MS so that any impact triggered
908c2963eb07660a06592c60224279685166390217dRandy Pan        // by screen state change can settle
909c2963eb07660a06592c60224279685166390217dRandy Pan        currentTimeStamp += WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS;
9105de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
911c2963eb07660a06592c60224279685166390217dRandy Pan
912b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        // Set WiFi to disconnected state to trigger periodic scan
913b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
914b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
915b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
916b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        // Get the first periodic scan interval
917b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        long firstIntervalMs = mAlarmManager
918b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG)
919b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                - currentTimeStamp;
920b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        assertEquals(firstIntervalMs, WifiConnectivityManager.PERIODIC_SCAN_INTERVAL_MS);
921b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
922c2963eb07660a06592c60224279685166390217dRandy Pan        currentTimeStamp += firstIntervalMs;
9235de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
924c2963eb07660a06592c60224279685166390217dRandy Pan
925b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        // Now fire the first periodic scan alarm timer
926b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG);
927b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        mLooper.dispatchAll();
928b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
929b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        // Get the second periodic scan interval
930b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        long secondIntervalMs = mAlarmManager
931b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG)
932b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                - currentTimeStamp;
933b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
934b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        // Verify the intervals are exponential back off
935b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        assertEquals(firstIntervalMs * 2, secondIntervalMs);
936b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
937c2963eb07660a06592c60224279685166390217dRandy Pan        currentTimeStamp += secondIntervalMs;
9385de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
939c2963eb07660a06592c60224279685166390217dRandy Pan
940b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        // Make sure we eventually stay at the maximum scan interval.
941b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        long intervalMs = 0;
942b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        for (int i = 0; i < 5; i++) {
943b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan            mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG);
944b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan            mLooper.dispatchAll();
945b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan            intervalMs = mAlarmManager
946b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan                    .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG)
947c2963eb07660a06592c60224279685166390217dRandy Pan                    - currentTimeStamp;
948c2963eb07660a06592c60224279685166390217dRandy Pan            currentTimeStamp += intervalMs;
9495de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang            when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
950b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        }
951b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
952b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        assertEquals(intervalMs, WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS);
953b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan    }
954b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
955b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan    /**
956b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     *  Verify that scan interval for screen on and wifi connected scenario
957b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     *  is in the exponential backoff fashion.
958b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     *
959b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     * Expected behavior: WifiConnectivityManager doubles periodic
960b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     * scan interval.
961b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan     */
962b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan    @Test
963b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan    public void checkPeriodicScanIntervalWhenConnected() {
964c2963eb07660a06592c60224279685166390217dRandy Pan        long currentTimeStamp = CURRENT_SYSTEM_TIME_MS;
9655de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
966b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
967b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        // Set screen to ON
968b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
969b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
970c2963eb07660a06592c60224279685166390217dRandy Pan        // Wait for MAX_PERIODIC_SCAN_INTERVAL_MS so that any impact triggered
971c2963eb07660a06592c60224279685166390217dRandy Pan        // by screen state change can settle
972c2963eb07660a06592c60224279685166390217dRandy Pan        currentTimeStamp += WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS;
9735de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
974c2963eb07660a06592c60224279685166390217dRandy Pan
975b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        // Set WiFi to connected state to trigger periodic scan
976b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
977b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan                WifiConnectivityManager.WIFI_STATE_CONNECTED);
978b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
979b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        // Get the first periodic scan interval
980b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        long firstIntervalMs = mAlarmManager
981b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG)
982b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                - currentTimeStamp;
983b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        assertEquals(firstIntervalMs, WifiConnectivityManager.PERIODIC_SCAN_INTERVAL_MS);
984b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
985c2963eb07660a06592c60224279685166390217dRandy Pan        currentTimeStamp += firstIntervalMs;
9865de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
987c2963eb07660a06592c60224279685166390217dRandy Pan
988b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        // Now fire the first periodic scan alarm timer
989b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG);
990b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        mLooper.dispatchAll();
991b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
992b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        // Get the second periodic scan interval
993b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        long secondIntervalMs = mAlarmManager
994b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG)
995b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                - currentTimeStamp;
996b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
997b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        // Verify the intervals are exponential back off
998b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        assertEquals(firstIntervalMs * 2, secondIntervalMs);
999b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
1000c2963eb07660a06592c60224279685166390217dRandy Pan        currentTimeStamp += secondIntervalMs;
10015de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
1002c2963eb07660a06592c60224279685166390217dRandy Pan
1003b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        // Make sure we eventually stay at the maximum scan interval.
1004b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        long intervalMs = 0;
1005b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        for (int i = 0; i < 5; i++) {
1006b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan            mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG);
1007b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan            mLooper.dispatchAll();
1008b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan            intervalMs = mAlarmManager
1009b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan                    .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG)
1010c2963eb07660a06592c60224279685166390217dRandy Pan                    - currentTimeStamp;
1011c2963eb07660a06592c60224279685166390217dRandy Pan            currentTimeStamp += intervalMs;
10125de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang            when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
1013b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        }
1014b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan
1015b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan        assertEquals(intervalMs, WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS);
1016b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan    }
1017fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1018fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius    /**
1019915a3782e33684562dff8a0897d1446227301b75Randy Pan     *  When screen on trigger a disconnected state change event then a connected state
1020915a3782e33684562dff8a0897d1446227301b75Randy Pan     *  change event back to back to verify that the minium scan interval is enforced.
1021c2963eb07660a06592c60224279685166390217dRandy Pan     *
1022c2963eb07660a06592c60224279685166390217dRandy Pan     * Expected behavior: WifiConnectivityManager start the second periodic single
1023c2963eb07660a06592c60224279685166390217dRandy Pan     * scan PERIODIC_SCAN_INTERVAL_MS after the first one.
1024c2963eb07660a06592c60224279685166390217dRandy Pan     */
1025c2963eb07660a06592c60224279685166390217dRandy Pan    @Test
1026915a3782e33684562dff8a0897d1446227301b75Randy Pan    public void checkMinimumPeriodicScanIntervalWhenScreenOnAndConnected() {
1027c2963eb07660a06592c60224279685166390217dRandy Pan        long currentTimeStamp = CURRENT_SYSTEM_TIME_MS;
10285de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
1029c2963eb07660a06592c60224279685166390217dRandy Pan
1030c2963eb07660a06592c60224279685166390217dRandy Pan        // Set screen to ON
1031c2963eb07660a06592c60224279685166390217dRandy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
1032c2963eb07660a06592c60224279685166390217dRandy Pan
1033c2963eb07660a06592c60224279685166390217dRandy Pan        // Wait for MAX_PERIODIC_SCAN_INTERVAL_MS so that any impact triggered
1034c2963eb07660a06592c60224279685166390217dRandy Pan        // by screen state change can settle
1035c2963eb07660a06592c60224279685166390217dRandy Pan        currentTimeStamp += WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS;
1036915a3782e33684562dff8a0897d1446227301b75Randy Pan        long scanForDisconnectedTimeStamp = currentTimeStamp;
1037915a3782e33684562dff8a0897d1446227301b75Randy Pan        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
1038915a3782e33684562dff8a0897d1446227301b75Randy Pan
1039915a3782e33684562dff8a0897d1446227301b75Randy Pan        // Set WiFi to disconnected state which triggers a scan immediately
1040915a3782e33684562dff8a0897d1446227301b75Randy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1041915a3782e33684562dff8a0897d1446227301b75Randy Pan                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
1042915a3782e33684562dff8a0897d1446227301b75Randy Pan        verify(mWifiScanner, times(1)).startScan(anyObject(), anyObject(), anyObject());
1043915a3782e33684562dff8a0897d1446227301b75Randy Pan
1044915a3782e33684562dff8a0897d1446227301b75Randy Pan        // Set up time stamp for when entering CONNECTED state
1045915a3782e33684562dff8a0897d1446227301b75Randy Pan        currentTimeStamp += 2000;
1046915a3782e33684562dff8a0897d1446227301b75Randy Pan        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
1047915a3782e33684562dff8a0897d1446227301b75Randy Pan
1048915a3782e33684562dff8a0897d1446227301b75Randy Pan        // Set WiFi to connected state to trigger its periodic scan
1049915a3782e33684562dff8a0897d1446227301b75Randy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1050915a3782e33684562dff8a0897d1446227301b75Randy Pan                WifiConnectivityManager.WIFI_STATE_CONNECTED);
1051915a3782e33684562dff8a0897d1446227301b75Randy Pan
1052915a3782e33684562dff8a0897d1446227301b75Randy Pan        // The very first scan triggered for connected state is actually via the alarm timer
1053915a3782e33684562dff8a0897d1446227301b75Randy Pan        // and it obeys the minimum scan interval
1054915a3782e33684562dff8a0897d1446227301b75Randy Pan        long firstScanForConnectedTimeStamp = mAlarmManager
1055915a3782e33684562dff8a0897d1446227301b75Randy Pan                .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG);
1056915a3782e33684562dff8a0897d1446227301b75Randy Pan
1057915a3782e33684562dff8a0897d1446227301b75Randy Pan        // Verify that the first scan for connected state is scheduled PERIODIC_SCAN_INTERVAL_MS
1058915a3782e33684562dff8a0897d1446227301b75Randy Pan        // after the scan for disconnected state
1059915a3782e33684562dff8a0897d1446227301b75Randy Pan        assertEquals(firstScanForConnectedTimeStamp, scanForDisconnectedTimeStamp
1060915a3782e33684562dff8a0897d1446227301b75Randy Pan                + WifiConnectivityManager.PERIODIC_SCAN_INTERVAL_MS);
1061915a3782e33684562dff8a0897d1446227301b75Randy Pan    }
1062915a3782e33684562dff8a0897d1446227301b75Randy Pan
1063915a3782e33684562dff8a0897d1446227301b75Randy Pan    /**
1064915a3782e33684562dff8a0897d1446227301b75Randy Pan     *  When screen on trigger a connected state change event then a disconnected state
1065915a3782e33684562dff8a0897d1446227301b75Randy Pan     *  change event back to back to verify that a scan is fired immediately for the
1066915a3782e33684562dff8a0897d1446227301b75Randy Pan     *  disconnected state change event.
1067915a3782e33684562dff8a0897d1446227301b75Randy Pan     *
1068915a3782e33684562dff8a0897d1446227301b75Randy Pan     * Expected behavior: WifiConnectivityManager directly starts the periodic immediately
1069915a3782e33684562dff8a0897d1446227301b75Randy Pan     * for the disconnected state change event. The second scan for disconnected state is
1070915a3782e33684562dff8a0897d1446227301b75Randy Pan     * via alarm timer.
1071915a3782e33684562dff8a0897d1446227301b75Randy Pan     */
1072915a3782e33684562dff8a0897d1446227301b75Randy Pan    @Test
1073915a3782e33684562dff8a0897d1446227301b75Randy Pan    public void scanImmediatelyWhenScreenOnAndDisconnected() {
1074915a3782e33684562dff8a0897d1446227301b75Randy Pan        long currentTimeStamp = CURRENT_SYSTEM_TIME_MS;
1075915a3782e33684562dff8a0897d1446227301b75Randy Pan        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
1076915a3782e33684562dff8a0897d1446227301b75Randy Pan
1077915a3782e33684562dff8a0897d1446227301b75Randy Pan        // Set screen to ON
1078915a3782e33684562dff8a0897d1446227301b75Randy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
1079915a3782e33684562dff8a0897d1446227301b75Randy Pan
1080915a3782e33684562dff8a0897d1446227301b75Randy Pan        // Wait for MAX_PERIODIC_SCAN_INTERVAL_MS so that any impact triggered
1081915a3782e33684562dff8a0897d1446227301b75Randy Pan        // by screen state change can settle
1082915a3782e33684562dff8a0897d1446227301b75Randy Pan        currentTimeStamp += WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS;
1083915a3782e33684562dff8a0897d1446227301b75Randy Pan        long scanForConnectedTimeStamp = currentTimeStamp;
10845de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
1085c2963eb07660a06592c60224279685166390217dRandy Pan
1086c2963eb07660a06592c60224279685166390217dRandy Pan        // Set WiFi to connected state to trigger the periodic scan
1087c2963eb07660a06592c60224279685166390217dRandy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1088c2963eb07660a06592c60224279685166390217dRandy Pan                WifiConnectivityManager.WIFI_STATE_CONNECTED);
1089915a3782e33684562dff8a0897d1446227301b75Randy Pan        verify(mWifiScanner, times(1)).startScan(anyObject(), anyObject(), anyObject());
1090c2963eb07660a06592c60224279685166390217dRandy Pan
1091915a3782e33684562dff8a0897d1446227301b75Randy Pan        // Set up the time stamp for when entering DISCONNECTED state
1092c2963eb07660a06592c60224279685166390217dRandy Pan        currentTimeStamp += 2000;
1093915a3782e33684562dff8a0897d1446227301b75Randy Pan        long enteringDisconnectedStateTimeStamp = currentTimeStamp;
10945de29ec72c54cb73fdc1b59072f66a2627b8764cNingyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
1095c2963eb07660a06592c60224279685166390217dRandy Pan
1096915a3782e33684562dff8a0897d1446227301b75Randy Pan        // Set WiFi to disconnected state to trigger its periodic scan
1097c2963eb07660a06592c60224279685166390217dRandy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1098c2963eb07660a06592c60224279685166390217dRandy Pan                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
1099c2963eb07660a06592c60224279685166390217dRandy Pan
1100915a3782e33684562dff8a0897d1446227301b75Randy Pan        // Verify the very first scan for DISCONNECTED state is fired immediately
1101915a3782e33684562dff8a0897d1446227301b75Randy Pan        verify(mWifiScanner, times(2)).startScan(anyObject(), anyObject(), anyObject());
1102915a3782e33684562dff8a0897d1446227301b75Randy Pan        long secondScanForDisconnectedTimeStamp = mAlarmManager
1103915a3782e33684562dff8a0897d1446227301b75Randy Pan                .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG);
1104c2963eb07660a06592c60224279685166390217dRandy Pan
1105915a3782e33684562dff8a0897d1446227301b75Randy Pan        // Verify that the second scan is scheduled PERIODIC_SCAN_INTERVAL_MS after
1106915a3782e33684562dff8a0897d1446227301b75Randy Pan        // entering DISCONNECTED state.
1107915a3782e33684562dff8a0897d1446227301b75Randy Pan        assertEquals(secondScanForDisconnectedTimeStamp, enteringDisconnectedStateTimeStamp
1108915a3782e33684562dff8a0897d1446227301b75Randy Pan                + WifiConnectivityManager.PERIODIC_SCAN_INTERVAL_MS);
1109c2963eb07660a06592c60224279685166390217dRandy Pan    }
1110c2963eb07660a06592c60224279685166390217dRandy Pan
1111c2963eb07660a06592c60224279685166390217dRandy Pan    /**
1112016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan     *  When screen on trigger a connection state change event and a forced connectivity
1113016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan     *  scan event back to back to verify that the minimum scan interval is not applied
1114016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan     *  in this scenario.
1115016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan     *
1116016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan     * Expected behavior: WifiConnectivityManager starts the second periodic single
1117016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan     * scan immediately.
1118016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan     */
1119016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan    @Test
1120016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan    public void checkMinimumPeriodicScanIntervalNotEnforced() {
1121016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        long currentTimeStamp = CURRENT_SYSTEM_TIME_MS;
11225967a15d36c76ba1aaeb89ce8bd66bb4bccfe998Paul Stewart        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
1123016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan
1124016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        // Set screen to ON
1125016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
1126016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan
1127016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        // Wait for MAX_PERIODIC_SCAN_INTERVAL_MS so that any impact triggered
1128016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        // by screen state change can settle
1129016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        currentTimeStamp += WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS;
1130016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        long firstScanTimeStamp = currentTimeStamp;
11315967a15d36c76ba1aaeb89ce8bd66bb4bccfe998Paul Stewart        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
1132016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan
1133016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        // Set WiFi to connected state to trigger the periodic scan
1134016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1135016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan                WifiConnectivityManager.WIFI_STATE_CONNECTED);
1136016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan
1137016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        // Set the second scan attempt time stamp
1138016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        currentTimeStamp += 2000;
11395967a15d36c76ba1aaeb89ce8bd66bb4bccfe998Paul Stewart        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
1140016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan
1141cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        // Allow untrusted networks so WifiConnectivityManager starts a periodic scan
1142cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        // immediately.
1143cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        mWifiConnectivityManager.setUntrustedConnectionAllowed(true);
1144016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan
1145016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        // Get the second periodic scan actual time stamp. Note, this scan is not
1146016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        // started from the AlarmManager.
1147016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        long secondScanTimeStamp = mWifiConnectivityManager.getLastPeriodicSingleScanTimeStamp();
1148016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan
1149016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        // Verify that the second scan is fired immediately
1150016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan        assertEquals(secondScanTimeStamp, currentTimeStamp);
1151016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan    }
1152016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan
1153016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan    /**
1154fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     * Verify that we perform full band scan when the currently connected network's tx/rx success
1155fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     * rate is low.
1156fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     *
1157fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     * Expected behavior: WifiConnectivityManager does full band scan.
1158fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     */
1159fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius    @Test
1160fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius    public void checkSingleScanSettingsWhenConnectedWithLowDataRate() {
1161fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        mWifiInfo.txSuccessRate = 0;
1162fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        mWifiInfo.rxSuccessRate = 0;
1163fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1164fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        final HashSet<Integer> channelList = new HashSet<>();
1165fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        channelList.add(1);
1166fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        channelList.add(2);
1167fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        channelList.add(3);
1168fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1169fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        when(mWifiStateMachine.getCurrentWifiConfiguration())
1170fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                .thenReturn(new WifiConfiguration());
11713697d5ed11fea02e6369336d54e19145ba76425fRandy Pan        when(mWifiConfigManager.fetchChannelSetForNetworkForPartialScan(anyInt(), anyLong(),
11723697d5ed11fea02e6369336d54e19145ba76425fRandy Pan                anyInt())).thenReturn(channelList);
1173fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1174fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        doAnswer(new AnswerWithArguments() {
1175fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius            public void answer(ScanSettings settings, ScanListener listener,
1176fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                    WorkSource workSource) throws Exception {
1177026cb51837e4cf3aea30b903320b992a3f5d0d7bChristopher Wiley                assertEquals(settings.band, WifiScanner.WIFI_BAND_BOTH_WITH_DFS);
1178fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                assertNull(settings.channels);
1179fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius            }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject());
1180fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1181fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        // Set screen to ON
1182fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        mWifiConnectivityManager.handleScreenStateChanged(true);
1183fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1184fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        // Set WiFi to connected state to trigger periodic scan
1185fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        mWifiConnectivityManager.handleConnectionStateChanged(
1186fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                WifiConnectivityManager.WIFI_STATE_CONNECTED);
1187fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1188fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        verify(mWifiScanner).startScan(anyObject(), anyObject(), anyObject());
1189fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius    }
1190fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1191fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius    /**
1192fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     * Verify that we perform partial scan when the currently connected network's tx/rx success
1193fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     * rate is high and when the currently connected network is present in scan
1194fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     * cache in WifiConfigManager.
119554e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang     * WifiConnectivityManager does partial scan only when firmware roaming is not supported.
1196fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     *
119754e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang     * Expected behavior: WifiConnectivityManager does partial scan.
1198fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     */
1199fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius    @Test
120054e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang    public void checkPartialScanRequestedWithHighDataRateWithoutFwRoaming() {
1201e4606e0f9532d250a1e06e8aba5fb48556225773Randy Pan        mWifiInfo.txSuccessRate = mFullScanMaxTxPacketRate * 2;
1202e4606e0f9532d250a1e06e8aba5fb48556225773Randy Pan        mWifiInfo.rxSuccessRate = mFullScanMaxRxPacketRate * 2;
1203fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1204fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        final HashSet<Integer> channelList = new HashSet<>();
1205fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        channelList.add(1);
1206fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        channelList.add(2);
1207fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        channelList.add(3);
1208fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1209fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        when(mWifiStateMachine.getCurrentWifiConfiguration())
1210fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                .thenReturn(new WifiConfiguration());
12113697d5ed11fea02e6369336d54e19145ba76425fRandy Pan        when(mWifiConfigManager.fetchChannelSetForNetworkForPartialScan(anyInt(), anyLong(),
121260ecc292c27e34df1a9414da0d6482cce718efbcRandy Pan                anyInt())).thenReturn(channelList);
121354e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(false);
1214fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1215fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        doAnswer(new AnswerWithArguments() {
1216fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius            public void answer(ScanSettings settings, ScanListener listener,
1217fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                    WorkSource workSource) throws Exception {
1218fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                assertEquals(settings.band, WifiScanner.WIFI_BAND_UNSPECIFIED);
1219fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                assertEquals(settings.channels.length, channelList.size());
1220fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                for (int chanIdx = 0; chanIdx < settings.channels.length; chanIdx++) {
1221fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                    assertTrue(channelList.contains(settings.channels[chanIdx].frequency));
1222fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                }
1223fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius            }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject());
1224fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1225fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        // Set screen to ON
1226fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        mWifiConnectivityManager.handleScreenStateChanged(true);
1227fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1228fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        // Set WiFi to connected state to trigger periodic scan
1229fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        mWifiConnectivityManager.handleConnectionStateChanged(
1230fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                WifiConnectivityManager.WIFI_STATE_CONNECTED);
1231fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1232fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        verify(mWifiScanner).startScan(anyObject(), anyObject(), anyObject());
1233fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius    }
1234fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1235fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius    /**
123654e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang     * Verify that we skip the partial scan when:
123754e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang     * 1. The currently connected network's tx/rx success rate is high.
123854e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang     * 2. When the currently connected network is present in scan
123954e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang     * cache in WifiConfigManager.
124054e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang     * 3. When firmware roaming is supported.
124154e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang     * Expected behavior: WifiConnectivityManager does no scan, but periodic scans
124254e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang     * are still scheduled.
124354e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang     */
124454e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang    @Test
124554e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang    public void checkPartialScanSkippedWithHighDataRateWithFwRoaming() {
124654e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        mWifiInfo.txSuccessRate = mFullScanMaxTxPacketRate * 2;
124754e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        mWifiInfo.rxSuccessRate = mFullScanMaxRxPacketRate * 2;
124854e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang
124954e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        long currentTimeStamp = CURRENT_SYSTEM_TIME_MS;
125054e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        when(mClock.getElapsedSinceBootMillis()).thenReturn(currentTimeStamp);
125154e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang
125254e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        final HashSet<Integer> channelList = new HashSet<>();
125354e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        channelList.add(1);
125454e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        channelList.add(2);
125554e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        channelList.add(3);
125654e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang
125754e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        when(mWifiStateMachine.getCurrentWifiConfiguration())
125854e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang                .thenReturn(new WifiConfiguration());
125954e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        when(mWifiConfigManager.fetchChannelSetForNetworkForPartialScan(anyInt(), anyLong(),
126054e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang                anyInt())).thenReturn(channelList);
126154e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        // No scan will be requested when firmware roaming control is not supported.
126254e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
126354e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang
126454e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        // Set screen to ON
126554e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        mWifiConnectivityManager.handleScreenStateChanged(true);
126654e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang
126754e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        // Set WiFi to connected state to trigger periodic scan
126854e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        mWifiConnectivityManager.handleConnectionStateChanged(
126954e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang                WifiConnectivityManager.WIFI_STATE_CONNECTED);
127054e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang
127154e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        verify(mWifiScanner, never()).startScan(anyObject(), anyObject(), anyObject());
127254e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang
127354e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        // Get the first periodic scan interval to check that we are still scheduling
127454e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        // periodic scans.
127554e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        long firstIntervalMs = mAlarmManager
127654e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang                .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG)
127754e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang                - currentTimeStamp;
127854e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang        assertEquals(firstIntervalMs, WifiConnectivityManager.PERIODIC_SCAN_INTERVAL_MS);
127954e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang    }
128054e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang
128154e1f042c35507cefb8bb7b88c5d1dbd6f45aa97Ningyuan Wang    /**
1282fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     * Verify that we fall back to full band scan when the currently connected network's tx/rx
1283fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     * success rate is high and the currently connected network is not present in scan cache in
1284fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     * WifiConfigManager. This is simulated by returning an empty hashset in |makeChannelList|.
1285fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     *
1286fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     * Expected behavior: WifiConnectivityManager does full band scan.
1287fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius     */
1288fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius    @Test
1289fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius    public void checkSingleScanSettingsWhenConnectedWithHighDataRateNotInCache() {
1290e4606e0f9532d250a1e06e8aba5fb48556225773Randy Pan        mWifiInfo.txSuccessRate = mFullScanMaxTxPacketRate * 2;
1291e4606e0f9532d250a1e06e8aba5fb48556225773Randy Pan        mWifiInfo.rxSuccessRate = mFullScanMaxRxPacketRate * 2;
1292fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1293fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        final HashSet<Integer> channelList = new HashSet<>();
1294fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1295fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        when(mWifiStateMachine.getCurrentWifiConfiguration())
1296fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                .thenReturn(new WifiConfiguration());
12973697d5ed11fea02e6369336d54e19145ba76425fRandy Pan        when(mWifiConfigManager.fetchChannelSetForNetworkForPartialScan(anyInt(), anyLong(),
129860ecc292c27e34df1a9414da0d6482cce718efbcRandy Pan                anyInt())).thenReturn(channelList);
1299fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1300fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        doAnswer(new AnswerWithArguments() {
1301fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius            public void answer(ScanSettings settings, ScanListener listener,
1302fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                    WorkSource workSource) throws Exception {
1303026cb51837e4cf3aea30b903320b992a3f5d0d7bChristopher Wiley                assertEquals(settings.band, WifiScanner.WIFI_BAND_BOTH_WITH_DFS);
1304fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                assertNull(settings.channels);
1305fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius            }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject());
1306fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1307fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        // Set screen to ON
1308fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        mWifiConnectivityManager.handleScreenStateChanged(true);
1309fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1310fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        // Set WiFi to connected state to trigger periodic scan
1311fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        mWifiConnectivityManager.handleConnectionStateChanged(
1312fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius                WifiConnectivityManager.WIFI_STATE_CONNECTED);
1313fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius
1314fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius        verify(mWifiScanner).startScan(anyObject(), anyObject(), anyObject());
1315fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius    }
1316de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan
1317de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan    /**
1318de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan     *  Verify that we retry connectivity scan up to MAX_SCAN_RESTART_ALLOWED times
1319de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan     *  when Wifi somehow gets into a bad state and fails to scan.
1320de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan     *
1321de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan     * Expected behavior: WifiConnectivityManager schedules connectivity scan
1322de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan     * MAX_SCAN_RESTART_ALLOWED times.
1323de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan     */
1324de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan    @Test
1325de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan    public void checkMaximumScanRetry() {
1326de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan        // Set screen to ON
1327de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
1328de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan
1329de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan        doAnswer(new AnswerWithArguments() {
1330de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan            public void answer(ScanSettings settings, ScanListener listener,
1331de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan                    WorkSource workSource) throws Exception {
1332de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan                listener.onFailure(-1, "ScanFailure");
1333de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan            }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject());
1334de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan
1335de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan        // Set WiFi to disconnected state to trigger the single scan based periodic scan
1336de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1337de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
1338de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan
1339de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan        // Fire the alarm timer 2x timers
1340de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan        for (int i = 0; i < (WifiConnectivityManager.MAX_SCAN_RESTART_ALLOWED * 2); i++) {
1341de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan            mAlarmManager.dispatch(WifiConnectivityManager.RESTART_SINGLE_SCAN_TIMER_TAG);
1342de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan            mLooper.dispatchAll();
1343de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan        }
1344de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan
1345de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan        // Verify that the connectivity scan has been retried for MAX_SCAN_RESTART_ALLOWED
1346de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan        // times. Note, WifiScanner.startScan() is invoked MAX_SCAN_RESTART_ALLOWED + 1 times.
1347de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan        // The very first scan is the initial one, and the other MAX_SCAN_RESTART_ALLOWED
1348de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan        // are the retrial ones.
1349de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan        verify(mWifiScanner, times(WifiConnectivityManager.MAX_SCAN_RESTART_ALLOWED + 1)).startScan(
1350de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan                anyObject(), anyObject(), anyObject());
1351de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan    }
1352cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan
1353cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan    /**
1354cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan     * Listen to scan results not requested by WifiConnectivityManager and
1355cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan     * act on them.
1356cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan     *
1357cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan     * Expected behavior: WifiConnectivityManager calls
1358fe993ca46449a8aab3f7f55e2132456064bcee94Roshan Pius     * WifiStateMachine.startConnectToNetwork() with the
1359cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan     * expected candidate network ID and BSSID.
1360cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan     */
1361cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan    @Test
1362cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan    public void listenToAllSingleScanResults() {
1363cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan        ScanSettings settings = new ScanSettings();
1364cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan        ScanListener scanListener = mock(ScanListener.class);
1365cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan
1366cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan        // Request a single scan outside of WifiConnectivityManager.
1367cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan        mWifiScanner.startScan(settings, scanListener, WIFI_WORK_SOURCE);
1368cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan
1369cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan        // Verify that WCM receives the scan results and initiates a connection
1370cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan        // to the network.
13719686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti        verify(mWifiStateMachine).startConnectToNetwork(
13729686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
1373cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan    }
1374cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan
1375cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan    /**
1376cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan     *  Verify that a forced connectivity scan waits for full band scan
1377cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan     *  results.
1378cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan     *
1379cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan     * Expected behavior: WifiConnectivityManager doesn't invoke
1380cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan     * WifiStateMachine.startConnectToNetwork() when full band scan
1381cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan     * results are not available.
1382cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan     */
1383cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan    @Test
1384cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan    public void waitForFullBandScanResults() {
1385cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        // Set WiFi to connected state.
1386cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1387cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan                WifiConnectivityManager.WIFI_STATE_CONNECTED);
1388cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan
1389cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        // Set up as partial scan results.
1390cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        when(mScanData.isAllChannelsScanned()).thenReturn(false);
1391cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan
1392cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        // Force a connectivity scan which enables WifiConnectivityManager
1393cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        // to wait for full band scan results.
1394470817b13e56d915805729ab4f51075f3fa2ec15Ningyuan Wang        mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE);
1395cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan
1396cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        // No roaming because no full band scan results.
1397cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        verify(mWifiStateMachine, times(0)).startConnectToNetwork(
13989686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
1399cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan
1400cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        // Set up as full band scan results.
1401cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        when(mScanData.isAllChannelsScanned()).thenReturn(true);
1402cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan
1403cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        // Force a connectivity scan which enables WifiConnectivityManager
1404cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        // to wait for full band scan results.
1405470817b13e56d915805729ab4f51075f3fa2ec15Ningyuan Wang        mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE);
1406cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan
1407cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan        // Roaming attempt because full band scan results are available.
14089686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti        verify(mWifiStateMachine).startConnectToNetwork(
14099686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
1410cf69e50f5344898a0a89f838f63322a2df01bf5dRandy Pan    }
1411167b90b5e002698378728a54a417a08c317d29dcRandy Pan
1412167b90b5e002698378728a54a417a08c317d29dcRandy Pan    /**
1413167b90b5e002698378728a54a417a08c317d29dcRandy Pan     *  Verify the BSSID blacklist implementation.
1414167b90b5e002698378728a54a417a08c317d29dcRandy Pan     *
1415167b90b5e002698378728a54a417a08c317d29dcRandy Pan     * Expected behavior: A BSSID gets blacklisted after being disabled
1416ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan     * for 3 times, and becomes available after being re-enabled. Firmware
1417ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan     * controlled roaming is supported, its roaming configuration needs to be
1418ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan     * updated as well.
1419167b90b5e002698378728a54a417a08c317d29dcRandy Pan     */
1420167b90b5e002698378728a54a417a08c317d29dcRandy Pan    @Test
1421167b90b5e002698378728a54a417a08c317d29dcRandy Pan    public void blacklistAndReenableBssid() {
1422167b90b5e002698378728a54a417a08c317d29dcRandy Pan        String bssid = "6c:f3:7f:ae:8c:f3";
1423167b90b5e002698378728a54a417a08c317d29dcRandy Pan
1424ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
1425167b90b5e002698378728a54a417a08c317d29dcRandy Pan        // Verify that a BSSID gets blacklisted only after being disabled
1426167b90b5e002698378728a54a417a08c317d29dcRandy Pan        // for BSSID_BLACKLIST_THRESHOLD times for reasons other than
1427167b90b5e002698378728a54a417a08c317d29dcRandy Pan        // REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA.
1428167b90b5e002698378728a54a417a08c317d29dcRandy Pan        for (int i = 0; i < WifiConnectivityManager.BSSID_BLACKLIST_THRESHOLD; i++) {
1429167b90b5e002698378728a54a417a08c317d29dcRandy Pan            assertFalse(mWifiConnectivityManager.isBssidDisabled(bssid));
1430167b90b5e002698378728a54a417a08c317d29dcRandy Pan            mWifiConnectivityManager.trackBssid(bssid, false, 1);
1431167b90b5e002698378728a54a417a08c317d29dcRandy Pan        }
1432167b90b5e002698378728a54a417a08c317d29dcRandy Pan
1433ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID is now blacklisted.
1434167b90b5e002698378728a54a417a08c317d29dcRandy Pan        assertTrue(mWifiConnectivityManager.isBssidDisabled(bssid));
1435ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID gets sent to firmware.
1436ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        verify(mWifiConnectivityHelper).setFirmwareRoamingConfiguration(
1437ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan                mBssidBlacklistCaptor.capture(), mSsidWhitelistCaptor.capture());
1438ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mBssidBlacklistCaptor.getValue().contains(bssid));
1439ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mSsidWhitelistCaptor.getValue().isEmpty());
1440167b90b5e002698378728a54a417a08c317d29dcRandy Pan
1441167b90b5e002698378728a54a417a08c317d29dcRandy Pan        // Re-enable the bssid.
1442167b90b5e002698378728a54a417a08c317d29dcRandy Pan        mWifiConnectivityManager.trackBssid(bssid, true, 1);
1443167b90b5e002698378728a54a417a08c317d29dcRandy Pan
1444ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the bssid is no longer blacklisted.
1445167b90b5e002698378728a54a417a08c317d29dcRandy Pan        assertFalse(mWifiConnectivityManager.isBssidDisabled(bssid));
1446ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID gets cleared from firmware.
1447ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        verify(mWifiConnectivityHelper, times(2)).setFirmwareRoamingConfiguration(
1448ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan                mBssidBlacklistCaptor.capture(), mSsidWhitelistCaptor.capture());
1449ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertFalse(mBssidBlacklistCaptor.getValue().contains(bssid));
1450ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mSsidWhitelistCaptor.getValue().isEmpty());
1451167b90b5e002698378728a54a417a08c317d29dcRandy Pan    }
1452167b90b5e002698378728a54a417a08c317d29dcRandy Pan
1453167b90b5e002698378728a54a417a08c317d29dcRandy Pan    /**
1454167b90b5e002698378728a54a417a08c317d29dcRandy Pan     *  Verify that a network gets blacklisted immediately if it is unable
1455167b90b5e002698378728a54a417a08c317d29dcRandy Pan     *  to handle new stations.
1456167b90b5e002698378728a54a417a08c317d29dcRandy Pan     */
1457167b90b5e002698378728a54a417a08c317d29dcRandy Pan    @Test
1458167b90b5e002698378728a54a417a08c317d29dcRandy Pan    public void blacklistNetworkImmediatelyIfApHasNoCapacityForNewStation() {
1459167b90b5e002698378728a54a417a08c317d29dcRandy Pan        String bssid = "6c:f3:7f:ae:8c:f3";
1460167b90b5e002698378728a54a417a08c317d29dcRandy Pan
1461ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
1462ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Blacklist the BSSID
1463167b90b5e002698378728a54a417a08c317d29dcRandy Pan        mWifiConnectivityManager.trackBssid(bssid, false,
1464167b90b5e002698378728a54a417a08c317d29dcRandy Pan                WifiConnectivityManager.REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA);
1465167b90b5e002698378728a54a417a08c317d29dcRandy Pan
1466ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID is now blacklisted.
1467167b90b5e002698378728a54a417a08c317d29dcRandy Pan        assertTrue(mWifiConnectivityManager.isBssidDisabled(bssid));
1468ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID gets sent to firmware.
1469ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        verify(mWifiConnectivityHelper).setFirmwareRoamingConfiguration(
1470ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan                mBssidBlacklistCaptor.capture(), mSsidWhitelistCaptor.capture());
1471ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mBssidBlacklistCaptor.getValue().contains(bssid));
1472ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mSsidWhitelistCaptor.getValue().isEmpty());
1473167b90b5e002698378728a54a417a08c317d29dcRandy Pan    }
1474167b90b5e002698378728a54a417a08c317d29dcRandy Pan
1475167b90b5e002698378728a54a417a08c317d29dcRandy Pan    /**
1476167b90b5e002698378728a54a417a08c317d29dcRandy Pan     *  Verify that a blacklisted BSSID becomes available only after
1477167b90b5e002698378728a54a417a08c317d29dcRandy Pan     *  BSSID_BLACKLIST_EXPIRE_TIME_MS.
1478167b90b5e002698378728a54a417a08c317d29dcRandy Pan     */
1479167b90b5e002698378728a54a417a08c317d29dcRandy Pan    @Test
1480167b90b5e002698378728a54a417a08c317d29dcRandy Pan    public void verifyBlacklistRefreshedAfterScanResults() {
1481167b90b5e002698378728a54a417a08c317d29dcRandy Pan        String bssid = "6c:f3:7f:ae:8c:f3";
1482167b90b5e002698378728a54a417a08c317d29dcRandy Pan
1483ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
1484ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Blacklist the BSSID.
1485167b90b5e002698378728a54a417a08c317d29dcRandy Pan        mWifiConnectivityManager.trackBssid(bssid, false,
1486167b90b5e002698378728a54a417a08c317d29dcRandy Pan                WifiConnectivityManager.REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA);
1487ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1488ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID is now blacklisted.
1489167b90b5e002698378728a54a417a08c317d29dcRandy Pan        assertTrue(mWifiConnectivityManager.isBssidDisabled(bssid));
1490ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID gets sent to firmware.
1491ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        verify(mWifiConnectivityHelper).setFirmwareRoamingConfiguration(
1492ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan                mBssidBlacklistCaptor.capture(), mSsidWhitelistCaptor.capture());
1493ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mBssidBlacklistCaptor.getValue().contains(bssid));
1494ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mSsidWhitelistCaptor.getValue().isEmpty());
1495167b90b5e002698378728a54a417a08c317d29dcRandy Pan
1496167b90b5e002698378728a54a417a08c317d29dcRandy Pan        // Force a connectivity scan in less than BSSID_BLACKLIST_EXPIRE_TIME_MS.
1497167b90b5e002698378728a54a417a08c317d29dcRandy Pan        // Arrival of scan results will trigger WifiConnectivityManager to refresh its
1498167b90b5e002698378728a54a417a08c317d29dcRandy Pan        // BSSID blacklist. Verify that the blacklisted BSSId is not freed because
1499167b90b5e002698378728a54a417a08c317d29dcRandy Pan        // its blacklist expiration time hasn't reached yet.
1500167b90b5e002698378728a54a417a08c317d29dcRandy Pan        when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
1501167b90b5e002698378728a54a417a08c317d29dcRandy Pan                + WifiConnectivityManager.BSSID_BLACKLIST_EXPIRE_TIME_MS / 2);
1502470817b13e56d915805729ab4f51075f3fa2ec15Ningyuan Wang        mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE);
1503167b90b5e002698378728a54a417a08c317d29dcRandy Pan        assertTrue(mWifiConnectivityManager.isBssidDisabled(bssid));
1504167b90b5e002698378728a54a417a08c317d29dcRandy Pan
1505167b90b5e002698378728a54a417a08c317d29dcRandy Pan        // Force another connectivity scan at BSSID_BLACKLIST_EXPIRE_TIME_MS from when the
1506167b90b5e002698378728a54a417a08c317d29dcRandy Pan        // BSSID was blacklisted. Verify that the blacklisted BSSId is freed.
1507167b90b5e002698378728a54a417a08c317d29dcRandy Pan        when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
1508167b90b5e002698378728a54a417a08c317d29dcRandy Pan                + WifiConnectivityManager.BSSID_BLACKLIST_EXPIRE_TIME_MS);
1509470817b13e56d915805729ab4f51075f3fa2ec15Ningyuan Wang        mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE);
1510ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1511ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID is no longer blacklisted.
1512ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertFalse(mWifiConnectivityManager.isBssidDisabled(bssid));
1513ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID gets cleared from firmware.
1514ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        verify(mWifiConnectivityHelper, times(2)).setFirmwareRoamingConfiguration(
1515ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan                mBssidBlacklistCaptor.capture(), mSsidWhitelistCaptor.capture());
1516ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertFalse(mBssidBlacklistCaptor.getValue().contains(bssid));
1517ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mSsidWhitelistCaptor.getValue().isEmpty());
1518ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    }
1519ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1520ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    /**
1521ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan     *  Verify that BSSID blacklist gets cleared when exiting Wifi client mode.
1522ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan     */
1523ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    @Test
1524ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    public void clearBssidBlacklistWhenExitingWifiClientMode() {
1525ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        String bssid = "6c:f3:7f:ae:8c:f3";
1526ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1527ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
1528ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1529ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Blacklist the BSSID.
1530ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        mWifiConnectivityManager.trackBssid(bssid, false,
1531ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan                WifiConnectivityManager.REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA);
1532ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1533ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID is now blacklisted.
1534ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mWifiConnectivityManager.isBssidDisabled(bssid));
1535ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID gets sent to firmware.
1536ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        verify(mWifiConnectivityHelper).setFirmwareRoamingConfiguration(
1537ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan                mBssidBlacklistCaptor.capture(), mSsidWhitelistCaptor.capture());
1538ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mBssidBlacklistCaptor.getValue().contains(bssid));
1539ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mSsidWhitelistCaptor.getValue().isEmpty());
1540ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1541ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Exit Wifi client mode.
1542ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        mWifiConnectivityManager.setWifiEnabled(false);
1543ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1544ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID blacklist is empty.
1545ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertFalse(mWifiConnectivityManager.isBssidDisabled(bssid));
1546ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        verify(mWifiConnectivityHelper, times(2)).setFirmwareRoamingConfiguration(
1547ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan                mBssidBlacklistCaptor.capture(), mSsidWhitelistCaptor.capture());
1548ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mBssidBlacklistCaptor.getValue().isEmpty());
1549ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mSsidWhitelistCaptor.getValue().isEmpty());
1550ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    }
1551ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1552ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    /**
1553ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan     *  Verify that BSSID blacklist gets cleared when preparing for a forced connection
1554ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan     *  initiated by user/app.
1555ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan     */
1556ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    @Test
1557ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    public void clearBssidBlacklistWhenPreparingForForcedConnection() {
1558ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        String bssid = "6c:f3:7f:ae:8c:f3";
1559ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1560ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
1561ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1562ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Blacklist the BSSID.
1563ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        mWifiConnectivityManager.trackBssid(bssid, false,
1564ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan                WifiConnectivityManager.REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA);
1565ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1566ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID is now blacklisted.
1567ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mWifiConnectivityManager.isBssidDisabled(bssid));
1568ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID gets sent to firmware.
1569ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        verify(mWifiConnectivityHelper).setFirmwareRoamingConfiguration(
1570ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan                mBssidBlacklistCaptor.capture(), mSsidWhitelistCaptor.capture());
1571ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mBssidBlacklistCaptor.getValue().contains(bssid));
1572ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mSsidWhitelistCaptor.getValue().isEmpty());
1573ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1574ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Prepare for a forced connection attempt.
1575ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        mWifiConnectivityManager.prepareForForcedConnection(1);
1576ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1577ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Verify the BSSID blacklist is empty.
1578167b90b5e002698378728a54a417a08c317d29dcRandy Pan        assertFalse(mWifiConnectivityManager.isBssidDisabled(bssid));
1579ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        verify(mWifiConnectivityHelper, times(2)).setFirmwareRoamingConfiguration(
1580ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan                mBssidBlacklistCaptor.capture(), mSsidWhitelistCaptor.capture());
1581ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mBssidBlacklistCaptor.getValue().isEmpty());
1582ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        assertTrue(mSsidWhitelistCaptor.getValue().isEmpty());
1583ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    }
1584ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1585ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    /**
1586ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    /**
1587ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan     *  Verify that BSSID blacklist gets trimmed down to fit firmware capability.
1588ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan     */
1589ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    @Test
1590ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan    public void trimDownBssidBlacklistForFirmware() {
1591ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
1592ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan
1593ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        // Blacklist more than MAX_BSSID_BLACKLIST_SIZE BSSIDs.
1594ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        for (int i = 0; i < MAX_BSSID_BLACKLIST_SIZE + 6; i++) {
1595ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan            StringBuilder bssid = new StringBuilder("55:44:33:22:11:00");
1596ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan            bssid.setCharAt(16, (char) ('0' + i));
1597ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan            mWifiConnectivityManager.trackBssid(bssid.toString(), false,
1598ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan                    WifiConnectivityManager.REASON_CODE_AP_UNABLE_TO_HANDLE_NEW_STA);
1599ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan            // Verify that up to MAX_BSSID_BLACKLIST_SIZE BSSIDs gets sent to firmware.
1600ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan            verify(mWifiConnectivityHelper, times(i + 1)).setFirmwareRoamingConfiguration(
1601ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan                    mBssidBlacklistCaptor.capture(), mSsidWhitelistCaptor.capture());
1602ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan            assertEquals((i + 1) <  MAX_BSSID_BLACKLIST_SIZE ? (i + 1) : MAX_BSSID_BLACKLIST_SIZE,
1603ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan                    mBssidBlacklistCaptor.getValue().size());
1604ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan            assertTrue(mSsidWhitelistCaptor.getValue().isEmpty());
1605ab8c62a5c348702090aceee23de12945cc3fdb0dRandy Pan        }
1606167b90b5e002698378728a54a417a08c317d29dcRandy Pan    }
1607a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1608a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    /**
1609a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * When WifiConnectivityManager is on and Wifi client mode is enabled, framework
1610a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * queries firmware via WifiConnectivityHelper to check if firmware roaming is
1611a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * supported and its capability.
1612a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     *
1613a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Expected behavior: WifiConnectivityManager#setWifiEnabled calls into
1614a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * WifiConnectivityHelper#getFirmwareRoamingInfo
1615a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     */
1616a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    @Test
1617a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    public void verifyGetFirmwareRoamingInfoIsCalledWhenEnableWiFiAndWcmOn() {
1618a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        reset(mWifiConnectivityHelper);
1619a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // WifiConnectivityManager is on by default
1620a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.setWifiEnabled(true);
1621a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        verify(mWifiConnectivityHelper).getFirmwareRoamingInfo();
1622a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    }
1623a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1624a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    /**
1625a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * When WifiConnectivityManager is off,  verify that framework does not
1626a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * query firmware via WifiConnectivityHelper to check if firmware roaming is
1627a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * supported and its capability when enabling Wifi client mode.
1628a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     *
1629a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Expected behavior: WifiConnectivityManager#setWifiEnabled does not call into
1630a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * WifiConnectivityHelper#getFirmwareRoamingInfo
1631a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     */
1632a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    @Test
1633a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    public void verifyGetFirmwareRoamingInfoIsNotCalledWhenEnableWiFiAndWcmOff() {
1634a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        reset(mWifiConnectivityHelper);
1635a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.enable(false);
1636a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.setWifiEnabled(true);
1637a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        verify(mWifiConnectivityHelper, times(0)).getFirmwareRoamingInfo();
1638a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    }
1639a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1640a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    /*
1641a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Firmware supports controlled roaming.
1642a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Connect to a network which doesn't have a config specified BSSID.
1643a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     *
1644a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Expected behavior: WifiConnectivityManager calls
1645a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * WifiStateMachine.startConnectToNetwork() with the
1646a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * expected candidate network ID, and the BSSID value should be
1647a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * 'any' since firmware controls the roaming.
1648a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     */
1649a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    @Test
1650a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    public void useAnyBssidToConnectWhenFirmwareRoamingOnAndConfigHasNoBssidSpecified() {
1651a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Firmware controls roaming
1652a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
1653a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1654a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Set screen to on
1655a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
1656a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1657a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Set WiFi to disconnected state
1658a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1659a54399f6da655dfbe440333ca3682b9199060a27Randy Pan                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
1660a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1661a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        verify(mWifiStateMachine).startConnectToNetwork(
16629686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, WifiStateMachine.SUPPLICANT_BSSID_ANY);
1663a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    }
1664a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1665a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    /*
1666a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Firmware supports controlled roaming.
1667a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Connect to a network which has a config specified BSSID.
1668a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     *
1669a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Expected behavior: WifiConnectivityManager calls
1670a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * WifiStateMachine.startConnectToNetwork() with the
1671a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * expected candidate network ID, and the BSSID value should be
1672b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     * the config specified one.
1673a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     */
1674a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    @Test
1675b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan    public void useConfigSpecifiedBssidToConnectWhenFirmwareRoamingOn() {
1676a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Firmware controls roaming
1677a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
1678a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1679a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Set up the candidate configuration such that it has a BSSID specified.
1680a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        WifiConfiguration candidate = generateWifiConfig(
1681a54399f6da655dfbe440333ca3682b9199060a27Randy Pan                0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null);
1682a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        candidate.BSSID = CANDIDATE_BSSID; // config specified
1683a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        ScanResult candidateScanResult = new ScanResult();
1684a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        candidateScanResult.SSID = CANDIDATE_SSID;
1685a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        candidateScanResult.BSSID = CANDIDATE_BSSID;
1686a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult);
1687a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1688a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(),
1689b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                anyBoolean(), anyBoolean())).thenReturn(candidate);
1690a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1691a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Set screen to on
1692a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
1693a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1694a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Set WiFi to disconnected state
1695a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1696a54399f6da655dfbe440333ca3682b9199060a27Randy Pan                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
1697a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
16989686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti        verify(mWifiStateMachine).startConnectToNetwork(
16999686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
1700a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    }
1701a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1702a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    /*
1703a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Firmware does not support controlled roaming.
1704a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Connect to a network which doesn't have a config specified BSSID.
1705a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     *
1706a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Expected behavior: WifiConnectivityManager calls
1707a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * WifiStateMachine.startConnectToNetwork() with the expected candidate network ID,
1708a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * and the BSSID value should be the candidate scan result specified.
1709a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     */
1710a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    @Test
1711a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    public void useScanResultBssidToConnectWhenFirmwareRoamingOffAndConfigHasNoBssidSpecified() {
1712a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Set screen to on
1713a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
1714a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1715a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Set WiFi to disconnected state
1716a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1717a54399f6da655dfbe440333ca3682b9199060a27Randy Pan                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
1718a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
17199686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti        verify(mWifiStateMachine).startConnectToNetwork(
17209686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
1721a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    }
1722a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1723a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    /*
1724a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Firmware does not support controlled roaming.
1725a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Connect to a network which has a config specified BSSID.
1726a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     *
1727a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Expected behavior: WifiConnectivityManager calls
1728a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * WifiStateMachine.startConnectToNetwork() with the expected candidate network ID,
1729a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * and the BSSID value should be the config specified one.
1730a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     */
1731a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    @Test
1732a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    public void useConfigSpecifiedBssidToConnectionWhenFirmwareRoamingOff() {
1733a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Set up the candidate configuration such that it has a BSSID specified.
1734a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        WifiConfiguration candidate = generateWifiConfig(
1735a54399f6da655dfbe440333ca3682b9199060a27Randy Pan                0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null);
1736a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        candidate.BSSID = CANDIDATE_BSSID; // config specified
1737a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        ScanResult candidateScanResult = new ScanResult();
1738a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        candidateScanResult.SSID = CANDIDATE_SSID;
1739a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        candidateScanResult.BSSID = CANDIDATE_BSSID;
1740a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult);
1741a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1742a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(),
1743b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                anyBoolean(), anyBoolean())).thenReturn(candidate);
1744a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1745a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Set screen to on
1746a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
1747a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1748a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Set WiFi to disconnected state
1749a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1750a54399f6da655dfbe440333ca3682b9199060a27Randy Pan                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
1751a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
17529686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti        verify(mWifiStateMachine).startConnectToNetwork(
17539686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
1754a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    }
1755a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1756a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    /**
1757a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Firmware does not support controlled roaming.
1758a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * WiFi in connected state, framework triggers roaming.
1759a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     *
1760a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Expected behavior: WifiConnectivityManager invokes
1761a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * WifiStateMachine.startRoamToNetwork().
1762a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     */
1763a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    @Test
1764a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    public void frameworkInitiatedRoaming() {
1765a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Mock the currently connected network which has the same networkID and
1766a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // SSID as the one to be selected.
1767a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        WifiConfiguration currentNetwork = generateWifiConfig(
1768a54399f6da655dfbe440333ca3682b9199060a27Randy Pan                0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null);
1769a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(currentNetwork);
1770a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1771a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Set WiFi to connected state
1772a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1773a54399f6da655dfbe440333ca3682b9199060a27Randy Pan                WifiConnectivityManager.WIFI_STATE_CONNECTED);
1774a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1775a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Set screen to on
1776a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
1777a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1778a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        verify(mWifiStateMachine).startRoamToNetwork(eq(CANDIDATE_NETWORK_ID),
1779a54399f6da655dfbe440333ca3682b9199060a27Randy Pan                mCandidateScanResultCaptor.capture());
1780a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        assertEquals(mCandidateScanResultCaptor.getValue().BSSID, CANDIDATE_BSSID);
1781a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    }
1782a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1783a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    /**
1784a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Firmware supports controlled roaming.
1785a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * WiFi in connected state, framework does not trigger roaming
1786a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * as it's handed off to the firmware.
1787a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     *
1788a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * Expected behavior: WifiConnectivityManager doesn't invoke
1789a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     * WifiStateMachine.startRoamToNetwork().
1790a54399f6da655dfbe440333ca3682b9199060a27Randy Pan     */
1791a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    @Test
1792a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    public void noFrameworkRoamingIfConnectedAndFirmwareRoamingSupported() {
1793a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Mock the currently connected network which has the same networkID and
1794a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // SSID as the one to be selected.
1795a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        WifiConfiguration currentNetwork = generateWifiConfig(
1796a54399f6da655dfbe440333ca3682b9199060a27Randy Pan                0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null);
1797a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(currentNetwork);
1798a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1799a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Firmware controls roaming
1800a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
1801a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1802a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Set WiFi to connected state
1803a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1804a54399f6da655dfbe440333ca3682b9199060a27Randy Pan                WifiConnectivityManager.WIFI_STATE_CONNECTED);
1805a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1806a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        // Set screen to on
1807a54399f6da655dfbe440333ca3682b9199060a27Randy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
1808a54399f6da655dfbe440333ca3682b9199060a27Randy Pan
1809b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        verify(mWifiStateMachine, times(0)).startRoamToNetwork(anyInt(), anyObject());
1810b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan    }
1811b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan
1812b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan    /*
1813b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     * Wifi in disconnected state. Drop the connection attempt if the recommended
1814b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     * network configuration has a BSSID specified but the scan result BSSID doesn't
1815b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     * match it.
1816b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     *
1817b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     * Expected behavior: WifiConnectivityManager doesn't invoke
1818b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     * WifiStateMachine.startConnectToNetwork().
1819b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     */
1820b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan    @Test
1821b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan    public void dropConnectAttemptIfConfigSpecifiedBssidDifferentFromScanResultBssid() {
1822b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        // Set up the candidate configuration such that it has a BSSID specified.
1823b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        WifiConfiguration candidate = generateWifiConfig(
1824b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null);
1825b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        candidate.BSSID = CANDIDATE_BSSID; // config specified
1826b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        ScanResult candidateScanResult = new ScanResult();
1827b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        candidateScanResult.SSID = CANDIDATE_SSID;
1828b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        // Set up the scan result BSSID to be different from the config specified one.
1829b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        candidateScanResult.BSSID = INVALID_SCAN_RESULT_BSSID;
1830b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult);
1831b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan
1832b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(),
1833b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                anyBoolean(), anyBoolean())).thenReturn(candidate);
1834b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan
1835b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        // Set screen to on
1836b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
1837b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan
1838b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        // Set WiFi to disconnected state
1839b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1840b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
1841b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan
1842b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        verify(mWifiStateMachine, times(0)).startConnectToNetwork(
18439686c96d8d0c0bc21ca069e244e2570c169724e1Lorenzo Colitti                CANDIDATE_NETWORK_ID, Process.WIFI_UID, CANDIDATE_BSSID);
1844b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan    }
1845b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan
1846b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan    /*
1847b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     * Wifi in connected state. Drop the roaming attempt if the recommended
1848b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     * network configuration has a BSSID specified but the scan result BSSID doesn't
1849b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     * match it.
1850b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     *
1851b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     * Expected behavior: WifiConnectivityManager doesn't invoke
1852b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     * WifiStateMachine.startRoamToNetwork().
1853b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan     */
1854b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan    @Test
1855b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan    public void dropRoamingAttemptIfConfigSpecifiedBssidDifferentFromScanResultBssid() {
1856b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        // Mock the currently connected network which has the same networkID and
1857b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        // SSID as the one to be selected.
1858b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        WifiConfiguration currentNetwork = generateWifiConfig(
1859b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null);
1860b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(currentNetwork);
1861b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan
1862b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        // Set up the candidate configuration such that it has a BSSID specified.
1863b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        WifiConfiguration candidate = generateWifiConfig(
1864b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null);
1865b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        candidate.BSSID = CANDIDATE_BSSID; // config specified
1866b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        ScanResult candidateScanResult = new ScanResult();
1867b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        candidateScanResult.SSID = CANDIDATE_SSID;
1868b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        // Set up the scan result BSSID to be different from the config specified one.
1869b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        candidateScanResult.BSSID = INVALID_SCAN_RESULT_BSSID;
1870b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult);
1871b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan
1872b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        when(mWifiNS.selectNetwork(anyObject(), anyObject(), anyObject(), anyBoolean(),
1873b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                anyBoolean(), anyBoolean())).thenReturn(candidate);
1874b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan
1875b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        // Set WiFi to connected state
1876b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        mWifiConnectivityManager.handleConnectionStateChanged(
1877b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan                WifiConnectivityManager.WIFI_STATE_CONNECTED);
1878b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan
1879b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        // Set screen to on
1880b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        mWifiConnectivityManager.handleScreenStateChanged(true);
1881b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan
1882b6686e9d42895f9c2b9f4278cd892149bee04e3aRandy Pan        verify(mWifiStateMachine, times(0)).startRoamToNetwork(anyInt(), anyObject());
1883a54399f6da655dfbe440333ca3682b9199060a27Randy Pan    }
188417c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan
188517c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan    /**
188617c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan     *  Dump local log buffer.
188717c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan     *
188817c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan     * Expected behavior: Logs dumped from WifiConnectivityManager.dump()
188917c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan     * contain the message we put in mLocalLog.
189017c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan     */
189117c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan    @Test
189217c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan    public void dumpLocalLog() {
189317c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan        final String localLogMessage = "This is a message from the test";
189417c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan        mLocalLog.log(localLogMessage);
189517c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan
189617c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan        StringWriter sw = new StringWriter();
189717c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan        PrintWriter pw = new PrintWriter(sw);
189817c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan        mWifiConnectivityManager.dump(new FileDescriptor(), pw, new String[]{});
189917c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan        assertTrue(sw.toString().contains(localLogMessage));
190017c2a7b30e5680b11fc0073ce322ee7bc14ef2c5Randy Pan    }
19013f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen
19023f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    /**
19033f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     *  Dump ONA controller.
19043f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     *
1905ce76a17ac5010e0b7ff5dcf6d8c9db8b48280f9cStephen Chen     * Expected behavior: {@link OpenNetworkNotifier#dump(FileDescriptor, PrintWriter,
19063f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     * String[])} is invoked.
19073f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen     */
19083f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    @Test
19093f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    public void dumpNotificationController() {
19103f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        StringWriter sw = new StringWriter();
19113f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        PrintWriter pw = new PrintWriter(sw);
19123f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen        mWifiConnectivityManager.dump(new FileDescriptor(), pw, new String[]{});
19133f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen
1914ce76a17ac5010e0b7ff5dcf6d8c9db8b48280f9cStephen Chen        verify(mOpenNetworkNotifier).dump(any(), any(), any());
19153f8483262cf59572d0c0b3c42e72d8ce65a096ffStephen Chen    }
1916652381b37461a4aa793327365e144bb4335cbd27Roshan Pius
1917652381b37461a4aa793327365e144bb4335cbd27Roshan Pius    /**
191886ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * Create scan data with different radio chain infos:
191986ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * First scan result has null radio chain info (No DBS support).
192086ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * Second scan result has empty radio chain info (No DBS support).
192186ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * Third scan result has 1 radio chain info (DBS scan).
192286ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * Fourth scan result has 2 radio chain info (non-DBS scan).
192386ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     */
192486ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius    private ScanData createScanDataWithDifferentRadioChainInfos() {
192586ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        // Create 4 scan results.
192686ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        ScanData[] scanDatas =
192786ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                ScanTestUtil.createScanDatas(new int[][]{{5150, 5175, 2412, 2400}}, new int[]{0});
192886ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        // WCM barfs if the scan result does not have an IE.
192986ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        scanDatas[0].getResults()[0].informationElements = new InformationElement[0];
193086ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        scanDatas[0].getResults()[1].informationElements = new InformationElement[0];
193186ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        scanDatas[0].getResults()[2].informationElements = new InformationElement[0];
193286ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        scanDatas[0].getResults()[3].informationElements = new InformationElement[0];
193386ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        scanDatas[0].getResults()[0].radioChainInfos = null;
193486ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        scanDatas[0].getResults()[1].radioChainInfos = new ScanResult.RadioChainInfo[0];
193586ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        scanDatas[0].getResults()[2].radioChainInfos = new ScanResult.RadioChainInfo[1];
193686ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        scanDatas[0].getResults()[3].radioChainInfos = new ScanResult.RadioChainInfo[2];
193786ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius
193886ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        return scanDatas[0];
193986ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius    }
194086ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius
194186ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius    /**
194286ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * If |config_wifi_framework_use_single_radio_chain_scan_results_network_selection| flag is
194386ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * false, WifiConnectivityManager should filter scan results which contain scans from a single
194486ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * radio chain (i.e DBS scan).
1945652381b37461a4aa793327365e144bb4335cbd27Roshan Pius     * Note:
1946652381b37461a4aa793327365e144bb4335cbd27Roshan Pius     * a) ScanResult with no radio chain indicates a lack of DBS support on the device.
1947652381b37461a4aa793327365e144bb4335cbd27Roshan Pius     * b) ScanResult with 2 radio chain info indicates a scan done using both the radio chains
1948652381b37461a4aa793327365e144bb4335cbd27Roshan Pius     * on a DBS supported device.
1949652381b37461a4aa793327365e144bb4335cbd27Roshan Pius     *
1950652381b37461a4aa793327365e144bb4335cbd27Roshan Pius     * Expected behavior: WifiConnectivityManager invokes
1951652381b37461a4aa793327365e144bb4335cbd27Roshan Pius     * {@link WifiNetworkSelector#selectNetwork(List, HashSet, WifiInfo, boolean, boolean, boolean)}
1952652381b37461a4aa793327365e144bb4335cbd27Roshan Pius     * after filtering out the scan results obtained via DBS scan.
1953652381b37461a4aa793327365e144bb4335cbd27Roshan Pius     */
1954652381b37461a4aa793327365e144bb4335cbd27Roshan Pius    @Test
195586ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius    public void filterScanResultsWithOneRadioChainInfoForNetworkSelectionIfConfigDisabled() {
195686ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        when(mResource.getBoolean(
195786ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                R.bool.config_wifi_framework_use_single_radio_chain_scan_results_network_selection))
195886ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                .thenReturn(false);
1959652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        when(mWifiNS.selectNetwork(any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()))
1960652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                .thenReturn(null);
196186ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        mWifiConnectivityManager = createConnectivityManager();
1962652381b37461a4aa793327365e144bb4335cbd27Roshan Pius
196386ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        mScanData = createScanDataWithDifferentRadioChainInfos();
1964652381b37461a4aa793327365e144bb4335cbd27Roshan Pius
1965652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        // Capture scan details which were sent to network selector.
1966652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        final List<ScanDetail> capturedScanDetails = new ArrayList<>();
1967652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        doAnswer(new AnswerWithArguments() {
1968652381b37461a4aa793327365e144bb4335cbd27Roshan Pius            public WifiConfiguration answer(
1969652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                    List<ScanDetail> scanDetails, HashSet<String> bssidBlacklist, WifiInfo wifiInfo,
1970652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                    boolean connected, boolean disconnected, boolean untrustedNetworkAllowed)
1971652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                    throws Exception {
1972652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                capturedScanDetails.addAll(scanDetails);
1973652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                return null;
1974652381b37461a4aa793327365e144bb4335cbd27Roshan Pius            }}).when(mWifiNS).selectNetwork(
1975652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                    any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean());
1976652381b37461a4aa793327365e144bb4335cbd27Roshan Pius
1977652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        // Set WiFi to disconnected state with screen on which triggers a scan immediately.
197886ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        mWifiConnectivityManager.setWifiEnabled(true);
1979652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        mWifiConnectivityManager.handleScreenStateChanged(true);
1980652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        mWifiConnectivityManager.handleConnectionStateChanged(
1981652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
1982652381b37461a4aa793327365e144bb4335cbd27Roshan Pius
1983652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        // We should have filtered out the 3rd scan result.
1984652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        assertEquals(3, capturedScanDetails.size());
1985652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        List<ScanResult> capturedScanResults =
1986652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                capturedScanDetails.stream().map(ScanDetail::getScanResult)
1987652381b37461a4aa793327365e144bb4335cbd27Roshan Pius                        .collect(Collectors.toList());
1988652381b37461a4aa793327365e144bb4335cbd27Roshan Pius
1989652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        assertEquals(3, capturedScanResults.size());
1990652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        assertTrue(capturedScanResults.contains(mScanData.getResults()[0]));
1991652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        assertTrue(capturedScanResults.contains(mScanData.getResults()[1]));
1992652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        assertFalse(capturedScanResults.contains(mScanData.getResults()[2]));
1993652381b37461a4aa793327365e144bb4335cbd27Roshan Pius        assertTrue(capturedScanResults.contains(mScanData.getResults()[3]));
1994652381b37461a4aa793327365e144bb4335cbd27Roshan Pius    }
1995652381b37461a4aa793327365e144bb4335cbd27Roshan Pius
199686ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius    /**
199786ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * If |config_wifi_framework_use_single_radio_chain_scan_results_network_selection| flag is
199886ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * true, WifiConnectivityManager should not filter scan results which contain scans from a
199986ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * single radio chain (i.e DBS scan).
200086ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * Note:
200186ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * a) ScanResult with no radio chain indicates a lack of DBS support on the device.
200286ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * b) ScanResult with 2 radio chain info indicates a scan done using both the radio chains
200386ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * on a DBS supported device.
200486ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     *
200586ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * Expected behavior: WifiConnectivityManager invokes
200686ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * {@link WifiNetworkSelector#selectNetwork(List, HashSet, WifiInfo, boolean, boolean, boolean)}
200786ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     * after filtering out the scan results obtained via DBS scan.
200886ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius     */
200986ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius    @Test
201086ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius    public void dontFilterScanResultsWithOneRadioChainInfoForNetworkSelectionIfConfigEnabled() {
201186ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        when(mResource.getBoolean(
201286ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                R.bool.config_wifi_framework_use_single_radio_chain_scan_results_network_selection))
201386ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                .thenReturn(true);
201486ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        when(mWifiNS.selectNetwork(any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean()))
201586ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                .thenReturn(null);
201686ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        mWifiConnectivityManager = createConnectivityManager();
201786ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius
201886ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        mScanData = createScanDataWithDifferentRadioChainInfos();
201986ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius
202086ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        // Capture scan details which were sent to network selector.
202186ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        final List<ScanDetail> capturedScanDetails = new ArrayList<>();
202286ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        doAnswer(new AnswerWithArguments() {
202386ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius            public WifiConfiguration answer(
202486ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                    List<ScanDetail> scanDetails, HashSet<String> bssidBlacklist, WifiInfo wifiInfo,
202586ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                    boolean connected, boolean disconnected, boolean untrustedNetworkAllowed)
202686ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                    throws Exception {
202786ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                capturedScanDetails.addAll(scanDetails);
202886ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                return null;
202986ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius            }}).when(mWifiNS).selectNetwork(
203086ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                any(), any(), any(), anyBoolean(), anyBoolean(), anyBoolean());
203186ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius
203286ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        // Set WiFi to disconnected state with screen on which triggers a scan immediately.
203386ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        mWifiConnectivityManager.setWifiEnabled(true);
203486ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        mWifiConnectivityManager.handleScreenStateChanged(true);
203586ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        mWifiConnectivityManager.handleConnectionStateChanged(
203686ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                WifiConnectivityManager.WIFI_STATE_DISCONNECTED);
203786ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius
203886ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        // We should not filter any of the scan results.
203986ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        assertEquals(4, capturedScanDetails.size());
204086ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        List<ScanResult> capturedScanResults =
204186ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                capturedScanDetails.stream().map(ScanDetail::getScanResult)
204286ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius                        .collect(Collectors.toList());
204386ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius
204486ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        assertEquals(4, capturedScanResults.size());
204586ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        assertTrue(capturedScanResults.contains(mScanData.getResults()[0]));
204686ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        assertTrue(capturedScanResults.contains(mScanData.getResults()[1]));
204786ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        assertTrue(capturedScanResults.contains(mScanData.getResults()[2]));
204886ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius        assertTrue(capturedScanResults.contains(mScanData.getResults()[3]));
204986ea918f785f665e0fa41ddd5d6803d73ad72650Roshan Pius    }
2050095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius
2051095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius    /**
2052095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius     * Disabling the network temporarily due to lack of internet is a special reason for which we
2053095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius     * don't want WCM to trigger a disconnect (by removing the network from supplicant).
2054095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius     */
2055095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius    @Test
2056095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius    public void dontDisconnectIfNetworkTemporarilyDisabledDueToNoInternet() {
2057095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius        assertNotNull(mSavedNetworkUpdateListenerCaptor.getValue());
2058095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius
2059095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius        mSavedNetworkUpdateListenerCaptor.getValue()
2060095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius                .onSavedNetworkPermanentlyDisabled(0, DISABLED_AUTHENTICATION_FAILURE);
2061095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius        verify(mWifiConnectivityHelper).removeNetworkIfCurrent(0);
2062095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius
2063095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius        mSavedNetworkUpdateListenerCaptor.getValue()
2064095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius                .onSavedNetworkPermanentlyDisabled(0, DISABLED_NO_INTERNET_TEMPORARY);
2065095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius        // Don't remove network.
2066095121ada1c9ea6034e86606395de20cddcad9baRoshan Pius    }
206784d962ec8f487f824214744498bba505a6db0c59Randy Pan}
2068