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 com.android.server.wifi.HalDeviceManager.START_HAL_RETRY_TIMES; 20 21 import static junit.framework.Assert.assertEquals; 22 23 import static org.hamcrest.core.IsEqual.equalTo; 24 import static org.junit.Assert.assertFalse; 25 import static org.junit.Assert.assertTrue; 26 import static org.mockito.Matchers.any; 27 import static org.mockito.Matchers.anyInt; 28 import static org.mockito.Matchers.anyLong; 29 import static org.mockito.Matchers.anyString; 30 import static org.mockito.Matchers.eq; 31 import static org.mockito.Mockito.doAnswer; 32 import static org.mockito.Mockito.inOrder; 33 import static org.mockito.Mockito.mock; 34 import static org.mockito.Mockito.times; 35 import static org.mockito.Mockito.verify; 36 import static org.mockito.Mockito.verifyNoMoreInteractions; 37 import static org.mockito.Mockito.when; 38 39 import android.app.test.MockAnswerUtil; 40 import android.hardware.wifi.V1_0.IWifi; 41 import android.hardware.wifi.V1_0.IWifiApIface; 42 import android.hardware.wifi.V1_0.IWifiChip; 43 import android.hardware.wifi.V1_0.IWifiChipEventCallback; 44 import android.hardware.wifi.V1_0.IWifiEventCallback; 45 import android.hardware.wifi.V1_0.IWifiIface; 46 import android.hardware.wifi.V1_0.IWifiNanIface; 47 import android.hardware.wifi.V1_0.IWifiP2pIface; 48 import android.hardware.wifi.V1_0.IWifiStaIface; 49 import android.hardware.wifi.V1_0.IfaceType; 50 import android.hardware.wifi.V1_0.WifiStatus; 51 import android.hardware.wifi.V1_0.WifiStatusCode; 52 import android.hidl.manager.V1_0.IServiceManager; 53 import android.hidl.manager.V1_0.IServiceNotification; 54 import android.os.IHwBinder; 55 import android.os.test.TestLooper; 56 import android.util.Log; 57 58 import org.hamcrest.core.IsNull; 59 import org.junit.After; 60 import org.junit.Before; 61 import org.junit.Rule; 62 import org.junit.Test; 63 import org.junit.rules.ErrorCollector; 64 import org.mockito.ArgumentCaptor; 65 import org.mockito.InOrder; 66 import org.mockito.Mock; 67 import org.mockito.MockitoAnnotations; 68 69 import java.io.PrintWriter; 70 import java.io.StringWriter; 71 import java.util.ArrayList; 72 import java.util.HashMap; 73 import java.util.HashSet; 74 import java.util.Map; 75 import java.util.Set; 76 77 /** 78 * Unit test harness for HalDeviceManagerTest. 79 */ 80 public class HalDeviceManagerTest { 81 private HalDeviceManager mDut; 82 @Mock IServiceManager mServiceManagerMock; 83 @Mock IWifi mWifiMock; 84 @Mock HalDeviceManager.ManagerStatusListener mManagerStatusListenerMock; 85 private TestLooper mTestLooper; 86 private ArgumentCaptor<IHwBinder.DeathRecipient> mDeathRecipientCaptor = 87 ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class); 88 private ArgumentCaptor<IServiceNotification.Stub> mServiceNotificationCaptor = 89 ArgumentCaptor.forClass(IServiceNotification.Stub.class); 90 private ArgumentCaptor<IWifiEventCallback> mWifiEventCallbackCaptor = ArgumentCaptor.forClass( 91 IWifiEventCallback.class); 92 private InOrder mInOrder; 93 @Rule public ErrorCollector collector = new ErrorCollector(); 94 private WifiStatus mStatusOk; 95 private WifiStatus mStatusFail; 96 97 private class HalDeviceManagerSpy extends HalDeviceManager { 98 @Override 99 protected IWifi getWifiServiceMockable() { 100 return mWifiMock; 101 } 102 103 @Override 104 protected IServiceManager getServiceManagerMockable() { 105 return mServiceManagerMock; 106 } 107 } 108 109 @Before 110 public void before() throws Exception { 111 MockitoAnnotations.initMocks(this); 112 113 mTestLooper = new TestLooper(); 114 115 // initialize dummy status objects 116 mStatusOk = getStatus(WifiStatusCode.SUCCESS); 117 mStatusFail = getStatus(WifiStatusCode.ERROR_UNKNOWN); 118 119 when(mServiceManagerMock.linkToDeath(any(IHwBinder.DeathRecipient.class), 120 anyLong())).thenReturn(true); 121 when(mServiceManagerMock.registerForNotifications(anyString(), anyString(), 122 any(IServiceNotification.Stub.class))).thenReturn(true); 123 when(mWifiMock.linkToDeath(any(IHwBinder.DeathRecipient.class), anyLong())).thenReturn( 124 true); 125 when(mWifiMock.registerEventCallback(any(IWifiEventCallback.class))).thenReturn(mStatusOk); 126 when(mWifiMock.start()).thenReturn(mStatusOk); 127 when(mWifiMock.stop()).thenReturn(mStatusOk); 128 129 mDut = new HalDeviceManagerSpy(); 130 } 131 132 /** 133 * Print out the dump of the device manager after each test. Not used in test validation 134 * (internal state) - but can help in debugging failed tests. 135 */ 136 @After 137 public void after() throws Exception { 138 dumpDut("after: "); 139 } 140 141 /** 142 * Test basic startup flow: 143 * - IServiceManager registrations 144 * - IWifi registrations 145 * - IWifi startup delayed 146 * - Start Wi-Fi -> onStart 147 * - Stop Wi-Fi -> onStop 148 */ 149 @Test 150 public void testStartStopFlow() throws Exception { 151 mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock); 152 executeAndValidateInitializationSequence(); 153 executeAndValidateStartupSequence(); 154 155 // act: stop Wi-Fi 156 mDut.stop(); 157 mTestLooper.dispatchAll(); 158 159 // verify: onStop called 160 mInOrder.verify(mWifiMock).stop(); 161 mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); 162 163 verifyNoMoreInteractions(mManagerStatusListenerMock); 164 } 165 166 /** 167 * Validate that multiple callback registrations are called and that duplicate ones are 168 * only called once. 169 */ 170 @Test 171 public void testMultipleCallbackRegistrations() throws Exception { 172 mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock); 173 executeAndValidateInitializationSequence(); 174 175 // register another 2 callbacks - one of them twice 176 HalDeviceManager.ManagerStatusListener callback1 = mock( 177 HalDeviceManager.ManagerStatusListener.class); 178 HalDeviceManager.ManagerStatusListener callback2 = mock( 179 HalDeviceManager.ManagerStatusListener.class); 180 mDut.registerStatusListener(callback2, mTestLooper.getLooper()); 181 mDut.registerStatusListener(callback1, mTestLooper.getLooper()); 182 mDut.registerStatusListener(callback2, mTestLooper.getLooper()); 183 184 // startup 185 executeAndValidateStartupSequence(); 186 187 // verify 188 verify(callback1).onStatusChanged(); 189 verify(callback2).onStatusChanged(); 190 191 verifyNoMoreInteractions(mManagerStatusListenerMock, callback1, callback2); 192 } 193 194 /** 195 * Validate IWifi death listener and registration flow. 196 */ 197 @Test 198 public void testWifiDeathAndRegistration() throws Exception { 199 mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock); 200 executeAndValidateInitializationSequence(); 201 executeAndValidateStartupSequence(); 202 203 // act: IWifi service death 204 mDeathRecipientCaptor.getValue().serviceDied(0); 205 mTestLooper.dispatchAll(); 206 207 // verify: getting onStop 208 mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); 209 210 // act: service startup 211 mServiceNotificationCaptor.getValue().onRegistration(IWifi.kInterfaceName, "", false); 212 213 // verify: initialization of IWifi 214 mInOrder.verify(mWifiMock).linkToDeath(mDeathRecipientCaptor.capture(), anyLong()); 215 mInOrder.verify(mWifiMock).registerEventCallback(mWifiEventCallbackCaptor.capture()); 216 217 // act: start 218 collector.checkThat(mDut.start(), equalTo(true)); 219 mWifiEventCallbackCaptor.getValue().onStart(); 220 mTestLooper.dispatchAll(); 221 222 // verify: service and callback calls 223 mInOrder.verify(mWifiMock).start(); 224 mInOrder.verify(mManagerStatusListenerMock, times(3)).onStatusChanged(); 225 226 verifyNoMoreInteractions(mManagerStatusListenerMock); 227 } 228 229 /** 230 * Validate IWifi onFailure causes notification 231 */ 232 @Test 233 public void testWifiFail() throws Exception { 234 mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock); 235 executeAndValidateInitializationSequence(); 236 executeAndValidateStartupSequence(); 237 238 // act: IWifi failure 239 mWifiEventCallbackCaptor.getValue().onFailure(mStatusFail); 240 mTestLooper.dispatchAll(); 241 242 // verify: getting onStop 243 mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); 244 245 // act: start again 246 collector.checkThat(mDut.start(), equalTo(true)); 247 mWifiEventCallbackCaptor.getValue().onStart(); 248 mTestLooper.dispatchAll(); 249 250 // verify: service and callback calls 251 mInOrder.verify(mWifiMock).start(); 252 mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); 253 254 verifyNoMoreInteractions(mManagerStatusListenerMock); 255 } 256 257 /** 258 * Validate creation of STA interface from blank start-up. The remove interface. 259 */ 260 @Test 261 public void testCreateStaInterfaceNoInitMode() throws Exception { 262 final String name = "sta0"; 263 264 BaselineChip chipMock = new BaselineChip(); 265 chipMock.initialize(); 266 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, 267 mManagerStatusListenerMock); 268 executeAndValidateInitializationSequence(); 269 executeAndValidateStartupSequence(); 270 271 HalDeviceManager.InterfaceDestroyedListener idl = mock( 272 HalDeviceManager.InterfaceDestroyedListener.class); 273 HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock( 274 HalDeviceManager.InterfaceAvailableForRequestListener.class); 275 276 IWifiStaIface iface = (IWifiStaIface) validateInterfaceSequence(chipMock, 277 false, // chipModeValid 278 -1000, // chipModeId (only used if chipModeValid is true) 279 IfaceType.STA, // ifaceTypeToCreate 280 name, // ifaceName 281 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 282 null, // tearDownList 283 idl, // destroyedListener 284 iafrl // availableListener 285 ); 286 collector.checkThat("allocated interface", iface, IsNull.notNullValue()); 287 288 // act: remove interface 289 mDut.removeIface(iface); 290 mTestLooper.dispatchAll(); 291 292 // verify: callback triggered 293 mInOrder.verify(chipMock.chip).removeStaIface(name); 294 verify(idl).onDestroyed(); 295 verify(iafrl).onAvailableForRequest(); 296 297 verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl); 298 } 299 300 /** 301 * Validate creation of AP interface from blank start-up. The remove interface. 302 */ 303 @Test 304 public void testCreateApInterfaceNoInitMode() throws Exception { 305 final String name = "ap0"; 306 307 BaselineChip chipMock = new BaselineChip(); 308 chipMock.initialize(); 309 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, 310 mManagerStatusListenerMock); 311 executeAndValidateInitializationSequence(); 312 executeAndValidateStartupSequence(); 313 314 HalDeviceManager.InterfaceDestroyedListener idl = mock( 315 HalDeviceManager.InterfaceDestroyedListener.class); 316 HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock( 317 HalDeviceManager.InterfaceAvailableForRequestListener.class); 318 319 IWifiApIface iface = (IWifiApIface) validateInterfaceSequence(chipMock, 320 false, // chipModeValid 321 -1000, // chipModeId (only used if chipModeValid is true) 322 IfaceType.AP, // ifaceTypeToCreate 323 name, // ifaceName 324 BaselineChip.AP_CHIP_MODE_ID, // finalChipMode 325 null, // tearDownList 326 idl, // destroyedListener 327 iafrl // availableListener 328 ); 329 collector.checkThat("allocated interface", iface, IsNull.notNullValue()); 330 331 // act: remove interface 332 mDut.removeIface(iface); 333 mTestLooper.dispatchAll(); 334 335 // verify: callback triggered 336 mInOrder.verify(chipMock.chip).removeApIface(name); 337 verify(idl).onDestroyed(); 338 verify(iafrl).onAvailableForRequest(); 339 340 verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl); 341 } 342 343 /** 344 * Validate creation of P2P interface from blank start-up. The remove interface. 345 */ 346 @Test 347 public void testCreateP2pInterfaceNoInitMode() throws Exception { 348 final String name = "p2p0"; 349 350 BaselineChip chipMock = new BaselineChip(); 351 chipMock.initialize(); 352 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, 353 mManagerStatusListenerMock); 354 executeAndValidateInitializationSequence(); 355 executeAndValidateStartupSequence(); 356 357 HalDeviceManager.InterfaceDestroyedListener idl = mock( 358 HalDeviceManager.InterfaceDestroyedListener.class); 359 HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock( 360 HalDeviceManager.InterfaceAvailableForRequestListener.class); 361 362 IWifiP2pIface iface = (IWifiP2pIface) validateInterfaceSequence(chipMock, 363 false, // chipModeValid 364 -1000, // chipModeId (only used if chipModeValid is true) 365 IfaceType.P2P, // ifaceTypeToCreate 366 name, // ifaceName 367 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 368 null, // tearDownList 369 idl, // destroyedListener 370 iafrl // availableListener 371 ); 372 collector.checkThat("allocated interface", iface, IsNull.notNullValue()); 373 374 // act: remove interface 375 mDut.removeIface(iface); 376 mTestLooper.dispatchAll(); 377 378 // verify: callback triggered 379 mInOrder.verify(chipMock.chip).removeP2pIface(name); 380 verify(idl).onDestroyed(); 381 verify(iafrl).onAvailableForRequest(); 382 383 verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl); 384 } 385 386 /** 387 * Validate creation of NAN interface from blank start-up. The remove interface. 388 */ 389 @Test 390 public void testCreateNanInterfaceNoInitMode() throws Exception { 391 final String name = "nan0"; 392 393 BaselineChip chipMock = new BaselineChip(); 394 chipMock.initialize(); 395 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, 396 mManagerStatusListenerMock); 397 executeAndValidateInitializationSequence(); 398 executeAndValidateStartupSequence(); 399 400 HalDeviceManager.InterfaceDestroyedListener idl = mock( 401 HalDeviceManager.InterfaceDestroyedListener.class); 402 HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock( 403 HalDeviceManager.InterfaceAvailableForRequestListener.class); 404 405 IWifiNanIface iface = (IWifiNanIface) validateInterfaceSequence(chipMock, 406 false, // chipModeValid 407 -1000, // chipModeId (only used if chipModeValid is true) 408 IfaceType.NAN, // ifaceTypeToCreate 409 name, // ifaceName 410 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 411 null, // tearDownList 412 idl, // destroyedListener 413 iafrl // availableListener 414 ); 415 collector.checkThat("allocated interface", iface, IsNull.notNullValue()); 416 417 // act: remove interface 418 mDut.removeIface(iface); 419 mTestLooper.dispatchAll(); 420 421 // verify: callback triggered 422 mInOrder.verify(chipMock.chip).removeNanIface(name); 423 verify(idl).onDestroyed(); 424 verify(iafrl).onAvailableForRequest(); 425 426 verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl); 427 } 428 429 /** 430 * Validate creation of AP interface when in STA mode - but with no interface created. Expect 431 * a change in chip mode. 432 */ 433 @Test 434 public void testCreateApWithStaModeUp() throws Exception { 435 final String name = "ap0"; 436 437 BaselineChip chipMock = new BaselineChip(); 438 chipMock.initialize(); 439 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, 440 mManagerStatusListenerMock); 441 executeAndValidateInitializationSequence(); 442 executeAndValidateStartupSequence(); 443 444 HalDeviceManager.InterfaceDestroyedListener idl = mock( 445 HalDeviceManager.InterfaceDestroyedListener.class); 446 HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock( 447 HalDeviceManager.InterfaceAvailableForRequestListener.class); 448 449 IWifiApIface iface = (IWifiApIface) validateInterfaceSequence(chipMock, 450 true, // chipModeValid 451 BaselineChip.STA_CHIP_MODE_ID, // chipModeId 452 IfaceType.AP, // ifaceTypeToCreate 453 name, // ifaceName 454 BaselineChip.AP_CHIP_MODE_ID, // finalChipMode 455 null, // tearDownList 456 idl, // destroyedListener 457 iafrl // availableListener 458 ); 459 collector.checkThat("allocated interface", iface, IsNull.notNullValue()); 460 461 // act: stop Wi-Fi 462 mDut.stop(); 463 mTestLooper.dispatchAll(); 464 465 // verify: callback triggered 466 verify(idl).onDestroyed(); 467 verify(mManagerStatusListenerMock, times(2)).onStatusChanged(); 468 469 verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl); 470 } 471 472 /** 473 * Validate creation of AP interface when in AP mode - but with no interface created. Expect 474 * no change in chip mode. 475 */ 476 @Test 477 public void testCreateApWithApModeUp() throws Exception { 478 final String name = "ap0"; 479 480 BaselineChip chipMock = new BaselineChip(); 481 chipMock.initialize(); 482 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, 483 mManagerStatusListenerMock); 484 executeAndValidateInitializationSequence(); 485 executeAndValidateStartupSequence(); 486 487 HalDeviceManager.InterfaceDestroyedListener idl = mock( 488 HalDeviceManager.InterfaceDestroyedListener.class); 489 HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock( 490 HalDeviceManager.InterfaceAvailableForRequestListener.class); 491 492 IWifiApIface iface = (IWifiApIface) validateInterfaceSequence(chipMock, 493 true, // chipModeValid 494 BaselineChip.AP_CHIP_MODE_ID, // chipModeId 495 IfaceType.AP, // ifaceTypeToCreate 496 name, // ifaceName 497 BaselineChip.AP_CHIP_MODE_ID, // finalChipMode 498 null, // tearDownList 499 idl, // destroyedListener 500 iafrl // availableListener 501 ); 502 collector.checkThat("allocated interface", iface, IsNull.notNullValue()); 503 504 // act: stop Wi-Fi 505 mDut.stop(); 506 mTestLooper.dispatchAll(); 507 508 // verify: callback triggered 509 verify(idl).onDestroyed(); 510 verify(mManagerStatusListenerMock, times(2)).onStatusChanged(); 511 512 verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl); 513 } 514 515 /** 516 * Validate AP up/down creation of AP interface when a STA already created. Expect: 517 * - STA created 518 * - P2P created 519 * - When AP requested: 520 * - STA & P2P torn down 521 * - AP created 522 * - P2P creation refused 523 * - Request STA: will tear down AP 524 * - When AP destroyed: 525 * - Get p2p available listener callback 526 * - Can create P2P when requested 527 * - Create P2P 528 * - Request NAN: will get refused 529 * - Tear down P2P: 530 * - should get nan available listener callback 531 * - Can create NAN when requested 532 */ 533 @Test 534 public void testCreateSameAndDiffPriorities() throws Exception { 535 BaselineChip chipMock = new BaselineChip(); 536 chipMock.initialize(); 537 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, 538 mManagerStatusListenerMock); 539 executeAndValidateInitializationSequence(); 540 executeAndValidateStartupSequence(); 541 542 HalDeviceManager.InterfaceDestroyedListener staDestroyedListener = mock( 543 HalDeviceManager.InterfaceDestroyedListener.class); 544 HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock( 545 HalDeviceManager.InterfaceAvailableForRequestListener.class); 546 547 HalDeviceManager.InterfaceDestroyedListener staDestroyedListener2 = mock( 548 HalDeviceManager.InterfaceDestroyedListener.class); 549 550 HalDeviceManager.InterfaceDestroyedListener apDestroyedListener = mock( 551 HalDeviceManager.InterfaceDestroyedListener.class); 552 HalDeviceManager.InterfaceAvailableForRequestListener apAvailListener = mock( 553 HalDeviceManager.InterfaceAvailableForRequestListener.class); 554 555 HalDeviceManager.InterfaceDestroyedListener p2pDestroyedListener = mock( 556 HalDeviceManager.InterfaceDestroyedListener.class); 557 HalDeviceManager.InterfaceAvailableForRequestListener p2pAvailListener = mock( 558 HalDeviceManager.InterfaceAvailableForRequestListener.class); 559 560 HalDeviceManager.InterfaceDestroyedListener p2pDestroyedListener2 = mock( 561 HalDeviceManager.InterfaceDestroyedListener.class); 562 563 HalDeviceManager.InterfaceDestroyedListener nanDestroyedListener = mock( 564 HalDeviceManager.InterfaceDestroyedListener.class); 565 HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock( 566 HalDeviceManager.InterfaceAvailableForRequestListener.class); 567 568 // Request STA 569 IWifiIface staIface = validateInterfaceSequence(chipMock, 570 false, // chipModeValid 571 -1000, // chipModeId (only used if chipModeValid is true) 572 IfaceType.STA, // ifaceTypeToCreate 573 "sta0", // ifaceName 574 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 575 null, // tearDownList 576 staDestroyedListener, // destroyedListener 577 staAvailListener // availableListener 578 ); 579 collector.checkThat("allocated STA interface", staIface, IsNull.notNullValue()); 580 581 // register additional InterfaceDestroyedListeners - including a duplicate (verify that 582 // only called once!) 583 mDut.registerDestroyedListener(staIface, staDestroyedListener2, mTestLooper.getLooper()); 584 mDut.registerDestroyedListener(staIface, staDestroyedListener, mTestLooper.getLooper()); 585 586 // Request P2P 587 IWifiIface p2pIface = validateInterfaceSequence(chipMock, 588 true, // chipModeValid 589 BaselineChip.STA_CHIP_MODE_ID, // chipModeId 590 IfaceType.P2P, // ifaceTypeToCreate 591 "p2p0", // ifaceName 592 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 593 null, // tearDownList 594 p2pDestroyedListener, // destroyedListener 595 p2pAvailListener // availableListener 596 ); 597 collector.checkThat("allocated P2P interface", p2pIface, IsNull.notNullValue()); 598 599 // Request AP 600 IWifiIface apIface = validateInterfaceSequence(chipMock, 601 true, // chipModeValid 602 BaselineChip.STA_CHIP_MODE_ID, // chipModeId 603 IfaceType.AP, // ifaceTypeToCreate 604 "ap0", // ifaceName 605 BaselineChip.AP_CHIP_MODE_ID, // finalChipMode 606 new IWifiIface[]{staIface, p2pIface}, // tearDownList 607 apDestroyedListener, // destroyedListener 608 apAvailListener, // availableListener 609 // destroyedInterfacesDestroyedListeners... 610 staDestroyedListener, staDestroyedListener2, p2pDestroyedListener 611 ); 612 collector.checkThat("allocated AP interface", apIface, IsNull.notNullValue()); 613 614 // Request P2P: expect failure 615 p2pIface = mDut.createP2pIface(p2pDestroyedListener, mTestLooper.getLooper()); 616 collector.checkThat("P2P can't be created", p2pIface, IsNull.nullValue()); 617 618 // Request STA: expect success 619 staIface = validateInterfaceSequence(chipMock, 620 true, // chipModeValid 621 BaselineChip.AP_CHIP_MODE_ID, // chipModeId 622 IfaceType.STA, // ifaceTypeToCreate 623 "sta0", // ifaceName 624 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 625 null, // tearDownList 626 staDestroyedListener, // destroyedListener 627 staAvailListener, // availableListener 628 apDestroyedListener // destroyedInterfacesDestroyedListeners... 629 ); 630 collector.checkThat("allocated STA interface", staIface, IsNull.notNullValue()); 631 632 mTestLooper.dispatchAll(); 633 verify(apDestroyedListener).onDestroyed(); 634 635 // Request P2P: expect success now 636 p2pIface = validateInterfaceSequence(chipMock, 637 true, // chipModeValid 638 BaselineChip.STA_CHIP_MODE_ID, // chipModeId 639 IfaceType.P2P, // ifaceTypeToCreate 640 "p2p0", // ifaceName 641 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 642 null, // tearDownList 643 p2pDestroyedListener2, // destroyedListener 644 p2pAvailListener // availableListener 645 ); 646 647 // Request NAN: should fail 648 IWifiIface nanIface = mDut.createNanIface(nanDestroyedListener, mTestLooper.getLooper()); 649 mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener, 650 mTestLooper.getLooper()); 651 collector.checkThat("NAN can't be created", nanIface, IsNull.nullValue()); 652 653 // Tear down P2P 654 mDut.removeIface(p2pIface); 655 mTestLooper.dispatchAll(); 656 657 verify(chipMock.chip, times(2)).removeP2pIface("p2p0"); 658 verify(p2pDestroyedListener2).onDestroyed(); 659 660 // Should now be able to request and get NAN 661 nanIface = validateInterfaceSequence(chipMock, 662 true, // chipModeValid 663 BaselineChip.STA_CHIP_MODE_ID, // chipModeId 664 IfaceType.NAN, // ifaceTypeToCreate 665 "nan0", // ifaceName 666 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 667 null, // tearDownList 668 nanDestroyedListener, // destroyedListener 669 nanAvailListener // availableListener 670 ); 671 collector.checkThat("allocated NAN interface", nanIface, IsNull.notNullValue()); 672 673 // available callback verification 674 verify(staAvailListener).onAvailableForRequest(); 675 verify(apAvailListener, times(4)).onAvailableForRequest(); 676 verify(p2pAvailListener, times(3)).onAvailableForRequest(); 677 verify(nanAvailListener).onAvailableForRequest(); 678 679 verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, staAvailListener, 680 staDestroyedListener2, apDestroyedListener, apAvailListener, p2pDestroyedListener, 681 nanDestroyedListener, nanAvailListener, p2pDestroyedListener2); 682 } 683 684 /** 685 * Validate P2P and NAN interactions. Expect: 686 * - STA created 687 * - NAN created 688 * - When P2P requested: 689 * - NAN torn down 690 * - P2P created 691 * - NAN creation refused 692 * - When P2P destroyed: 693 * - get nan available listener 694 * - Can create NAN when requested 695 */ 696 @Test 697 public void testP2pAndNanInteractions() throws Exception { 698 BaselineChip chipMock = new BaselineChip(); 699 chipMock.initialize(); 700 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, 701 mManagerStatusListenerMock); 702 executeAndValidateInitializationSequence(); 703 executeAndValidateStartupSequence(); 704 705 HalDeviceManager.InterfaceDestroyedListener staDestroyedListener = mock( 706 HalDeviceManager.InterfaceDestroyedListener.class); 707 HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock( 708 HalDeviceManager.InterfaceAvailableForRequestListener.class); 709 710 HalDeviceManager.InterfaceDestroyedListener nanDestroyedListener = mock( 711 HalDeviceManager.InterfaceDestroyedListener.class); 712 HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock( 713 HalDeviceManager.InterfaceAvailableForRequestListener.class); 714 715 HalDeviceManager.InterfaceDestroyedListener p2pDestroyedListener = mock( 716 HalDeviceManager.InterfaceDestroyedListener.class); 717 HalDeviceManager.InterfaceAvailableForRequestListener p2pAvailListener = null; 718 719 // Request STA 720 IWifiIface staIface = validateInterfaceSequence(chipMock, 721 false, // chipModeValid 722 -1000, // chipModeId (only used if chipModeValid is true) 723 IfaceType.STA, // ifaceTypeToCreate 724 "sta0", // ifaceName 725 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 726 null, // tearDownList 727 staDestroyedListener, // destroyedListener 728 staAvailListener // availableListener 729 ); 730 731 // Request NAN 732 IWifiIface nanIface = validateInterfaceSequence(chipMock, 733 true, // chipModeValid 734 BaselineChip.STA_CHIP_MODE_ID, // chipModeId 735 IfaceType.NAN, // ifaceTypeToCreate 736 "nan0", // ifaceName 737 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 738 null, // tearDownList 739 nanDestroyedListener, // destroyedListener 740 nanAvailListener // availableListener 741 ); 742 743 // Request P2P 744 IWifiIface p2pIface = validateInterfaceSequence(chipMock, 745 true, // chipModeValid 746 BaselineChip.STA_CHIP_MODE_ID, // chipModeId 747 IfaceType.P2P, // ifaceTypeToCreate 748 "p2p0", // ifaceName 749 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 750 new IWifiIface[]{nanIface}, // tearDownList 751 p2pDestroyedListener, // destroyedListener 752 p2pAvailListener, // availableListener 753 nanDestroyedListener // destroyedInterfacesDestroyedListeners... 754 ); 755 756 // Request NAN: expect failure 757 nanIface = mDut.createNanIface(nanDestroyedListener, mTestLooper.getLooper()); 758 mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener, 759 mTestLooper.getLooper()); 760 collector.checkThat("NAN can't be created", nanIface, IsNull.nullValue()); 761 762 // Destroy P2P interface 763 boolean status = mDut.removeIface(p2pIface); 764 mInOrder.verify(chipMock.chip).removeP2pIface("p2p0"); 765 collector.checkThat("P2P removal success", status, equalTo(true)); 766 767 mTestLooper.dispatchAll(); 768 verify(p2pDestroyedListener).onDestroyed(); 769 verify(nanAvailListener).onAvailableForRequest(); 770 771 // Request NAN: expect success now 772 nanIface = validateInterfaceSequence(chipMock, 773 true, // chipModeValid 774 BaselineChip.STA_CHIP_MODE_ID, // chipModeId 775 IfaceType.NAN, // ifaceTypeToCreate 776 "nan0", // ifaceName 777 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 778 null, // tearDownList 779 nanDestroyedListener, // destroyedListener 780 nanAvailListener // availableListener 781 ); 782 783 verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, staAvailListener, 784 nanDestroyedListener, nanAvailListener, p2pDestroyedListener); 785 } 786 787 /** 788 * Validates that when (for some reason) the cache is out-of-sync with the actual chip status 789 * then Wi-Fi is shut-down. 790 */ 791 @Test 792 public void testCacheMismatchError() throws Exception { 793 BaselineChip chipMock = new BaselineChip(); 794 chipMock.initialize(); 795 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, 796 mManagerStatusListenerMock); 797 executeAndValidateInitializationSequence(); 798 executeAndValidateStartupSequence(); 799 800 HalDeviceManager.InterfaceDestroyedListener staDestroyedListener = mock( 801 HalDeviceManager.InterfaceDestroyedListener.class); 802 HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock( 803 HalDeviceManager.InterfaceAvailableForRequestListener.class); 804 805 HalDeviceManager.InterfaceDestroyedListener nanDestroyedListener = mock( 806 HalDeviceManager.InterfaceDestroyedListener.class); 807 HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock( 808 HalDeviceManager.InterfaceAvailableForRequestListener.class); 809 810 // Request STA 811 IWifiIface staIface = validateInterfaceSequence(chipMock, 812 false, // chipModeValid 813 -1000, // chipModeId (only used if chipModeValid is true) 814 IfaceType.STA, // ifaceTypeToCreate 815 "sta0", // ifaceName 816 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 817 null, // tearDownList 818 staDestroyedListener, // destroyedListener 819 staAvailListener // availableListener 820 ); 821 822 // Request NAN 823 IWifiIface nanIface = validateInterfaceSequence(chipMock, 824 true, // chipModeValid 825 BaselineChip.STA_CHIP_MODE_ID, // chipModeId 826 IfaceType.NAN, // ifaceTypeToCreate 827 "nan0", // ifaceName 828 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 829 null, // tearDownList 830 nanDestroyedListener, // destroyedListener 831 nanAvailListener // availableListener 832 ); 833 834 // fiddle with the "chip" by removing the STA 835 chipMock.interfaceNames.get(IfaceType.STA).remove("sta0"); 836 837 // now try to request another NAN 838 nanIface = mDut.createNanIface(nanDestroyedListener, mTestLooper.getLooper()); 839 mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener, 840 mTestLooper.getLooper()); 841 collector.checkThat("NAN can't be created", nanIface, IsNull.nullValue()); 842 843 // verify that Wi-Fi is shut-down: should also get all onDestroyed messages that are 844 // registered (even if they seem out-of-sync to chip) 845 mTestLooper.dispatchAll(); 846 verify(mWifiMock, times(2)).stop(); 847 verify(mManagerStatusListenerMock, times(2)).onStatusChanged(); 848 verify(staDestroyedListener).onDestroyed(); 849 verify(nanDestroyedListener).onDestroyed(); 850 851 verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, staAvailListener, 852 nanDestroyedListener, nanAvailListener); 853 } 854 855 /** 856 * Validates that trying to allocate a STA and then another STA fails. Only one STA at a time 857 * is permitted (by baseline chip). 858 */ 859 @Test 860 public void testDuplicateStaRequests() throws Exception { 861 BaselineChip chipMock = new BaselineChip(); 862 chipMock.initialize(); 863 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, 864 mManagerStatusListenerMock); 865 executeAndValidateInitializationSequence(); 866 executeAndValidateStartupSequence(); 867 868 HalDeviceManager.InterfaceDestroyedListener staDestroyedListener1 = mock( 869 HalDeviceManager.InterfaceDestroyedListener.class); 870 HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener1 = mock( 871 HalDeviceManager.InterfaceAvailableForRequestListener.class); 872 873 HalDeviceManager.InterfaceDestroyedListener staDestroyedListener2 = mock( 874 HalDeviceManager.InterfaceDestroyedListener.class); 875 876 // get STA interface 877 IWifiIface staIface1 = validateInterfaceSequence(chipMock, 878 false, // chipModeValid 879 -1000, // chipModeId (only used if chipModeValid is true) 880 IfaceType.STA, // ifaceTypeToCreate 881 "sta0", // ifaceName 882 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 883 null, // tearDownList 884 staDestroyedListener1, // destroyedListener 885 staAvailListener1 // availableListener 886 ); 887 collector.checkThat("STA created", staIface1, IsNull.notNullValue()); 888 889 // get STA interface again 890 IWifiIface staIface2 = mDut.createStaIface(staDestroyedListener2, mTestLooper.getLooper()); 891 collector.checkThat("STA created", staIface2, IsNull.nullValue()); 892 893 verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener1, 894 staAvailListener1, staDestroyedListener2); 895 } 896 897 /** 898 * Validates that a duplicate registration of the same InterfaceAvailableForRequestListener 899 * listener will result in a single callback. 900 * 901 * Also validates that get an immediate call on registration if available. 902 */ 903 @Test 904 public void testDuplicateAvailableRegistrations() throws Exception { 905 BaselineChip chipMock = new BaselineChip(); 906 chipMock.initialize(); 907 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, 908 mManagerStatusListenerMock); 909 executeAndValidateInitializationSequence(); 910 executeAndValidateStartupSequence(); 911 912 HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock( 913 HalDeviceManager.InterfaceAvailableForRequestListener.class); 914 915 // get STA interface 916 IWifiIface staIface = validateInterfaceSequence(chipMock, 917 false, // chipModeValid 918 -1000, // chipModeId (only used if chipModeValid is true) 919 IfaceType.STA, // ifaceTypeToCreate 920 "sta0", // ifaceName 921 BaselineChip.STA_CHIP_MODE_ID, // finalChipMode 922 null, // tearDownList 923 null, // destroyedListener 924 null // availableListener 925 ); 926 collector.checkThat("STA created", staIface, IsNull.notNullValue()); 927 928 // act: register the same listener twice 929 mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener, 930 mTestLooper.getLooper()); 931 mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener, 932 mTestLooper.getLooper()); 933 mTestLooper.dispatchAll(); 934 935 // remove STA interface -> should trigger callbacks 936 mDut.removeIface(staIface); 937 mTestLooper.dispatchAll(); 938 939 // verify: only a single trigger 940 verify(staAvailListener).onAvailableForRequest(); 941 942 verifyNoMoreInteractions(staAvailListener); 943 } 944 945 /** 946 * Validate that the getSupportedIfaceTypes API works when requesting for all chips. 947 */ 948 @Test 949 public void testGetSupportedIfaceTypesAll() throws Exception { 950 BaselineChip chipMock = new BaselineChip(); 951 chipMock.initialize(); 952 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, 953 mManagerStatusListenerMock); 954 executeAndValidateInitializationSequence(); 955 executeAndValidateStartupSequence(); 956 957 // try API 958 Set<Integer> results = mDut.getSupportedIfaceTypes(); 959 960 // verify results 961 Set<Integer> correctResults = new HashSet<>(); 962 correctResults.add(IfaceType.AP); 963 correctResults.add(IfaceType.STA); 964 correctResults.add(IfaceType.P2P); 965 correctResults.add(IfaceType.NAN); 966 967 assertEquals(correctResults, results); 968 } 969 970 /** 971 * Validate that the getSupportedIfaceTypes API works when requesting for a specific chip. 972 */ 973 @Test 974 public void testGetSupportedIfaceTypesOneChip() throws Exception { 975 BaselineChip chipMock = new BaselineChip(); 976 chipMock.initialize(); 977 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, 978 mManagerStatusListenerMock); 979 executeAndValidateInitializationSequence(); 980 executeAndValidateStartupSequence(); 981 982 // try API 983 Set<Integer> results = mDut.getSupportedIfaceTypes(chipMock.chip); 984 985 // verify results 986 Set<Integer> correctResults = new HashSet<>(); 987 correctResults.add(IfaceType.AP); 988 correctResults.add(IfaceType.STA); 989 correctResults.add(IfaceType.P2P); 990 correctResults.add(IfaceType.NAN); 991 992 assertEquals(correctResults, results); 993 } 994 995 /** 996 * Validate that when no chip info is found an empty list is returned. 997 */ 998 @Test 999 public void testGetSupportedIfaceTypesError() throws Exception { 1000 // try API 1001 Set<Integer> results = mDut.getSupportedIfaceTypes(); 1002 1003 // verify results 1004 assertEquals(0, results.size()); 1005 } 1006 1007 /** 1008 * Test start HAL can retry upon failure. 1009 */ 1010 @Test 1011 public void testStartHalRetryUponNotAvailableFailure() throws Exception { 1012 // Override the stubbing for mWifiMock in before(). 1013 when(mWifiMock.start()) 1014 .thenReturn(getStatus(WifiStatusCode.ERROR_NOT_AVAILABLE)) 1015 .thenReturn(mStatusOk); 1016 1017 BaselineChip chipMock = new BaselineChip(); 1018 chipMock.initialize(); 1019 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip, 1020 mManagerStatusListenerMock); 1021 executeAndValidateInitializationSequence(); 1022 executeAndValidateStartupSequence(2, true); 1023 } 1024 1025 /** 1026 * Test start HAL fails after multiple retry failures. 1027 */ 1028 @Test 1029 public void testStartHalRetryFailUponMultipleNotAvailableFailures() throws Exception { 1030 // Override the stubbing for mWifiMock in before(). 1031 when(mWifiMock.start()).thenReturn(getStatus(WifiStatusCode.ERROR_NOT_AVAILABLE)); 1032 1033 BaselineChip chipMock = new BaselineChip(); 1034 chipMock.initialize(); 1035 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip); 1036 executeAndValidateInitializationSequence(); 1037 executeAndValidateStartupSequence(START_HAL_RETRY_TIMES + 1, false); 1038 } 1039 1040 /** 1041 * Test start HAL fails after multiple retry failures. 1042 */ 1043 @Test 1044 public void testStartHalRetryFailUponTrueFailure() throws Exception { 1045 // Override the stubbing for mWifiMock in before(). 1046 when(mWifiMock.start()).thenReturn(getStatus(WifiStatusCode.ERROR_UNKNOWN)); 1047 1048 BaselineChip chipMock = new BaselineChip(); 1049 chipMock.initialize(); 1050 mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip); 1051 executeAndValidateInitializationSequence(); 1052 executeAndValidateStartupSequence(1, false); 1053 } 1054 1055 /** 1056 * Validate that isSupported() returns true when IServiceManager finds the vendor HAL daemon in 1057 * the VINTF. 1058 */ 1059 @Test 1060 public void testIsSupportedTrue() throws Exception { 1061 when(mServiceManagerMock.getTransport( 1062 eq(IWifi.kInterfaceName), eq(HalDeviceManager.HAL_INSTANCE_NAME))) 1063 .thenReturn(IServiceManager.Transport.HWBINDER); 1064 mInOrder = inOrder(mServiceManagerMock, mWifiMock); 1065 executeAndValidateInitializationSequence(); 1066 assertTrue(mDut.isSupported()); 1067 } 1068 1069 /** 1070 * Validate that isSupported() returns true when IServiceManager finds the vendor HAL daemon in 1071 * the VINTF. 1072 */ 1073 @Test 1074 public void testIsSupportedFalse() throws Exception { 1075 when(mServiceManagerMock.getTransport( 1076 eq(IWifi.kInterfaceName), eq(HalDeviceManager.HAL_INSTANCE_NAME))) 1077 .thenReturn(IServiceManager.Transport.EMPTY); 1078 mInOrder = inOrder(mServiceManagerMock, mWifiMock); 1079 executeAndValidateInitializationSequence(); 1080 assertFalse(mDut.isSupported()); 1081 } 1082 1083 // utilities 1084 private void dumpDut(String prefix) { 1085 StringWriter sw = new StringWriter(); 1086 mDut.dump(null, new PrintWriter(sw), null); 1087 Log.e("HalDeviceManager", prefix + sw.toString()); 1088 } 1089 1090 private void executeAndValidateInitializationSequence() throws Exception { 1091 // act: 1092 mDut.initialize(); 1093 1094 // verify: service manager initialization sequence 1095 mInOrder.verify(mServiceManagerMock).linkToDeath(any(IHwBinder.DeathRecipient.class), 1096 anyLong()); 1097 mInOrder.verify(mServiceManagerMock).registerForNotifications(eq(IWifi.kInterfaceName), 1098 eq(""), mServiceNotificationCaptor.capture()); 1099 1100 // act: get the service started (which happens even when service was already up) 1101 mServiceNotificationCaptor.getValue().onRegistration(IWifi.kInterfaceName, "", true); 1102 1103 // verify: wifi initialization sequence 1104 mInOrder.verify(mWifiMock).linkToDeath(mDeathRecipientCaptor.capture(), anyLong()); 1105 mInOrder.verify(mWifiMock).registerEventCallback(mWifiEventCallbackCaptor.capture()); 1106 collector.checkThat("isReady is true", mDut.isReady(), equalTo(true)); 1107 } 1108 1109 private void executeAndValidateStartupSequence()throws Exception { 1110 executeAndValidateStartupSequence(1, true); 1111 } 1112 1113 private void executeAndValidateStartupSequence(int numAttempts, boolean success) 1114 throws Exception { 1115 // act: register listener & start Wi-Fi 1116 mDut.registerStatusListener(mManagerStatusListenerMock, mTestLooper.getLooper()); 1117 collector.checkThat(mDut.start(), equalTo(success)); 1118 1119 // verify 1120 mInOrder.verify(mWifiMock, times(numAttempts)).start(); 1121 1122 if (success) { 1123 // act: trigger onStart callback of IWifiEventCallback 1124 mWifiEventCallbackCaptor.getValue().onStart(); 1125 mTestLooper.dispatchAll(); 1126 1127 // verify: onStart called on registered listener 1128 mInOrder.verify(mManagerStatusListenerMock).onStatusChanged(); 1129 } 1130 } 1131 1132 private IWifiIface validateInterfaceSequence(ChipMockBase chipMock, 1133 boolean chipModeValid, int chipModeId, 1134 int ifaceTypeToCreate, String ifaceName, int finalChipMode, IWifiIface[] tearDownList, 1135 HalDeviceManager.InterfaceDestroyedListener destroyedListener, 1136 HalDeviceManager.InterfaceAvailableForRequestListener availableListener, 1137 HalDeviceManager.InterfaceDestroyedListener... destroyedInterfacesDestroyedListeners) 1138 throws Exception { 1139 // configure chip mode response 1140 chipMock.chipModeValid = chipModeValid; 1141 chipMock.chipModeId = chipModeId; 1142 1143 IWifiIface iface = null; 1144 1145 // configure: interface to be created 1146 // act: request the interface 1147 switch (ifaceTypeToCreate) { 1148 case IfaceType.STA: 1149 iface = mock(IWifiStaIface.class); 1150 doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName( 1151 any(IWifiIface.getNameCallback.class)); 1152 doAnswer(new GetTypeAnswer(IfaceType.STA)).when(iface).getType( 1153 any(IWifiIface.getTypeCallback.class)); 1154 doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when( 1155 chipMock.chip).createStaIface(any(IWifiChip.createStaIfaceCallback.class)); 1156 1157 mDut.createStaIface(destroyedListener, mTestLooper.getLooper()); 1158 break; 1159 case IfaceType.AP: 1160 iface = mock(IWifiApIface.class); 1161 doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName( 1162 any(IWifiIface.getNameCallback.class)); 1163 doAnswer(new GetTypeAnswer(IfaceType.AP)).when(iface).getType( 1164 any(IWifiIface.getTypeCallback.class)); 1165 doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when( 1166 chipMock.chip).createApIface(any(IWifiChip.createApIfaceCallback.class)); 1167 1168 mDut.createApIface(destroyedListener, mTestLooper.getLooper()); 1169 break; 1170 case IfaceType.P2P: 1171 iface = mock(IWifiP2pIface.class); 1172 doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName( 1173 any(IWifiIface.getNameCallback.class)); 1174 doAnswer(new GetTypeAnswer(IfaceType.P2P)).when(iface).getType( 1175 any(IWifiIface.getTypeCallback.class)); 1176 doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when( 1177 chipMock.chip).createP2pIface(any(IWifiChip.createP2pIfaceCallback.class)); 1178 1179 mDut.createP2pIface(destroyedListener, mTestLooper.getLooper()); 1180 break; 1181 case IfaceType.NAN: 1182 iface = mock(IWifiNanIface.class); 1183 doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName( 1184 any(IWifiIface.getNameCallback.class)); 1185 doAnswer(new GetTypeAnswer(IfaceType.NAN)).when(iface).getType( 1186 any(IWifiIface.getTypeCallback.class)); 1187 doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when( 1188 chipMock.chip).createNanIface(any(IWifiChip.createNanIfaceCallback.class)); 1189 1190 mDut.createNanIface(destroyedListener, mTestLooper.getLooper()); 1191 break; 1192 } 1193 if (availableListener != null) { 1194 mDut.registerInterfaceAvailableForRequestListener(ifaceTypeToCreate, availableListener, 1195 mTestLooper.getLooper()); 1196 } 1197 1198 // validate: optional tear down of interfaces 1199 if (tearDownList != null) { 1200 for (IWifiIface tearDownIface: tearDownList) { 1201 switch (getType(tearDownIface)) { 1202 case IfaceType.STA: 1203 mInOrder.verify(chipMock.chip).removeStaIface(getName(tearDownIface)); 1204 break; 1205 case IfaceType.AP: 1206 mInOrder.verify(chipMock.chip).removeApIface(getName(tearDownIface)); 1207 break; 1208 case IfaceType.P2P: 1209 mInOrder.verify(chipMock.chip).removeP2pIface(getName(tearDownIface)); 1210 break; 1211 case IfaceType.NAN: 1212 mInOrder.verify(chipMock.chip).removeNanIface(getName(tearDownIface)); 1213 break; 1214 } 1215 } 1216 } 1217 1218 // validate: optional switch to the requested mode 1219 if (!chipModeValid || chipModeId != finalChipMode) { 1220 mInOrder.verify(chipMock.chip).configureChip(finalChipMode); 1221 } else { 1222 mInOrder.verify(chipMock.chip, times(0)).configureChip(anyInt()); 1223 } 1224 1225 // validate: create interface 1226 switch (ifaceTypeToCreate) { 1227 case IfaceType.STA: 1228 mInOrder.verify(chipMock.chip).createStaIface( 1229 any(IWifiChip.createStaIfaceCallback.class)); 1230 break; 1231 case IfaceType.AP: 1232 mInOrder.verify(chipMock.chip).createApIface( 1233 any(IWifiChip.createApIfaceCallback.class)); 1234 break; 1235 case IfaceType.P2P: 1236 mInOrder.verify(chipMock.chip).createP2pIface( 1237 any(IWifiChip.createP2pIfaceCallback.class)); 1238 break; 1239 case IfaceType.NAN: 1240 mInOrder.verify(chipMock.chip).createNanIface( 1241 any(IWifiChip.createNanIfaceCallback.class)); 1242 break; 1243 } 1244 1245 // verify: callbacks on deleted interfaces 1246 mTestLooper.dispatchAll(); 1247 for (int i = 0; i < destroyedInterfacesDestroyedListeners.length; ++i) { 1248 verify(destroyedInterfacesDestroyedListeners[i]).onDestroyed(); 1249 } 1250 1251 return iface; 1252 } 1253 1254 private int getType(IWifiIface iface) throws Exception { 1255 Mutable<Integer> typeResp = new Mutable<>(); 1256 iface.getType((WifiStatus status, int type) -> { 1257 typeResp.value = type; 1258 }); 1259 return typeResp.value; 1260 } 1261 1262 private String getName(IWifiIface iface) throws Exception { 1263 Mutable<String> nameResp = new Mutable<>(); 1264 iface.getName((WifiStatus status, String name) -> { 1265 nameResp.value = name; 1266 }); 1267 return nameResp.value; 1268 } 1269 1270 private WifiStatus getStatus(int code) { 1271 WifiStatus status = new WifiStatus(); 1272 status.code = code; 1273 return status; 1274 } 1275 1276 private static class Mutable<E> { 1277 public E value; 1278 1279 Mutable() { 1280 value = null; 1281 } 1282 1283 Mutable(E value) { 1284 this.value = value; 1285 } 1286 } 1287 1288 // Answer objects 1289 private class GetChipIdsAnswer extends MockAnswerUtil.AnswerWithArguments { 1290 private WifiStatus mStatus; 1291 private ArrayList<Integer> mChipIds; 1292 1293 GetChipIdsAnswer(WifiStatus status, ArrayList<Integer> chipIds) { 1294 mStatus = status; 1295 mChipIds = chipIds; 1296 } 1297 1298 public void answer(IWifi.getChipIdsCallback cb) { 1299 cb.onValues(mStatus, mChipIds); 1300 } 1301 } 1302 1303 private class GetChipAnswer extends MockAnswerUtil.AnswerWithArguments { 1304 private WifiStatus mStatus; 1305 private IWifiChip mChip; 1306 1307 GetChipAnswer(WifiStatus status, IWifiChip chip) { 1308 mStatus = status; 1309 mChip = chip; 1310 } 1311 1312 public void answer(int chipId, IWifi.getChipCallback cb) { 1313 cb.onValues(mStatus, mChip); 1314 } 1315 } 1316 1317 private class GetIdAnswer extends MockAnswerUtil.AnswerWithArguments { 1318 private ChipMockBase mChipMockBase; 1319 1320 GetIdAnswer(ChipMockBase chipMockBase) { 1321 mChipMockBase = chipMockBase; 1322 } 1323 1324 public void answer(IWifiChip.getIdCallback cb) { 1325 cb.onValues(mStatusOk, mChipMockBase.chipId); 1326 } 1327 } 1328 1329 private class GetAvailableModesAnswer extends MockAnswerUtil.AnswerWithArguments { 1330 private ChipMockBase mChipMockBase; 1331 1332 GetAvailableModesAnswer(ChipMockBase chipMockBase) { 1333 mChipMockBase = chipMockBase; 1334 } 1335 1336 public void answer(IWifiChip.getAvailableModesCallback cb) { 1337 cb.onValues(mStatusOk, mChipMockBase.availableModes); 1338 } 1339 } 1340 1341 private class GetModeAnswer extends MockAnswerUtil.AnswerWithArguments { 1342 private ChipMockBase mChipMockBase; 1343 1344 GetModeAnswer(ChipMockBase chipMockBase) { 1345 mChipMockBase = chipMockBase; 1346 } 1347 1348 public void answer(IWifiChip.getModeCallback cb) { 1349 cb.onValues(mChipMockBase.chipModeValid ? mStatusOk 1350 : getStatus(WifiStatusCode.ERROR_NOT_AVAILABLE), mChipMockBase.chipModeId); 1351 } 1352 } 1353 1354 private class ConfigureChipAnswer extends MockAnswerUtil.AnswerWithArguments { 1355 private ChipMockBase mChipMockBase; 1356 1357 ConfigureChipAnswer(ChipMockBase chipMockBase) { 1358 mChipMockBase = chipMockBase; 1359 } 1360 1361 public WifiStatus answer(int chipMode) { 1362 mChipMockBase.chipModeId = chipMode; 1363 return mStatusOk; 1364 } 1365 } 1366 1367 private class GetXxxIfaceNamesAnswer extends MockAnswerUtil.AnswerWithArguments { 1368 private ChipMockBase mChipMockBase; 1369 1370 GetXxxIfaceNamesAnswer(ChipMockBase chipMockBase) { 1371 mChipMockBase = chipMockBase; 1372 } 1373 1374 public void answer(IWifiChip.getStaIfaceNamesCallback cb) { 1375 cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.STA)); 1376 } 1377 1378 public void answer(IWifiChip.getApIfaceNamesCallback cb) { 1379 cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.AP)); 1380 } 1381 1382 public void answer(IWifiChip.getP2pIfaceNamesCallback cb) { 1383 cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.P2P)); 1384 } 1385 1386 public void answer(IWifiChip.getNanIfaceNamesCallback cb) { 1387 cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.NAN)); 1388 } 1389 } 1390 1391 private class GetXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments { 1392 private ChipMockBase mChipMockBase; 1393 1394 GetXxxIfaceAnswer(ChipMockBase chipMockBase) { 1395 mChipMockBase = chipMockBase; 1396 } 1397 1398 public void answer(String name, IWifiChip.getStaIfaceCallback cb) { 1399 IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.STA).get(name); 1400 cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiStaIface) iface); 1401 } 1402 1403 public void answer(String name, IWifiChip.getApIfaceCallback cb) { 1404 IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.AP).get(name); 1405 cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiApIface) iface); 1406 } 1407 1408 public void answer(String name, IWifiChip.getP2pIfaceCallback cb) { 1409 IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.P2P).get(name); 1410 cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiP2pIface) iface); 1411 } 1412 1413 public void answer(String name, IWifiChip.getNanIfaceCallback cb) { 1414 IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.NAN).get(name); 1415 cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiNanIface) iface); 1416 } 1417 } 1418 1419 private class CreateXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments { 1420 private ChipMockBase mChipMockBase; 1421 private WifiStatus mStatus; 1422 private IWifiIface mWifiIface; 1423 1424 CreateXxxIfaceAnswer(ChipMockBase chipMockBase, WifiStatus status, IWifiIface wifiIface) { 1425 mChipMockBase = chipMockBase; 1426 mStatus = status; 1427 mWifiIface = wifiIface; 1428 } 1429 1430 private void addInterfaceInfo(int type) { 1431 if (mStatus.code == WifiStatusCode.SUCCESS) { 1432 try { 1433 mChipMockBase.interfaceNames.get(type).add(getName(mWifiIface)); 1434 mChipMockBase.interfacesByName.get(type).put(getName(mWifiIface), mWifiIface); 1435 } catch (Exception e) { 1436 // do nothing 1437 } 1438 } 1439 } 1440 1441 public void answer(IWifiChip.createStaIfaceCallback cb) { 1442 cb.onValues(mStatus, (IWifiStaIface) mWifiIface); 1443 addInterfaceInfo(IfaceType.STA); 1444 } 1445 1446 public void answer(IWifiChip.createApIfaceCallback cb) { 1447 cb.onValues(mStatus, (IWifiApIface) mWifiIface); 1448 addInterfaceInfo(IfaceType.AP); 1449 } 1450 1451 public void answer(IWifiChip.createP2pIfaceCallback cb) { 1452 cb.onValues(mStatus, (IWifiP2pIface) mWifiIface); 1453 addInterfaceInfo(IfaceType.P2P); 1454 } 1455 1456 public void answer(IWifiChip.createNanIfaceCallback cb) { 1457 cb.onValues(mStatus, (IWifiNanIface) mWifiIface); 1458 addInterfaceInfo(IfaceType.NAN); 1459 } 1460 } 1461 1462 private class RemoveXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments { 1463 private ChipMockBase mChipMockBase; 1464 private int mType; 1465 1466 RemoveXxxIfaceAnswer(ChipMockBase chipMockBase, int type) { 1467 mChipMockBase = chipMockBase; 1468 mType = type; 1469 } 1470 1471 private WifiStatus removeIface(int type, String ifname) { 1472 try { 1473 if (!mChipMockBase.interfaceNames.get(type).remove(ifname)) { 1474 return mStatusFail; 1475 } 1476 if (mChipMockBase.interfacesByName.get(type).remove(ifname) == null) { 1477 return mStatusFail; 1478 } 1479 } catch (Exception e) { 1480 return mStatusFail; 1481 } 1482 return mStatusOk; 1483 } 1484 1485 public WifiStatus answer(String ifname) { 1486 return removeIface(mType, ifname); 1487 } 1488 } 1489 1490 private class GetNameAnswer extends MockAnswerUtil.AnswerWithArguments { 1491 private String mName; 1492 1493 GetNameAnswer(String name) { 1494 mName = name; 1495 } 1496 1497 public void answer(IWifiIface.getNameCallback cb) { 1498 cb.onValues(mStatusOk, mName); 1499 } 1500 } 1501 1502 private class GetTypeAnswer extends MockAnswerUtil.AnswerWithArguments { 1503 private int mType; 1504 1505 GetTypeAnswer(int type) { 1506 mType = type; 1507 } 1508 1509 public void answer(IWifiIface.getTypeCallback cb) { 1510 cb.onValues(mStatusOk, mType); 1511 } 1512 } 1513 1514 // chip configuration 1515 1516 private class ChipMockBase { 1517 public IWifiChip chip; 1518 public int chipId; 1519 public boolean chipModeValid = false; 1520 public int chipModeId = -1000; 1521 public Map<Integer, ArrayList<String>> interfaceNames = new HashMap<>(); 1522 public Map<Integer, Map<String, IWifiIface>> interfacesByName = new HashMap<>(); 1523 1524 public ArrayList<IWifiChip.ChipMode> availableModes; 1525 1526 void initialize() throws Exception { 1527 chip = mock(IWifiChip.class); 1528 1529 interfaceNames.put(IfaceType.STA, new ArrayList<>()); 1530 interfaceNames.put(IfaceType.AP, new ArrayList<>()); 1531 interfaceNames.put(IfaceType.P2P, new ArrayList<>()); 1532 interfaceNames.put(IfaceType.NAN, new ArrayList<>()); 1533 1534 interfacesByName.put(IfaceType.STA, new HashMap<>()); 1535 interfacesByName.put(IfaceType.AP, new HashMap<>()); 1536 interfacesByName.put(IfaceType.P2P, new HashMap<>()); 1537 interfacesByName.put(IfaceType.NAN, new HashMap<>()); 1538 1539 when(chip.registerEventCallback(any(IWifiChipEventCallback.class))).thenReturn( 1540 mStatusOk); 1541 when(chip.configureChip(anyInt())).thenAnswer(new ConfigureChipAnswer(this)); 1542 doAnswer(new GetIdAnswer(this)).when(chip).getId(any(IWifiChip.getIdCallback.class)); 1543 doAnswer(new GetModeAnswer(this)).when(chip).getMode( 1544 any(IWifiChip.getModeCallback.class)); 1545 GetXxxIfaceNamesAnswer getXxxIfaceNamesAnswer = new GetXxxIfaceNamesAnswer(this); 1546 doAnswer(getXxxIfaceNamesAnswer).when(chip).getStaIfaceNames( 1547 any(IWifiChip.getStaIfaceNamesCallback.class)); 1548 doAnswer(getXxxIfaceNamesAnswer).when(chip).getApIfaceNames( 1549 any(IWifiChip.getApIfaceNamesCallback.class)); 1550 doAnswer(getXxxIfaceNamesAnswer).when(chip).getP2pIfaceNames( 1551 any(IWifiChip.getP2pIfaceNamesCallback.class)); 1552 doAnswer(getXxxIfaceNamesAnswer).when(chip).getNanIfaceNames( 1553 any(IWifiChip.getNanIfaceNamesCallback.class)); 1554 GetXxxIfaceAnswer getXxxIfaceAnswer = new GetXxxIfaceAnswer(this); 1555 doAnswer(getXxxIfaceAnswer).when(chip).getStaIface(anyString(), 1556 any(IWifiChip.getStaIfaceCallback.class)); 1557 doAnswer(getXxxIfaceAnswer).when(chip).getApIface(anyString(), 1558 any(IWifiChip.getApIfaceCallback.class)); 1559 doAnswer(getXxxIfaceAnswer).when(chip).getP2pIface(anyString(), 1560 any(IWifiChip.getP2pIfaceCallback.class)); 1561 doAnswer(getXxxIfaceAnswer).when(chip).getNanIface(anyString(), 1562 any(IWifiChip.getNanIfaceCallback.class)); 1563 doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.STA)).when(chip).removeStaIface( 1564 anyString()); 1565 doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.AP)).when(chip).removeApIface( 1566 anyString()); 1567 doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.P2P)).when(chip).removeP2pIface( 1568 anyString()); 1569 doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.NAN)).when(chip).removeNanIface( 1570 anyString()); 1571 } 1572 } 1573 1574 // emulate baseline/legacy config: 1575 // mode: STA + NAN || P2P 1576 // mode: NAN 1577 private class BaselineChip extends ChipMockBase { 1578 static final int STA_CHIP_MODE_ID = 0; 1579 static final int AP_CHIP_MODE_ID = 1; 1580 1581 void initialize() throws Exception { 1582 super.initialize(); 1583 1584 // chip Id configuration 1585 ArrayList<Integer> chipIds; 1586 chipId = 10; 1587 chipIds = new ArrayList<>(); 1588 chipIds.add(chipId); 1589 doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds( 1590 any(IWifi.getChipIdsCallback.class)); 1591 1592 doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(10), 1593 any(IWifi.getChipCallback.class)); 1594 1595 // initialize dummy chip modes 1596 IWifiChip.ChipMode cm; 1597 IWifiChip.ChipIfaceCombination cic; 1598 IWifiChip.ChipIfaceCombinationLimit cicl; 1599 1600 // Mode 0: 1xSTA + 1x{P2P,NAN} 1601 // Mode 1: 1xAP 1602 availableModes = new ArrayList<>(); 1603 cm = new IWifiChip.ChipMode(); 1604 cm.id = STA_CHIP_MODE_ID; 1605 1606 cic = new IWifiChip.ChipIfaceCombination(); 1607 1608 cicl = new IWifiChip.ChipIfaceCombinationLimit(); 1609 cicl.maxIfaces = 1; 1610 cicl.types.add(IfaceType.STA); 1611 cic.limits.add(cicl); 1612 1613 cicl = new IWifiChip.ChipIfaceCombinationLimit(); 1614 cicl.maxIfaces = 1; 1615 cicl.types.add(IfaceType.P2P); 1616 cicl.types.add(IfaceType.NAN); 1617 cic.limits.add(cicl); 1618 cm.availableCombinations.add(cic); 1619 availableModes.add(cm); 1620 1621 cm = new IWifiChip.ChipMode(); 1622 cm.id = AP_CHIP_MODE_ID; 1623 cic = new IWifiChip.ChipIfaceCombination(); 1624 cicl = new IWifiChip.ChipIfaceCombinationLimit(); 1625 cicl.maxIfaces = 1; 1626 cicl.types.add(IfaceType.AP); 1627 cic.limits.add(cicl); 1628 cm.availableCombinations.add(cic); 1629 availableModes.add(cm); 1630 1631 doAnswer(new GetAvailableModesAnswer(this)).when(chip) 1632 .getAvailableModes(any(IWifiChip.getAvailableModesCallback.class)); 1633 } 1634 } 1635 } 1636