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 package com.android.server.wifi; 17 18 import static org.junit.Assert.*; 19 import static org.mockito.Matchers.any; 20 import static org.mockito.Matchers.anyBoolean; 21 import static org.mockito.Matchers.anyInt; 22 import static org.mockito.Matchers.anyLong; 23 import static org.mockito.Matchers.anyShort; 24 import static org.mockito.Matchers.anyString; 25 import static org.mockito.Matchers.eq; 26 import static org.mockito.Mockito.doAnswer; 27 import static org.mockito.Mockito.doThrow; 28 import static org.mockito.Mockito.inOrder; 29 import static org.mockito.Mockito.mock; 30 import static org.mockito.Mockito.never; 31 import static org.mockito.Mockito.reset; 32 import static org.mockito.Mockito.times; 33 import static org.mockito.Mockito.verify; 34 import static org.mockito.Mockito.when; 35 36 import android.app.test.MockAnswerUtil; 37 import android.content.Context; 38 import android.hardware.wifi.supplicant.V1_0.ISupplicant; 39 import android.hardware.wifi.supplicant.V1_0.ISupplicantIface; 40 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIface; 41 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback; 42 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback.BssidChangeReason; 43 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork; 44 import android.hardware.wifi.supplicant.V1_0.IfaceType; 45 import android.hardware.wifi.supplicant.V1_0.SupplicantStatus; 46 import android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode; 47 import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods; 48 import android.hidl.manager.V1_0.IServiceManager; 49 import android.hidl.manager.V1_0.IServiceNotification; 50 import android.net.IpConfiguration; 51 import android.net.wifi.SupplicantState; 52 import android.net.wifi.WifiConfiguration; 53 import android.net.wifi.WifiManager; 54 import android.net.wifi.WifiSsid; 55 import android.os.IHwBinder; 56 import android.os.RemoteException; 57 import android.util.SparseArray; 58 59 import com.android.server.wifi.hotspot2.AnqpEvent; 60 import com.android.server.wifi.hotspot2.IconEvent; 61 import com.android.server.wifi.hotspot2.WnmData; 62 import com.android.server.wifi.util.NativeUtil; 63 64 import org.junit.Before; 65 import org.junit.Test; 66 import org.mockito.ArgumentCaptor; 67 import org.mockito.InOrder; 68 import org.mockito.Mock; 69 import org.mockito.MockitoAnnotations; 70 71 import java.nio.ByteBuffer; 72 import java.nio.ByteOrder; 73 import java.util.ArrayList; 74 import java.util.Arrays; 75 import java.util.HashMap; 76 import java.util.Map; 77 import java.util.Random; 78 79 /** 80 * Unit tests for SupplicantStaIfaceHal 81 */ 82 public class SupplicantStaIfaceHalTest { 83 private static final String TAG = "SupplicantStaIfaceHalTest"; 84 private static final Map<Integer, String> NETWORK_ID_TO_SSID = new HashMap<Integer, String>() {{ 85 put(1, "\"ssid1\""); 86 put(2, "\"ssid2\""); 87 put(3, "\"ssid3\""); 88 }}; 89 private static final int SUPPLICANT_NETWORK_ID = 2; 90 private static final String SUPPLICANT_SSID = NETWORK_ID_TO_SSID.get(SUPPLICANT_NETWORK_ID); 91 private static final int ROAM_NETWORK_ID = 4; 92 private static final String BSSID = "fa:45:23:23:12:12"; 93 private static final String WLAN_IFACE_NAME = "wlan0"; 94 private static final String P2P_IFACE_NAME = "p2p0"; 95 private static final String ICON_FILE_NAME = "blahblah"; 96 private static final int ICON_FILE_SIZE = 72; 97 private static final String HS20_URL = "http://blahblah"; 98 99 @Mock IServiceManager mServiceManagerMock; 100 @Mock ISupplicant mISupplicantMock; 101 @Mock ISupplicantIface mISupplicantIfaceMock; 102 @Mock ISupplicantStaIface mISupplicantStaIfaceMock; 103 @Mock Context mContext; 104 @Mock WifiMonitor mWifiMonitor; 105 @Mock SupplicantStaNetworkHal mSupplicantStaNetworkMock; 106 SupplicantStatus mStatusSuccess; 107 SupplicantStatus mStatusFailure; 108 ISupplicant.IfaceInfo mStaIface; 109 ISupplicant.IfaceInfo mP2pIface; 110 ArrayList<ISupplicant.IfaceInfo> mIfaceInfoList; 111 ISupplicantStaIfaceCallback mISupplicantStaIfaceCallback; 112 private SupplicantStaIfaceHal mDut; 113 private ArgumentCaptor<IHwBinder.DeathRecipient> mServiceManagerDeathCaptor = 114 ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class); 115 private ArgumentCaptor<IHwBinder.DeathRecipient> mSupplicantDeathCaptor = 116 ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class); 117 private ArgumentCaptor<IHwBinder.DeathRecipient> mSupplicantStaIfaceDeathCaptor = 118 ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class); 119 private ArgumentCaptor<IServiceNotification.Stub> mServiceNotificationCaptor = 120 ArgumentCaptor.forClass(IServiceNotification.Stub.class); 121 private InOrder mInOrder; 122 123 private class SupplicantStaIfaceHalSpy extends SupplicantStaIfaceHal { 124 SupplicantStaIfaceHalSpy(Context context, WifiMonitor monitor) { 125 super(context, monitor); 126 } 127 128 @Override 129 protected IServiceManager getServiceManagerMockable() throws RemoteException { 130 return mServiceManagerMock; 131 } 132 133 @Override 134 protected ISupplicant getSupplicantMockable() throws RemoteException { 135 return mISupplicantMock; 136 } 137 138 @Override 139 protected ISupplicantStaIface getStaIfaceMockable(ISupplicantIface iface) { 140 return mISupplicantStaIfaceMock; 141 } 142 143 @Override 144 protected SupplicantStaNetworkHal getStaNetworkMockable( 145 ISupplicantStaNetwork iSupplicantStaNetwork) { 146 return mSupplicantStaNetworkMock; 147 } 148 } 149 150 @Before 151 public void setUp() throws Exception { 152 MockitoAnnotations.initMocks(this); 153 mStatusSuccess = createSupplicantStatus(SupplicantStatusCode.SUCCESS); 154 mStatusFailure = createSupplicantStatus(SupplicantStatusCode.FAILURE_UNKNOWN); 155 mStaIface = createIfaceInfo(IfaceType.STA, WLAN_IFACE_NAME); 156 mP2pIface = createIfaceInfo(IfaceType.P2P, P2P_IFACE_NAME); 157 158 mIfaceInfoList = new ArrayList<>(); 159 mIfaceInfoList.add(mStaIface); 160 mIfaceInfoList.add(mP2pIface); 161 162 when(mServiceManagerMock.linkToDeath(any(IHwBinder.DeathRecipient.class), 163 anyLong())).thenReturn(true); 164 when(mServiceManagerMock.registerForNotifications(anyString(), anyString(), 165 any(IServiceNotification.Stub.class))).thenReturn(true); 166 when(mISupplicantMock.linkToDeath(any(IHwBinder.DeathRecipient.class), 167 anyLong())).thenReturn(true); 168 when(mISupplicantStaIfaceMock.linkToDeath(any(IHwBinder.DeathRecipient.class), 169 anyLong())).thenReturn(true); 170 mDut = new SupplicantStaIfaceHalSpy(mContext, mWifiMonitor); 171 } 172 173 /** 174 * Sunny day scenario for SupplicantStaIfaceHal initialization 175 * Asserts successful initialization 176 */ 177 @Test 178 public void testInitialize_success() throws Exception { 179 executeAndValidateInitializationSequence(false, false, false, false); 180 } 181 182 /** 183 * Tests the initialization flow, with a RemoteException occurring when 'getInterface' is called 184 * Ensures initialization fails. 185 */ 186 @Test 187 public void testInitialize_remoteExceptionFailure() throws Exception { 188 executeAndValidateInitializationSequence(true, false, false, false); 189 } 190 191 /** 192 * Tests the initialization flow, with listInterfaces returning 0 interfaces. 193 * Ensures failure 194 */ 195 @Test 196 public void testInitialize_zeroInterfacesFailure() throws Exception { 197 executeAndValidateInitializationSequence(false, true, false, false); 198 } 199 200 /** 201 * Tests the initialization flow, with a null interface being returned by getInterface. 202 * Ensures initialization fails. 203 */ 204 @Test 205 public void testInitialize_nullInterfaceFailure() throws Exception { 206 executeAndValidateInitializationSequence(false, false, true, false); 207 } 208 209 /** 210 * Tests the initialization flow, with a callback registration failure. 211 * Ensures initialization fails. 212 */ 213 @Test 214 public void testInitialize_callbackRegistrationFailure() throws Exception { 215 executeAndValidateInitializationSequence(false, false, false, true); 216 } 217 218 /** 219 * Tests the loading of networks using {@link SupplicantStaNetworkHal}. 220 * Fills up only the SSID field of configs and uses it as a configKey as well. 221 */ 222 @Test 223 public void testLoadNetworks() throws Exception { 224 executeAndValidateInitializationSequence(); 225 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 226 public void answer(ISupplicantStaIface.listNetworksCallback cb) { 227 cb.onValues(mStatusSuccess, new ArrayList<>(NETWORK_ID_TO_SSID.keySet())); 228 } 229 }).when(mISupplicantStaIfaceMock) 230 .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class)); 231 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 232 public void answer(final int networkId, ISupplicantStaIface.getNetworkCallback cb) { 233 // Reset the |mSupplicantStaNetwork| mock for each network. 234 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 235 public boolean answer( 236 WifiConfiguration config, Map<String, String> networkExtra) { 237 config.SSID = NETWORK_ID_TO_SSID.get(networkId); 238 config.networkId = networkId; 239 networkExtra.put( 240 SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY, config.SSID); 241 return true; 242 } 243 }).when(mSupplicantStaNetworkMock) 244 .loadWifiConfiguration(any(WifiConfiguration.class), any(Map.class)); 245 cb.onValues(mStatusSuccess, mock(ISupplicantStaNetwork.class)); 246 return; 247 } 248 }).when(mISupplicantStaIfaceMock) 249 .getNetwork(anyInt(), any(ISupplicantStaIface.getNetworkCallback.class)); 250 251 Map<String, WifiConfiguration> configs = new HashMap<>(); 252 SparseArray<Map<String, String>> extras = new SparseArray<>(); 253 assertTrue(mDut.loadNetworks(configs, extras)); 254 255 assertEquals(3, configs.size()); 256 assertEquals(3, extras.size()); 257 for (Map.Entry<Integer, String> network : NETWORK_ID_TO_SSID.entrySet()) { 258 WifiConfiguration config = configs.get(network.getValue()); 259 assertTrue(config != null); 260 assertEquals(network.getKey(), Integer.valueOf(config.networkId)); 261 assertEquals(network.getValue(), config.SSID); 262 assertEquals(IpConfiguration.IpAssignment.DHCP, config.getIpAssignment()); 263 assertEquals(IpConfiguration.ProxySettings.NONE, config.getProxySettings()); 264 } 265 } 266 267 /** 268 * Tests the loading of networks using {@link SupplicantStaNetworkHal} removes any networks 269 * with duplicate config key. 270 * Fills up only the SSID field of configs and uses it as a configKey as well. 271 */ 272 @Test 273 public void testLoadNetworksRemovesDuplicates() throws Exception { 274 // Network ID which will have the same config key as the previous one. 275 final int duplicateNetworkId = 2; 276 final int toRemoveNetworkId = duplicateNetworkId - 1; 277 executeAndValidateInitializationSequence(); 278 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 279 public void answer(ISupplicantStaIface.listNetworksCallback cb) { 280 cb.onValues(mStatusSuccess, new ArrayList<>(NETWORK_ID_TO_SSID.keySet())); 281 } 282 }).when(mISupplicantStaIfaceMock) 283 .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class)); 284 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 285 public SupplicantStatus answer(int id) { 286 return mStatusSuccess; 287 } 288 }).when(mISupplicantStaIfaceMock).removeNetwork(eq(toRemoveNetworkId)); 289 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 290 public void answer(final int networkId, ISupplicantStaIface.getNetworkCallback cb) { 291 // Reset the |mSupplicantStaNetwork| mock for each network. 292 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 293 public boolean answer( 294 WifiConfiguration config, Map<String, String> networkExtra) { 295 config.SSID = NETWORK_ID_TO_SSID.get(networkId); 296 config.networkId = networkId; 297 // Duplicate network gets the same config key as the to removed one. 298 if (networkId == duplicateNetworkId) { 299 networkExtra.put( 300 SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY, 301 NETWORK_ID_TO_SSID.get(toRemoveNetworkId)); 302 } else { 303 networkExtra.put( 304 SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY, 305 NETWORK_ID_TO_SSID.get(networkId)); 306 } 307 return true; 308 } 309 }).when(mSupplicantStaNetworkMock) 310 .loadWifiConfiguration(any(WifiConfiguration.class), any(Map.class)); 311 cb.onValues(mStatusSuccess, mock(ISupplicantStaNetwork.class)); 312 return; 313 } 314 }).when(mISupplicantStaIfaceMock) 315 .getNetwork(anyInt(), any(ISupplicantStaIface.getNetworkCallback.class)); 316 317 Map<String, WifiConfiguration> configs = new HashMap<>(); 318 SparseArray<Map<String, String>> extras = new SparseArray<>(); 319 assertTrue(mDut.loadNetworks(configs, extras)); 320 321 assertEquals(2, configs.size()); 322 assertEquals(2, extras.size()); 323 for (Map.Entry<Integer, String> network : NETWORK_ID_TO_SSID.entrySet()) { 324 if (network.getKey() == toRemoveNetworkId) { 325 continue; 326 } 327 WifiConfiguration config; 328 // Duplicate network gets the same config key as the to removed one. So, use that to 329 // lookup the map. 330 if (network.getKey() == duplicateNetworkId) { 331 config = configs.get(NETWORK_ID_TO_SSID.get(toRemoveNetworkId)); 332 } else { 333 config = configs.get(network.getValue()); 334 } 335 assertTrue(config != null); 336 assertEquals(network.getKey(), Integer.valueOf(config.networkId)); 337 assertEquals(network.getValue(), config.SSID); 338 assertEquals(IpConfiguration.IpAssignment.DHCP, config.getIpAssignment()); 339 assertEquals(IpConfiguration.ProxySettings.NONE, config.getProxySettings()); 340 } 341 } 342 343 /** 344 * Tests the failure to load networks because of listNetworks failure. 345 */ 346 @Test 347 public void testLoadNetworksFailedDueToListNetworks() throws Exception { 348 executeAndValidateInitializationSequence(); 349 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 350 public void answer(ISupplicantStaIface.listNetworksCallback cb) { 351 cb.onValues(mStatusFailure, null); 352 } 353 }).when(mISupplicantStaIfaceMock) 354 .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class)); 355 356 Map<String, WifiConfiguration> configs = new HashMap<>(); 357 SparseArray<Map<String, String>> extras = new SparseArray<>(); 358 assertFalse(mDut.loadNetworks(configs, extras)); 359 } 360 361 /** 362 * Tests the failure to load networks because of getNetwork failure. 363 */ 364 @Test 365 public void testLoadNetworksFailedDueToGetNetwork() throws Exception { 366 executeAndValidateInitializationSequence(); 367 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 368 public void answer(ISupplicantStaIface.listNetworksCallback cb) { 369 cb.onValues(mStatusSuccess, new ArrayList<>(NETWORK_ID_TO_SSID.keySet())); 370 } 371 }).when(mISupplicantStaIfaceMock) 372 .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class)); 373 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 374 public void answer(final int networkId, ISupplicantStaIface.getNetworkCallback cb) { 375 cb.onValues(mStatusFailure, mock(ISupplicantStaNetwork.class)); 376 return; 377 } 378 }).when(mISupplicantStaIfaceMock) 379 .getNetwork(anyInt(), any(ISupplicantStaIface.getNetworkCallback.class)); 380 381 Map<String, WifiConfiguration> configs = new HashMap<>(); 382 SparseArray<Map<String, String>> extras = new SparseArray<>(); 383 assertFalse(mDut.loadNetworks(configs, extras)); 384 } 385 386 /** 387 * Tests the failure to load networks because of loadWifiConfiguration failure. 388 */ 389 @Test 390 public void testLoadNetworksFailedDueToLoadWifiConfiguration() throws Exception { 391 executeAndValidateInitializationSequence(); 392 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 393 public void answer(ISupplicantStaIface.listNetworksCallback cb) { 394 cb.onValues(mStatusSuccess, new ArrayList<>(NETWORK_ID_TO_SSID.keySet())); 395 } 396 }).when(mISupplicantStaIfaceMock) 397 .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class)); 398 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 399 public void answer(final int networkId, ISupplicantStaIface.getNetworkCallback cb) { 400 cb.onValues(mStatusSuccess, mock(ISupplicantStaNetwork.class)); 401 return; 402 } 403 }).when(mISupplicantStaIfaceMock) 404 .getNetwork(anyInt(), any(ISupplicantStaIface.getNetworkCallback.class)); 405 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 406 public boolean answer(WifiConfiguration config, Map<String, String> networkExtra) { 407 return false; 408 } 409 }).when(mSupplicantStaNetworkMock) 410 .loadWifiConfiguration(any(WifiConfiguration.class), any(Map.class)); 411 412 Map<String, WifiConfiguration> configs = new HashMap<>(); 413 SparseArray<Map<String, String>> extras = new SparseArray<>(); 414 assertTrue(mDut.loadNetworks(configs, extras)); 415 assertTrue(configs.isEmpty()); 416 } 417 418 /** 419 * Tests the failure to load networks because of loadWifiConfiguration exception. 420 */ 421 @Test 422 public void testLoadNetworksFailedDueToExceptionInLoadWifiConfiguration() throws Exception { 423 executeAndValidateInitializationSequence(); 424 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 425 public void answer(ISupplicantStaIface.listNetworksCallback cb) { 426 cb.onValues(mStatusSuccess, new ArrayList<>(NETWORK_ID_TO_SSID.keySet())); 427 } 428 }).when(mISupplicantStaIfaceMock) 429 .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class)); 430 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 431 public void answer(final int networkId, ISupplicantStaIface.getNetworkCallback cb) { 432 cb.onValues(mStatusSuccess, mock(ISupplicantStaNetwork.class)); 433 return; 434 } 435 }).when(mISupplicantStaIfaceMock) 436 .getNetwork(anyInt(), any(ISupplicantStaIface.getNetworkCallback.class)); 437 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 438 public boolean answer(WifiConfiguration config, Map<String, String> networkExtra) 439 throws Exception { 440 throw new IllegalArgumentException(); 441 } 442 }).when(mSupplicantStaNetworkMock) 443 .loadWifiConfiguration(any(WifiConfiguration.class), any(Map.class)); 444 445 Map<String, WifiConfiguration> configs = new HashMap<>(); 446 SparseArray<Map<String, String>> extras = new SparseArray<>(); 447 assertTrue(mDut.loadNetworks(configs, extras)); 448 assertTrue(configs.isEmpty()); 449 } 450 451 /** 452 * Tests connection to a specified network with empty existing network. 453 */ 454 @Test 455 public void testConnectWithEmptyExistingNetwork() throws Exception { 456 executeAndValidateInitializationSequence(); 457 executeAndValidateConnectSequence(0, false); 458 } 459 460 @Test 461 public void testConnectToNetworkWithDifferentConfigReplacesNetworkInSupplicant() 462 throws Exception { 463 executeAndValidateInitializationSequence(); 464 WifiConfiguration config = executeAndValidateConnectSequence( 465 SUPPLICANT_NETWORK_ID, false); 466 // Reset mocks for mISupplicantStaIfaceMock because we finished the first connection. 467 reset(mISupplicantStaIfaceMock); 468 setupMocksForConnectSequence(true /*haveExistingNetwork*/); 469 // Make this network different by changing SSID. 470 config.SSID = "AnDifferentSSID"; 471 assertTrue(mDut.connectToNetwork(config)); 472 verify(mISupplicantStaIfaceMock).removeNetwork(SUPPLICANT_NETWORK_ID); 473 verify(mISupplicantStaIfaceMock) 474 .addNetwork(any(ISupplicantStaIface.addNetworkCallback.class)); 475 } 476 477 @Test 478 public void connectToNetworkWithSameNetworkDoesNotRemoveNetworkFromSupplicant() 479 throws Exception { 480 executeAndValidateInitializationSequence(); 481 WifiConfiguration config = executeAndValidateConnectSequence(SUPPLICANT_NETWORK_ID, false); 482 // Reset mocks for mISupplicantStaIfaceMock because we finished the first connection. 483 reset(mISupplicantStaIfaceMock); 484 setupMocksForConnectSequence(true /*haveExistingNetwork*/); 485 assertTrue(mDut.connectToNetwork(config)); 486 verify(mISupplicantStaIfaceMock, never()).removeNetwork(anyInt()); 487 verify(mISupplicantStaIfaceMock, never()) 488 .addNetwork(any(ISupplicantStaIface.addNetworkCallback.class)); 489 } 490 491 /** 492 * Tests connection to a specified network failure due to network add. 493 */ 494 @Test 495 public void testConnectFailureDueToNetworkAddFailure() throws Exception { 496 executeAndValidateInitializationSequence(); 497 setupMocksForConnectSequence(false); 498 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 499 public void answer(ISupplicantStaIface.addNetworkCallback cb) throws RemoteException { 500 cb.onValues(mStatusFailure, mock(ISupplicantStaNetwork.class)); 501 return; 502 } 503 }).when(mISupplicantStaIfaceMock).addNetwork( 504 any(ISupplicantStaIface.addNetworkCallback.class)); 505 506 assertFalse(mDut.connectToNetwork(createTestWifiConfiguration())); 507 } 508 509 /** 510 * Tests connection to a specified network failure due to network save. 511 */ 512 @Test 513 public void testConnectFailureDueToNetworkSaveFailure() throws Exception { 514 executeAndValidateInitializationSequence(); 515 setupMocksForConnectSequence(true); 516 517 when(mSupplicantStaNetworkMock.saveWifiConfiguration(any(WifiConfiguration.class))) 518 .thenReturn(false); 519 520 assertFalse(mDut.connectToNetwork(createTestWifiConfiguration())); 521 // We should have removed the existing network once before connection and once more 522 // on failure to save network configuration. 523 verify(mISupplicantStaIfaceMock, times(2)).removeNetwork(anyInt()); 524 } 525 526 /** 527 * Tests connection to a specified network failure due to exception in network save. 528 */ 529 @Test 530 public void testConnectFailureDueToNetworkSaveException() throws Exception { 531 executeAndValidateInitializationSequence(); 532 setupMocksForConnectSequence(true); 533 534 doThrow(new IllegalArgumentException("Some error!!!")) 535 .when(mSupplicantStaNetworkMock).saveWifiConfiguration( 536 any(WifiConfiguration.class)); 537 538 assertFalse(mDut.connectToNetwork(createTestWifiConfiguration())); 539 // We should have removed the existing network once before connection and once more 540 // on failure to save network configuration. 541 verify(mISupplicantStaIfaceMock, times(2)).removeNetwork(anyInt()); 542 } 543 544 /** 545 * Tests connection to a specified network failure due to network select. 546 */ 547 @Test 548 public void testConnectFailureDueToNetworkSelectFailure() throws Exception { 549 executeAndValidateInitializationSequence(); 550 setupMocksForConnectSequence(false); 551 552 when(mSupplicantStaNetworkMock.select()).thenReturn(false); 553 554 assertFalse(mDut.connectToNetwork(createTestWifiConfiguration())); 555 } 556 557 /** 558 * Tests roaming to the same network as the currently connected one. 559 */ 560 @Test 561 public void testRoamToSameNetwork() throws Exception { 562 executeAndValidateInitializationSequence(); 563 executeAndValidateRoamSequence(true); 564 assertTrue(mDut.connectToNetwork(createTestWifiConfiguration())); 565 } 566 567 /** 568 * Tests roaming to a different network. 569 */ 570 @Test 571 public void testRoamToDifferentNetwork() throws Exception { 572 executeAndValidateInitializationSequence(); 573 executeAndValidateRoamSequence(false); 574 } 575 576 /** 577 * Tests roaming failure because of unable to set bssid. 578 */ 579 @Test 580 public void testRoamFailureDueToBssidSet() throws Exception { 581 executeAndValidateInitializationSequence(); 582 int connectedNetworkId = 5; 583 executeAndValidateConnectSequence(connectedNetworkId, false); 584 when(mSupplicantStaNetworkMock.setBssid(anyString())).thenReturn(false); 585 586 WifiConfiguration roamingConfig = new WifiConfiguration(); 587 roamingConfig.networkId = connectedNetworkId; 588 roamingConfig.getNetworkSelectionStatus().setNetworkSelectionBSSID("45:34:23:23:ab:ed"); 589 assertFalse(mDut.roamToNetwork(roamingConfig)); 590 } 591 592 /** 593 * Tests removal of all configured networks from wpa_supplicant. 594 */ 595 @Test 596 public void testRemoveAllNetworks() throws Exception { 597 executeAndValidateInitializationSequence(); 598 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 599 public void answer(ISupplicantStaIface.listNetworksCallback cb) { 600 cb.onValues(mStatusSuccess, new ArrayList<>(NETWORK_ID_TO_SSID.keySet())); 601 } 602 }).when(mISupplicantStaIfaceMock) 603 .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class)); 604 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 605 public SupplicantStatus answer(int id) { 606 assertTrue(NETWORK_ID_TO_SSID.containsKey(id)); 607 return mStatusSuccess; 608 } 609 }).when(mISupplicantStaIfaceMock).removeNetwork(anyInt()); 610 611 assertTrue(mDut.removeAllNetworks()); 612 verify(mISupplicantStaIfaceMock, times(NETWORK_ID_TO_SSID.size())).removeNetwork(anyInt()); 613 } 614 615 /** 616 * Remove all networks while connected, verify that the current network info is resetted. 617 */ 618 @Test 619 public void testRemoveAllNetworksWhileConnected() throws Exception { 620 String testBssid = "11:22:33:44:55:66"; 621 when(mSupplicantStaNetworkMock.setBssid(eq(testBssid))).thenReturn(true); 622 623 executeAndValidateInitializationSequence(); 624 625 // Connect to a network and verify current network is set. 626 executeAndValidateConnectSequence(4, false); 627 assertTrue(mDut.setCurrentNetworkBssid(testBssid)); 628 verify(mSupplicantStaNetworkMock).setBssid(eq(testBssid)); 629 reset(mSupplicantStaNetworkMock); 630 631 // Remove all networks and verify current network info is resetted. 632 assertTrue(mDut.removeAllNetworks()); 633 assertFalse(mDut.setCurrentNetworkBssid(testBssid)); 634 verify(mSupplicantStaNetworkMock, never()).setBssid(eq(testBssid)); 635 } 636 637 /** 638 * Tests roaming failure because of unable to reassociate. 639 */ 640 @Test 641 public void testRoamFailureDueToReassociate() throws Exception { 642 executeAndValidateInitializationSequence(); 643 int connectedNetworkId = 5; 644 executeAndValidateConnectSequence(connectedNetworkId, false); 645 646 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 647 public SupplicantStatus answer() throws RemoteException { 648 return mStatusFailure; 649 } 650 }).when(mISupplicantStaIfaceMock).reassociate(); 651 when(mSupplicantStaNetworkMock.setBssid(anyString())).thenReturn(true); 652 653 WifiConfiguration roamingConfig = new WifiConfiguration(); 654 roamingConfig.networkId = connectedNetworkId; 655 roamingConfig.getNetworkSelectionStatus().setNetworkSelectionBSSID("45:34:23:23:ab:ed"); 656 assertFalse(mDut.roamToNetwork(roamingConfig)); 657 } 658 659 /** 660 * Tests the retrieval of WPS NFC token. 661 */ 662 @Test 663 public void testGetCurrentNetworkWpsNfcConfigurationToken() throws Exception { 664 String token = "45adbc1"; 665 when(mSupplicantStaNetworkMock.getWpsNfcConfigurationToken()).thenReturn(token); 666 667 executeAndValidateInitializationSequence(); 668 // Return null when not connected to the network. 669 assertTrue(mDut.getCurrentNetworkWpsNfcConfigurationToken() == null); 670 verify(mSupplicantStaNetworkMock, never()).getWpsNfcConfigurationToken(); 671 executeAndValidateConnectSequence(4, false); 672 assertEquals(token, mDut.getCurrentNetworkWpsNfcConfigurationToken()); 673 verify(mSupplicantStaNetworkMock).getWpsNfcConfigurationToken(); 674 } 675 676 /** 677 * Tests the setting of BSSID. 678 */ 679 @Test 680 public void testSetCurrentNetworkBssid() throws Exception { 681 String bssidStr = "34:34:12:12:12:90"; 682 when(mSupplicantStaNetworkMock.setBssid(eq(bssidStr))).thenReturn(true); 683 684 executeAndValidateInitializationSequence(); 685 // Fail when not connected to a network. 686 assertFalse(mDut.setCurrentNetworkBssid(bssidStr)); 687 verify(mSupplicantStaNetworkMock, never()).setBssid(eq(bssidStr)); 688 executeAndValidateConnectSequence(4, false); 689 assertTrue(mDut.setCurrentNetworkBssid(bssidStr)); 690 verify(mSupplicantStaNetworkMock).setBssid(eq(bssidStr)); 691 } 692 693 /** 694 * Tests the sending identity response for the current network. 695 */ 696 @Test 697 public void testSetCurrentNetworkEapIdentityResponse() throws Exception { 698 String identity = "blah (at) blah.com"; 699 when(mSupplicantStaNetworkMock.sendNetworkEapIdentityResponse(eq(identity))) 700 .thenReturn(true); 701 702 executeAndValidateInitializationSequence(); 703 // Fail when not connected to a network. 704 assertFalse(mDut.sendCurrentNetworkEapIdentityResponse(identity)); 705 verify(mSupplicantStaNetworkMock, never()).sendNetworkEapIdentityResponse(eq(identity)); 706 executeAndValidateConnectSequence(4, false); 707 assertTrue(mDut.sendCurrentNetworkEapIdentityResponse(identity)); 708 verify(mSupplicantStaNetworkMock).sendNetworkEapIdentityResponse(eq(identity)); 709 } 710 711 /** 712 * Tests the getting of anonymous identity for the current network. 713 */ 714 @Test 715 public void testGetCurrentNetworkEapAnonymousIdentity() throws Exception { 716 String anonymousIdentity = "aaa (at) bbb.ccc"; 717 when(mSupplicantStaNetworkMock.fetchEapAnonymousIdentity()) 718 .thenReturn(anonymousIdentity); 719 executeAndValidateInitializationSequence(); 720 721 // Return null when not connected to the network. 722 assertEquals(null, mDut.getCurrentNetworkEapAnonymousIdentity()); 723 executeAndValidateConnectSequence(4, false); 724 // Return anonymous identity for the current network. 725 assertEquals(anonymousIdentity, mDut.getCurrentNetworkEapAnonymousIdentity()); 726 } 727 728 /** 729 * Tests the sending gsm auth response for the current network. 730 */ 731 @Test 732 public void testSetCurrentNetworkEapSimGsmAuthResponse() throws Exception { 733 String params = "test"; 734 when(mSupplicantStaNetworkMock.sendNetworkEapSimGsmAuthResponse(eq(params))) 735 .thenReturn(true); 736 737 executeAndValidateInitializationSequence(); 738 // Fail when not connected to a network. 739 assertFalse(mDut.sendCurrentNetworkEapSimGsmAuthResponse(params)); 740 verify(mSupplicantStaNetworkMock, never()).sendNetworkEapSimGsmAuthResponse(eq(params)); 741 executeAndValidateConnectSequence(4, false); 742 assertTrue(mDut.sendCurrentNetworkEapSimGsmAuthResponse(params)); 743 verify(mSupplicantStaNetworkMock).sendNetworkEapSimGsmAuthResponse(eq(params)); 744 } 745 746 /** 747 * Tests the sending umts auth response for the current network. 748 */ 749 @Test 750 public void testSetCurrentNetworkEapSimUmtsAuthResponse() throws Exception { 751 String params = "test"; 752 when(mSupplicantStaNetworkMock.sendNetworkEapSimUmtsAuthResponse(eq(params))) 753 .thenReturn(true); 754 755 executeAndValidateInitializationSequence(); 756 // Fail when not connected to a network. 757 assertFalse(mDut.sendCurrentNetworkEapSimUmtsAuthResponse(params)); 758 verify(mSupplicantStaNetworkMock, never()).sendNetworkEapSimUmtsAuthResponse(eq(params)); 759 executeAndValidateConnectSequence(4, false); 760 assertTrue(mDut.sendCurrentNetworkEapSimUmtsAuthResponse(params)); 761 verify(mSupplicantStaNetworkMock).sendNetworkEapSimUmtsAuthResponse(eq(params)); 762 } 763 764 /** 765 * Tests the sending umts auts response for the current network. 766 */ 767 @Test 768 public void testSetCurrentNetworkEapSimUmtsAutsResponse() throws Exception { 769 String params = "test"; 770 when(mSupplicantStaNetworkMock.sendNetworkEapSimUmtsAutsResponse(eq(params))) 771 .thenReturn(true); 772 773 executeAndValidateInitializationSequence(); 774 // Fail when not connected to a network. 775 assertFalse(mDut.sendCurrentNetworkEapSimUmtsAutsResponse(params)); 776 verify(mSupplicantStaNetworkMock, never()).sendNetworkEapSimUmtsAutsResponse(eq(params)); 777 executeAndValidateConnectSequence(4, false); 778 assertTrue(mDut.sendCurrentNetworkEapSimUmtsAutsResponse(params)); 779 verify(mSupplicantStaNetworkMock).sendNetworkEapSimUmtsAutsResponse(eq(params)); 780 } 781 782 /** 783 * Tests the setting of WPS device type. 784 */ 785 @Test 786 public void testSetWpsDeviceType() throws Exception { 787 String validDeviceTypeStr = "10-0050F204-5"; 788 byte[] expectedDeviceType = { 0x0, 0xa, 0x0, 0x50, (byte) 0xf2, 0x04, 0x0, 0x05}; 789 String invalidDeviceType1Str = "10-02050F204-5"; 790 String invalidDeviceType2Str = "10-0050F204-534"; 791 when(mISupplicantStaIfaceMock.setWpsDeviceType(any(byte[].class))) 792 .thenReturn(mStatusSuccess); 793 794 executeAndValidateInitializationSequence(); 795 796 // This should work. 797 assertTrue(mDut.setWpsDeviceType(validDeviceTypeStr)); 798 verify(mISupplicantStaIfaceMock).setWpsDeviceType(eq(expectedDeviceType)); 799 800 // This should not work 801 assertFalse(mDut.setWpsDeviceType(invalidDeviceType1Str)); 802 // This should not work 803 assertFalse(mDut.setWpsDeviceType(invalidDeviceType2Str)); 804 } 805 806 /** 807 * Tests the setting of WPS config methods. 808 */ 809 @Test 810 public void testSetWpsConfigMethods() throws Exception { 811 String validConfigMethodsStr = "physical_display virtual_push_button"; 812 Short expectedConfigMethods = 813 WpsConfigMethods.PHY_DISPLAY | WpsConfigMethods.VIRT_PUSHBUTTON; 814 String invalidConfigMethodsStr = "physical_display virtual_push_button test"; 815 when(mISupplicantStaIfaceMock.setWpsConfigMethods(anyShort())).thenReturn(mStatusSuccess); 816 817 executeAndValidateInitializationSequence(); 818 819 // This should work. 820 assertTrue(mDut.setWpsConfigMethods(validConfigMethodsStr)); 821 verify(mISupplicantStaIfaceMock).setWpsConfigMethods(eq(expectedConfigMethods)); 822 823 // This should throw an illegal argument exception. 824 try { 825 assertFalse(mDut.setWpsConfigMethods(invalidConfigMethodsStr)); 826 } catch (IllegalArgumentException e) { 827 return; 828 } 829 assertTrue(false); 830 } 831 832 /** 833 * Tests the handling of ANQP done callback. 834 * Note: Since the ANQP element parsing methods are static, this can only test the negative test 835 * where all the parsing fails because the data is empty. It'll be non-trivial and unnecessary 836 * to test out the parsing logic here. 837 */ 838 @Test 839 public void testAnqpDoneCallback() throws Exception { 840 executeAndValidateInitializationSequence(); 841 assertNotNull(mISupplicantStaIfaceCallback); 842 byte[] bssid = NativeUtil.macAddressToByteArray(BSSID); 843 mISupplicantStaIfaceCallback.onAnqpQueryDone( 844 bssid, new ISupplicantStaIfaceCallback.AnqpData(), 845 new ISupplicantStaIfaceCallback.Hs20AnqpData()); 846 847 ArgumentCaptor<AnqpEvent> anqpEventCaptor = ArgumentCaptor.forClass(AnqpEvent.class); 848 verify(mWifiMonitor).broadcastAnqpDoneEvent(eq(WLAN_IFACE_NAME), anqpEventCaptor.capture()); 849 assertEquals( 850 ByteBufferReader.readInteger( 851 ByteBuffer.wrap(bssid), ByteOrder.BIG_ENDIAN, bssid.length), 852 anqpEventCaptor.getValue().getBssid()); 853 } 854 855 /** 856 * Tests the handling of Icon done callback. 857 */ 858 @Test 859 public void testIconDoneCallback() throws Exception { 860 executeAndValidateInitializationSequence(); 861 assertNotNull(mISupplicantStaIfaceCallback); 862 863 byte[] bssid = NativeUtil.macAddressToByteArray(BSSID); 864 byte[] iconData = new byte[ICON_FILE_SIZE]; 865 new Random().nextBytes(iconData); 866 mISupplicantStaIfaceCallback.onHs20IconQueryDone( 867 bssid, ICON_FILE_NAME, NativeUtil.byteArrayToArrayList(iconData)); 868 869 ArgumentCaptor<IconEvent> iconEventCaptor = ArgumentCaptor.forClass(IconEvent.class); 870 verify(mWifiMonitor).broadcastIconDoneEvent(eq(WLAN_IFACE_NAME), iconEventCaptor.capture()); 871 assertEquals( 872 ByteBufferReader.readInteger( 873 ByteBuffer.wrap(bssid), ByteOrder.BIG_ENDIAN, bssid.length), 874 iconEventCaptor.getValue().getBSSID()); 875 assertEquals(ICON_FILE_NAME, iconEventCaptor.getValue().getFileName()); 876 assertArrayEquals(iconData, iconEventCaptor.getValue().getData()); 877 } 878 879 /** 880 * Tests the handling of HS20 subscription remediation callback. 881 */ 882 @Test 883 public void testHs20SubscriptionRemediationCallback() throws Exception { 884 executeAndValidateInitializationSequence(); 885 assertNotNull(mISupplicantStaIfaceCallback); 886 887 byte[] bssid = NativeUtil.macAddressToByteArray(BSSID); 888 byte osuMethod = ISupplicantStaIfaceCallback.OsuMethod.OMA_DM; 889 mISupplicantStaIfaceCallback.onHs20SubscriptionRemediation( 890 bssid, osuMethod, HS20_URL); 891 892 ArgumentCaptor<WnmData> wnmDataCaptor = ArgumentCaptor.forClass(WnmData.class); 893 verify(mWifiMonitor).broadcastWnmEvent(eq(WLAN_IFACE_NAME), wnmDataCaptor.capture()); 894 assertEquals( 895 ByteBufferReader.readInteger( 896 ByteBuffer.wrap(bssid), ByteOrder.BIG_ENDIAN, bssid.length), 897 wnmDataCaptor.getValue().getBssid()); 898 assertEquals(osuMethod, wnmDataCaptor.getValue().getMethod()); 899 assertEquals(HS20_URL, wnmDataCaptor.getValue().getUrl()); 900 } 901 902 /** 903 * Tests the handling of HS20 deauth imminent callback. 904 */ 905 @Test 906 public void testHs20DeauthImminentCallbackWithEssReasonCode() throws Exception { 907 executeAndValidateHs20DeauthImminentCallback(true); 908 } 909 910 /** 911 * Tests the handling of HS20 deauth imminent callback. 912 */ 913 @Test 914 public void testHs20DeauthImminentCallbackWithNonEssReasonCode() throws Exception { 915 executeAndValidateHs20DeauthImminentCallback(false); 916 917 } 918 919 /** 920 * Tests the handling of state change notification without any configured network. 921 */ 922 @Test 923 public void testStateChangeCallbackWithNoConfiguredNetwork() throws Exception { 924 executeAndValidateInitializationSequence(); 925 assertNotNull(mISupplicantStaIfaceCallback); 926 927 mISupplicantStaIfaceCallback.onStateChanged( 928 ISupplicantStaIfaceCallback.State.INACTIVE, 929 NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID, 930 NativeUtil.decodeSsid(SUPPLICANT_SSID)); 931 932 // Can't compare WifiSsid instances because they lack an equals. 933 verify(mWifiMonitor).broadcastSupplicantStateChangeEvent( 934 eq(WLAN_IFACE_NAME), eq(WifiConfiguration.INVALID_NETWORK_ID), 935 any(WifiSsid.class), eq(BSSID), eq(SupplicantState.INACTIVE)); 936 } 937 938 /** 939 * Tests the handling of state change notification to associated after configuring a network. 940 */ 941 @Test 942 public void testStateChangeToAssociatedCallback() throws Exception { 943 executeAndValidateInitializationSequence(); 944 int frameworkNetworkId = 6; 945 executeAndValidateConnectSequence(frameworkNetworkId, false); 946 assertNotNull(mISupplicantStaIfaceCallback); 947 948 mISupplicantStaIfaceCallback.onStateChanged( 949 ISupplicantStaIfaceCallback.State.ASSOCIATED, 950 NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID, 951 NativeUtil.decodeSsid(SUPPLICANT_SSID)); 952 953 verify(mWifiMonitor).broadcastSupplicantStateChangeEvent( 954 eq(WLAN_IFACE_NAME), eq(frameworkNetworkId), 955 any(WifiSsid.class), eq(BSSID), eq(SupplicantState.ASSOCIATED)); 956 } 957 958 /** 959 * Tests the handling of state change notification to completed after configuring a network. 960 */ 961 @Test 962 public void testStateChangeToCompletedCallback() throws Exception { 963 InOrder wifiMonitorInOrder = inOrder(mWifiMonitor); 964 executeAndValidateInitializationSequence(); 965 int frameworkNetworkId = 6; 966 executeAndValidateConnectSequence(frameworkNetworkId, false); 967 assertNotNull(mISupplicantStaIfaceCallback); 968 969 mISupplicantStaIfaceCallback.onStateChanged( 970 ISupplicantStaIfaceCallback.State.COMPLETED, 971 NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID, 972 NativeUtil.decodeSsid(SUPPLICANT_SSID)); 973 974 wifiMonitorInOrder.verify(mWifiMonitor).broadcastNetworkConnectionEvent( 975 eq(WLAN_IFACE_NAME), eq(frameworkNetworkId), eq(BSSID)); 976 wifiMonitorInOrder.verify(mWifiMonitor).broadcastSupplicantStateChangeEvent( 977 eq(WLAN_IFACE_NAME), eq(frameworkNetworkId), 978 any(WifiSsid.class), eq(BSSID), eq(SupplicantState.COMPLETED)); 979 } 980 981 /** 982 * Tests the handling of network disconnected notification. 983 */ 984 @Test 985 public void testDisconnectedCallback() throws Exception { 986 executeAndValidateInitializationSequence(); 987 assertNotNull(mISupplicantStaIfaceCallback); 988 989 int reasonCode = 5; 990 mISupplicantStaIfaceCallback.onDisconnected( 991 NativeUtil.macAddressToByteArray(BSSID), true, reasonCode); 992 verify(mWifiMonitor).broadcastNetworkDisconnectionEvent( 993 eq(WLAN_IFACE_NAME), eq(1), eq(reasonCode), eq(BSSID)); 994 995 mISupplicantStaIfaceCallback.onDisconnected( 996 NativeUtil.macAddressToByteArray(BSSID), false, reasonCode); 997 verify(mWifiMonitor).broadcastNetworkDisconnectionEvent( 998 eq(WLAN_IFACE_NAME), eq(0), eq(reasonCode), eq(BSSID)); 999 } 1000 1001 /** 1002 * Tests the handling of incorrect network passwords. 1003 */ 1004 @Test 1005 public void testAuthFailurePassword() throws Exception { 1006 executeAndValidateInitializationSequence(); 1007 assertNotNull(mISupplicantStaIfaceCallback); 1008 1009 int reasonCode = 3; 1010 mISupplicantStaIfaceCallback.onDisconnected( 1011 NativeUtil.macAddressToByteArray(BSSID), true, reasonCode); 1012 verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt()); 1013 1014 mISupplicantStaIfaceCallback.onDisconnected( 1015 NativeUtil.macAddressToByteArray(BSSID), false, reasonCode); 1016 verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt()); 1017 1018 mISupplicantStaIfaceCallback.onStateChanged( 1019 ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE, 1020 NativeUtil.macAddressToByteArray(BSSID), 1021 SUPPLICANT_NETWORK_ID, 1022 NativeUtil.decodeSsid(SUPPLICANT_SSID)); 1023 mISupplicantStaIfaceCallback.onDisconnected( 1024 NativeUtil.macAddressToByteArray(BSSID), true, reasonCode); 1025 mISupplicantStaIfaceCallback.onDisconnected( 1026 NativeUtil.macAddressToByteArray(BSSID), false, reasonCode); 1027 1028 verify(mWifiMonitor, times(2)).broadcastAuthenticationFailureEvent(eq(WLAN_IFACE_NAME), 1029 eq(WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD)); 1030 1031 } 1032 1033 /** 1034 * Tests the handling of incorrect network passwords, edge case. 1035 * 1036 * If the disconnect reason is "IE in 4way differs", do not call it a password mismatch. 1037 */ 1038 @Test 1039 public void testIeDiffers() throws Exception { 1040 executeAndValidateInitializationSequence(); 1041 assertNotNull(mISupplicantStaIfaceCallback); 1042 1043 int reasonCode = 17; // IEEE 802.11i WLAN_REASON_IE_IN_4WAY_DIFFERS 1044 1045 mISupplicantStaIfaceCallback.onStateChanged( 1046 ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE, 1047 NativeUtil.macAddressToByteArray(BSSID), 1048 SUPPLICANT_NETWORK_ID, 1049 NativeUtil.decodeSsid(SUPPLICANT_SSID)); 1050 mISupplicantStaIfaceCallback.onDisconnected( 1051 NativeUtil.macAddressToByteArray(BSSID), true, reasonCode); 1052 verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt()); 1053 } 1054 1055 1056 /** 1057 * Tests the handling of association rejection notification. 1058 */ 1059 @Test 1060 public void testAssociationRejectionCallback() throws Exception { 1061 executeAndValidateInitializationSequence(); 1062 assertNotNull(mISupplicantStaIfaceCallback); 1063 1064 int statusCode = 7; 1065 mISupplicantStaIfaceCallback.onAssociationRejected( 1066 NativeUtil.macAddressToByteArray(BSSID), statusCode, false); 1067 verify(mWifiMonitor).broadcastAssociationRejectionEvent( 1068 eq(WLAN_IFACE_NAME), eq(statusCode), eq(false), eq(BSSID)); 1069 } 1070 1071 /** 1072 * Tests the handling of authentification timeout notification. 1073 */ 1074 @Test 1075 public void testAuthenticationTimeoutCallback() throws Exception { 1076 executeAndValidateInitializationSequence(); 1077 assertNotNull(mISupplicantStaIfaceCallback); 1078 1079 mISupplicantStaIfaceCallback.onAuthenticationTimeout( 1080 NativeUtil.macAddressToByteArray(BSSID)); 1081 verify(mWifiMonitor).broadcastAuthenticationFailureEvent(eq(WLAN_IFACE_NAME), 1082 eq(WifiManager.ERROR_AUTH_FAILURE_TIMEOUT)); 1083 } 1084 1085 /** 1086 * Tests the handling of bssid change notification. 1087 */ 1088 @Test 1089 public void testBssidChangedCallback() throws Exception { 1090 executeAndValidateInitializationSequence(); 1091 assertNotNull(mISupplicantStaIfaceCallback); 1092 1093 mISupplicantStaIfaceCallback.onBssidChanged( 1094 BssidChangeReason.ASSOC_START, NativeUtil.macAddressToByteArray(BSSID)); 1095 verify(mWifiMonitor).broadcastTargetBssidEvent(eq(WLAN_IFACE_NAME), eq(BSSID)); 1096 verify(mWifiMonitor, never()).broadcastAssociatedBssidEvent(eq(WLAN_IFACE_NAME), eq(BSSID)); 1097 1098 reset(mWifiMonitor); 1099 mISupplicantStaIfaceCallback.onBssidChanged( 1100 BssidChangeReason.ASSOC_COMPLETE, NativeUtil.macAddressToByteArray(BSSID)); 1101 verify(mWifiMonitor, never()).broadcastTargetBssidEvent(eq(WLAN_IFACE_NAME), eq(BSSID)); 1102 verify(mWifiMonitor).broadcastAssociatedBssidEvent(eq(WLAN_IFACE_NAME), eq(BSSID)); 1103 1104 reset(mWifiMonitor); 1105 mISupplicantStaIfaceCallback.onBssidChanged( 1106 BssidChangeReason.DISASSOC, NativeUtil.macAddressToByteArray(BSSID)); 1107 verify(mWifiMonitor, never()).broadcastTargetBssidEvent(eq(WLAN_IFACE_NAME), eq(BSSID)); 1108 verify(mWifiMonitor, never()).broadcastAssociatedBssidEvent(eq(WLAN_IFACE_NAME), eq(BSSID)); 1109 } 1110 1111 /** 1112 * Tests the handling of EAP failure notification. 1113 */ 1114 @Test 1115 public void testEapFailureCallback() throws Exception { 1116 executeAndValidateInitializationSequence(); 1117 assertNotNull(mISupplicantStaIfaceCallback); 1118 1119 mISupplicantStaIfaceCallback.onEapFailure(); 1120 verify(mWifiMonitor).broadcastAuthenticationFailureEvent(eq(WLAN_IFACE_NAME), 1121 eq(WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE)); 1122 } 1123 1124 /** 1125 * Tests the handling of Wps success notification. 1126 */ 1127 @Test 1128 public void testWpsSuccessCallback() throws Exception { 1129 executeAndValidateInitializationSequence(); 1130 assertNotNull(mISupplicantStaIfaceCallback); 1131 1132 mISupplicantStaIfaceCallback.onWpsEventSuccess(); 1133 verify(mWifiMonitor).broadcastWpsSuccessEvent(eq(WLAN_IFACE_NAME)); 1134 } 1135 1136 /** 1137 * Tests the handling of Wps fail notification. 1138 */ 1139 @Test 1140 public void testWpsFailureCallback() throws Exception { 1141 executeAndValidateInitializationSequence(); 1142 assertNotNull(mISupplicantStaIfaceCallback); 1143 1144 short cfgError = ISupplicantStaIfaceCallback.WpsConfigError.MULTIPLE_PBC_DETECTED; 1145 short errorInd = ISupplicantStaIfaceCallback.WpsErrorIndication.SECURITY_WEP_PROHIBITED; 1146 mISupplicantStaIfaceCallback.onWpsEventFail( 1147 NativeUtil.macAddressToByteArray(BSSID), cfgError, errorInd); 1148 verify(mWifiMonitor).broadcastWpsFailEvent(eq(WLAN_IFACE_NAME), 1149 eq((int) cfgError), eq((int) errorInd)); 1150 } 1151 1152 /** 1153 * Tests the handling of Wps fail notification. 1154 */ 1155 @Test 1156 public void testWpsTimeoutCallback() throws Exception { 1157 executeAndValidateInitializationSequence(); 1158 assertNotNull(mISupplicantStaIfaceCallback); 1159 1160 short cfgError = ISupplicantStaIfaceCallback.WpsConfigError.MSG_TIMEOUT; 1161 short errorInd = ISupplicantStaIfaceCallback.WpsErrorIndication.NO_ERROR; 1162 mISupplicantStaIfaceCallback.onWpsEventFail( 1163 NativeUtil.macAddressToByteArray(BSSID), cfgError, errorInd); 1164 verify(mWifiMonitor).broadcastWpsTimeoutEvent(eq(WLAN_IFACE_NAME)); 1165 } 1166 1167 /** 1168 * Tests the handling of Wps pbc overlap notification. 1169 */ 1170 @Test 1171 public void testWpsPbcOverlapCallback() throws Exception { 1172 executeAndValidateInitializationSequence(); 1173 assertNotNull(mISupplicantStaIfaceCallback); 1174 1175 mISupplicantStaIfaceCallback.onWpsEventPbcOverlap(); 1176 verify(mWifiMonitor).broadcastWpsOverlapEvent(eq(WLAN_IFACE_NAME)); 1177 } 1178 1179 /** 1180 * Tests the handling of service manager death notification. 1181 */ 1182 @Test 1183 public void testServiceManagerDeathCallback() throws Exception { 1184 executeAndValidateInitializationSequence(); 1185 assertNotNull(mServiceManagerDeathCaptor.getValue()); 1186 assertTrue(mDut.isInitializationComplete()); 1187 1188 mServiceManagerDeathCaptor.getValue().serviceDied(5L); 1189 1190 assertFalse(mDut.isInitializationComplete()); 1191 verify(mWifiMonitor).broadcastSupplicantDisconnectionEvent(eq(WLAN_IFACE_NAME)); 1192 } 1193 1194 /** 1195 * Tests the handling of supplicant death notification. 1196 */ 1197 @Test 1198 public void testSupplicantDeathCallback() throws Exception { 1199 executeAndValidateInitializationSequence(); 1200 assertNotNull(mSupplicantDeathCaptor.getValue()); 1201 assertTrue(mDut.isInitializationComplete()); 1202 1203 mSupplicantDeathCaptor.getValue().serviceDied(5L); 1204 1205 assertFalse(mDut.isInitializationComplete()); 1206 verify(mWifiMonitor).broadcastSupplicantDisconnectionEvent(eq(WLAN_IFACE_NAME)); 1207 } 1208 1209 /** 1210 * Tests the handling of supplicant sta iface death notification. 1211 */ 1212 @Test 1213 public void testSupplicantStaIfaceDeathCallback() throws Exception { 1214 executeAndValidateInitializationSequence(); 1215 assertNotNull(mSupplicantStaIfaceDeathCaptor.getValue()); 1216 assertTrue(mDut.isInitializationComplete()); 1217 1218 mSupplicantStaIfaceDeathCaptor.getValue().serviceDied(5L); 1219 1220 assertFalse(mDut.isInitializationComplete()); 1221 verify(mWifiMonitor).broadcastSupplicantDisconnectionEvent(eq(WLAN_IFACE_NAME)); 1222 } 1223 1224 /** 1225 * Tests the setting of log level. 1226 */ 1227 @Test 1228 public void testSetLogLevel() throws Exception { 1229 when(mISupplicantMock.setDebugParams(anyInt(), anyBoolean(), anyBoolean())) 1230 .thenReturn(mStatusSuccess); 1231 1232 // Fail before initialization is performed. 1233 assertFalse(mDut.setLogLevel(true)); 1234 1235 executeAndValidateInitializationSequence(); 1236 1237 // This should work. 1238 assertTrue(mDut.setLogLevel(true)); 1239 verify(mISupplicantMock) 1240 .setDebugParams(eq(ISupplicant.DebugLevel.DEBUG), eq(false), eq(false)); 1241 } 1242 1243 /** 1244 * Tests the setting of concurrency priority. 1245 */ 1246 @Test 1247 public void testConcurrencyPriority() throws Exception { 1248 when(mISupplicantMock.setConcurrencyPriority(anyInt())).thenReturn(mStatusSuccess); 1249 1250 // Fail before initialization is performed. 1251 assertFalse(mDut.setConcurrencyPriority(false)); 1252 1253 executeAndValidateInitializationSequence(); 1254 1255 // This should work. 1256 assertTrue(mDut.setConcurrencyPriority(false)); 1257 verify(mISupplicantMock).setConcurrencyPriority(eq(IfaceType.P2P)); 1258 assertTrue(mDut.setConcurrencyPriority(true)); 1259 verify(mISupplicantMock).setConcurrencyPriority(eq(IfaceType.STA)); 1260 } 1261 1262 /** 1263 * Tests the start of wps registrar. 1264 */ 1265 @Test 1266 public void testStartWpsRegistrar() throws Exception { 1267 when(mISupplicantStaIfaceMock.startWpsRegistrar(any(byte[].class), anyString())) 1268 .thenReturn(mStatusSuccess); 1269 1270 // Fail before initialization is performed. 1271 assertFalse(mDut.startWpsRegistrar(null, null)); 1272 1273 executeAndValidateInitializationSequence(); 1274 1275 assertFalse(mDut.startWpsRegistrar(null, null)); 1276 verify(mISupplicantStaIfaceMock, never()).startWpsRegistrar(any(byte[].class), anyString()); 1277 1278 assertFalse(mDut.startWpsRegistrar(new String(), "452233")); 1279 verify(mISupplicantStaIfaceMock, never()).startWpsRegistrar(any(byte[].class), anyString()); 1280 1281 assertTrue(mDut.startWpsRegistrar("45:23:12:12:12:98", "562535")); 1282 verify(mISupplicantStaIfaceMock).startWpsRegistrar(any(byte[].class), anyString()); 1283 } 1284 1285 /** 1286 * Tests the start of wps PBC. 1287 */ 1288 @Test 1289 public void testStartWpsPbc() throws Exception { 1290 when(mISupplicantStaIfaceMock.startWpsPbc(any(byte[].class))).thenReturn(mStatusSuccess); 1291 String bssid = "45:23:12:12:12:98"; 1292 byte[] bssidBytes = {0x45, 0x23, 0x12, 0x12, 0x12, (byte) 0x98}; 1293 byte[] anyBssidBytes = {0, 0, 0, 0, 0, 0}; 1294 1295 // Fail before initialization is performed. 1296 assertFalse(mDut.startWpsPbc(bssid)); 1297 verify(mISupplicantStaIfaceMock, never()).startWpsPbc(any(byte[].class)); 1298 1299 executeAndValidateInitializationSequence(); 1300 1301 assertTrue(mDut.startWpsPbc(bssid)); 1302 verify(mISupplicantStaIfaceMock).startWpsPbc(eq(bssidBytes)); 1303 1304 assertTrue(mDut.startWpsPbc(null)); 1305 verify(mISupplicantStaIfaceMock).startWpsPbc(eq(anyBssidBytes)); 1306 } 1307 1308 private WifiConfiguration createTestWifiConfiguration() { 1309 WifiConfiguration config = new WifiConfiguration(); 1310 config.networkId = SUPPLICANT_NETWORK_ID; 1311 return config; 1312 } 1313 1314 private void executeAndValidateHs20DeauthImminentCallback(boolean isEss) throws Exception { 1315 executeAndValidateInitializationSequence(); 1316 assertNotNull(mISupplicantStaIfaceCallback); 1317 1318 byte[] bssid = NativeUtil.macAddressToByteArray(BSSID); 1319 int reasonCode = isEss ? WnmData.ESS : WnmData.ESS + 1; 1320 int reauthDelay = 5; 1321 mISupplicantStaIfaceCallback.onHs20DeauthImminentNotice( 1322 bssid, reasonCode, reauthDelay, HS20_URL); 1323 1324 ArgumentCaptor<WnmData> wnmDataCaptor = ArgumentCaptor.forClass(WnmData.class); 1325 verify(mWifiMonitor).broadcastWnmEvent(eq(WLAN_IFACE_NAME), wnmDataCaptor.capture()); 1326 assertEquals( 1327 ByteBufferReader.readInteger( 1328 ByteBuffer.wrap(bssid), ByteOrder.BIG_ENDIAN, bssid.length), 1329 wnmDataCaptor.getValue().getBssid()); 1330 assertEquals(isEss, wnmDataCaptor.getValue().isEss()); 1331 assertEquals(reauthDelay, wnmDataCaptor.getValue().getDelay()); 1332 assertEquals(HS20_URL, wnmDataCaptor.getValue().getUrl()); 1333 } 1334 1335 private void executeAndValidateInitializationSequence() throws Exception { 1336 executeAndValidateInitializationSequence(false, false, false, false); 1337 } 1338 1339 /** 1340 * Calls.initialize(), mocking various call back answers and verifying flow, asserting for the 1341 * expected result. Verifies if ISupplicantStaIface manager is initialized or reset. 1342 * Each of the arguments will cause a different failure mode when set true. 1343 */ 1344 private void executeAndValidateInitializationSequence(boolean causeRemoteException, 1345 boolean getZeroInterfaces, 1346 boolean getNullInterface, 1347 boolean causeCallbackRegFailure) 1348 throws Exception { 1349 boolean shouldSucceed = 1350 !causeRemoteException && !getZeroInterfaces && !getNullInterface 1351 && !causeCallbackRegFailure; 1352 // Setup callback mock answers 1353 ArrayList<ISupplicant.IfaceInfo> interfaces; 1354 if (getZeroInterfaces) { 1355 interfaces = new ArrayList<>(); 1356 } else { 1357 interfaces = mIfaceInfoList; 1358 } 1359 doAnswer(new GetListInterfacesAnswer(interfaces)).when(mISupplicantMock) 1360 .listInterfaces(any(ISupplicant.listInterfacesCallback.class)); 1361 if (causeRemoteException) { 1362 doThrow(new RemoteException("Some error!!!")) 1363 .when(mISupplicantMock).getInterface(any(ISupplicant.IfaceInfo.class), 1364 any(ISupplicant.getInterfaceCallback.class)); 1365 } else { 1366 doAnswer(new GetGetInterfaceAnswer(getNullInterface)) 1367 .when(mISupplicantMock).getInterface(any(ISupplicant.IfaceInfo.class), 1368 any(ISupplicant.getInterfaceCallback.class)); 1369 } 1370 /** Callback registeration */ 1371 if (causeCallbackRegFailure) { 1372 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 1373 public SupplicantStatus answer(ISupplicantStaIfaceCallback cb) 1374 throws RemoteException { 1375 return mStatusFailure; 1376 } 1377 }).when(mISupplicantStaIfaceMock) 1378 .registerCallback(any(ISupplicantStaIfaceCallback.class)); 1379 } else { 1380 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 1381 public SupplicantStatus answer(ISupplicantStaIfaceCallback cb) 1382 throws RemoteException { 1383 mISupplicantStaIfaceCallback = cb; 1384 return mStatusSuccess; 1385 } 1386 }).when(mISupplicantStaIfaceMock) 1387 .registerCallback(any(ISupplicantStaIfaceCallback.class)); 1388 } 1389 1390 mInOrder = inOrder(mServiceManagerMock, mISupplicantMock, mISupplicantStaIfaceMock, 1391 mWifiMonitor); 1392 // Initialize SupplicantStaIfaceHal, should call serviceManager.registerForNotifications 1393 assertTrue(mDut.initialize()); 1394 // verify: service manager initialization sequence 1395 mInOrder.verify(mServiceManagerMock).linkToDeath(mServiceManagerDeathCaptor.capture(), 1396 anyLong()); 1397 mInOrder.verify(mServiceManagerMock).registerForNotifications( 1398 eq(ISupplicant.kInterfaceName), eq(""), mServiceNotificationCaptor.capture()); 1399 // act: cause the onRegistration(...) callback to execute 1400 mServiceNotificationCaptor.getValue().onRegistration(ISupplicant.kInterfaceName, "", true); 1401 1402 assertTrue(mDut.isInitializationComplete() == shouldSucceed); 1403 mInOrder.verify(mISupplicantMock).linkToDeath(mSupplicantDeathCaptor.capture(), 1404 anyLong()); 1405 // verify: listInterfaces is called 1406 mInOrder.verify(mISupplicantMock).listInterfaces( 1407 any(ISupplicant.listInterfacesCallback.class)); 1408 if (!getZeroInterfaces) { 1409 mInOrder.verify(mISupplicantMock) 1410 .getInterface(any(ISupplicant.IfaceInfo.class), 1411 any(ISupplicant.getInterfaceCallback.class)); 1412 } 1413 if (causeRemoteException) { 1414 mInOrder.verify(mWifiMonitor).broadcastSupplicantDisconnectionEvent(eq(null)); 1415 } 1416 if (!causeRemoteException && !getZeroInterfaces && !getNullInterface) { 1417 mInOrder.verify(mISupplicantStaIfaceMock).linkToDeath( 1418 mSupplicantStaIfaceDeathCaptor.capture(), anyLong()); 1419 mInOrder.verify(mISupplicantStaIfaceMock) 1420 .registerCallback(any(ISupplicantStaIfaceCallback.class)); 1421 } 1422 } 1423 1424 private SupplicantStatus createSupplicantStatus(int code) { 1425 SupplicantStatus status = new SupplicantStatus(); 1426 status.code = code; 1427 return status; 1428 } 1429 1430 /** 1431 * Create an IfaceInfo with given type and name 1432 */ 1433 private ISupplicant.IfaceInfo createIfaceInfo(int type, String name) { 1434 ISupplicant.IfaceInfo info = new ISupplicant.IfaceInfo(); 1435 info.type = type; 1436 info.name = name; 1437 return info; 1438 } 1439 1440 private class GetListInterfacesAnswer extends MockAnswerUtil.AnswerWithArguments { 1441 private ArrayList<ISupplicant.IfaceInfo> mInterfaceList; 1442 1443 GetListInterfacesAnswer(ArrayList<ISupplicant.IfaceInfo> ifaces) { 1444 mInterfaceList = ifaces; 1445 } 1446 1447 public void answer(ISupplicant.listInterfacesCallback cb) { 1448 cb.onValues(mStatusSuccess, mInterfaceList); 1449 } 1450 } 1451 1452 private class GetGetInterfaceAnswer extends MockAnswerUtil.AnswerWithArguments { 1453 boolean mGetNullInterface; 1454 1455 GetGetInterfaceAnswer(boolean getNullInterface) { 1456 mGetNullInterface = getNullInterface; 1457 } 1458 1459 public void answer(ISupplicant.IfaceInfo iface, ISupplicant.getInterfaceCallback cb) { 1460 if (mGetNullInterface) { 1461 cb.onValues(mStatusSuccess, null); 1462 } else { 1463 cb.onValues(mStatusSuccess, mISupplicantIfaceMock); 1464 } 1465 } 1466 } 1467 1468 /** 1469 * Setup mocks for connect sequence. 1470 */ 1471 private void setupMocksForConnectSequence(final boolean haveExistingNetwork) throws Exception { 1472 final int existingNetworkId = SUPPLICANT_NETWORK_ID; 1473 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 1474 public SupplicantStatus answer() throws RemoteException { 1475 return mStatusSuccess; 1476 } 1477 }).when(mISupplicantStaIfaceMock).disconnect(); 1478 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 1479 public void answer(ISupplicantStaIface.listNetworksCallback cb) throws RemoteException { 1480 if (haveExistingNetwork) { 1481 cb.onValues(mStatusSuccess, new ArrayList<>(Arrays.asList(existingNetworkId))); 1482 } else { 1483 cb.onValues(mStatusSuccess, new ArrayList<>()); 1484 } 1485 } 1486 }).when(mISupplicantStaIfaceMock) 1487 .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class)); 1488 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 1489 public SupplicantStatus answer(int id) throws RemoteException { 1490 return mStatusSuccess; 1491 } 1492 }).when(mISupplicantStaIfaceMock).removeNetwork(eq(existingNetworkId)); 1493 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 1494 public void answer(ISupplicantStaIface.addNetworkCallback cb) throws RemoteException { 1495 cb.onValues(mStatusSuccess, mock(ISupplicantStaNetwork.class)); 1496 return; 1497 } 1498 }).when(mISupplicantStaIfaceMock).addNetwork( 1499 any(ISupplicantStaIface.addNetworkCallback.class)); 1500 when(mSupplicantStaNetworkMock.saveWifiConfiguration(any(WifiConfiguration.class))) 1501 .thenReturn(true); 1502 when(mSupplicantStaNetworkMock.select()).thenReturn(true); 1503 } 1504 1505 /** 1506 * Helper function to validate the connect sequence. 1507 */ 1508 private void validateConnectSequence( 1509 final boolean haveExistingNetwork, int numNetworkAdditions) throws Exception { 1510 if (haveExistingNetwork) { 1511 verify(mISupplicantStaIfaceMock).removeNetwork(anyInt()); 1512 } 1513 verify(mISupplicantStaIfaceMock, times(numNetworkAdditions)) 1514 .addNetwork(any(ISupplicantStaIface.addNetworkCallback.class)); 1515 verify(mSupplicantStaNetworkMock, times(numNetworkAdditions)) 1516 .saveWifiConfiguration(any(WifiConfiguration.class)); 1517 verify(mSupplicantStaNetworkMock, times(numNetworkAdditions)).select(); 1518 } 1519 1520 /** 1521 * Helper function to execute all the actions to perform connection to the network. 1522 * 1523 * @param newFrameworkNetworkId Framework Network Id of the new network to connect. 1524 * @param haveExistingNetwork Removes the existing network. 1525 * @return the WifiConfiguration object of the new network to connect. 1526 */ 1527 private WifiConfiguration executeAndValidateConnectSequence( 1528 final int newFrameworkNetworkId, final boolean haveExistingNetwork) throws Exception { 1529 setupMocksForConnectSequence(haveExistingNetwork); 1530 WifiConfiguration config = new WifiConfiguration(); 1531 config.networkId = newFrameworkNetworkId; 1532 assertTrue(mDut.connectToNetwork(config)); 1533 validateConnectSequence(haveExistingNetwork, 1); 1534 return config; 1535 } 1536 1537 /** 1538 * Setup mocks for roam sequence. 1539 */ 1540 private void setupMocksForRoamSequence(String roamBssid) throws Exception { 1541 doAnswer(new MockAnswerUtil.AnswerWithArguments() { 1542 public SupplicantStatus answer() throws RemoteException { 1543 return mStatusSuccess; 1544 } 1545 }).when(mISupplicantStaIfaceMock).reassociate(); 1546 when(mSupplicantStaNetworkMock.setBssid(eq(roamBssid))).thenReturn(true); 1547 } 1548 1549 /** 1550 * Helper function to execute all the actions to perform roaming to the network. 1551 * 1552 * @param sameNetwork Roam to the same network or not. 1553 */ 1554 private void executeAndValidateRoamSequence(boolean sameNetwork) throws Exception { 1555 int connectedNetworkId = ROAM_NETWORK_ID; 1556 String roamBssid = BSSID; 1557 int roamNetworkId; 1558 if (sameNetwork) { 1559 roamNetworkId = connectedNetworkId; 1560 } else { 1561 roamNetworkId = connectedNetworkId + 1; 1562 } 1563 executeAndValidateConnectSequence(connectedNetworkId, false); 1564 setupMocksForRoamSequence(roamBssid); 1565 1566 WifiConfiguration roamingConfig = new WifiConfiguration(); 1567 roamingConfig.networkId = roamNetworkId; 1568 roamingConfig.getNetworkSelectionStatus().setNetworkSelectionBSSID(roamBssid); 1569 assertTrue(mDut.roamToNetwork(roamingConfig)); 1570 1571 if (!sameNetwork) { 1572 validateConnectSequence(false, 2); 1573 verify(mSupplicantStaNetworkMock, never()).setBssid(anyString()); 1574 verify(mISupplicantStaIfaceMock, never()).reassociate(); 1575 } else { 1576 verify(mSupplicantStaNetworkMock).setBssid(eq(roamBssid)); 1577 verify(mISupplicantStaIfaceMock).reassociate(); 1578 } 1579 } 1580 } 1581