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 1984d962ec8f487f824214744498bba505a6db0c59Randy Panimport static com.android.server.wifi.WifiConfigurationTestUtil.generateWifiConfig; 20cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Panimport static com.android.server.wifi.WifiStateMachine.WIFI_WORK_SOURCE; 2184d962ec8f487f824214744498bba505a6db0c59Randy Pan 22fb196453c07daad5e525520cecad84cec5d89fb7Roshan Piusimport static org.junit.Assert.*; 2384d962ec8f487f824214744498bba505a6db0c59Randy Panimport static org.mockito.Mockito.*; 2484d962ec8f487f824214744498bba505a6db0c59Randy Pan 2584d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.content.Context; 2684d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.content.res.Resources; 2784d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.ScanResult; 28fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Piusimport android.net.wifi.ScanResult.InformationElement; 2950abba06efa7834b5309df561375e4a2e2df630dRandy Panimport android.net.wifi.SupplicantState; 3084d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiConfiguration; 3184d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiInfo; 32fb196453c07daad5e525520cecad84cec5d89fb7Roshan Piusimport android.net.wifi.WifiManager; 3384d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiScanner; 34fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Piusimport android.net.wifi.WifiScanner.PnoScanListener; 35fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Piusimport android.net.wifi.WifiScanner.PnoSettings; 368cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Panimport android.net.wifi.WifiScanner.ScanData; 3784d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiScanner.ScanListener; 3884d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.net.wifi.WifiScanner.ScanSettings; 391d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Piusimport android.net.wifi.WifiSsid; 40ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Piusimport android.os.SystemClock; 41e78a18cf874b4d9bb5db2ef7804b8ac576e56489Mitchell Willsimport android.os.WorkSource; 4284d962ec8f487f824214744498bba505a6db0c59Randy Panimport android.test.suitebuilder.annotation.SmallTest; 4384d962ec8f487f824214744498bba505a6db0c59Randy Pan 4484d962ec8f487f824214744498bba505a6db0c59Randy Panimport com.android.internal.R; 4584d962ec8f487f824214744498bba505a6db0c59Randy Panimport com.android.server.wifi.MockAnswerUtil.AnswerWithArguments; 4684d962ec8f487f824214744498bba505a6db0c59Randy Pan 4784d962ec8f487f824214744498bba505a6db0c59Randy Panimport org.junit.After; 4884d962ec8f487f824214744498bba505a6db0c59Randy Panimport org.junit.Before; 4984d962ec8f487f824214744498bba505a6db0c59Randy Panimport org.junit.Test; 50cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Panimport org.mockito.ArgumentCaptor; 5184d962ec8f487f824214744498bba505a6db0c59Randy Pan 52fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Piusimport java.nio.charset.StandardCharsets; 53fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Piusimport java.util.ArrayList; 54fb196453c07daad5e525520cecad84cec5d89fb7Roshan Piusimport java.util.HashSet; 5584d962ec8f487f824214744498bba505a6db0c59Randy Panimport java.util.concurrent.atomic.AtomicInteger; 5684d962ec8f487f824214744498bba505a6db0c59Randy Pan 5784d962ec8f487f824214744498bba505a6db0c59Randy Pan/** 5884d962ec8f487f824214744498bba505a6db0c59Randy Pan * Unit tests for {@link com.android.server.wifi.WifiConnectivityManager}. 5984d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 6084d962ec8f487f824214744498bba505a6db0c59Randy Pan@SmallTest 6184d962ec8f487f824214744498bba505a6db0c59Randy Panpublic class WifiConnectivityManagerTest { 6284d962ec8f487f824214744498bba505a6db0c59Randy Pan 6384d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 6484d962ec8f487f824214744498bba505a6db0c59Randy Pan * Called before each test 6584d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 6684d962ec8f487f824214744498bba505a6db0c59Randy Pan @Before 6784d962ec8f487f824214744498bba505a6db0c59Randy Pan public void setUp() throws Exception { 6809abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mWifiInjector = mockWifiInjector(); 6909abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mResource = mockResource(); 701d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius mAlarmManager = new MockAlarmManager(); 7109abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mContext = mockContext(); 7209abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mWifiStateMachine = mockWifiStateMachine(); 7309abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mWifiConfigManager = mockWifiConfigManager(); 74fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius mWifiInfo = getWifiInfo(); 758cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan mScanData = mockScanData(); 7609abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mWifiScanner = mockWifiScanner(); 7709abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mWifiQNS = mockWifiQualifiedNetworkSelector(); 7884d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiConnectivityManager = new WifiConnectivityManager(mContext, mWifiStateMachine, 79c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan mWifiScanner, mWifiConfigManager, mWifiInfo, mWifiQNS, mWifiInjector, 80c4d044acc589188f25b8dcd962db52e1fc08fe8dRandy Pan mLooper.getLooper(), true); 8184d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiConnectivityManager.setWifiEnabled(true); 82ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius when(mClock.elapsedRealtime()).thenReturn(SystemClock.elapsedRealtime()); 8384d962ec8f487f824214744498bba505a6db0c59Randy Pan } 8484d962ec8f487f824214744498bba505a6db0c59Randy Pan 8584d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 8684d962ec8f487f824214744498bba505a6db0c59Randy Pan * Called after each test 8784d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 8884d962ec8f487f824214744498bba505a6db0c59Randy Pan @After 8984d962ec8f487f824214744498bba505a6db0c59Randy Pan public void cleanup() { 9084d962ec8f487f824214744498bba505a6db0c59Randy Pan validateMockitoUsage(); 9184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 9284d962ec8f487f824214744498bba505a6db0c59Randy Pan 9384d962ec8f487f824214744498bba505a6db0c59Randy Pan private Resources mResource; 9484d962ec8f487f824214744498bba505a6db0c59Randy Pan private Context mContext; 951d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius private MockAlarmManager mAlarmManager; 96c8a21e495dfaa5c44e87fda330621a1ed6c8aaceRandy Pan private MockLooper mLooper = new MockLooper(); 9784d962ec8f487f824214744498bba505a6db0c59Randy Pan private WifiConnectivityManager mWifiConnectivityManager; 9884d962ec8f487f824214744498bba505a6db0c59Randy Pan private WifiQualifiedNetworkSelector mWifiQNS; 9984d962ec8f487f824214744498bba505a6db0c59Randy Pan private WifiStateMachine mWifiStateMachine; 10084d962ec8f487f824214744498bba505a6db0c59Randy Pan private WifiScanner mWifiScanner; 1018cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan private ScanData mScanData; 10284d962ec8f487f824214744498bba505a6db0c59Randy Pan private WifiConfigManager mWifiConfigManager; 10384d962ec8f487f824214744498bba505a6db0c59Randy Pan private WifiInfo mWifiInfo; 104fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius private Clock mClock = mock(Clock.class); 10509abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne private WifiLastResortWatchdog mWifiLastResortWatchdog; 1061d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius private WifiMetrics mWifiMetrics; 10709abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne private WifiInjector mWifiInjector; 10884d962ec8f487f824214744498bba505a6db0c59Randy Pan 10984d962ec8f487f824214744498bba505a6db0c59Randy Pan private static final int CANDIDATE_NETWORK_ID = 0; 11084d962ec8f487f824214744498bba505a6db0c59Randy Pan private static final String CANDIDATE_SSID = "\"AnSsid\""; 11184d962ec8f487f824214744498bba505a6db0c59Randy Pan private static final String CANDIDATE_BSSID = "6c:f3:7f:ae:8c:f3"; 11284d962ec8f487f824214744498bba505a6db0c59Randy Pan private static final String TAG = "WifiConnectivityManager Unit Test"; 113b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan private static final long CURRENT_SYSTEM_TIME_MS = 1000; 11484d962ec8f487f824214744498bba505a6db0c59Randy Pan 11509abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne Resources mockResource() { 11684d962ec8f487f824214744498bba505a6db0c59Randy Pan Resources resource = mock(Resources.class); 11784d962ec8f487f824214744498bba505a6db0c59Randy Pan 11884d962ec8f487f824214744498bba505a6db0c59Randy Pan when(resource.getInteger(R.integer.config_wifi_framework_SECURITY_AWARD)).thenReturn(80); 11984d962ec8f487f824214744498bba505a6db0c59Randy Pan when(resource.getInteger(R.integer.config_wifi_framework_SAME_BSSID_AWARD)).thenReturn(24); 12084d962ec8f487f824214744498bba505a6db0c59Randy Pan 12184d962ec8f487f824214744498bba505a6db0c59Randy Pan return resource; 12284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 12384d962ec8f487f824214744498bba505a6db0c59Randy Pan 12409abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne Context mockContext() { 12584d962ec8f487f824214744498bba505a6db0c59Randy Pan Context context = mock(Context.class); 12684d962ec8f487f824214744498bba505a6db0c59Randy Pan 12784d962ec8f487f824214744498bba505a6db0c59Randy Pan when(context.getResources()).thenReturn(mResource); 12884d962ec8f487f824214744498bba505a6db0c59Randy Pan when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn( 1291d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius mAlarmManager.getAlarmManager()); 13084d962ec8f487f824214744498bba505a6db0c59Randy Pan 13184d962ec8f487f824214744498bba505a6db0c59Randy Pan return context; 13284d962ec8f487f824214744498bba505a6db0c59Randy Pan } 13384d962ec8f487f824214744498bba505a6db0c59Randy Pan 1348cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan ScanData mockScanData() { 1358cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan ScanData scanData = mock(ScanData.class); 1368cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan 1378cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan when(scanData.isAllChannelsScanned()).thenReturn(true); 1388cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan 1398cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan return scanData; 1408cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan } 1418cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan 14209abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne WifiScanner mockWifiScanner() { 14384d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiScanner scanner = mock(WifiScanner.class); 144cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan ArgumentCaptor<ScanListener> allSingleScanListenerCaptor = 145cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan ArgumentCaptor.forClass(ScanListener.class); 146cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan 147cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan doNothing().when(scanner).registerScanListener(allSingleScanListenerCaptor.capture()); 14884d962ec8f487f824214744498bba505a6db0c59Randy Pan 1498cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan ScanData[] scanDatas = new ScanData[1]; 1508cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan scanDatas[0] = mScanData; 15184d962ec8f487f824214744498bba505a6db0c59Randy Pan 15284d962ec8f487f824214744498bba505a6db0c59Randy Pan // do a synchronous answer for the ScanListener callbacks 15384d962ec8f487f824214744498bba505a6db0c59Randy Pan doAnswer(new AnswerWithArguments() { 154e78a18cf874b4d9bb5db2ef7804b8ac576e56489Mitchell Wills public void answer(ScanSettings settings, ScanListener listener, 155e78a18cf874b4d9bb5db2ef7804b8ac576e56489Mitchell Wills WorkSource workSource) throws Exception { 156fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius listener.onResults(scanDatas); 157e78a18cf874b4d9bb5db2ef7804b8ac576e56489Mitchell Wills }}).when(scanner).startBackgroundScan(anyObject(), anyObject(), anyObject()); 15884d962ec8f487f824214744498bba505a6db0c59Randy Pan 15984d962ec8f487f824214744498bba505a6db0c59Randy Pan doAnswer(new AnswerWithArguments() { 160e78a18cf874b4d9bb5db2ef7804b8ac576e56489Mitchell Wills public void answer(ScanSettings settings, ScanListener listener, 161e78a18cf874b4d9bb5db2ef7804b8ac576e56489Mitchell Wills WorkSource workSource) throws Exception { 162fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius listener.onResults(scanDatas); 163cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan allSingleScanListenerCaptor.getValue().onResults(scanDatas); 164e78a18cf874b4d9bb5db2ef7804b8ac576e56489Mitchell Wills }}).when(scanner).startScan(anyObject(), anyObject(), anyObject()); 16584d962ec8f487f824214744498bba505a6db0c59Randy Pan 166fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // This unfortunately needs to be a somewhat valid scan result, otherwise 167fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // |ScanDetailUtil.toScanDetail| raises exceptions. 168fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius final ScanResult[] scanResults = new ScanResult[1]; 169fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius scanResults[0] = new ScanResult(WifiSsid.createFromAsciiEncoded(CANDIDATE_SSID), 170fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius CANDIDATE_SSID, CANDIDATE_BSSID, 1245, 0, "some caps", 171fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius -78, 2450, 1025, 22, 33, 20, 0, 0, true); 172fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius scanResults[0].informationElements = new InformationElement[1]; 173fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius scanResults[0].informationElements[0] = new InformationElement(); 174fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius scanResults[0].informationElements[0].id = InformationElement.EID_SSID; 175fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius scanResults[0].informationElements[0].bytes = 176fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius CANDIDATE_SSID.getBytes(StandardCharsets.UTF_8); 177fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 178fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius doAnswer(new AnswerWithArguments() { 179fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius public void answer(ScanSettings settings, PnoSettings pnoSettings, 180fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius PnoScanListener listener) throws Exception { 181fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius listener.onPnoNetworkFound(scanResults); 182fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius }}).when(scanner).startDisconnectedPnoScan(anyObject(), anyObject(), anyObject()); 183fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 184fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius doAnswer(new AnswerWithArguments() { 185fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius public void answer(ScanSettings settings, PnoSettings pnoSettings, 186fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius PnoScanListener listener) throws Exception { 187fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius listener.onPnoNetworkFound(scanResults); 188fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius }}).when(scanner).startConnectedPnoScan(anyObject(), anyObject(), anyObject()); 189fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 19084d962ec8f487f824214744498bba505a6db0c59Randy Pan return scanner; 19184d962ec8f487f824214744498bba505a6db0c59Randy Pan } 19284d962ec8f487f824214744498bba505a6db0c59Randy Pan 19309abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne WifiStateMachine mockWifiStateMachine() { 19484d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiStateMachine stateMachine = mock(WifiStateMachine.class); 19584d962ec8f487f824214744498bba505a6db0c59Randy Pan 19684d962ec8f487f824214744498bba505a6db0c59Randy Pan when(stateMachine.getFrequencyBand()).thenReturn(1); 19784d962ec8f487f824214744498bba505a6db0c59Randy Pan when(stateMachine.isLinkDebouncing()).thenReturn(false); 19884d962ec8f487f824214744498bba505a6db0c59Randy Pan when(stateMachine.isConnected()).thenReturn(false); 19984d962ec8f487f824214744498bba505a6db0c59Randy Pan when(stateMachine.isDisconnected()).thenReturn(true); 20084d962ec8f487f824214744498bba505a6db0c59Randy Pan when(stateMachine.isSupplicantTransientState()).thenReturn(false); 20184d962ec8f487f824214744498bba505a6db0c59Randy Pan 20284d962ec8f487f824214744498bba505a6db0c59Randy Pan return stateMachine; 20384d962ec8f487f824214744498bba505a6db0c59Randy Pan } 20484d962ec8f487f824214744498bba505a6db0c59Randy Pan 20509abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne WifiQualifiedNetworkSelector mockWifiQualifiedNetworkSelector() { 20684d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiQualifiedNetworkSelector qns = mock(WifiQualifiedNetworkSelector.class); 20784d962ec8f487f824214744498bba505a6db0c59Randy Pan 20884d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiConfiguration candidate = generateWifiConfig( 20984d962ec8f487f824214744498bba505a6db0c59Randy Pan 0, CANDIDATE_NETWORK_ID, CANDIDATE_SSID, false, true, null, null); 21084d962ec8f487f824214744498bba505a6db0c59Randy Pan candidate.BSSID = CANDIDATE_BSSID; 21184d962ec8f487f824214744498bba505a6db0c59Randy Pan ScanResult candidateScanResult = new ScanResult(); 21284d962ec8f487f824214744498bba505a6db0c59Randy Pan candidateScanResult.SSID = CANDIDATE_SSID; 21384d962ec8f487f824214744498bba505a6db0c59Randy Pan candidateScanResult.BSSID = CANDIDATE_BSSID; 21484d962ec8f487f824214744498bba505a6db0c59Randy Pan candidate.getNetworkSelectionStatus().setCandidate(candidateScanResult); 21584d962ec8f487f824214744498bba505a6db0c59Randy Pan 21684d962ec8f487f824214744498bba505a6db0c59Randy Pan when(qns.selectQualifiedNetwork(anyBoolean(), anyBoolean(), anyObject(), 21784d962ec8f487f824214744498bba505a6db0c59Randy Pan anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean())).thenReturn(candidate); 21884d962ec8f487f824214744498bba505a6db0c59Randy Pan return qns; 21984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 22084d962ec8f487f824214744498bba505a6db0c59Randy Pan 221fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius WifiInfo getWifiInfo() { 222fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius WifiInfo wifiInfo = new WifiInfo(); 22384d962ec8f487f824214744498bba505a6db0c59Randy Pan 224fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius wifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID); 225fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius wifiInfo.setBSSID(null); 226fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius wifiInfo.setSupplicantState(SupplicantState.DISCONNECTED); 22784d962ec8f487f824214744498bba505a6db0c59Randy Pan 22884d962ec8f487f824214744498bba505a6db0c59Randy Pan return wifiInfo; 22984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 23084d962ec8f487f824214744498bba505a6db0c59Randy Pan 23109abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne WifiConfigManager mockWifiConfigManager() { 23284d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiConfigManager wifiConfigManager = mock(WifiConfigManager.class); 23384d962ec8f487f824214744498bba505a6db0c59Randy Pan 23484d962ec8f487f824214744498bba505a6db0c59Randy Pan when(wifiConfigManager.getWifiConfiguration(anyInt())).thenReturn(null); 235a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan when(wifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(true); 23673a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan wifiConfigManager.mThresholdSaturatedRssi24 = new AtomicInteger( 23784d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiQualifiedNetworkSelector.RSSI_SATURATION_2G_BAND); 23873a52d3336a40903965b946f6d3624a223ad5aacSamuel Tan wifiConfigManager.mCurrentNetworkBoost = new AtomicInteger( 23984d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiQualifiedNetworkSelector.SAME_NETWORK_AWARD); 24084d962ec8f487f824214744498bba505a6db0c59Randy Pan 241fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // Pass dummy pno network list, otherwise Pno scan requests will not be triggered. 242fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius PnoSettings.PnoNetwork pnoNetwork = new PnoSettings.PnoNetwork(CANDIDATE_SSID); 243fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius ArrayList<PnoSettings.PnoNetwork> pnoNetworkList = new ArrayList<>(); 244fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius pnoNetworkList.add(pnoNetwork); 245fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius when(wifiConfigManager.retrieveDisconnectedPnoNetworkList()).thenReturn(pnoNetworkList); 246fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius when(wifiConfigManager.retrieveConnectedPnoNetworkList()).thenReturn(pnoNetworkList); 247fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 24884d962ec8f487f824214744498bba505a6db0c59Randy Pan return wifiConfigManager; 24984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 25084d962ec8f487f824214744498bba505a6db0c59Randy Pan 25109abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne WifiInjector mockWifiInjector() { 25209abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne WifiInjector wifiInjector = mock(WifiInjector.class); 25309abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne mWifiLastResortWatchdog = mock(WifiLastResortWatchdog.class); 2541d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius mWifiMetrics = mock(WifiMetrics.class); 25509abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne when(wifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog); 2561d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius when(wifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); 257fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius when(wifiInjector.getClock()).thenReturn(mClock); 25809abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne return wifiInjector; 25909abbe29be6e552a2531b0367bd6d29647d33767Glen Kuhne } 26084d962ec8f487f824214744498bba505a6db0c59Randy Pan 26184d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 26284d962ec8f487f824214744498bba505a6db0c59Randy Pan * Wifi enters disconnected state while screen is on. 26384d962ec8f487f824214744498bba505a6db0c59Randy Pan * 26484d962ec8f487f824214744498bba505a6db0c59Randy Pan * Expected behavior: WifiConnectivityManager calls 26584d962ec8f487f824214744498bba505a6db0c59Randy Pan * WifiStateMachine.autoConnectToNetwork() with the 26684d962ec8f487f824214744498bba505a6db0c59Randy Pan * expected candidate network ID and BSSID. 26784d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 26884d962ec8f487f824214744498bba505a6db0c59Randy Pan @Test 26984d962ec8f487f824214744498bba505a6db0c59Randy Pan public void enterWifiDisconnectedStateWhenScreenOn() { 27084d962ec8f487f824214744498bba505a6db0c59Randy Pan // Set screen to on 27184d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiConnectivityManager.handleScreenStateChanged(true); 27284d962ec8f487f824214744498bba505a6db0c59Randy Pan 27384d962ec8f487f824214744498bba505a6db0c59Randy Pan // Set WiFi to disconnected state 27484d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiConnectivityManager.handleConnectionStateChanged( 27584d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 27684d962ec8f487f824214744498bba505a6db0c59Randy Pan 27784d962ec8f487f824214744498bba505a6db0c59Randy Pan verify(mWifiStateMachine).autoConnectToNetwork( 27884d962ec8f487f824214744498bba505a6db0c59Randy Pan CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 27984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 28084d962ec8f487f824214744498bba505a6db0c59Randy Pan 28184d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 28284d962ec8f487f824214744498bba505a6db0c59Randy Pan * Wifi enters connected state while screen is on. 28384d962ec8f487f824214744498bba505a6db0c59Randy Pan * 28484d962ec8f487f824214744498bba505a6db0c59Randy Pan * Expected behavior: WifiConnectivityManager calls 28584d962ec8f487f824214744498bba505a6db0c59Randy Pan * WifiStateMachine.autoConnectToNetwork() with the 28684d962ec8f487f824214744498bba505a6db0c59Randy Pan * expected candidate network ID and BSSID. 28784d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 28884d962ec8f487f824214744498bba505a6db0c59Randy Pan @Test 28984d962ec8f487f824214744498bba505a6db0c59Randy Pan public void enterWifiConnectedStateWhenScreenOn() { 29084d962ec8f487f824214744498bba505a6db0c59Randy Pan // Set screen to on 29184d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiConnectivityManager.handleScreenStateChanged(true); 29284d962ec8f487f824214744498bba505a6db0c59Randy Pan 29384d962ec8f487f824214744498bba505a6db0c59Randy Pan // Set WiFi to connected state 29484d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiConnectivityManager.handleConnectionStateChanged( 29584d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiConnectivityManager.WIFI_STATE_CONNECTED); 29684d962ec8f487f824214744498bba505a6db0c59Randy Pan 29784d962ec8f487f824214744498bba505a6db0c59Randy Pan verify(mWifiStateMachine).autoConnectToNetwork( 29884d962ec8f487f824214744498bba505a6db0c59Randy Pan CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 29984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 30084d962ec8f487f824214744498bba505a6db0c59Randy Pan 30184d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 30284d962ec8f487f824214744498bba505a6db0c59Randy Pan * Screen turned on while WiFi in disconnected state. 30384d962ec8f487f824214744498bba505a6db0c59Randy Pan * 30484d962ec8f487f824214744498bba505a6db0c59Randy Pan * Expected behavior: WifiConnectivityManager calls 30584d962ec8f487f824214744498bba505a6db0c59Randy Pan * WifiStateMachine.autoConnectToNetwork() with the 30684d962ec8f487f824214744498bba505a6db0c59Randy Pan * expected candidate network ID and BSSID. 30784d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 30884d962ec8f487f824214744498bba505a6db0c59Randy Pan @Test 30984d962ec8f487f824214744498bba505a6db0c59Randy Pan public void turnScreenOnWhenWifiInDisconnectedState() { 31084d962ec8f487f824214744498bba505a6db0c59Randy Pan // Set WiFi to disconnected state 31184d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiConnectivityManager.handleConnectionStateChanged( 31284d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 31384d962ec8f487f824214744498bba505a6db0c59Randy Pan 31484d962ec8f487f824214744498bba505a6db0c59Randy Pan // Set screen to on 31584d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiConnectivityManager.handleScreenStateChanged(true); 31684d962ec8f487f824214744498bba505a6db0c59Randy Pan 317fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius verify(mWifiStateMachine, atLeastOnce()).autoConnectToNetwork( 31884d962ec8f487f824214744498bba505a6db0c59Randy Pan CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 31984d962ec8f487f824214744498bba505a6db0c59Randy Pan } 32084d962ec8f487f824214744498bba505a6db0c59Randy Pan 32184d962ec8f487f824214744498bba505a6db0c59Randy Pan /** 32284d962ec8f487f824214744498bba505a6db0c59Randy Pan * Screen turned on while WiFi in connected state. 32384d962ec8f487f824214744498bba505a6db0c59Randy Pan * 32484d962ec8f487f824214744498bba505a6db0c59Randy Pan * Expected behavior: WifiConnectivityManager calls 32584d962ec8f487f824214744498bba505a6db0c59Randy Pan * WifiStateMachine.autoConnectToNetwork() with the 32684d962ec8f487f824214744498bba505a6db0c59Randy Pan * expected candidate network ID and BSSID. 32784d962ec8f487f824214744498bba505a6db0c59Randy Pan */ 32884d962ec8f487f824214744498bba505a6db0c59Randy Pan @Test 32984d962ec8f487f824214744498bba505a6db0c59Randy Pan public void turnScreenOnWhenWifiInConnectedState() { 33084d962ec8f487f824214744498bba505a6db0c59Randy Pan // Set WiFi to connected state 33184d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiConnectivityManager.handleConnectionStateChanged( 33284d962ec8f487f824214744498bba505a6db0c59Randy Pan WifiConnectivityManager.WIFI_STATE_CONNECTED); 33384d962ec8f487f824214744498bba505a6db0c59Randy Pan 33484d962ec8f487f824214744498bba505a6db0c59Randy Pan // Set screen to on 33584d962ec8f487f824214744498bba505a6db0c59Randy Pan mWifiConnectivityManager.handleScreenStateChanged(true); 33684d962ec8f487f824214744498bba505a6db0c59Randy Pan 337fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius verify(mWifiStateMachine, atLeastOnce()).autoConnectToNetwork( 338fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 339fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius } 340fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 341fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius /** 342a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan * Screen turned on while WiFi in connected state but 343a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan * auto roaming is disabled. 344a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan * 345a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan * Expected behavior: WifiConnectivityManager doesn't invoke 346a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan * WifiStateMachine.autoConnectToNetwork() because roaming 347a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan * is turned off. 348a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan */ 349a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan @Test 350a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan public void turnScreenOnWhenWifiInConnectedStateRoamingDisabled() { 351a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan // Set WiFi to connected state 352a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan mWifiConnectivityManager.handleConnectionStateChanged( 353a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan WifiConnectivityManager.WIFI_STATE_CONNECTED); 354a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan 355a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan // Turn off auto roaming 356a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan when(mWifiConfigManager.getEnableAutoJoinWhenAssociated()).thenReturn(false); 357a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan 358a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan // Set screen to on 359a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan mWifiConnectivityManager.handleScreenStateChanged(true); 360a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan 361a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan verify(mWifiStateMachine, times(0)).autoConnectToNetwork( 362a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 363a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan } 364a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan 365a68f3e359ac27285b10332ea2461469e5e03bfd4Randy Pan /** 366fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * Multiple back to back connection attempts within the rate interval should be rate limited. 367fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * 368fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * Expected behavior: WifiConnectivityManager calls WifiStateMachine.autoConnectToNetwork() 369fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * with the expected candidate network ID and BSSID for only the expected number of times within 370fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * the given interval. 371fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius */ 372fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius @Test 373fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius public void connectionAttemptRateLimitedWhenScreenOff() { 374fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius int maxAttemptRate = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_RATE; 375fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius int timeInterval = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS; 376fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius int numAttempts = 0; 377fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius int connectionAttemptIntervals = timeInterval / maxAttemptRate; 378fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 379fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mWifiConnectivityManager.handleScreenStateChanged(false); 380fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 381fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // First attempt the max rate number of connections within the rate interval. 382fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius long currentTimeStamp = 0; 383fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius for (int attempt = 0; attempt < maxAttemptRate; attempt++) { 384fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius currentTimeStamp += connectionAttemptIntervals; 385ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 386fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // Set WiFi to disconnected state to trigger PNO scan 387fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mWifiConnectivityManager.handleConnectionStateChanged( 388fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 389fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius numAttempts++; 390fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius } 391fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // Now trigger another connection attempt before the rate interval, this should be 392fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // skipped because we've crossed rate limit. 393ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 394fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // Set WiFi to disconnected state to trigger PNO scan 395fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mWifiConnectivityManager.handleConnectionStateChanged( 396fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 397fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 398fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // Verify that we attempt to connect upto the rate. 399fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius verify(mWifiStateMachine, times(numAttempts)).autoConnectToNetwork( 400fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 401fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius } 402fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 403fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius /** 404fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * Multiple back to back connection attempts outside the rate interval should not be rate 405fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * limited. 406fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * 407fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * Expected behavior: WifiConnectivityManager calls WifiStateMachine.autoConnectToNetwork() 408fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * with the expected candidate network ID and BSSID for only the expected number of times within 409fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * the given interval. 410fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius */ 411fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius @Test 412fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius public void connectionAttemptNotRateLimitedWhenScreenOff() { 413fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius int maxAttemptRate = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_RATE; 414fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius int timeInterval = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS; 415fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius int numAttempts = 0; 416fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius int connectionAttemptIntervals = timeInterval / maxAttemptRate; 417fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 418fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mWifiConnectivityManager.handleScreenStateChanged(false); 419fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 420fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // First attempt the max rate number of connections within the rate interval. 421fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius long currentTimeStamp = 0; 422fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius for (int attempt = 0; attempt < maxAttemptRate; attempt++) { 423fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius currentTimeStamp += connectionAttemptIntervals; 424ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 425fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // Set WiFi to disconnected state to trigger PNO scan 426fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mWifiConnectivityManager.handleConnectionStateChanged( 427fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 428fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius numAttempts++; 429fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius } 430fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // Now trigger another connection attempt after the rate interval, this should not be 431fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // skipped because we should've evicted the older attempt. 432ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius when(mClock.elapsedRealtime()).thenReturn( 433fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius currentTimeStamp + connectionAttemptIntervals * 2); 434fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // Set WiFi to disconnected state to trigger PNO scan 435fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mWifiConnectivityManager.handleConnectionStateChanged( 436fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 437fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius numAttempts++; 438fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 439fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // Verify that all the connection attempts went through 440fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius verify(mWifiStateMachine, times(numAttempts)).autoConnectToNetwork( 441fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 442fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius } 443fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 444fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius /** 445fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * Multiple back to back connection attempts after a user selection should not be rate limited. 446fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * 447fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * Expected behavior: WifiConnectivityManager calls WifiStateMachine.autoConnectToNetwork() 448fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * with the expected candidate network ID and BSSID for only the expected number of times within 449fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius * the given interval. 450fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius */ 451fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius @Test 452fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius public void connectionAttemptNotRateLimitedWhenScreenOffAfterUserSelection() { 453fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius int maxAttemptRate = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_RATE; 454fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius int timeInterval = WifiConnectivityManager.MAX_CONNECTION_ATTEMPTS_TIME_INTERVAL_MS; 455fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius int numAttempts = 0; 456fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius int connectionAttemptIntervals = timeInterval / maxAttemptRate; 457fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 458fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mWifiConnectivityManager.handleScreenStateChanged(false); 459fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 460fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // First attempt the max rate number of connections within the rate interval. 461fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius long currentTimeStamp = 0; 462fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius for (int attempt = 0; attempt < maxAttemptRate; attempt++) { 463fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius currentTimeStamp += connectionAttemptIntervals; 464ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 465fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // Set WiFi to disconnected state to trigger PNO scan 466fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mWifiConnectivityManager.handleConnectionStateChanged( 467fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 468fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius numAttempts++; 469fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius } 470fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 471fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mWifiConnectivityManager.connectToUserSelectNetwork(CANDIDATE_NETWORK_ID, false); 472fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 473fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius for (int attempt = 0; attempt < maxAttemptRate; attempt++) { 474fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius currentTimeStamp += connectionAttemptIntervals; 475ee0ab818341d44614ffe56ae73ecc08b974c2cbbRoshan Pius when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 476fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // Set WiFi to disconnected state to trigger PNO scan 477fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius mWifiConnectivityManager.handleConnectionStateChanged( 478fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 479fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius numAttempts++; 480fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius } 481fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius 482fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius // Verify that all the connection attempts went through 483fa2ac2743307559e8dcc5aaf54873536315fbe62Roshan Pius verify(mWifiStateMachine, times(numAttempts)).autoConnectToNetwork( 48484d962ec8f487f824214744498bba505a6db0c59Randy Pan CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 48584d962ec8f487f824214744498bba505a6db0c59Randy Pan } 4863d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 4873d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan /** 4883d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan * PNO retry for low RSSI networks. 4893d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan * 4903d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan * Expected behavior: WifiConnectivityManager doubles the low RSSI 4913d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan * network retry delay value after QNS skips the PNO scan results 4923d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan * because of their low RSSI values. 4933d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan */ 4943d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan @Test 4953d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan public void PnoRetryForLowRssiNetwork() { 4963d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan when(mWifiQNS.selectQualifiedNetwork(anyBoolean(), anyBoolean(), anyObject(), 4973d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean())).thenReturn(null); 4983d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 4993d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // Set screen to off 5003d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan mWifiConnectivityManager.handleScreenStateChanged(false); 5013d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 5023d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // Get the current retry delay value 5033d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan int lowRssiNetworkRetryDelayStartValue = mWifiConnectivityManager 5043d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan .getLowRssiNetworkRetryDelay(); 5053d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 5063d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // Set WiFi to disconnected state to trigger PNO scan 5073d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan mWifiConnectivityManager.handleConnectionStateChanged( 5083d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 5093d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 5103d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // Get the retry delay value after QNS didn't select a 5113d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan // network candicate from the PNO scan results. 5123d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan int lowRssiNetworkRetryDelayAfterPnoValue = mWifiConnectivityManager 5133d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan .getLowRssiNetworkRetryDelay(); 5143d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan 5153d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan assertEquals(lowRssiNetworkRetryDelayStartValue * 2, 5163d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan lowRssiNetworkRetryDelayAfterPnoValue); 5173d09b9117df33608a43c1fbe0135123e2de9aea2Randy Pan } 5181d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius 5191d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius /** 5201d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius * Ensure that the watchdog bite increments the "Pno bad" metric. 5211d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius * 5221d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius * Expected behavior: WifiConnectivityManager detects that the PNO scan failed to find 5231d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius * a candidate while watchdog single scan did. 5241d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius */ 5251d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius @Test 5261d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius public void watchdogBitePnoBadIncrementsMetrics() { 5271d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius // Set screen to off 5281d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius mWifiConnectivityManager.handleScreenStateChanged(false); 5291d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius 5301d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius // Set WiFi to disconnected state to trigger PNO scan 5311d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius mWifiConnectivityManager.handleConnectionStateChanged( 5321d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 5331d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius 5341d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius // Now fire the watchdog alarm and verify the metrics were incremented. 5351d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius mAlarmManager.dispatch(WifiConnectivityManager.WATCHDOG_TIMER_TAG); 5361d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius mLooper.dispatchAll(); 5371d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius 5381d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius verify(mWifiMetrics).incrementNumConnectivityWatchdogPnoBad(); 5391d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius verify(mWifiMetrics, never()).incrementNumConnectivityWatchdogPnoGood(); 5401d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius } 5411d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius 5421d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius /** 5431d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius * Ensure that the watchdog bite increments the "Pno good" metric. 5441d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius * 5451d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius * Expected behavior: WifiConnectivityManager detects that the PNO scan failed to find 5461d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius * a candidate which was the same with watchdog single scan. 5471d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius */ 5481d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius @Test 5491d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius public void watchdogBitePnoGoodIncrementsMetrics() { 5501d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius // Qns returns no candidate after watchdog single scan. 5511d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius when(mWifiQNS.selectQualifiedNetwork(anyBoolean(), anyBoolean(), anyObject(), 5521d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius anyBoolean(), anyBoolean(), anyBoolean(), anyBoolean())).thenReturn(null); 5531d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius 5541d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius // Set screen to off 5551d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius mWifiConnectivityManager.handleScreenStateChanged(false); 5561d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius 5571d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius // Set WiFi to disconnected state to trigger PNO scan 5581d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius mWifiConnectivityManager.handleConnectionStateChanged( 5591d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 5601d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius 5611d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius // Now fire the watchdog alarm and verify the metrics were incremented. 5621d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius mAlarmManager.dispatch(WifiConnectivityManager.WATCHDOG_TIMER_TAG); 5631d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius mLooper.dispatchAll(); 5641d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius 5651d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius verify(mWifiMetrics).incrementNumConnectivityWatchdogPnoGood(); 5661d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius verify(mWifiMetrics, never()).incrementNumConnectivityWatchdogPnoBad(); 5671d7d62393181cc36b6f87c3cf2151adc54275f9cRoshan Pius } 568b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 569b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan /** 570b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan * Verify that scan interval for screen on and wifi disconnected scenario 571b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan * is in the exponential backoff fashion. 572b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan * 573b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan * Expected behavior: WifiConnectivityManager doubles periodic 574b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan * scan interval. 575b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan */ 576b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan @Test 577b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan public void checkPeriodicScanIntervalWhenDisconnected() { 578c2963eb07660a06592c60224279685166390217dRandy Pan long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; 579c2963eb07660a06592c60224279685166390217dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 580b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 581b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan // Set screen to ON 582b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan mWifiConnectivityManager.handleScreenStateChanged(true); 583b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 584c2963eb07660a06592c60224279685166390217dRandy Pan // Wait for MAX_PERIODIC_SCAN_INTERVAL_MS so that any impact triggered 585c2963eb07660a06592c60224279685166390217dRandy Pan // by screen state change can settle 586c2963eb07660a06592c60224279685166390217dRandy Pan currentTimeStamp += WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS; 587c2963eb07660a06592c60224279685166390217dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 588c2963eb07660a06592c60224279685166390217dRandy Pan 589b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan // Set WiFi to disconnected state to trigger periodic scan 590b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan mWifiConnectivityManager.handleConnectionStateChanged( 591b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 592b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 593b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan // Get the first periodic scan interval 594b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan long firstIntervalMs = mAlarmManager 595b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) 596c2963eb07660a06592c60224279685166390217dRandy Pan - currentTimeStamp; 597b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan assertEquals(firstIntervalMs, WifiConnectivityManager.PERIODIC_SCAN_INTERVAL_MS); 598b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 599c2963eb07660a06592c60224279685166390217dRandy Pan currentTimeStamp += firstIntervalMs; 600c2963eb07660a06592c60224279685166390217dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 601c2963eb07660a06592c60224279685166390217dRandy Pan 602b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan // Now fire the first periodic scan alarm timer 603b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); 604b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan mLooper.dispatchAll(); 605b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 606b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan // Get the second periodic scan interval 607b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan long secondIntervalMs = mAlarmManager 608b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) 609c2963eb07660a06592c60224279685166390217dRandy Pan - currentTimeStamp; 610b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 611b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan // Verify the intervals are exponential back off 612b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan assertEquals(firstIntervalMs * 2, secondIntervalMs); 613b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 614c2963eb07660a06592c60224279685166390217dRandy Pan currentTimeStamp += secondIntervalMs; 615c2963eb07660a06592c60224279685166390217dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 616c2963eb07660a06592c60224279685166390217dRandy Pan 617b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan // Make sure we eventually stay at the maximum scan interval. 618b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan long intervalMs = 0; 619b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan for (int i = 0; i < 5; i++) { 620b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); 621b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan mLooper.dispatchAll(); 622b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan intervalMs = mAlarmManager 623b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) 624c2963eb07660a06592c60224279685166390217dRandy Pan - currentTimeStamp; 625c2963eb07660a06592c60224279685166390217dRandy Pan currentTimeStamp += intervalMs; 626c2963eb07660a06592c60224279685166390217dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 627b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan } 628b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 629b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan assertEquals(intervalMs, WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS); 630b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan } 631b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 632b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan /** 633b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan * Verify that scan interval for screen on and wifi connected scenario 634b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan * is in the exponential backoff fashion. 635b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan * 636b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan * Expected behavior: WifiConnectivityManager doubles periodic 637b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan * scan interval. 638b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan */ 639b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan @Test 640b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan public void checkPeriodicScanIntervalWhenConnected() { 641c2963eb07660a06592c60224279685166390217dRandy Pan long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; 642c2963eb07660a06592c60224279685166390217dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 643b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 644b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan // Set screen to ON 645b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan mWifiConnectivityManager.handleScreenStateChanged(true); 646b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 647c2963eb07660a06592c60224279685166390217dRandy Pan // Wait for MAX_PERIODIC_SCAN_INTERVAL_MS so that any impact triggered 648c2963eb07660a06592c60224279685166390217dRandy Pan // by screen state change can settle 649c2963eb07660a06592c60224279685166390217dRandy Pan currentTimeStamp += WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS; 650c2963eb07660a06592c60224279685166390217dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 651c2963eb07660a06592c60224279685166390217dRandy Pan 652b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan // Set WiFi to connected state to trigger periodic scan 653b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan mWifiConnectivityManager.handleConnectionStateChanged( 654b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan WifiConnectivityManager.WIFI_STATE_CONNECTED); 655b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 656b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan // Get the first periodic scan interval 657b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan long firstIntervalMs = mAlarmManager 658b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) 659c2963eb07660a06592c60224279685166390217dRandy Pan - currentTimeStamp; 660b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan assertEquals(firstIntervalMs, WifiConnectivityManager.PERIODIC_SCAN_INTERVAL_MS); 661b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 662c2963eb07660a06592c60224279685166390217dRandy Pan currentTimeStamp += firstIntervalMs; 663c2963eb07660a06592c60224279685166390217dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 664c2963eb07660a06592c60224279685166390217dRandy Pan 665b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan // Now fire the first periodic scan alarm timer 666b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); 667b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan mLooper.dispatchAll(); 668b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 669b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan // Get the second periodic scan interval 670b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan long secondIntervalMs = mAlarmManager 671b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) 672c2963eb07660a06592c60224279685166390217dRandy Pan - currentTimeStamp; 673b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 674b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan // Verify the intervals are exponential back off 675b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan assertEquals(firstIntervalMs * 2, secondIntervalMs); 676b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 677c2963eb07660a06592c60224279685166390217dRandy Pan currentTimeStamp += secondIntervalMs; 678c2963eb07660a06592c60224279685166390217dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 679c2963eb07660a06592c60224279685166390217dRandy Pan 680b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan // Make sure we eventually stay at the maximum scan interval. 681b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan long intervalMs = 0; 682b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan for (int i = 0; i < 5; i++) { 683b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan mAlarmManager.dispatch(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); 684b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan mLooper.dispatchAll(); 685b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan intervalMs = mAlarmManager 686b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG) 687c2963eb07660a06592c60224279685166390217dRandy Pan - currentTimeStamp; 688c2963eb07660a06592c60224279685166390217dRandy Pan currentTimeStamp += intervalMs; 689c2963eb07660a06592c60224279685166390217dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 690b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan } 691b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan 692b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan assertEquals(intervalMs, WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS); 693b32b649c815b0b50fd0127d9d4a4563c54a536fbRandy Pan } 694fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 695fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius /** 696c2963eb07660a06592c60224279685166390217dRandy Pan * When screen on trigger two connection state change events back to back to 697c2963eb07660a06592c60224279685166390217dRandy Pan * verify that the minium scan interval is enforced. 698c2963eb07660a06592c60224279685166390217dRandy Pan * 699c2963eb07660a06592c60224279685166390217dRandy Pan * Expected behavior: WifiConnectivityManager start the second periodic single 700c2963eb07660a06592c60224279685166390217dRandy Pan * scan PERIODIC_SCAN_INTERVAL_MS after the first one. 701c2963eb07660a06592c60224279685166390217dRandy Pan */ 702c2963eb07660a06592c60224279685166390217dRandy Pan @Test 703c2963eb07660a06592c60224279685166390217dRandy Pan public void checkMinimumPeriodicScanIntervalWhenScreenOn() { 704c2963eb07660a06592c60224279685166390217dRandy Pan long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; 705c2963eb07660a06592c60224279685166390217dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 706c2963eb07660a06592c60224279685166390217dRandy Pan 707c2963eb07660a06592c60224279685166390217dRandy Pan // Set screen to ON 708c2963eb07660a06592c60224279685166390217dRandy Pan mWifiConnectivityManager.handleScreenStateChanged(true); 709c2963eb07660a06592c60224279685166390217dRandy Pan 710c2963eb07660a06592c60224279685166390217dRandy Pan // Wait for MAX_PERIODIC_SCAN_INTERVAL_MS so that any impact triggered 711c2963eb07660a06592c60224279685166390217dRandy Pan // by screen state change can settle 712c2963eb07660a06592c60224279685166390217dRandy Pan currentTimeStamp += WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS; 713c2963eb07660a06592c60224279685166390217dRandy Pan long firstScanTimeStamp = currentTimeStamp; 714c2963eb07660a06592c60224279685166390217dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 715c2963eb07660a06592c60224279685166390217dRandy Pan 716c2963eb07660a06592c60224279685166390217dRandy Pan // Set WiFi to connected state to trigger the periodic scan 717c2963eb07660a06592c60224279685166390217dRandy Pan mWifiConnectivityManager.handleConnectionStateChanged( 718c2963eb07660a06592c60224279685166390217dRandy Pan WifiConnectivityManager.WIFI_STATE_CONNECTED); 719c2963eb07660a06592c60224279685166390217dRandy Pan 720c2963eb07660a06592c60224279685166390217dRandy Pan // Set the second scan attempt time stamp. 721c2963eb07660a06592c60224279685166390217dRandy Pan currentTimeStamp += 2000; 722c2963eb07660a06592c60224279685166390217dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 723c2963eb07660a06592c60224279685166390217dRandy Pan 724c2963eb07660a06592c60224279685166390217dRandy Pan // Set WiFi to disconnected state to trigger another periodic scan 725c2963eb07660a06592c60224279685166390217dRandy Pan mWifiConnectivityManager.handleConnectionStateChanged( 726c2963eb07660a06592c60224279685166390217dRandy Pan WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 727c2963eb07660a06592c60224279685166390217dRandy Pan 728c2963eb07660a06592c60224279685166390217dRandy Pan // Get the second periodic scan actual time stamp 729c2963eb07660a06592c60224279685166390217dRandy Pan long secondScanTimeStamp = mAlarmManager 730c2963eb07660a06592c60224279685166390217dRandy Pan .getTriggerTimeMillis(WifiConnectivityManager.PERIODIC_SCAN_TIMER_TAG); 731c2963eb07660a06592c60224279685166390217dRandy Pan 732c2963eb07660a06592c60224279685166390217dRandy Pan // Verify that the second scan is scheduled PERIODIC_SCAN_INTERVAL_MS after the 733c2963eb07660a06592c60224279685166390217dRandy Pan // very first scan. 734c2963eb07660a06592c60224279685166390217dRandy Pan assertEquals(secondScanTimeStamp, firstScanTimeStamp 735c2963eb07660a06592c60224279685166390217dRandy Pan + WifiConnectivityManager.PERIODIC_SCAN_INTERVAL_MS); 736c2963eb07660a06592c60224279685166390217dRandy Pan 737c2963eb07660a06592c60224279685166390217dRandy Pan } 738c2963eb07660a06592c60224279685166390217dRandy Pan 739c2963eb07660a06592c60224279685166390217dRandy Pan /** 740016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan * When screen on trigger a connection state change event and a forced connectivity 741016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan * scan event back to back to verify that the minimum scan interval is not applied 742016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan * in this scenario. 743016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan * 744016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan * Expected behavior: WifiConnectivityManager starts the second periodic single 745016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan * scan immediately. 746016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan */ 747016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan @Test 748016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan public void checkMinimumPeriodicScanIntervalNotEnforced() { 749016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan long currentTimeStamp = CURRENT_SYSTEM_TIME_MS; 750016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 751016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan 752016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan // Set screen to ON 753016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan mWifiConnectivityManager.handleScreenStateChanged(true); 754016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan 755016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan // Wait for MAX_PERIODIC_SCAN_INTERVAL_MS so that any impact triggered 756016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan // by screen state change can settle 757016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan currentTimeStamp += WifiConnectivityManager.MAX_PERIODIC_SCAN_INTERVAL_MS; 758016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan long firstScanTimeStamp = currentTimeStamp; 759016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 760016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan 761016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan // Set WiFi to connected state to trigger the periodic scan 762016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan mWifiConnectivityManager.handleConnectionStateChanged( 763016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan WifiConnectivityManager.WIFI_STATE_CONNECTED); 764016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan 765016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan // Set the second scan attempt time stamp 766016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan currentTimeStamp += 2000; 767016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan when(mClock.elapsedRealtime()).thenReturn(currentTimeStamp); 768016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan 7698cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan // Allow untrusted networks so WifiConnectivityManager starts a periodic scan 7708cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan // immediately. 7718cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan mWifiConnectivityManager.setUntrustedConnectionAllowed(true); 772016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan 773016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan // Get the second periodic scan actual time stamp. Note, this scan is not 774016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan // started from the AlarmManager. 775016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan long secondScanTimeStamp = mWifiConnectivityManager.getLastPeriodicSingleScanTimeStamp(); 776016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan 777016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan // Verify that the second scan is fired immediately 778016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan assertEquals(secondScanTimeStamp, currentTimeStamp); 779016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan } 780016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan 781016ca1ae5e33eb9529ae10c2510a56fa5c7fec4dRandy Pan /** 782fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius * Verify that we perform full band scan when the currently connected network's tx/rx success 783fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius * rate is low. 784fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius * 785fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius * Expected behavior: WifiConnectivityManager does full band scan. 786fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius */ 787fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius @Test 788fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius public void checkSingleScanSettingsWhenConnectedWithLowDataRate() { 789fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius mWifiInfo.txSuccessRate = 0; 790fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius mWifiInfo.rxSuccessRate = 0; 791fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 792fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius final HashSet<Integer> channelList = new HashSet<>(); 793fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius channelList.add(1); 794fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius channelList.add(2); 795fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius channelList.add(3); 796fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 797fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius when(mWifiStateMachine.getCurrentWifiConfiguration()) 798fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius .thenReturn(new WifiConfiguration()); 799fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius when(mWifiStateMachine.getFrequencyBand()) 800fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius .thenReturn(WifiManager.WIFI_FREQUENCY_BAND_5GHZ); 801fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius when(mWifiConfigManager.makeChannelList(any(WifiConfiguration.class), anyInt())) 802fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius .thenReturn(channelList); 803fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 804fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius doAnswer(new AnswerWithArguments() { 805fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius public void answer(ScanSettings settings, ScanListener listener, 806fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius WorkSource workSource) throws Exception { 807fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius assertEquals(settings.band, WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS); 808fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius assertNull(settings.channels); 809fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject()); 810fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 811fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius // Set screen to ON 812fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius mWifiConnectivityManager.handleScreenStateChanged(true); 813fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 814fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius // Set WiFi to connected state to trigger periodic scan 815fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius mWifiConnectivityManager.handleConnectionStateChanged( 816fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius WifiConnectivityManager.WIFI_STATE_CONNECTED); 817fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 818fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius verify(mWifiScanner).startScan(anyObject(), anyObject(), anyObject()); 819fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius } 820fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 821fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius /** 822fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius * Verify that we perform partial scan when the currently connected network's tx/rx success 823fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius * rate is high and when the currently connected network is present in scan 824fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius * cache in WifiConfigManager. 825fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius * 826fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius * Expected behavior: WifiConnectivityManager does full band scan. 827fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius */ 828fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius @Test 829fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius public void checkSingleScanSettingsWhenConnectedWithHighDataRate() { 830fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius mWifiInfo.txSuccessRate = WifiConfigManager.MAX_TX_PACKET_FOR_FULL_SCANS * 2; 831fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius mWifiInfo.rxSuccessRate = WifiConfigManager.MAX_RX_PACKET_FOR_FULL_SCANS * 2; 832fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 833fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius final HashSet<Integer> channelList = new HashSet<>(); 834fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius channelList.add(1); 835fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius channelList.add(2); 836fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius channelList.add(3); 837fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 838fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius when(mWifiStateMachine.getCurrentWifiConfiguration()) 839fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius .thenReturn(new WifiConfiguration()); 840fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius when(mWifiConfigManager.makeChannelList(any(WifiConfiguration.class), anyInt())) 841fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius .thenReturn(channelList); 842fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 843fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius doAnswer(new AnswerWithArguments() { 844fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius public void answer(ScanSettings settings, ScanListener listener, 845fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius WorkSource workSource) throws Exception { 846fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius assertEquals(settings.band, WifiScanner.WIFI_BAND_UNSPECIFIED); 847fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius assertEquals(settings.channels.length, channelList.size()); 848fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius for (int chanIdx = 0; chanIdx < settings.channels.length; chanIdx++) { 849fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius assertTrue(channelList.contains(settings.channels[chanIdx].frequency)); 850fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius } 851fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject()); 852fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 853fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius // Set screen to ON 854fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius mWifiConnectivityManager.handleScreenStateChanged(true); 855fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 856fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius // Set WiFi to connected state to trigger periodic scan 857fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius mWifiConnectivityManager.handleConnectionStateChanged( 858fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius WifiConnectivityManager.WIFI_STATE_CONNECTED); 859fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 860fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius verify(mWifiScanner).startScan(anyObject(), anyObject(), anyObject()); 861fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius } 862fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 863fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius /** 864fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius * Verify that we fall back to full band scan when the currently connected network's tx/rx 865fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius * success rate is high and the currently connected network is not present in scan cache in 866fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius * WifiConfigManager. This is simulated by returning an empty hashset in |makeChannelList|. 867fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius * 868fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius * Expected behavior: WifiConnectivityManager does full band scan. 869fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius */ 870fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius @Test 871fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius public void checkSingleScanSettingsWhenConnectedWithHighDataRateNotInCache() { 872fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius mWifiInfo.txSuccessRate = WifiConfigManager.MAX_TX_PACKET_FOR_FULL_SCANS * 2; 873fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius mWifiInfo.rxSuccessRate = WifiConfigManager.MAX_RX_PACKET_FOR_FULL_SCANS * 2; 874fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 875fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius final HashSet<Integer> channelList = new HashSet<>(); 876fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 877fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius when(mWifiStateMachine.getCurrentWifiConfiguration()) 878fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius .thenReturn(new WifiConfiguration()); 879fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius when(mWifiStateMachine.getFrequencyBand()) 880fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius .thenReturn(WifiManager.WIFI_FREQUENCY_BAND_5GHZ); 881fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius when(mWifiConfigManager.makeChannelList(any(WifiConfiguration.class), anyInt())) 882fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius .thenReturn(channelList); 883fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 884fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius doAnswer(new AnswerWithArguments() { 885fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius public void answer(ScanSettings settings, ScanListener listener, 886fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius WorkSource workSource) throws Exception { 887fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius assertEquals(settings.band, WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS); 888fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius assertNull(settings.channels); 889fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject()); 890fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 891fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius // Set screen to ON 892fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius mWifiConnectivityManager.handleScreenStateChanged(true); 893fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 894fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius // Set WiFi to connected state to trigger periodic scan 895fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius mWifiConnectivityManager.handleConnectionStateChanged( 896fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius WifiConnectivityManager.WIFI_STATE_CONNECTED); 897fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius 898fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius verify(mWifiScanner).startScan(anyObject(), anyObject(), anyObject()); 899fb196453c07daad5e525520cecad84cec5d89fb7Roshan Pius } 900de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan 901de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan /** 902de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan * Verify that we retry connectivity scan up to MAX_SCAN_RESTART_ALLOWED times 903de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan * when Wifi somehow gets into a bad state and fails to scan. 904de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan * 905de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan * Expected behavior: WifiConnectivityManager schedules connectivity scan 906de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan * MAX_SCAN_RESTART_ALLOWED times. 907de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan */ 908de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan @Test 909de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan public void checkMaximumScanRetry() { 910de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan // Set screen to ON 911de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan mWifiConnectivityManager.handleScreenStateChanged(true); 912de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan 913de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan doAnswer(new AnswerWithArguments() { 914de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan public void answer(ScanSettings settings, ScanListener listener, 915de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan WorkSource workSource) throws Exception { 916de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan listener.onFailure(-1, "ScanFailure"); 917de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan }}).when(mWifiScanner).startScan(anyObject(), anyObject(), anyObject()); 918de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan 919de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan // Set WiFi to disconnected state to trigger the single scan based periodic scan 920de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan mWifiConnectivityManager.handleConnectionStateChanged( 921de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan WifiConnectivityManager.WIFI_STATE_DISCONNECTED); 922de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan 923de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan // Fire the alarm timer 2x timers 924de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan for (int i = 0; i < (WifiConnectivityManager.MAX_SCAN_RESTART_ALLOWED * 2); i++) { 925de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan mAlarmManager.dispatch(WifiConnectivityManager.RESTART_SINGLE_SCAN_TIMER_TAG); 926de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan mLooper.dispatchAll(); 927de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan } 928de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan 929de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan // Verify that the connectivity scan has been retried for MAX_SCAN_RESTART_ALLOWED 930de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan // times. Note, WifiScanner.startScan() is invoked MAX_SCAN_RESTART_ALLOWED + 1 times. 931de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan // The very first scan is the initial one, and the other MAX_SCAN_RESTART_ALLOWED 932de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan // are the retrial ones. 933de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan verify(mWifiScanner, times(WifiConnectivityManager.MAX_SCAN_RESTART_ALLOWED + 1)).startScan( 934de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan anyObject(), anyObject(), anyObject()); 935de5fadf2e5c7bb769705c830efb04133b1e0219dRandy Pan } 936cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan 937cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan /** 938cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan * Listen to scan results not requested by WifiConnectivityManager and 939cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan * act on them. 940cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan * 941cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan * Expected behavior: WifiConnectivityManager calls 942cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan * WifiStateMachine.autoConnectToNetwork() with the 943cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan * expected candidate network ID and BSSID. 944cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan */ 945cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan @Test 946cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan public void listenToAllSingleScanResults() { 947cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan ScanSettings settings = new ScanSettings(); 948cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan ScanListener scanListener = mock(ScanListener.class); 949cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan 950cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan // Request a single scan outside of WifiConnectivityManager. 951cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan mWifiScanner.startScan(settings, scanListener, WIFI_WORK_SOURCE); 952cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan 953cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan // Verify that WCM receives the scan results and initiates a connection 954cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan // to the network. 955cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan verify(mWifiStateMachine).autoConnectToNetwork( 956cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 957cb26f07ae9c558f8c6136c951a7f633d0ccfe79fRandy Pan } 9588cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan 9598cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan /** 9608cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan * Verify that a forced connectivity scan waits for full band scan 9618cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan * results. 9628cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan * 9638cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan * Expected behavior: WifiConnectivityManager doesn't invoke 9648cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan * WifiStateMachine.autoConnectToNetwork() when full band scan 9658cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan * results are not available. 9668cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan */ 9678cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan @Test 9688cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan public void waitForFullBandScanResults() { 9698cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan // Set WiFi to connected state. 9708cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan mWifiConnectivityManager.handleConnectionStateChanged( 9718cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan WifiConnectivityManager.WIFI_STATE_CONNECTED); 9728cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan 9738cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan // Set up as partial scan results. 9748cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan when(mScanData.isAllChannelsScanned()).thenReturn(false); 9758cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan 9768cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan // Force a connectivity scan which enables WifiConnectivityManager 9778cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan // to wait for full band scan results. 9788cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan mWifiConnectivityManager.forceConnectivityScan(); 9798cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan 9808cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan // No roaming because no full band scan results. 9818cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan verify(mWifiStateMachine, times(0)).autoConnectToNetwork( 9828cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 9838cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan 9848cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan // Set up as full band scan results. 9858cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan when(mScanData.isAllChannelsScanned()).thenReturn(true); 9868cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan 9878cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan // Force a connectivity scan which enables WifiConnectivityManager 9888cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan // to wait for full band scan results. 9898cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan mWifiConnectivityManager.forceConnectivityScan(); 9908cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan 9918cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan // Roaming attempt because full band scan results are available. 9928cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan verify(mWifiStateMachine).autoConnectToNetwork( 9938cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan CANDIDATE_NETWORK_ID, CANDIDATE_BSSID); 9948cf5bfbee9d70dac8c83729a979bd7208a47d44dRandy Pan } 99584d962ec8f487f824214744498bba505a6db0c59Randy Pan} 996