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