1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wifi; 18 19 import static org.junit.Assert.assertArrayEquals; 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertFalse; 22 import static org.junit.Assert.assertNotNull; 23 import static org.junit.Assert.assertNull; 24 import static org.junit.Assert.assertTrue; 25 import static org.mockito.ArgumentMatchers.anyInt; 26 import static org.mockito.ArgumentMatchers.eq; 27 import static org.mockito.Matchers.argThat; 28 import static org.mockito.Mockito.any; 29 import static org.mockito.Mockito.anyLong; 30 import static org.mockito.Mockito.anyString; 31 import static org.mockito.Mockito.doNothing; 32 import static org.mockito.Mockito.doThrow; 33 import static org.mockito.Mockito.mock; 34 import static org.mockito.Mockito.never; 35 import static org.mockito.Mockito.reset; 36 import static org.mockito.Mockito.times; 37 import static org.mockito.Mockito.verify; 38 import static org.mockito.Mockito.verifyNoMoreInteractions; 39 import static org.mockito.Mockito.when; 40 41 import android.app.AlarmManager; 42 import android.net.wifi.IApInterface; 43 import android.net.wifi.IApInterfaceEventCallback; 44 import android.net.wifi.IClientInterface; 45 import android.net.wifi.IPnoScanEvent; 46 import android.net.wifi.IScanEvent; 47 import android.net.wifi.ISendMgmtFrameEvent; 48 import android.net.wifi.IWifiScannerImpl; 49 import android.net.wifi.IWificond; 50 import android.net.wifi.ScanResult; 51 import android.net.wifi.WifiConfiguration; 52 import android.net.wifi.WifiEnterpriseConfig; 53 import android.net.wifi.WifiScanner; 54 import android.os.Handler; 55 import android.os.IBinder; 56 import android.os.RemoteException; 57 import android.os.test.TestLooper; 58 59 import androidx.test.filters.SmallTest; 60 61 import com.android.server.wifi.WifiNative.SendMgmtFrameCallback; 62 import com.android.server.wifi.util.NativeUtil; 63 import com.android.server.wifi.wificond.ChannelSettings; 64 import com.android.server.wifi.wificond.HiddenNetwork; 65 import com.android.server.wifi.wificond.NativeScanResult; 66 import com.android.server.wifi.wificond.PnoSettings; 67 import com.android.server.wifi.wificond.RadioChainInfo; 68 import com.android.server.wifi.wificond.SingleScanSettings; 69 70 import org.junit.Before; 71 import org.junit.Test; 72 import org.mockito.AdditionalMatchers; 73 import org.mockito.ArgumentCaptor; 74 import org.mockito.ArgumentMatcher; 75 import org.mockito.Mock; 76 import org.mockito.MockitoAnnotations; 77 78 import java.io.ByteArrayOutputStream; 79 import java.nio.charset.StandardCharsets; 80 import java.util.ArrayList; 81 import java.util.Arrays; 82 import java.util.BitSet; 83 import java.util.HashSet; 84 import java.util.List; 85 import java.util.Set; 86 87 /** 88 * Unit tests for {@link com.android.server.wifi.WificondControl}. 89 */ 90 @SmallTest 91 public class WificondControlTest { 92 @Mock private WifiInjector mWifiInjector; 93 @Mock private WifiMonitor mWifiMonitor; 94 @Mock private WifiMetrics mWifiMetrics; 95 @Mock private IWificond mWificond; 96 @Mock private IBinder mWifiCondBinder; 97 @Mock private IClientInterface mClientInterface; 98 @Mock private IWifiScannerImpl mWifiScannerImpl; 99 @Mock private CarrierNetworkConfig mCarrierNetworkConfig; 100 @Mock private IApInterface mApInterface; 101 @Mock private WifiNative.SoftApListener mSoftApListener; 102 @Mock private AlarmManager mAlarmManager; 103 @Mock private Clock mClock; 104 @Mock private SendMgmtFrameCallback mSendMgmtFrameCallback; 105 private TestLooper mLooper; 106 private WificondControl mWificondControl; 107 private static final String TEST_INTERFACE_NAME = "test_wlan_if"; 108 private static final String TEST_INTERFACE_NAME1 = "test_wlan_if1"; 109 private static final String TEST_INVALID_INTERFACE_NAME = "asdf"; 110 private static final byte[] TEST_SSID = 111 new byte[] {'G', 'o', 'o', 'g', 'l', 'e', 'G', 'u', 'e', 's', 't'}; 112 private static final byte[] TEST_PSK = 113 new byte[] {'T', 'e', 's', 't'}; 114 private static final byte[] TEST_BSSID = 115 new byte[] {(byte) 0x12, (byte) 0xef, (byte) 0xa1, 116 (byte) 0x2c, (byte) 0x97, (byte) 0x8b}; 117 // This the IE buffer which is consistent with TEST_SSID. 118 private static final byte[] TEST_INFO_ELEMENT_SSID = 119 new byte[] { 120 // Element ID for SSID. 121 (byte) 0x00, 122 // Length of the SSID: 0x0b or 11. 123 (byte) 0x0b, 124 // This is string "GoogleGuest" 125 'G', 'o', 'o', 'g', 'l', 'e', 'G', 'u', 'e', 's', 't'}; 126 // RSN IE data indicating EAP key management. 127 private static final byte[] TEST_INFO_ELEMENT_RSN = 128 new byte[] { 129 // Element ID for RSN. 130 (byte) 0x30, 131 // Length of the element data. 132 (byte) 0x18, 133 (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02, 134 (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04, 135 (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02, (byte) 0x01, (byte) 0x00, 136 (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x01, (byte) 0x00, (byte) 0x00 }; 137 138 private static final int TEST_FREQUENCY = 2456; 139 private static final int TEST_SIGNAL_MBM = -4500; 140 private static final long TEST_TSF = 34455441; 141 private static final BitSet TEST_CAPABILITY = new BitSet(16) {{ set(2); set(5); }}; 142 private static final boolean TEST_ASSOCIATED = true; 143 private static final NativeScanResult MOCK_NATIVE_SCAN_RESULT = 144 new NativeScanResult() {{ 145 ssid = TEST_SSID; 146 bssid = TEST_BSSID; 147 infoElement = TEST_INFO_ELEMENT_SSID; 148 frequency = TEST_FREQUENCY; 149 signalMbm = TEST_SIGNAL_MBM; 150 capability = TEST_CAPABILITY; 151 associated = TEST_ASSOCIATED; 152 radioChainInfos = new ArrayList<>(); 153 }}; 154 private static final RadioChainInfo MOCK_NATIVE_RADIO_CHAIN_INFO_1 = 155 new RadioChainInfo() {{ 156 chainId = 1; 157 level = -89; 158 }}; 159 private static final RadioChainInfo MOCK_NATIVE_RADIO_CHAIN_INFO_2 = 160 new RadioChainInfo() {{ 161 chainId = 0; 162 level = -78; 163 }}; 164 private static final Set<Integer> SCAN_FREQ_SET = 165 new HashSet<Integer>() {{ 166 add(2410); 167 add(2450); 168 add(5050); 169 add(5200); 170 }}; 171 private static final String TEST_QUOTED_SSID_1 = "\"testSsid1\""; 172 private static final String TEST_QUOTED_SSID_2 = "\"testSsid2\""; 173 private static final int[] TEST_FREQUENCIES_1 = {}; 174 private static final int[] TEST_FREQUENCIES_2 = {2500, 5124}; 175 176 private static final List<String> SCAN_HIDDEN_NETWORK_SSID_LIST = 177 new ArrayList<String>() {{ 178 add(TEST_QUOTED_SSID_1); 179 add(TEST_QUOTED_SSID_2); 180 }}; 181 182 183 private static final WifiNative.PnoSettings TEST_PNO_SETTINGS = 184 new WifiNative.PnoSettings() {{ 185 isConnected = false; 186 periodInMs = 6000; 187 networkList = new WifiNative.PnoNetwork[2]; 188 networkList[0] = new WifiNative.PnoNetwork(); 189 networkList[1] = new WifiNative.PnoNetwork(); 190 networkList[0].ssid = TEST_QUOTED_SSID_1; 191 networkList[0].flags = WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN; 192 networkList[0].frequencies = TEST_FREQUENCIES_1; 193 networkList[1].ssid = TEST_QUOTED_SSID_2; 194 networkList[1].flags = 0; 195 networkList[1].frequencies = TEST_FREQUENCIES_2; 196 }}; 197 198 private static final int TEST_MCS_RATE = 5; 199 private static final int TEST_SEND_MGMT_FRAME_ELAPSED_TIME_MS = 100; 200 private static final byte[] TEST_PROBE_FRAME = { 201 0x40, 0x00, 0x3c, 0x00, (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b, 202 0x33, 0x72, (byte) 0xf4, (byte) 0xf5, (byte) 0xe8, 0x51, (byte) 0x9e, 0x09, 203 (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b, 0x33, 0x72, (byte) 0xb0, 0x66, 204 0x00, 0x00 205 }; 206 207 @Before setUp()208 public void setUp() throws Exception { 209 // Setup mocks for successful WificondControl operation. Failure case mocks should be 210 // created in specific tests 211 MockitoAnnotations.initMocks(this); 212 when(mWifiInjector.makeWificond()).thenReturn(mWificond); 213 when(mWificond.asBinder()).thenReturn(mWifiCondBinder); 214 when(mClientInterface.getWifiScannerImpl()).thenReturn(mWifiScannerImpl); 215 when(mWificond.createClientInterface(any())).thenReturn(mClientInterface); 216 when(mWificond.createApInterface(any())).thenReturn(mApInterface); 217 when(mWificond.tearDownClientInterface(any())).thenReturn(true); 218 when(mWificond.tearDownApInterface(any())).thenReturn(true); 219 when(mClientInterface.getWifiScannerImpl()).thenReturn(mWifiScannerImpl); 220 when(mClientInterface.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME); 221 when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); 222 mLooper = new TestLooper(); 223 mWificondControl = new WificondControl(mWifiInjector, mWifiMonitor, mCarrierNetworkConfig, 224 mAlarmManager, mLooper.getLooper(), mClock); 225 assertEquals(mClientInterface, mWificondControl.setupInterfaceForClientMode( 226 TEST_INTERFACE_NAME)); 227 verify(mWifiInjector).makeWificond(); 228 verify(mWifiCondBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); 229 } 230 231 /** 232 * Verifies that setupInterfaceForClientMode(TEST_INTERFACE_NAME) calls Wificond. 233 */ 234 @Test testSetupInterfaceForClientMode()235 public void testSetupInterfaceForClientMode() throws Exception { 236 when(mWifiInjector.makeWificond()).thenReturn(mWificond); 237 when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(mClientInterface); 238 verify(mWificond).createClientInterface(TEST_INTERFACE_NAME); 239 } 240 241 /** 242 * Verifies that setupInterfaceForClientMode(TEST_INTERFACE_NAME) calls subscribeScanEvents(). 243 */ 244 @Test testSetupInterfaceForClientModeCallsScanEventSubscripiton()245 public void testSetupInterfaceForClientModeCallsScanEventSubscripiton() throws Exception { 246 verify(mWifiScannerImpl).subscribeScanEvents(any(IScanEvent.class)); 247 } 248 249 /** 250 * Verifies that setupInterfaceForClientMode(TEST_INTERFACE_NAME) returns null when wificond is 251 * not started. 252 */ 253 @Test testSetupInterfaceForClientModeErrorWhenWificondIsNotStarted()254 public void testSetupInterfaceForClientModeErrorWhenWificondIsNotStarted() throws Exception { 255 // Invoke wificond death handler to clear the handle. 256 mWificondControl.binderDied(); 257 mLooper.dispatchAll(); 258 when(mWifiInjector.makeWificond()).thenReturn(null); 259 IClientInterface returnedClientInterface = 260 mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME); 261 assertEquals(null, returnedClientInterface); 262 verify(mWifiInjector, times(2)).makeWificond(); 263 } 264 265 /** 266 * Verifies that setupInterfaceForClientMode(TEST_INTERFACE_NAME) returns null when wificond 267 * failed to setup client interface. 268 */ 269 @Test testSetupInterfaceForClientModeErrorWhenWificondFailedToSetupInterface()270 public void testSetupInterfaceForClientModeErrorWhenWificondFailedToSetupInterface() 271 throws Exception { 272 when(mWifiInjector.makeWificond()).thenReturn(mWificond); 273 when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(null); 274 275 IClientInterface returnedClientInterface = 276 mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME); 277 assertEquals(null, returnedClientInterface); 278 } 279 280 /** 281 * Verifies that tearDownClientInterface(TEST_INTERFACE_NAME) calls Wificond. 282 */ 283 @Test testTeardownClientInterface()284 public void testTeardownClientInterface() throws Exception { 285 when(mWificond.tearDownClientInterface(TEST_INTERFACE_NAME)).thenReturn(true); 286 287 assertTrue(mWificondControl.tearDownClientInterface(TEST_INTERFACE_NAME)); 288 verify(mWifiScannerImpl).unsubscribeScanEvents(); 289 verify(mWifiScannerImpl).unsubscribePnoScanEvents(); 290 verify(mWificond).tearDownClientInterface(TEST_INTERFACE_NAME); 291 } 292 293 /** 294 * Verifies that tearDownClientInterface(TEST_INTERFACE_NAME) calls Wificond. 295 */ 296 @Test testTeardownClientInterfaceOnInvalidIface()297 public void testTeardownClientInterfaceOnInvalidIface() throws Exception { 298 when(mWificond.tearDownClientInterface(TEST_INTERFACE_NAME1)).thenReturn(true); 299 300 assertFalse(mWificondControl.tearDownClientInterface(TEST_INTERFACE_NAME1)); 301 verify(mWifiScannerImpl, never()).unsubscribeScanEvents(); 302 verify(mWifiScannerImpl, never()).unsubscribePnoScanEvents(); 303 verify(mWificond, never()).tearDownClientInterface(any()); 304 } 305 306 /** 307 * Verifies that tearDownClientInterface(TEST_INTERFACE_NAME) calls Wificond. 308 */ 309 @Test testTeardownClientInterfaceFailDueToExceptionScannerUnsubscribe()310 public void testTeardownClientInterfaceFailDueToExceptionScannerUnsubscribe() throws Exception { 311 when(mWificond.tearDownClientInterface(TEST_INTERFACE_NAME)).thenReturn(true); 312 doThrow(new RemoteException()).when(mWifiScannerImpl).unsubscribeScanEvents(); 313 314 assertFalse(mWificondControl.tearDownClientInterface(TEST_INTERFACE_NAME)); 315 verify(mWifiScannerImpl).unsubscribeScanEvents(); 316 verify(mWifiScannerImpl, never()).unsubscribePnoScanEvents(); 317 verify(mWificond, never()).tearDownClientInterface(TEST_INTERFACE_NAME); 318 } 319 /** 320 * Verifies that tearDownClientInterface(TEST_INTERFACE_NAME) calls Wificond. 321 */ 322 @Test testTeardownClientInterfaceErrorWhenWificondFailed()323 public void testTeardownClientInterfaceErrorWhenWificondFailed() throws Exception { 324 when(mWificond.tearDownClientInterface(TEST_INTERFACE_NAME)).thenReturn(false); 325 326 assertFalse(mWificondControl.tearDownClientInterface(TEST_INTERFACE_NAME)); 327 verify(mWifiScannerImpl).unsubscribeScanEvents(); 328 verify(mWifiScannerImpl).unsubscribePnoScanEvents(); 329 verify(mWificond).tearDownClientInterface(TEST_INTERFACE_NAME); 330 } 331 332 /** 333 * Verifies that the client handles are cleared after teardown. 334 */ 335 @Test testTeardownClientInterfaceClearsHandles()336 public void testTeardownClientInterfaceClearsHandles() throws Exception { 337 testTeardownClientInterface(); 338 339 assertNull(mWificondControl.signalPoll(TEST_INTERFACE_NAME)); 340 verify(mClientInterface, never()).signalPoll(); 341 342 assertFalse(mWificondControl.scan( 343 TEST_INTERFACE_NAME, WifiNative.SCAN_TYPE_LOW_LATENCY, 344 SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST)); 345 verify(mWifiScannerImpl, never()).scan(any()); 346 } 347 348 /** 349 * Verifies that setupInterfaceForSoftApMode(TEST_INTERFACE_NAME) calls wificond. 350 */ 351 @Test testSetupInterfaceForSoftApMode()352 public void testSetupInterfaceForSoftApMode() throws Exception { 353 when(mWifiInjector.makeWificond()).thenReturn(mWificond); 354 when(mWificond.createApInterface(TEST_INTERFACE_NAME)).thenReturn(mApInterface); 355 356 IApInterface returnedApInterface = 357 mWificondControl.setupInterfaceForSoftApMode(TEST_INTERFACE_NAME); 358 assertEquals(mApInterface, returnedApInterface); 359 verify(mWifiInjector).makeWificond(); 360 verify(mWifiCondBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); 361 verify(mWificond).createApInterface(TEST_INTERFACE_NAME); 362 } 363 364 /** 365 * Verifies that setupInterfaceForSoftAp() returns null when wificond is not started. 366 */ 367 @Test testSetupInterfaceForSoftApModeErrorWhenWificondIsNotStarted()368 public void testSetupInterfaceForSoftApModeErrorWhenWificondIsNotStarted() throws Exception { 369 // Invoke wificond death handler to clear the handle. 370 mWificondControl.binderDied(); 371 mLooper.dispatchAll(); 372 when(mWifiInjector.makeWificond()).thenReturn(null); 373 374 IApInterface returnedApInterface = 375 mWificondControl.setupInterfaceForSoftApMode(TEST_INTERFACE_NAME); 376 377 assertEquals(null, returnedApInterface); 378 verify(mWifiInjector, times(2)).makeWificond(); 379 } 380 381 /** 382 * Verifies that setupInterfaceForSoftApMode(TEST_INTERFACE_NAME) returns null when wificond 383 * failed to setup AP interface. 384 */ 385 @Test testSetupInterfaceForSoftApModeErrorWhenWificondFailedToSetupInterface()386 public void testSetupInterfaceForSoftApModeErrorWhenWificondFailedToSetupInterface() 387 throws Exception { 388 when(mWifiInjector.makeWificond()).thenReturn(mWificond); 389 when(mWificond.createApInterface(TEST_INTERFACE_NAME)).thenReturn(null); 390 391 IApInterface returnedApInterface = 392 mWificondControl.setupInterfaceForSoftApMode(TEST_INTERFACE_NAME); 393 assertEquals(null, returnedApInterface); 394 } 395 396 /** 397 * Verifies that tearDownClientInterface(TEST_INTERFACE_NAME) calls Wificond. 398 */ 399 @Test testTeardownSoftApInterface()400 public void testTeardownSoftApInterface() throws Exception { 401 testSetupInterfaceForSoftApMode(); 402 when(mWificond.tearDownApInterface(TEST_INTERFACE_NAME)).thenReturn(true); 403 404 assertTrue(mWificondControl.tearDownSoftApInterface(TEST_INTERFACE_NAME)); 405 verify(mWificond).tearDownApInterface(TEST_INTERFACE_NAME); 406 } 407 408 /** 409 * Verifies that tearDownSoftapInterface(TEST_INTERFACE_NAME) calls Wificond. 410 */ 411 @Test testTeardownSoftApInterfaceOnInvalidIface()412 public void testTeardownSoftApInterfaceOnInvalidIface() throws Exception { 413 testSetupInterfaceForSoftApMode(); 414 when(mWificond.tearDownApInterface(TEST_INTERFACE_NAME1)).thenReturn(true); 415 416 assertFalse(mWificondControl.tearDownSoftApInterface(TEST_INTERFACE_NAME1)); 417 verify(mWificond, never()).tearDownApInterface(any()); 418 } 419 420 /** 421 * Verifies that tearDownClientInterface(TEST_INTERFACE_NAME) calls Wificond. 422 */ 423 @Test testTeardownSoftApInterfaceErrorWhenWificondFailed()424 public void testTeardownSoftApInterfaceErrorWhenWificondFailed() throws Exception { 425 testSetupInterfaceForSoftApMode(); 426 when(mWificond.tearDownApInterface(TEST_INTERFACE_NAME)).thenReturn(false); 427 428 assertFalse(mWificondControl.tearDownSoftApInterface(TEST_INTERFACE_NAME)); 429 verify(mWificond).tearDownApInterface(TEST_INTERFACE_NAME); 430 } 431 432 /** 433 * Verifies that the SoftAp handles are cleared after teardown. 434 */ 435 @Test testTeardownSoftApInterfaceClearsHandles()436 public void testTeardownSoftApInterfaceClearsHandles() throws Exception { 437 testTeardownSoftApInterface(); 438 439 assertFalse(mWificondControl.registerApListener( 440 TEST_INTERFACE_NAME, mSoftApListener)); 441 verify(mApInterface, never()).registerCallback(any()); 442 } 443 444 /** 445 * Verifies that we can setup concurrent interfaces. 446 */ 447 @Test testSetupMulitpleInterfaces()448 public void testSetupMulitpleInterfaces() throws Exception { 449 when(mWificond.createApInterface(TEST_INTERFACE_NAME1)).thenReturn(mApInterface); 450 451 IApInterface returnedApInterface = 452 mWificondControl.setupInterfaceForSoftApMode(TEST_INTERFACE_NAME1); 453 assertEquals(mApInterface, returnedApInterface); 454 verify(mWifiInjector).makeWificond(); 455 verify(mWifiCondBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); 456 457 verify(mWificond).createClientInterface(TEST_INTERFACE_NAME); 458 verify(mWificond).createApInterface(TEST_INTERFACE_NAME1); 459 } 460 461 /** 462 * Verifies that we can setup concurrent interfaces. 463 */ 464 @Test testTeardownMulitpleInterfaces()465 public void testTeardownMulitpleInterfaces() throws Exception { 466 testSetupMulitpleInterfaces(); 467 assertTrue(mWificondControl.tearDownClientInterface(TEST_INTERFACE_NAME)); 468 assertTrue(mWificondControl.tearDownSoftApInterface(TEST_INTERFACE_NAME1)); 469 470 verify(mWificond).tearDownClientInterface(TEST_INTERFACE_NAME); 471 verify(mWificond).tearDownApInterface(TEST_INTERFACE_NAME1); 472 } 473 474 /** 475 * Verifies that tearDownInterfaces() calls wificond. 476 */ 477 @Test testTearDownInterfaces()478 public void testTearDownInterfaces() throws Exception { 479 when(mWifiInjector.makeWificond()).thenReturn(mWificond); 480 assertTrue(mWificondControl.tearDownInterfaces()); 481 verify(mWificond).tearDownInterfaces(); 482 } 483 484 /** 485 * Verifies that tearDownInterfaces() calls unsubscribeScanEvents() when there was 486 * a configured client interface. 487 */ 488 @Test testTearDownInterfacesRemovesScanEventSubscription()489 public void testTearDownInterfacesRemovesScanEventSubscription() throws Exception { 490 assertTrue(mWificondControl.tearDownInterfaces()); 491 verify(mWifiScannerImpl).unsubscribeScanEvents(); 492 } 493 494 495 /** 496 * Verifies that tearDownInterfaces() returns false when wificond is not started. 497 */ 498 @Test testTearDownInterfacesErrorWhenWificondIsNotStarterd()499 public void testTearDownInterfacesErrorWhenWificondIsNotStarterd() throws Exception { 500 // Invoke wificond death handler to clear the handle. 501 mWificondControl.binderDied(); 502 mLooper.dispatchAll(); 503 when(mWifiInjector.makeWificond()).thenReturn(null); 504 assertFalse(mWificondControl.tearDownInterfaces()); 505 } 506 507 /** 508 * Verifies that signalPoll() calls wificond. 509 */ 510 @Test testSignalPoll()511 public void testSignalPoll() throws Exception { 512 when(mWifiInjector.makeWificond()).thenReturn(mWificond); 513 when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(mClientInterface); 514 515 mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME); 516 mWificondControl.signalPoll(TEST_INTERFACE_NAME); 517 verify(mClientInterface).signalPoll(); 518 } 519 520 /** 521 * Verifies that signalPoll() returns null when there is no configured client interface. 522 */ 523 @Test testSignalPollErrorWhenNoClientInterfaceConfigured()524 public void testSignalPollErrorWhenNoClientInterfaceConfigured() throws Exception { 525 when(mWifiInjector.makeWificond()).thenReturn(mWificond); 526 when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(mClientInterface); 527 528 // Configure client interface. 529 IClientInterface returnedClientInterface = 530 mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME); 531 assertEquals(mClientInterface, returnedClientInterface); 532 533 // Tear down interfaces. 534 assertTrue(mWificondControl.tearDownInterfaces()); 535 536 // Signal poll should fail. 537 assertEquals(null, mWificondControl.signalPoll(TEST_INTERFACE_NAME)); 538 } 539 540 /** 541 * Verifies that getTxPacketCounters() calls wificond. 542 */ 543 @Test testGetTxPacketCounters()544 public void testGetTxPacketCounters() throws Exception { 545 when(mWifiInjector.makeWificond()).thenReturn(mWificond); 546 when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(mClientInterface); 547 548 mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME); 549 mWificondControl.getTxPacketCounters(TEST_INTERFACE_NAME); 550 verify(mClientInterface).getPacketCounters(); 551 } 552 553 /** 554 * Verifies that getTxPacketCounters() returns null when there is no configured client 555 * interface. 556 */ 557 @Test testGetTxPacketCountersErrorWhenNoClientInterfaceConfigured()558 public void testGetTxPacketCountersErrorWhenNoClientInterfaceConfigured() throws Exception { 559 when(mWifiInjector.makeWificond()).thenReturn(mWificond); 560 when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(mClientInterface); 561 562 // Configure client interface. 563 IClientInterface returnedClientInterface = 564 mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME); 565 assertEquals(mClientInterface, returnedClientInterface); 566 567 // Tear down interfaces. 568 assertTrue(mWificondControl.tearDownInterfaces()); 569 570 // Signal poll should fail. 571 assertEquals(null, mWificondControl.getTxPacketCounters(TEST_INTERFACE_NAME)); 572 } 573 574 /** 575 * Verifies that getScanResults() returns null when there is no configured client 576 * interface. 577 */ 578 @Test testGetScanResultsErrorWhenNoClientInterfaceConfigured()579 public void testGetScanResultsErrorWhenNoClientInterfaceConfigured() throws Exception { 580 when(mWifiInjector.makeWificond()).thenReturn(mWificond); 581 when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(mClientInterface); 582 583 // Configure client interface. 584 IClientInterface returnedClientInterface = 585 mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME); 586 assertEquals(mClientInterface, returnedClientInterface); 587 588 // Tear down interfaces. 589 assertTrue(mWificondControl.tearDownInterfaces()); 590 591 // getScanResults should fail. 592 assertEquals(0, 593 mWificondControl.getScanResults(TEST_INTERFACE_NAME, 594 WificondControl.SCAN_TYPE_SINGLE_SCAN).size()); 595 } 596 597 /** 598 * Verifies that getScanResults() can parse NativeScanResult from wificond correctly, 599 */ 600 @Test testGetScanResults()601 public void testGetScanResults() throws Exception { 602 assertNotNull(mWifiScannerImpl); 603 604 // Mock the returned array of NativeScanResult. 605 NativeScanResult[] mockScanResults = {MOCK_NATIVE_SCAN_RESULT}; 606 when(mWifiScannerImpl.getScanResults()).thenReturn(mockScanResults); 607 608 ArrayList<ScanDetail> returnedScanResults = mWificondControl.getScanResults( 609 TEST_INTERFACE_NAME, WificondControl.SCAN_TYPE_SINGLE_SCAN); 610 // The test IEs {@link #TEST_INFO_ELEMENT} doesn't contained RSN IE, which means non-EAP 611 // AP. So verify carrier network is not checked, since EAP is currently required for a 612 // carrier network. 613 verify(mCarrierNetworkConfig, never()).isCarrierNetwork(anyString()); 614 assertEquals(mockScanResults.length, returnedScanResults.size()); 615 // Since NativeScanResult is organized differently from ScanResult, this only checks 616 // a few fields. 617 for (int i = 0; i < mockScanResults.length; i++) { 618 assertArrayEquals(mockScanResults[i].ssid, 619 returnedScanResults.get(i).getScanResult().SSID.getBytes()); 620 assertEquals(mockScanResults[i].frequency, 621 returnedScanResults.get(i).getScanResult().frequency); 622 assertEquals(mockScanResults[i].tsf, 623 returnedScanResults.get(i).getScanResult().timestamp); 624 } 625 } 626 627 /** 628 * Verifies that scan result's carrier network info {@link ScanResult#isCarrierAp} and 629 * {@link ScanResult#getCarrierApEapType} is set appropriated based on the carrier network 630 * config. 631 * 632 * @throws Exception 633 */ 634 @Test testGetScanResultsForCarrierAp()635 public void testGetScanResultsForCarrierAp() throws Exception { 636 assertNotNull(mWifiScannerImpl); 637 638 // Include RSN IE to indicate EAP key management. 639 ByteArrayOutputStream out = new ByteArrayOutputStream(); 640 out.write(TEST_INFO_ELEMENT_SSID); 641 out.write(TEST_INFO_ELEMENT_RSN); 642 NativeScanResult nativeScanResult = new NativeScanResult(MOCK_NATIVE_SCAN_RESULT); 643 nativeScanResult.infoElement = out.toByteArray(); 644 when(mWifiScannerImpl.getScanResults()).thenReturn( 645 new NativeScanResult[] {nativeScanResult}); 646 647 // AP associated with a carrier network. 648 int eapType = WifiEnterpriseConfig.Eap.SIM; 649 String carrierName = "Test Carrier"; 650 when(mCarrierNetworkConfig.isCarrierNetwork(new String(nativeScanResult.ssid))) 651 .thenReturn(true); 652 when(mCarrierNetworkConfig.getNetworkEapType(new String(nativeScanResult.ssid))) 653 .thenReturn(eapType); 654 when(mCarrierNetworkConfig.getCarrierName(new String(nativeScanResult.ssid))) 655 .thenReturn(carrierName); 656 ArrayList<ScanDetail> returnedScanResults = mWificondControl.getScanResults( 657 TEST_INTERFACE_NAME, WificondControl.SCAN_TYPE_SINGLE_SCAN); 658 assertEquals(1, returnedScanResults.size()); 659 // Verify returned scan result. 660 ScanResult scanResult = returnedScanResults.get(0).getScanResult(); 661 assertArrayEquals(nativeScanResult.ssid, scanResult.SSID.getBytes()); 662 assertTrue(scanResult.isCarrierAp); 663 assertEquals(eapType, scanResult.carrierApEapType); 664 assertEquals(carrierName, scanResult.carrierName); 665 reset(mCarrierNetworkConfig); 666 667 // AP not associated with a carrier network. 668 when(mCarrierNetworkConfig.isCarrierNetwork(new String(nativeScanResult.ssid))) 669 .thenReturn(false); 670 returnedScanResults = mWificondControl.getScanResults( 671 TEST_INTERFACE_NAME, WificondControl.SCAN_TYPE_SINGLE_SCAN); 672 assertEquals(1, returnedScanResults.size()); 673 // Verify returned scan result. 674 scanResult = returnedScanResults.get(0).getScanResult(); 675 assertArrayEquals(nativeScanResult.ssid, scanResult.SSID.getBytes()); 676 assertFalse(scanResult.isCarrierAp); 677 assertEquals(ScanResult.UNSPECIFIED, scanResult.carrierApEapType); 678 assertEquals(null, scanResult.carrierName); 679 } 680 681 /** 682 * Verifies that getScanResults() can parse NativeScanResult from wificond correctly, 683 * when there is radio chain info. 684 */ 685 @Test testGetScanResultsWithRadioChainInfo()686 public void testGetScanResultsWithRadioChainInfo() throws Exception { 687 assertNotNull(mWifiScannerImpl); 688 689 // Mock the returned array of NativeScanResult. 690 NativeScanResult nativeScanResult = new NativeScanResult(MOCK_NATIVE_SCAN_RESULT); 691 // Add radio chain info 692 ArrayList<RadioChainInfo> nativeRadioChainInfos = new ArrayList<RadioChainInfo>() {{ 693 add(MOCK_NATIVE_RADIO_CHAIN_INFO_1); 694 add(MOCK_NATIVE_RADIO_CHAIN_INFO_2); 695 }}; 696 nativeScanResult.radioChainInfos = nativeRadioChainInfos; 697 NativeScanResult[] mockScanResults = { nativeScanResult }; 698 699 when(mWifiScannerImpl.getScanResults()).thenReturn(mockScanResults); 700 701 ArrayList<ScanDetail> returnedScanResults = mWificondControl.getScanResults( 702 TEST_INTERFACE_NAME, WificondControl.SCAN_TYPE_SINGLE_SCAN); 703 // The test IEs {@link #TEST_INFO_ELEMENT} doesn't contained RSN IE, which means non-EAP 704 // AP. So verify carrier network is not checked, since EAP is currently required for a 705 // carrier network. 706 verify(mCarrierNetworkConfig, never()).isCarrierNetwork(anyString()); 707 assertEquals(mockScanResults.length, returnedScanResults.size()); 708 // Since NativeScanResult is organized differently from ScanResult, this only checks 709 // a few fields. 710 for (int i = 0; i < mockScanResults.length; i++) { 711 assertArrayEquals(mockScanResults[i].ssid, 712 returnedScanResults.get(i).getScanResult().SSID.getBytes()); 713 assertEquals(mockScanResults[i].frequency, 714 returnedScanResults.get(i).getScanResult().frequency); 715 assertEquals(mockScanResults[i].tsf, 716 returnedScanResults.get(i).getScanResult().timestamp); 717 assertRadioChainInfosEqual(nativeRadioChainInfos, 718 returnedScanResults.get(i).getScanResult().radioChainInfos); 719 } 720 } 721 722 /** 723 * Verifies that Scan() can convert input parameters to SingleScanSettings correctly. 724 */ 725 @Test testScan()726 public void testScan() throws Exception { 727 when(mWifiScannerImpl.scan(any(SingleScanSettings.class))).thenReturn(true); 728 assertTrue(mWificondControl.scan( 729 TEST_INTERFACE_NAME, WifiNative.SCAN_TYPE_LOW_POWER, 730 SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST)); 731 verify(mWifiScannerImpl).scan(argThat(new ScanMatcher( 732 IWifiScannerImpl.SCAN_TYPE_LOW_POWER, 733 SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST))); 734 } 735 736 /** 737 * Verifies that Scan() removes duplicates hiddenSsids passed in from input. 738 */ 739 @Test testScanWithDuplicateHiddenSsids()740 public void testScanWithDuplicateHiddenSsids() throws Exception { 741 when(mWifiScannerImpl.scan(any(SingleScanSettings.class))).thenReturn(true); 742 // Create a list of hiddenSsid that has a duplicate element 743 List<String> hiddenSsidWithDup = new ArrayList<>(SCAN_HIDDEN_NETWORK_SSID_LIST); 744 hiddenSsidWithDup.add(SCAN_HIDDEN_NETWORK_SSID_LIST.get(0)); 745 assertEquals(hiddenSsidWithDup.get(0), 746 hiddenSsidWithDup.get(hiddenSsidWithDup.size() - 1)); 747 // Pass the List with duplicate elements into scan() 748 assertTrue(mWificondControl.scan( 749 TEST_INTERFACE_NAME, WifiNative.SCAN_TYPE_LOW_POWER, 750 SCAN_FREQ_SET, hiddenSsidWithDup)); 751 // But the argument passed down should have the duplicate removed. 752 verify(mWifiScannerImpl).scan(argThat(new ScanMatcher( 753 IWifiScannerImpl.SCAN_TYPE_LOW_POWER, 754 SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST))); 755 } 756 757 /** 758 * Verifies that Scan() can handle null input parameters correctly. 759 */ 760 @Test testScanNullParameters()761 public void testScanNullParameters() throws Exception { 762 when(mWifiScannerImpl.scan(any(SingleScanSettings.class))).thenReturn(true); 763 assertTrue(mWificondControl.scan( 764 TEST_INTERFACE_NAME, WifiNative.SCAN_TYPE_HIGH_ACCURACY, null, null)); 765 verify(mWifiScannerImpl).scan(argThat(new ScanMatcher( 766 IWifiScannerImpl.SCAN_TYPE_HIGH_ACCURACY, null, null))); 767 } 768 769 /** 770 * Verifies that Scan() can handle wificond scan failure. 771 */ 772 @Test testScanFailure()773 public void testScanFailure() throws Exception { 774 when(mWifiScannerImpl.scan(any(SingleScanSettings.class))).thenReturn(false); 775 assertFalse(mWificondControl.scan( 776 TEST_INTERFACE_NAME, WifiNative.SCAN_TYPE_LOW_LATENCY, 777 SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST)); 778 verify(mWifiScannerImpl).scan(any(SingleScanSettings.class)); 779 } 780 781 /** 782 * Verifies that Scan() can handle invalid type. 783 */ 784 @Test testScanFailureDueToInvalidType()785 public void testScanFailureDueToInvalidType() throws Exception { 786 assertFalse(mWificondControl.scan( 787 TEST_INTERFACE_NAME, 100, 788 SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST)); 789 verify(mWifiScannerImpl, never()).scan(any(SingleScanSettings.class)); 790 } 791 792 /** 793 * Verifies that startPnoScan() can convert input parameters to PnoSettings correctly. 794 */ 795 @Test testStartPnoScan()796 public void testStartPnoScan() throws Exception { 797 when(mWifiScannerImpl.startPnoScan(any(PnoSettings.class))).thenReturn(true); 798 assertTrue(mWificondControl.startPnoScan(TEST_INTERFACE_NAME, TEST_PNO_SETTINGS)); 799 verify(mWifiScannerImpl).startPnoScan(argThat(new PnoScanMatcher(TEST_PNO_SETTINGS))); 800 } 801 802 /** 803 * Verifies that stopPnoScan() calls underlying wificond. 804 */ 805 @Test testStopPnoScan()806 public void testStopPnoScan() throws Exception { 807 when(mWifiScannerImpl.stopPnoScan()).thenReturn(true); 808 assertTrue(mWificondControl.stopPnoScan(TEST_INTERFACE_NAME)); 809 verify(mWifiScannerImpl).stopPnoScan(); 810 } 811 812 /** 813 * Verifies that stopPnoScan() can handle wificond failure. 814 */ 815 @Test testStopPnoScanFailure()816 public void testStopPnoScanFailure() throws Exception { 817 818 when(mWifiScannerImpl.stopPnoScan()).thenReturn(false); 819 assertFalse(mWificondControl.stopPnoScan(TEST_INTERFACE_NAME)); 820 verify(mWifiScannerImpl).stopPnoScan(); 821 } 822 823 /** 824 * Verifies that WificondControl can invoke WifiMonitor broadcast methods upon scan 825 * reuslt event. 826 */ 827 @Test testScanResultEvent()828 public void testScanResultEvent() throws Exception { 829 ArgumentCaptor<IScanEvent> messageCaptor = ArgumentCaptor.forClass(IScanEvent.class); 830 verify(mWifiScannerImpl).subscribeScanEvents(messageCaptor.capture()); 831 IScanEvent scanEvent = messageCaptor.getValue(); 832 assertNotNull(scanEvent); 833 scanEvent.OnScanResultReady(); 834 835 verify(mWifiMonitor).broadcastScanResultEvent(any(String.class)); 836 } 837 838 /** 839 * Verifies that WificondControl can invoke WifiMonitor broadcast methods upon scan 840 * failed event. 841 */ 842 @Test testScanFailedEvent()843 public void testScanFailedEvent() throws Exception { 844 845 ArgumentCaptor<IScanEvent> messageCaptor = ArgumentCaptor.forClass(IScanEvent.class); 846 verify(mWifiScannerImpl).subscribeScanEvents(messageCaptor.capture()); 847 IScanEvent scanEvent = messageCaptor.getValue(); 848 assertNotNull(scanEvent); 849 scanEvent.OnScanFailed(); 850 851 verify(mWifiMonitor).broadcastScanFailedEvent(any(String.class)); 852 } 853 854 /** 855 * Verifies that WificondControl can invoke WifiMonitor broadcast methods upon pno scan 856 * result event. 857 */ 858 @Test testPnoScanResultEvent()859 public void testPnoScanResultEvent() throws Exception { 860 ArgumentCaptor<IPnoScanEvent> messageCaptor = ArgumentCaptor.forClass(IPnoScanEvent.class); 861 verify(mWifiScannerImpl).subscribePnoScanEvents(messageCaptor.capture()); 862 IPnoScanEvent pnoScanEvent = messageCaptor.getValue(); 863 assertNotNull(pnoScanEvent); 864 pnoScanEvent.OnPnoNetworkFound(); 865 verify(mWifiMonitor).broadcastPnoScanResultEvent(any(String.class)); 866 } 867 868 /** 869 * Verifies that WificondControl can invoke WifiMetrics pno scan count methods upon pno event. 870 */ 871 @Test testPnoScanEventsForMetrics()872 public void testPnoScanEventsForMetrics() throws Exception { 873 ArgumentCaptor<IPnoScanEvent> messageCaptor = ArgumentCaptor.forClass(IPnoScanEvent.class); 874 verify(mWifiScannerImpl).subscribePnoScanEvents(messageCaptor.capture()); 875 IPnoScanEvent pnoScanEvent = messageCaptor.getValue(); 876 assertNotNull(pnoScanEvent); 877 878 pnoScanEvent.OnPnoNetworkFound(); 879 verify(mWifiMetrics).incrementPnoFoundNetworkEventCount(); 880 881 pnoScanEvent.OnPnoScanFailed(); 882 verify(mWifiMetrics).incrementPnoScanFailedCount(); 883 884 pnoScanEvent.OnPnoScanOverOffloadStarted(); 885 verify(mWifiMetrics).incrementPnoScanStartedOverOffloadCount(); 886 887 pnoScanEvent.OnPnoScanOverOffloadFailed(0); 888 verify(mWifiMetrics).incrementPnoScanFailedOverOffloadCount(); 889 } 890 891 /** 892 * Verifies that startPnoScan() can invoke WifiMetrics pno scan count methods correctly. 893 */ 894 @Test testStartPnoScanForMetrics()895 public void testStartPnoScanForMetrics() throws Exception { 896 when(mWifiScannerImpl.startPnoScan(any(PnoSettings.class))).thenReturn(false); 897 assertFalse(mWificondControl.startPnoScan(TEST_INTERFACE_NAME, TEST_PNO_SETTINGS)); 898 verify(mWifiMetrics).incrementPnoScanStartAttempCount(); 899 verify(mWifiMetrics).incrementPnoScanFailedCount(); 900 } 901 902 /** 903 * Verifies that abortScan() calls underlying wificond. 904 */ 905 @Test testAbortScan()906 public void testAbortScan() throws Exception { 907 mWificondControl.abortScan(TEST_INTERFACE_NAME); 908 verify(mWifiScannerImpl).abortScan(); 909 } 910 911 /** 912 * Ensures that the Ap interface callbacks are forwarded to the 913 * SoftApListener used for starting soft AP. 914 */ 915 @Test testSoftApListenerInvocation()916 public void testSoftApListenerInvocation() throws Exception { 917 testSetupInterfaceForSoftApMode(); 918 919 WifiConfiguration config = new WifiConfiguration(); 920 config.SSID = new String(TEST_SSID, StandardCharsets.UTF_8); 921 922 when(mApInterface.registerCallback(any())).thenReturn(true); 923 924 final ArgumentCaptor<IApInterfaceEventCallback> apInterfaceCallbackCaptor = 925 ArgumentCaptor.forClass(IApInterfaceEventCallback.class); 926 927 assertTrue(mWificondControl.registerApListener( 928 TEST_INTERFACE_NAME, mSoftApListener)); 929 verify(mApInterface).registerCallback(apInterfaceCallbackCaptor.capture()); 930 931 int numStations = 5; 932 apInterfaceCallbackCaptor.getValue().onNumAssociatedStationsChanged(numStations); 933 verify(mSoftApListener).onNumAssociatedStationsChanged(eq(numStations)); 934 935 int channelFrequency = 2437; 936 int channelBandwidth = IApInterfaceEventCallback.BANDWIDTH_20; 937 apInterfaceCallbackCaptor.getValue().onSoftApChannelSwitched(channelFrequency, 938 channelBandwidth); 939 verify(mSoftApListener).onSoftApChannelSwitched(eq(channelFrequency), eq(channelBandwidth)); 940 } 941 942 /** 943 * Verifies registration and invocation of wificond death handler. 944 */ 945 @Test testRegisterDeathHandler()946 public void testRegisterDeathHandler() throws Exception { 947 WifiNative.WificondDeathEventHandler handler = 948 mock(WifiNative.WificondDeathEventHandler.class); 949 assertTrue(mWificondControl.initialize(handler)); 950 verify(mWificond).tearDownInterfaces(); 951 mWificondControl.binderDied(); 952 mLooper.dispatchAll(); 953 verify(handler).onDeath(); 954 } 955 956 /** 957 * Verifies handling of wificond death and ensures that all internal state is cleared and 958 * handlers are invoked. 959 */ 960 @Test testDeathHandling()961 public void testDeathHandling() throws Exception { 962 WifiNative.WificondDeathEventHandler handler = 963 mock(WifiNative.WificondDeathEventHandler.class); 964 assertTrue(mWificondControl.initialize(handler)); 965 966 testSetupInterfaceForClientMode(); 967 968 mWificondControl.binderDied(); 969 mLooper.dispatchAll(); 970 verify(handler).onDeath(); 971 972 // The handles should be cleared after death. 973 assertNull(mWificondControl.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ)); 974 verify(mWificond, never()).getAvailable5gNonDFSChannels(); 975 } 976 977 /** 978 * sendMgmtFrame() should fail if a null callback is passed in. 979 */ 980 @Test testSendMgmtFrameNullCallback()981 public void testSendMgmtFrameNullCallback() throws Exception { 982 mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, null, TEST_MCS_RATE); 983 984 verify(mClientInterface, never()).SendMgmtFrame(any(), any(), anyInt()); 985 } 986 987 /** 988 * sendMgmtFrame() should fail if a null frame is passed in. 989 */ 990 @Test testSendMgmtFrameNullFrame()991 public void testSendMgmtFrameNullFrame() throws Exception { 992 mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, null, 993 mSendMgmtFrameCallback, TEST_MCS_RATE); 994 995 verify(mClientInterface, never()).SendMgmtFrame(any(), any(), anyInt()); 996 verify(mSendMgmtFrameCallback).onFailure(anyInt()); 997 } 998 999 /** 1000 * sendMgmtFrame() should fail if an interface name that does not exist is passed in. 1001 */ 1002 @Test testSendMgmtFrameInvalidInterfaceName()1003 public void testSendMgmtFrameInvalidInterfaceName() throws Exception { 1004 mWificondControl.sendMgmtFrame(TEST_INVALID_INTERFACE_NAME, TEST_PROBE_FRAME, 1005 mSendMgmtFrameCallback, TEST_MCS_RATE); 1006 1007 verify(mClientInterface, never()).SendMgmtFrame(any(), any(), anyInt()); 1008 verify(mSendMgmtFrameCallback).onFailure(anyInt()); 1009 } 1010 1011 /** 1012 * sendMgmtFrame() should fail if it is called a second time before the first call completed. 1013 */ 1014 @Test testSendMgmtFrameCalledTwiceBeforeFinished()1015 public void testSendMgmtFrameCalledTwiceBeforeFinished() throws Exception { 1016 SendMgmtFrameCallback cb1 = mock(SendMgmtFrameCallback.class); 1017 SendMgmtFrameCallback cb2 = mock(SendMgmtFrameCallback.class); 1018 1019 mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb1, TEST_MCS_RATE); 1020 verify(cb1, never()).onFailure(anyInt()); 1021 verify(mClientInterface, times(1)) 1022 .SendMgmtFrame(AdditionalMatchers.aryEq(TEST_PROBE_FRAME), 1023 any(), eq(TEST_MCS_RATE)); 1024 1025 mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb2, TEST_MCS_RATE); 1026 verify(cb2).onFailure(WifiNative.SEND_MGMT_FRAME_ERROR_ALREADY_STARTED); 1027 // verify SendMgmtFrame() still was only called once i.e. not called again 1028 verify(mClientInterface, times(1)) 1029 .SendMgmtFrame(any(), any(), anyInt()); 1030 } 1031 1032 /** 1033 * Tests that when a RemoteException is triggered on AIDL call, onFailure() is called only once. 1034 */ 1035 @Test testSendMgmtFrameThrowsException()1036 public void testSendMgmtFrameThrowsException() throws Exception { 1037 SendMgmtFrameCallback cb = mock(SendMgmtFrameCallback.class); 1038 1039 final ArgumentCaptor<ISendMgmtFrameEvent> sendMgmtFrameEventCaptor = 1040 ArgumentCaptor.forClass(ISendMgmtFrameEvent.class); 1041 1042 doThrow(new RemoteException()).when(mClientInterface) 1043 .SendMgmtFrame(any(), sendMgmtFrameEventCaptor.capture(), anyInt()); 1044 1045 final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor = 1046 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class); 1047 final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class); 1048 doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(), 1049 alarmListenerCaptor.capture(), handlerCaptor.capture()); 1050 1051 mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, 1052 cb, TEST_MCS_RATE); 1053 mLooper.dispatchAll(); 1054 1055 verify(cb).onFailure(anyInt()); 1056 verify(mAlarmManager).cancel(eq(alarmListenerCaptor.getValue())); 1057 1058 sendMgmtFrameEventCaptor.getValue().OnFailure(WifiNative.SEND_MGMT_FRAME_ERROR_UNKNOWN); 1059 mLooper.dispatchAll(); 1060 1061 handlerCaptor.getValue().post(() -> alarmListenerCaptor.getValue().onAlarm()); 1062 mLooper.dispatchAll(); 1063 1064 verifyNoMoreInteractions(cb); 1065 } 1066 1067 /** 1068 * Tests that the onAck() callback is triggered correctly. 1069 */ 1070 @Test testSendMgmtFrameSuccess()1071 public void testSendMgmtFrameSuccess() throws Exception { 1072 SendMgmtFrameCallback cb = mock(SendMgmtFrameCallback.class); 1073 1074 final ArgumentCaptor<ISendMgmtFrameEvent> sendMgmtFrameEventCaptor = 1075 ArgumentCaptor.forClass(ISendMgmtFrameEvent.class); 1076 doNothing().when(mClientInterface) 1077 .SendMgmtFrame(any(), sendMgmtFrameEventCaptor.capture(), anyInt()); 1078 final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor = 1079 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class); 1080 final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class); 1081 doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(), 1082 alarmListenerCaptor.capture(), handlerCaptor.capture()); 1083 mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb, TEST_MCS_RATE); 1084 1085 sendMgmtFrameEventCaptor.getValue().OnAck(TEST_SEND_MGMT_FRAME_ELAPSED_TIME_MS); 1086 mLooper.dispatchAll(); 1087 verify(cb).onAck(eq(TEST_SEND_MGMT_FRAME_ELAPSED_TIME_MS)); 1088 verify(cb, never()).onFailure(anyInt()); 1089 verify(mAlarmManager).cancel(eq(alarmListenerCaptor.getValue())); 1090 1091 // verify that even if timeout is triggered afterwards, SendMgmtFrameCallback is not 1092 // triggered again 1093 handlerCaptor.getValue().post(() -> alarmListenerCaptor.getValue().onAlarm()); 1094 mLooper.dispatchAll(); 1095 verify(cb, times(1)).onAck(anyInt()); 1096 verify(cb, never()).onFailure(anyInt()); 1097 } 1098 1099 /** 1100 * Tests that the onFailure() callback is triggered correctly. 1101 */ 1102 @Test testSendMgmtFrameFailure()1103 public void testSendMgmtFrameFailure() throws Exception { 1104 SendMgmtFrameCallback cb = mock(SendMgmtFrameCallback.class); 1105 1106 final ArgumentCaptor<ISendMgmtFrameEvent> sendMgmtFrameEventCaptor = 1107 ArgumentCaptor.forClass(ISendMgmtFrameEvent.class); 1108 doNothing().when(mClientInterface) 1109 .SendMgmtFrame(any(), sendMgmtFrameEventCaptor.capture(), anyInt()); 1110 final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor = 1111 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class); 1112 final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class); 1113 doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(), 1114 alarmListenerCaptor.capture(), handlerCaptor.capture()); 1115 mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb, TEST_MCS_RATE); 1116 1117 sendMgmtFrameEventCaptor.getValue().OnFailure(WifiNative.SEND_MGMT_FRAME_ERROR_UNKNOWN); 1118 mLooper.dispatchAll(); 1119 verify(cb, never()).onAck(anyInt()); 1120 verify(cb).onFailure(eq(WifiNative.SEND_MGMT_FRAME_ERROR_UNKNOWN)); 1121 verify(mAlarmManager).cancel(eq(alarmListenerCaptor.getValue())); 1122 1123 // verify that even if timeout is triggered afterwards, SendMgmtFrameCallback is not 1124 // triggered again 1125 handlerCaptor.getValue().post(() -> alarmListenerCaptor.getValue().onAlarm()); 1126 mLooper.dispatchAll(); 1127 verify(cb, never()).onAck(anyInt()); 1128 verify(cb, times(1)).onFailure(anyInt()); 1129 } 1130 1131 /** 1132 * Tests that the onTimeout() callback is triggered correctly. 1133 */ 1134 @Test testSendMgmtFrameTimeout()1135 public void testSendMgmtFrameTimeout() throws Exception { 1136 SendMgmtFrameCallback cb = mock(SendMgmtFrameCallback.class); 1137 1138 final ArgumentCaptor<ISendMgmtFrameEvent> sendMgmtFrameEventCaptor = 1139 ArgumentCaptor.forClass(ISendMgmtFrameEvent.class); 1140 doNothing().when(mClientInterface) 1141 .SendMgmtFrame(any(), sendMgmtFrameEventCaptor.capture(), anyInt()); 1142 final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor = 1143 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class); 1144 final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class); 1145 doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(), 1146 alarmListenerCaptor.capture(), handlerCaptor.capture()); 1147 mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb, TEST_MCS_RATE); 1148 1149 handlerCaptor.getValue().post(() -> alarmListenerCaptor.getValue().onAlarm()); 1150 mLooper.dispatchAll(); 1151 verify(cb, never()).onAck(anyInt()); 1152 verify(cb).onFailure(eq(WifiNative.SEND_MGMT_FRAME_ERROR_TIMEOUT)); 1153 1154 // verify that even if onAck() callback is triggered after timeout, 1155 // SendMgmtFrameCallback is not triggered again 1156 sendMgmtFrameEventCaptor.getValue().OnAck(TEST_SEND_MGMT_FRAME_ELAPSED_TIME_MS); 1157 mLooper.dispatchAll(); 1158 verify(cb, never()).onAck(anyInt()); 1159 verify(cb, times(1)).onFailure(anyInt()); 1160 } 1161 1162 /** 1163 * Tests every possible test outcome followed by every other test outcome to ensure that the 1164 * internal state is reset correctly between calls. 1165 * i.e. (success, success), (success, failure), (success, timeout), 1166 * (failure, failure), (failure, success), (failure, timeout), 1167 * (timeout, timeout), (timeout, success), (timeout, failure) 1168 * 1169 * Also tests that internal state is reset correctly after a transient AIDL RemoteException. 1170 */ 1171 @Test testSendMgmtFrameMixed()1172 public void testSendMgmtFrameMixed() throws Exception { 1173 testSendMgmtFrameThrowsException(); 1174 testSendMgmtFrameSuccess(); 1175 testSendMgmtFrameSuccess(); 1176 testSendMgmtFrameFailure(); 1177 testSendMgmtFrameFailure(); 1178 testSendMgmtFrameTimeout(); 1179 testSendMgmtFrameTimeout(); 1180 testSendMgmtFrameSuccess(); 1181 testSendMgmtFrameTimeout(); 1182 testSendMgmtFrameFailure(); 1183 testSendMgmtFrameSuccess(); 1184 } 1185 1186 /** 1187 * Tests that OnAck() does not perform any non-thread-safe operations on the binder thread. 1188 * 1189 * The sequence of instructions are: 1190 * 1. post onAlarm() onto main thread 1191 * 2. OnAck() 1192 * 3. mLooper.dispatchAll() 1193 * 1194 * The actual order of execution is: 1195 * 1. binder thread portion of OnAck() 1196 * 2. onAlarm() (which purely executes on the main thread) 1197 * 3. main thread portion of OnAck() 1198 * 1199 * If the binder thread portion of OnAck() is not thread-safe, it can possibly mess up 1200 * onAlarm(). Tests that this does not occur. 1201 */ 1202 @Test testSendMgmtFrameTimeoutAckThreadSafe()1203 public void testSendMgmtFrameTimeoutAckThreadSafe() throws Exception { 1204 final ArgumentCaptor<ISendMgmtFrameEvent> sendMgmtFrameEventCaptor = 1205 ArgumentCaptor.forClass(ISendMgmtFrameEvent.class); 1206 doNothing().when(mClientInterface) 1207 .SendMgmtFrame(any(), sendMgmtFrameEventCaptor.capture(), anyInt()); 1208 final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor = 1209 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class); 1210 final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class); 1211 doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(), 1212 alarmListenerCaptor.capture(), handlerCaptor.capture()); 1213 mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, 1214 mSendMgmtFrameCallback, TEST_MCS_RATE); 1215 1216 // AlarmManager should post the onAlarm() callback onto the handler, but since we are 1217 // triggering onAlarm() ourselves during the test, manually post onto handler 1218 handlerCaptor.getValue().post(() -> alarmListenerCaptor.getValue().onAlarm()); 1219 // OnAck posts to the handler 1220 sendMgmtFrameEventCaptor.getValue().OnAck(TEST_SEND_MGMT_FRAME_ELAPSED_TIME_MS); 1221 mLooper.dispatchAll(); 1222 verify(mSendMgmtFrameCallback, never()).onAck(anyInt()); 1223 verify(mSendMgmtFrameCallback).onFailure(eq(WifiNative.SEND_MGMT_FRAME_ERROR_TIMEOUT)); 1224 } 1225 1226 /** 1227 * See {@link #testSendMgmtFrameTimeoutAckThreadSafe()}. This test replaces OnAck() with 1228 * OnFailure(). 1229 */ 1230 @Test testSendMgmtFrameTimeoutFailureThreadSafe()1231 public void testSendMgmtFrameTimeoutFailureThreadSafe() throws Exception { 1232 final ArgumentCaptor<ISendMgmtFrameEvent> sendMgmtFrameEventCaptor = 1233 ArgumentCaptor.forClass(ISendMgmtFrameEvent.class); 1234 doNothing().when(mClientInterface) 1235 .SendMgmtFrame(any(), sendMgmtFrameEventCaptor.capture(), anyInt()); 1236 final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor = 1237 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class); 1238 final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class); 1239 doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(), 1240 alarmListenerCaptor.capture(), handlerCaptor.capture()); 1241 mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, 1242 mSendMgmtFrameCallback, TEST_MCS_RATE); 1243 1244 // AlarmManager should post the onAlarm() callback onto the handler, but since we are 1245 // triggering onAlarm() ourselves during the test, manually post onto handler 1246 handlerCaptor.getValue().post(() -> alarmListenerCaptor.getValue().onAlarm()); 1247 // OnFailure posts to the handler 1248 sendMgmtFrameEventCaptor.getValue().OnFailure(WifiNative.SEND_MGMT_FRAME_ERROR_UNKNOWN); 1249 mLooper.dispatchAll(); 1250 verify(mSendMgmtFrameCallback).onFailure(eq(WifiNative.SEND_MGMT_FRAME_ERROR_TIMEOUT)); 1251 } 1252 assertRadioChainInfosEqual( List<RadioChainInfo> expected, android.net.wifi.ScanResult.RadioChainInfo[] actual)1253 private void assertRadioChainInfosEqual( 1254 List<RadioChainInfo> expected, android.net.wifi.ScanResult.RadioChainInfo[] actual) { 1255 assertEquals(expected.size(), actual.length); 1256 for (int i = 0; i < actual.length; i++) { 1257 RadioChainInfo nativeRadioChainInfo = 1258 new RadioChainInfo(actual[i].id, actual[i].level); 1259 assertTrue(expected.contains(nativeRadioChainInfo)); 1260 } 1261 } 1262 1263 // Create a ArgumentMatcher which captures a SingleScanSettings parameter and checks if it 1264 // matches the provided frequency set and ssid set. 1265 private class ScanMatcher implements ArgumentMatcher<SingleScanSettings> { 1266 int mExpectedScanType; 1267 private final Set<Integer> mExpectedFreqs; 1268 private final List<String> mExpectedSsids; ScanMatcher(int expectedScanType, Set<Integer> expectedFreqs, List<String> expectedSsids)1269 ScanMatcher(int expectedScanType, Set<Integer> expectedFreqs, List<String> expectedSsids) { 1270 this.mExpectedScanType = expectedScanType; 1271 this.mExpectedFreqs = expectedFreqs; 1272 this.mExpectedSsids = expectedSsids; 1273 } 1274 1275 @Override matches(SingleScanSettings settings)1276 public boolean matches(SingleScanSettings settings) { 1277 if (settings.scanType != mExpectedScanType) { 1278 return false; 1279 } 1280 ArrayList<ChannelSettings> channelSettings = settings.channelSettings; 1281 ArrayList<HiddenNetwork> hiddenNetworks = settings.hiddenNetworks; 1282 if (mExpectedFreqs != null) { 1283 Set<Integer> freqSet = new HashSet<Integer>(); 1284 for (ChannelSettings channel : channelSettings) { 1285 freqSet.add(channel.frequency); 1286 } 1287 if (!mExpectedFreqs.equals(freqSet)) { 1288 return false; 1289 } 1290 } else { 1291 if (channelSettings != null && channelSettings.size() > 0) { 1292 return false; 1293 } 1294 } 1295 1296 if (mExpectedSsids != null) { 1297 List<String> ssidSet = new ArrayList<String>(); 1298 for (HiddenNetwork network : hiddenNetworks) { 1299 ssidSet.add(NativeUtil.encodeSsid( 1300 NativeUtil.byteArrayToArrayList(network.ssid))); 1301 } 1302 if (!mExpectedSsids.equals(ssidSet)) { 1303 return false; 1304 } 1305 1306 } else { 1307 if (hiddenNetworks != null && hiddenNetworks.size() > 0) { 1308 return false; 1309 } 1310 } 1311 return true; 1312 } 1313 1314 @Override toString()1315 public String toString() { 1316 return "ScanMatcher{mExpectedFreqs=" + mExpectedFreqs 1317 + ", mExpectedSsids=" + mExpectedSsids + '}'; 1318 } 1319 } 1320 1321 // Create a ArgumentMatcher which captures a PnoSettings parameter and checks if it 1322 // matches the WifiNative.PnoSettings; 1323 private class PnoScanMatcher implements ArgumentMatcher<PnoSettings> { 1324 private final WifiNative.PnoSettings mExpectedPnoSettings; PnoScanMatcher(WifiNative.PnoSettings expectedPnoSettings)1325 PnoScanMatcher(WifiNative.PnoSettings expectedPnoSettings) { 1326 this.mExpectedPnoSettings = expectedPnoSettings; 1327 } 1328 @Override matches(PnoSettings settings)1329 public boolean matches(PnoSettings settings) { 1330 if (mExpectedPnoSettings == null) { 1331 return false; 1332 } 1333 if (settings.intervalMs != mExpectedPnoSettings.periodInMs 1334 || settings.min2gRssi != mExpectedPnoSettings.min24GHzRssi 1335 || settings.min5gRssi != mExpectedPnoSettings.min5GHzRssi) { 1336 return false; 1337 } 1338 if (settings.pnoNetworks == null || mExpectedPnoSettings.networkList == null) { 1339 return false; 1340 } 1341 if (settings.pnoNetworks.size() != mExpectedPnoSettings.networkList.length) { 1342 return false; 1343 } 1344 1345 for (int i = 0; i < settings.pnoNetworks.size(); i++) { 1346 if (!mExpectedPnoSettings.networkList[i].ssid.equals(NativeUtil.encodeSsid( 1347 NativeUtil.byteArrayToArrayList(settings.pnoNetworks.get(i).ssid)))) { 1348 return false; 1349 } 1350 boolean isNetworkHidden = (mExpectedPnoSettings.networkList[i].flags 1351 & WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN) != 0; 1352 if (isNetworkHidden != settings.pnoNetworks.get(i).isHidden) { 1353 return false; 1354 } 1355 if (!Arrays.equals(mExpectedPnoSettings.networkList[i].frequencies, 1356 settings.pnoNetworks.get(i).frequencies)) { 1357 return false; 1358 } 1359 } 1360 return true; 1361 } 1362 1363 @Override toString()1364 public String toString() { 1365 return "PnoScanMatcher{" + "mExpectedPnoSettings=" + mExpectedPnoSettings + '}'; 1366 } 1367 } 1368 } 1369