blob: 4635f843b5078aa89bfc1af7997308b359fe54f8 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wifi;
import static junit.framework.Assert.assertEquals;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.app.test.MockAnswerUtil;
import android.hardware.wifi.V1_0.IWifi;
import android.hardware.wifi.V1_0.IWifiApIface;
import android.hardware.wifi.V1_0.IWifiChip;
import android.hardware.wifi.V1_0.IWifiChipEventCallback;
import android.hardware.wifi.V1_0.IWifiEventCallback;
import android.hardware.wifi.V1_0.IWifiIface;
import android.hardware.wifi.V1_0.IWifiNanIface;
import android.hardware.wifi.V1_0.IWifiP2pIface;
import android.hardware.wifi.V1_0.IWifiStaIface;
import android.hardware.wifi.V1_0.IfaceType;
import android.hardware.wifi.V1_0.WifiStatus;
import android.hardware.wifi.V1_0.WifiStatusCode;
import android.hidl.manager.V1_0.IServiceManager;
import android.hidl.manager.V1_0.IServiceNotification;
import android.os.IHwBinder;
import android.os.test.TestLooper;
import android.util.Log;
import org.hamcrest.core.IsNull;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Unit test harness for HalDeviceManagerTest.
*/
public class HalDeviceManagerTest {
private HalDeviceManager mDut;
@Mock IServiceManager mServiceManagerMock;
@Mock IWifi mWifiMock;
@Mock HalDeviceManager.ManagerStatusListener mManagerStatusListenerMock;
private TestLooper mTestLooper;
private ArgumentCaptor<IHwBinder.DeathRecipient> mDeathRecipientCaptor =
ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class);
private ArgumentCaptor<IServiceNotification.Stub> mServiceNotificationCaptor =
ArgumentCaptor.forClass(IServiceNotification.Stub.class);
private ArgumentCaptor<IWifiEventCallback> mWifiEventCallbackCaptor = ArgumentCaptor.forClass(
IWifiEventCallback.class);
private InOrder mInOrder;
@Rule public ErrorCollector collector = new ErrorCollector();
private WifiStatus mStatusOk;
private WifiStatus mStatusFail;
private class HalDeviceManagerSpy extends HalDeviceManager {
@Override
protected IWifi getWifiServiceMockable() {
return mWifiMock;
}
@Override
protected IServiceManager getServiceManagerMockable() {
return mServiceManagerMock;
}
}
@Before
public void before() throws Exception {
MockitoAnnotations.initMocks(this);
mTestLooper = new TestLooper();
// initialize dummy status objects
mStatusOk = getStatus(WifiStatusCode.SUCCESS);
mStatusFail = getStatus(WifiStatusCode.ERROR_UNKNOWN);
when(mServiceManagerMock.linkToDeath(any(IHwBinder.DeathRecipient.class),
anyLong())).thenReturn(true);
when(mServiceManagerMock.registerForNotifications(anyString(), anyString(),
any(IServiceNotification.Stub.class))).thenReturn(true);
when(mWifiMock.linkToDeath(any(IHwBinder.DeathRecipient.class), anyLong())).thenReturn(
true);
when(mWifiMock.registerEventCallback(any(IWifiEventCallback.class))).thenReturn(mStatusOk);
when(mWifiMock.start()).thenReturn(mStatusOk);
when(mWifiMock.stop()).thenReturn(mStatusOk);
mDut = new HalDeviceManagerSpy();
}
/**
* Print out the dump of the device manager after each test. Not used in test validation
* (internal state) - but can help in debugging failed tests.
*/
@After
public void after() throws Exception {
dumpDut("after: ");
}
/**
* Test basic startup flow:
* - IServiceManager registrations
* - IWifi registrations
* - IWifi startup delayed
* - Start Wi-Fi -> onStart
* - Stop Wi-Fi -> onStop
*/
@Test
public void testStartStopFlow() throws Exception {
mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
// act: stop Wi-Fi
mDut.stop();
mTestLooper.dispatchAll();
// verify: onStop called
mInOrder.verify(mWifiMock).stop();
mInOrder.verify(mManagerStatusListenerMock).onStatusChanged();
verifyNoMoreInteractions(mManagerStatusListenerMock);
}
/**
* Validate that multiple callback registrations are called and that duplicate ones are
* only called once.
*/
@Test
public void testMultipleCallbackRegistrations() throws Exception {
mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
// register another 2 callbacks - one of them twice
HalDeviceManager.ManagerStatusListener callback1 = mock(
HalDeviceManager.ManagerStatusListener.class);
HalDeviceManager.ManagerStatusListener callback2 = mock(
HalDeviceManager.ManagerStatusListener.class);
mDut.registerStatusListener(callback2, mTestLooper.getLooper());
mDut.registerStatusListener(callback1, mTestLooper.getLooper());
mDut.registerStatusListener(callback2, mTestLooper.getLooper());
// startup
executeAndValidateStartupSequence();
// verify
verify(callback1).onStatusChanged();
verify(callback2).onStatusChanged();
verifyNoMoreInteractions(mManagerStatusListenerMock, callback1, callback2);
}
/**
* Validate IWifi death listener and registration flow.
*/
@Test
public void testWifiDeathAndRegistration() throws Exception {
mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
// act: IWifi service death
mDeathRecipientCaptor.getValue().serviceDied(0);
mTestLooper.dispatchAll();
// verify: getting onStop
mInOrder.verify(mManagerStatusListenerMock).onStatusChanged();
// act: service startup
mServiceNotificationCaptor.getValue().onRegistration(IWifi.kInterfaceName, "", false);
// verify: initialization of IWifi
mInOrder.verify(mWifiMock).linkToDeath(mDeathRecipientCaptor.capture(), anyLong());
mInOrder.verify(mWifiMock).registerEventCallback(mWifiEventCallbackCaptor.capture());
// act: start
mDut.start();
mWifiEventCallbackCaptor.getValue().onStart();
mTestLooper.dispatchAll();
// verify: service and callback calls
mInOrder.verify(mWifiMock).start();
mInOrder.verify(mManagerStatusListenerMock, times(3)).onStatusChanged();
verifyNoMoreInteractions(mManagerStatusListenerMock);
}
/**
* Validate IWifi onFailure causes notification
*/
@Test
public void testWifiFail() throws Exception {
mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
// act: IWifi failure
mWifiEventCallbackCaptor.getValue().onFailure(mStatusFail);
mTestLooper.dispatchAll();
// verify: getting onStop
mInOrder.verify(mManagerStatusListenerMock).onStatusChanged();
// act: start again
mDut.start();
mWifiEventCallbackCaptor.getValue().onStart();
mTestLooper.dispatchAll();
// verify: service and callback calls
mInOrder.verify(mWifiMock).start();
mInOrder.verify(mManagerStatusListenerMock).onStatusChanged();
verifyNoMoreInteractions(mManagerStatusListenerMock);
}
/**
* Validate creation of STA interface from blank start-up. The remove interface.
*/
@Test
public void testCreateStaInterfaceNoInitMode() throws Exception {
final String name = "sta0";
BaselineChip chipMock = new BaselineChip();
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
HalDeviceManager.InterfaceDestroyedListener idl = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
IWifiStaIface iface = (IWifiStaIface) validateInterfaceSequence(chipMock,
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.STA, // ifaceTypeToCreate
name, // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
idl, // destroyedListener
iafrl // availableListener
);
collector.checkThat("allocated interface", iface, IsNull.notNullValue());
// act: remove interface
mDut.removeIface(iface);
mTestLooper.dispatchAll();
// verify: callback triggered
mInOrder.verify(chipMock.chip).removeStaIface(name);
verify(idl).onDestroyed();
verify(iafrl).onAvailableForRequest();
verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl);
}
/**
* Validate creation of AP interface from blank start-up. The remove interface.
*/
@Test
public void testCreateApInterfaceNoInitMode() throws Exception {
final String name = "ap0";
BaselineChip chipMock = new BaselineChip();
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
HalDeviceManager.InterfaceDestroyedListener idl = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
IWifiApIface iface = (IWifiApIface) validateInterfaceSequence(chipMock,
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.AP, // ifaceTypeToCreate
name, // ifaceName
BaselineChip.AP_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
idl, // destroyedListener
iafrl // availableListener
);
collector.checkThat("allocated interface", iface, IsNull.notNullValue());
// act: remove interface
mDut.removeIface(iface);
mTestLooper.dispatchAll();
// verify: callback triggered
mInOrder.verify(chipMock.chip).removeApIface(name);
verify(idl).onDestroyed();
verify(iafrl).onAvailableForRequest();
verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl);
}
/**
* Validate creation of P2P interface from blank start-up. The remove interface.
*/
@Test
public void testCreateP2pInterfaceNoInitMode() throws Exception {
final String name = "p2p0";
BaselineChip chipMock = new BaselineChip();
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
HalDeviceManager.InterfaceDestroyedListener idl = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
IWifiP2pIface iface = (IWifiP2pIface) validateInterfaceSequence(chipMock,
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.P2P, // ifaceTypeToCreate
name, // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
idl, // destroyedListener
iafrl // availableListener
);
collector.checkThat("allocated interface", iface, IsNull.notNullValue());
// act: remove interface
mDut.removeIface(iface);
mTestLooper.dispatchAll();
// verify: callback triggered
mInOrder.verify(chipMock.chip).removeP2pIface(name);
verify(idl).onDestroyed();
verify(iafrl).onAvailableForRequest();
verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl);
}
/**
* Validate creation of NAN interface from blank start-up. The remove interface.
*/
@Test
public void testCreateNanInterfaceNoInitMode() throws Exception {
final String name = "nan0";
BaselineChip chipMock = new BaselineChip();
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
HalDeviceManager.InterfaceDestroyedListener idl = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
IWifiNanIface iface = (IWifiNanIface) validateInterfaceSequence(chipMock,
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.NAN, // ifaceTypeToCreate
name, // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
idl, // destroyedListener
iafrl // availableListener
);
collector.checkThat("allocated interface", iface, IsNull.notNullValue());
// act: remove interface
mDut.removeIface(iface);
mTestLooper.dispatchAll();
// verify: callback triggered
mInOrder.verify(chipMock.chip).removeNanIface(name);
verify(idl).onDestroyed();
verify(iafrl).onAvailableForRequest();
verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl);
}
/**
* Validate creation of AP interface when in STA mode - but with no interface created. Expect
* a change in chip mode.
*/
@Test
public void testCreateApWithStaModeUp() throws Exception {
final String name = "ap0";
BaselineChip chipMock = new BaselineChip();
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
HalDeviceManager.InterfaceDestroyedListener idl = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
IWifiApIface iface = (IWifiApIface) validateInterfaceSequence(chipMock,
true, // chipModeValid
BaselineChip.STA_CHIP_MODE_ID, // chipModeId
IfaceType.AP, // ifaceTypeToCreate
name, // ifaceName
BaselineChip.AP_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
idl, // destroyedListener
iafrl // availableListener
);
collector.checkThat("allocated interface", iface, IsNull.notNullValue());
// act: stop Wi-Fi
mDut.stop();
mTestLooper.dispatchAll();
// verify: callback triggered
verify(idl).onDestroyed();
verify(mManagerStatusListenerMock, times(2)).onStatusChanged();
verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl);
}
/**
* Validate creation of AP interface when in AP mode - but with no interface created. Expect
* no change in chip mode.
*/
@Test
public void testCreateApWithApModeUp() throws Exception {
final String name = "ap0";
BaselineChip chipMock = new BaselineChip();
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
HalDeviceManager.InterfaceDestroyedListener idl = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
IWifiApIface iface = (IWifiApIface) validateInterfaceSequence(chipMock,
true, // chipModeValid
BaselineChip.AP_CHIP_MODE_ID, // chipModeId
IfaceType.AP, // ifaceTypeToCreate
name, // ifaceName
BaselineChip.AP_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
idl, // destroyedListener
iafrl // availableListener
);
collector.checkThat("allocated interface", iface, IsNull.notNullValue());
// act: stop Wi-Fi
mDut.stop();
mTestLooper.dispatchAll();
// verify: callback triggered
verify(idl).onDestroyed();
verify(mManagerStatusListenerMock, times(2)).onStatusChanged();
verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl);
}
/**
* Validate AP up/down creation of AP interface when a STA already created. Expect:
* - STA created
* - P2P created
* - When AP requested:
* - STA & P2P torn down
* - AP created
* - P2P creation refused
* - Request STA: will tear down AP
* - When AP destroyed:
* - Get p2p available listener callback
* - Can create P2P when requested
* - Create P2P
* - Request NAN: will get refused
* - Tear down P2P:
* - should get nan available listener callback
* - Can create NAN when requested
*/
@Test
public void testCreateSameAndDiffPriorities() throws Exception {
BaselineChip chipMock = new BaselineChip();
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
HalDeviceManager.InterfaceDestroyedListener staDestroyedListener = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
HalDeviceManager.InterfaceDestroyedListener staDestroyedListener2 = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceDestroyedListener apDestroyedListener = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener apAvailListener = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
HalDeviceManager.InterfaceDestroyedListener p2pDestroyedListener = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener p2pAvailListener = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
HalDeviceManager.InterfaceDestroyedListener p2pDestroyedListener2 = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceDestroyedListener nanDestroyedListener = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
// Request STA
IWifiIface staIface = validateInterfaceSequence(chipMock,
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.STA, // ifaceTypeToCreate
"sta0", // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
staDestroyedListener, // destroyedListener
staAvailListener // availableListener
);
collector.checkThat("allocated STA interface", staIface, IsNull.notNullValue());
// register additional InterfaceDestroyedListeners - including a duplicate (verify that
// only called once!)
mDut.registerDestroyedListener(staIface, staDestroyedListener2, mTestLooper.getLooper());
mDut.registerDestroyedListener(staIface, staDestroyedListener, mTestLooper.getLooper());
// Request P2P
IWifiIface p2pIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
BaselineChip.STA_CHIP_MODE_ID, // chipModeId
IfaceType.P2P, // ifaceTypeToCreate
"p2p0", // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
p2pDestroyedListener, // destroyedListener
p2pAvailListener // availableListener
);
collector.checkThat("allocated P2P interface", p2pIface, IsNull.notNullValue());
// Request AP
IWifiIface apIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
BaselineChip.STA_CHIP_MODE_ID, // chipModeId
IfaceType.AP, // ifaceTypeToCreate
"ap0", // ifaceName
BaselineChip.AP_CHIP_MODE_ID, // finalChipMode
new IWifiIface[]{staIface, p2pIface}, // tearDownList
apDestroyedListener, // destroyedListener
apAvailListener, // availableListener
// destroyedInterfacesDestroyedListeners...
staDestroyedListener, staDestroyedListener2, p2pDestroyedListener
);
collector.checkThat("allocated AP interface", apIface, IsNull.notNullValue());
// Request P2P: expect failure
p2pIface = mDut.createP2pIface(p2pDestroyedListener, mTestLooper.getLooper());
collector.checkThat("P2P can't be created", p2pIface, IsNull.nullValue());
// Request STA: expect success
staIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
BaselineChip.AP_CHIP_MODE_ID, // chipModeId
IfaceType.STA, // ifaceTypeToCreate
"sta0", // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
staDestroyedListener, // destroyedListener
staAvailListener, // availableListener
apDestroyedListener // destroyedInterfacesDestroyedListeners...
);
collector.checkThat("allocated STA interface", staIface, IsNull.notNullValue());
mTestLooper.dispatchAll();
verify(apDestroyedListener).onDestroyed();
// Request P2P: expect success now
p2pIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
BaselineChip.STA_CHIP_MODE_ID, // chipModeId
IfaceType.P2P, // ifaceTypeToCreate
"p2p0", // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
p2pDestroyedListener2, // destroyedListener
p2pAvailListener // availableListener
);
// Request NAN: should fail
IWifiIface nanIface = mDut.createNanIface(nanDestroyedListener, mTestLooper.getLooper());
mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener,
mTestLooper.getLooper());
collector.checkThat("NAN can't be created", nanIface, IsNull.nullValue());
// Tear down P2P
mDut.removeIface(p2pIface);
mTestLooper.dispatchAll();
verify(chipMock.chip, times(2)).removeP2pIface("p2p0");
verify(p2pDestroyedListener2).onDestroyed();
// Should now be able to request and get NAN
nanIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
BaselineChip.STA_CHIP_MODE_ID, // chipModeId
IfaceType.NAN, // ifaceTypeToCreate
"nan0", // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
nanDestroyedListener, // destroyedListener
nanAvailListener // availableListener
);
collector.checkThat("allocated NAN interface", nanIface, IsNull.notNullValue());
// available callback verification
verify(staAvailListener).onAvailableForRequest();
verify(apAvailListener, times(4)).onAvailableForRequest();
verify(p2pAvailListener, times(3)).onAvailableForRequest();
verify(nanAvailListener).onAvailableForRequest();
verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, staAvailListener,
staDestroyedListener2, apDestroyedListener, apAvailListener, p2pDestroyedListener,
nanDestroyedListener, nanAvailListener, p2pDestroyedListener2);
}
/**
* Validate P2P and NAN interactions. Expect:
* - STA created
* - NAN created
* - When P2P requested:
* - NAN torn down
* - P2P created
* - NAN creation refused
* - When P2P destroyed:
* - get nan available listener
* - Can create NAN when requested
*/
@Test
public void testP2pAndNanInteractions() throws Exception {
BaselineChip chipMock = new BaselineChip();
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
HalDeviceManager.InterfaceDestroyedListener staDestroyedListener = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
HalDeviceManager.InterfaceDestroyedListener nanDestroyedListener = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
HalDeviceManager.InterfaceDestroyedListener p2pDestroyedListener = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener p2pAvailListener = null;
// Request STA
IWifiIface staIface = validateInterfaceSequence(chipMock,
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.STA, // ifaceTypeToCreate
"sta0", // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
staDestroyedListener, // destroyedListener
staAvailListener // availableListener
);
// Request NAN
IWifiIface nanIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
BaselineChip.STA_CHIP_MODE_ID, // chipModeId
IfaceType.NAN, // ifaceTypeToCreate
"nan0", // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
nanDestroyedListener, // destroyedListener
nanAvailListener // availableListener
);
// Request P2P
IWifiIface p2pIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
BaselineChip.STA_CHIP_MODE_ID, // chipModeId
IfaceType.P2P, // ifaceTypeToCreate
"p2p0", // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
new IWifiIface[]{nanIface}, // tearDownList
p2pDestroyedListener, // destroyedListener
p2pAvailListener, // availableListener
nanDestroyedListener // destroyedInterfacesDestroyedListeners...
);
// Request NAN: expect failure
nanIface = mDut.createNanIface(nanDestroyedListener, mTestLooper.getLooper());
mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener,
mTestLooper.getLooper());
collector.checkThat("NAN can't be created", nanIface, IsNull.nullValue());
// Destroy P2P interface
boolean status = mDut.removeIface(p2pIface);
mInOrder.verify(chipMock.chip).removeP2pIface("p2p0");
collector.checkThat("P2P removal success", status, equalTo(true));
mTestLooper.dispatchAll();
verify(p2pDestroyedListener).onDestroyed();
verify(nanAvailListener).onAvailableForRequest();
// Request NAN: expect success now
nanIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
BaselineChip.STA_CHIP_MODE_ID, // chipModeId
IfaceType.NAN, // ifaceTypeToCreate
"nan0", // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
nanDestroyedListener, // destroyedListener
nanAvailListener // availableListener
);
verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, staAvailListener,
nanDestroyedListener, nanAvailListener, p2pDestroyedListener);
}
/**
* Validates that when (for some reason) the cache is out-of-sync with the actual chip status
* then Wi-Fi is shut-down.
*/
@Test
public void testCacheMismatchError() throws Exception {
BaselineChip chipMock = new BaselineChip();
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
HalDeviceManager.InterfaceDestroyedListener staDestroyedListener = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
HalDeviceManager.InterfaceDestroyedListener nanDestroyedListener = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
// Request STA
IWifiIface staIface = validateInterfaceSequence(chipMock,
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.STA, // ifaceTypeToCreate
"sta0", // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
staDestroyedListener, // destroyedListener
staAvailListener // availableListener
);
// Request NAN
IWifiIface nanIface = validateInterfaceSequence(chipMock,
true, // chipModeValid
BaselineChip.STA_CHIP_MODE_ID, // chipModeId
IfaceType.NAN, // ifaceTypeToCreate
"nan0", // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
nanDestroyedListener, // destroyedListener
nanAvailListener // availableListener
);
// fiddle with the "chip" by removing the STA
chipMock.interfaceNames.get(IfaceType.STA).remove("sta0");
// now try to request another NAN
nanIface = mDut.createNanIface(nanDestroyedListener, mTestLooper.getLooper());
mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener,
mTestLooper.getLooper());
collector.checkThat("NAN can't be created", nanIface, IsNull.nullValue());
// verify that Wi-Fi is shut-down: should also get all onDestroyed messages that are
// registered (even if they seem out-of-sync to chip)
mTestLooper.dispatchAll();
verify(mWifiMock, times(2)).stop();
verify(mManagerStatusListenerMock, times(2)).onStatusChanged();
verify(staDestroyedListener).onDestroyed();
verify(nanDestroyedListener).onDestroyed();
verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, staAvailListener,
nanDestroyedListener, nanAvailListener);
}
/**
* Validates that trying to allocate a STA and then another STA fails. Only one STA at a time
* is permitted (by baseline chip).
*/
@Test
public void testDuplicateStaRequests() throws Exception {
BaselineChip chipMock = new BaselineChip();
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
HalDeviceManager.InterfaceDestroyedListener staDestroyedListener1 = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener1 = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
HalDeviceManager.InterfaceDestroyedListener staDestroyedListener2 = mock(
HalDeviceManager.InterfaceDestroyedListener.class);
// get STA interface
IWifiIface staIface1 = validateInterfaceSequence(chipMock,
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.STA, // ifaceTypeToCreate
"sta0", // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
staDestroyedListener1, // destroyedListener
staAvailListener1 // availableListener
);
collector.checkThat("STA created", staIface1, IsNull.notNullValue());
// get STA interface again
IWifiIface staIface2 = mDut.createStaIface(staDestroyedListener2, mTestLooper.getLooper());
collector.checkThat("STA created", staIface2, IsNull.nullValue());
verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener1,
staAvailListener1, staDestroyedListener2);
}
/**
* Validates that a duplicate registration of the same InterfaceAvailableForRequestListener
* listener will result in a single callback.
*
* Also validates that get an immediate call on registration if available.
*/
@Test
public void testDuplicateAvailableRegistrations() throws Exception {
BaselineChip chipMock = new BaselineChip();
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock(
HalDeviceManager.InterfaceAvailableForRequestListener.class);
// get STA interface
IWifiIface staIface = validateInterfaceSequence(chipMock,
false, // chipModeValid
-1000, // chipModeId (only used if chipModeValid is true)
IfaceType.STA, // ifaceTypeToCreate
"sta0", // ifaceName
BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
null, // tearDownList
null, // destroyedListener
null // availableListener
);
collector.checkThat("STA created", staIface, IsNull.notNullValue());
// act: register the same listener twice
mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener,
mTestLooper.getLooper());
mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener,
mTestLooper.getLooper());
mTestLooper.dispatchAll();
// remove STA interface -> should trigger callbacks
mDut.removeIface(staIface);
mTestLooper.dispatchAll();
// verify: only a single trigger
verify(staAvailListener).onAvailableForRequest();
verifyNoMoreInteractions(staAvailListener);
}
/**
* Validate that the getSupportedIfaceTypes API works when requesting for all chips.
*/
@Test
public void testGetSupportedIfaceTypesAll() throws Exception {
BaselineChip chipMock = new BaselineChip();
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
// try API
Set<Integer> results = mDut.getSupportedIfaceTypes();
// verify results
Set<Integer> correctResults = new HashSet<>();
correctResults.add(IfaceType.AP);
correctResults.add(IfaceType.STA);
correctResults.add(IfaceType.P2P);
correctResults.add(IfaceType.NAN);
assertEquals(correctResults, results);
}
/**
* Validate that the getSupportedIfaceTypes API works when requesting for a specific chip.
*/
@Test
public void testGetSupportedIfaceTypesOneChip() throws Exception {
BaselineChip chipMock = new BaselineChip();
chipMock.initialize();
mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
mManagerStatusListenerMock);
executeAndValidateInitializationSequence();
executeAndValidateStartupSequence();
// try API
Set<Integer> results = mDut.getSupportedIfaceTypes(chipMock.chip);
// verify results
Set<Integer> correctResults = new HashSet<>();
correctResults.add(IfaceType.AP);
correctResults.add(IfaceType.STA);
correctResults.add(IfaceType.P2P);
correctResults.add(IfaceType.NAN);
assertEquals(correctResults, results);
}
/**
* Validate that when no chip info is found an empty list is returned.
*/
@Test
public void testGetSupportedIfaceTypesError() throws Exception {
// try API
Set<Integer> results = mDut.getSupportedIfaceTypes();
// verify results
assertEquals(0, results.size());
}
// utilities
private void dumpDut(String prefix) {
StringWriter sw = new StringWriter();
mDut.dump(null, new PrintWriter(sw), null);
Log.e("HalDeviceManager", prefix + sw.toString());
}
private void executeAndValidateInitializationSequence() throws Exception {
// act:
mDut.initialize();
// verify: service manager initialization sequence
mInOrder.verify(mServiceManagerMock).linkToDeath(any(IHwBinder.DeathRecipient.class),
anyLong());
mInOrder.verify(mServiceManagerMock).registerForNotifications(eq(IWifi.kInterfaceName),
eq(""), mServiceNotificationCaptor.capture());
// act: get the service started (which happens even when service was already up)
mServiceNotificationCaptor.getValue().onRegistration(IWifi.kInterfaceName, "", true);
// verify: wifi initialization sequence
mInOrder.verify(mWifiMock).linkToDeath(mDeathRecipientCaptor.capture(), anyLong());
mInOrder.verify(mWifiMock).registerEventCallback(mWifiEventCallbackCaptor.capture());
collector.checkThat("isReady is true", mDut.isReady(), equalTo(true));
}
private void executeAndValidateStartupSequence() throws Exception {
// act: register listener & start Wi-Fi
mDut.registerStatusListener(mManagerStatusListenerMock, mTestLooper.getLooper());
mDut.start();
// verify
mInOrder.verify(mWifiMock).start();
// act: trigger onStart callback of IWifiEventCallback
mWifiEventCallbackCaptor.getValue().onStart();
mTestLooper.dispatchAll();
// verify: onStart called on registered listener
mInOrder.verify(mManagerStatusListenerMock).onStatusChanged();
}
private IWifiIface validateInterfaceSequence(ChipMockBase chipMock,
boolean chipModeValid, int chipModeId,
int ifaceTypeToCreate, String ifaceName, int finalChipMode, IWifiIface[] tearDownList,
HalDeviceManager.InterfaceDestroyedListener destroyedListener,
HalDeviceManager.InterfaceAvailableForRequestListener availableListener,
HalDeviceManager.InterfaceDestroyedListener... destroyedInterfacesDestroyedListeners)
throws Exception {
// configure chip mode response
chipMock.chipModeValid = chipModeValid;
chipMock.chipModeId = chipModeId;
IWifiIface iface = null;
// configure: interface to be created
// act: request the interface
switch (ifaceTypeToCreate) {
case IfaceType.STA:
iface = mock(IWifiStaIface.class);
doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName(
any(IWifiIface.getNameCallback.class));
doAnswer(new GetTypeAnswer(IfaceType.STA)).when(iface).getType(
any(IWifiIface.getTypeCallback.class));
doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when(
chipMock.chip).createStaIface(any(IWifiChip.createStaIfaceCallback.class));
mDut.createStaIface(destroyedListener, mTestLooper.getLooper());
break;
case IfaceType.AP:
iface = mock(IWifiApIface.class);
doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName(
any(IWifiIface.getNameCallback.class));
doAnswer(new GetTypeAnswer(IfaceType.AP)).when(iface).getType(
any(IWifiIface.getTypeCallback.class));
doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when(
chipMock.chip).createApIface(any(IWifiChip.createApIfaceCallback.class));
mDut.createApIface(destroyedListener, mTestLooper.getLooper());
break;
case IfaceType.P2P:
iface = mock(IWifiP2pIface.class);
doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName(
any(IWifiIface.getNameCallback.class));
doAnswer(new GetTypeAnswer(IfaceType.P2P)).when(iface).getType(
any(IWifiIface.getTypeCallback.class));
doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when(
chipMock.chip).createP2pIface(any(IWifiChip.createP2pIfaceCallback.class));
mDut.createP2pIface(destroyedListener, mTestLooper.getLooper());
break;
case IfaceType.NAN:
iface = mock(IWifiNanIface.class);
doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName(
any(IWifiIface.getNameCallback.class));
doAnswer(new GetTypeAnswer(IfaceType.NAN)).when(iface).getType(
any(IWifiIface.getTypeCallback.class));
doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when(
chipMock.chip).createNanIface(any(IWifiChip.createNanIfaceCallback.class));
mDut.createNanIface(destroyedListener, mTestLooper.getLooper());
break;
}
if (availableListener != null) {
mDut.registerInterfaceAvailableForRequestListener(ifaceTypeToCreate, availableListener,
mTestLooper.getLooper());
}
// validate: optional tear down of interfaces
if (tearDownList != null) {
for (IWifiIface tearDownIface: tearDownList) {
switch (getType(tearDownIface)) {
case IfaceType.STA:
mInOrder.verify(chipMock.chip).removeStaIface(getName(tearDownIface));
break;
case IfaceType.AP:
mInOrder.verify(chipMock.chip).removeApIface(getName(tearDownIface));
break;
case IfaceType.P2P:
mInOrder.verify(chipMock.chip).removeP2pIface(getName(tearDownIface));
break;
case IfaceType.NAN:
mInOrder.verify(chipMock.chip).removeNanIface(getName(tearDownIface));
break;
}
}
}
// validate: optional switch to the requested mode
if (!chipModeValid || chipModeId != finalChipMode) {
mInOrder.verify(chipMock.chip).configureChip(finalChipMode);
} else {
mInOrder.verify(chipMock.chip, times(0)).configureChip(anyInt());
}
// validate: create interface
switch (ifaceTypeToCreate) {
case IfaceType.STA:
mInOrder.verify(chipMock.chip).createStaIface(
any(IWifiChip.createStaIfaceCallback.class));
break;
case IfaceType.AP:
mInOrder.verify(chipMock.chip).createApIface(
any(IWifiChip.createApIfaceCallback.class));
break;
case IfaceType.P2P:
mInOrder.verify(chipMock.chip).createP2pIface(
any(IWifiChip.createP2pIfaceCallback.class));
break;
case IfaceType.NAN:
mInOrder.verify(chipMock.chip).createNanIface(
any(IWifiChip.createNanIfaceCallback.class));
break;
}
// verify: callbacks on deleted interfaces
mTestLooper.dispatchAll();
for (int i = 0; i < destroyedInterfacesDestroyedListeners.length; ++i) {
verify(destroyedInterfacesDestroyedListeners[i]).onDestroyed();
}
return iface;
}
private int getType(IWifiIface iface) throws Exception {
Mutable<Integer> typeResp = new Mutable<>();
iface.getType((WifiStatus status, int type) -> {
typeResp.value = type;
});
return typeResp.value;
}
private String getName(IWifiIface iface) throws Exception {
Mutable<String> nameResp = new Mutable<>();
iface.getName((WifiStatus status, String name) -> {
nameResp.value = name;
});
return nameResp.value;
}
private WifiStatus getStatus(int code) {
WifiStatus status = new WifiStatus();
status.code = code;
return status;
}
private static class Mutable<E> {
public E value;
Mutable() {
value = null;
}
Mutable(E value) {
this.value = value;
}
}
// Answer objects
private class GetChipIdsAnswer extends MockAnswerUtil.AnswerWithArguments {
private WifiStatus mStatus;
private ArrayList<Integer> mChipIds;
GetChipIdsAnswer(WifiStatus status, ArrayList<Integer> chipIds) {
mStatus = status;
mChipIds = chipIds;
}
public void answer(IWifi.getChipIdsCallback cb) {
cb.onValues(mStatus, mChipIds);
}
}
private class GetChipAnswer extends MockAnswerUtil.AnswerWithArguments {
private WifiStatus mStatus;
private IWifiChip mChip;
GetChipAnswer(WifiStatus status, IWifiChip chip) {
mStatus = status;
mChip = chip;
}
public void answer(int chipId, IWifi.getChipCallback cb) {
cb.onValues(mStatus, mChip);
}
}
private class GetIdAnswer extends MockAnswerUtil.AnswerWithArguments {
private ChipMockBase mChipMockBase;
GetIdAnswer(ChipMockBase chipMockBase) {
mChipMockBase = chipMockBase;
}
public void answer(IWifiChip.getIdCallback cb) {
cb.onValues(mStatusOk, mChipMockBase.chipId);
}
}
private class GetAvailableModesAnswer extends MockAnswerUtil.AnswerWithArguments {
private ChipMockBase mChipMockBase;
GetAvailableModesAnswer(ChipMockBase chipMockBase) {
mChipMockBase = chipMockBase;
}
public void answer(IWifiChip.getAvailableModesCallback cb) {
cb.onValues(mStatusOk, mChipMockBase.availableModes);
}
}
private class GetModeAnswer extends MockAnswerUtil.AnswerWithArguments {
private ChipMockBase mChipMockBase;
GetModeAnswer(ChipMockBase chipMockBase) {
mChipMockBase = chipMockBase;
}
public void answer(IWifiChip.getModeCallback cb) {
cb.onValues(mChipMockBase.chipModeValid ? mStatusOk
: getStatus(WifiStatusCode.ERROR_NOT_AVAILABLE), mChipMockBase.chipModeId);
}
}
private class ConfigureChipAnswer extends MockAnswerUtil.AnswerWithArguments {
private ChipMockBase mChipMockBase;
ConfigureChipAnswer(ChipMockBase chipMockBase) {
mChipMockBase = chipMockBase;
}
public WifiStatus answer(int chipMode) {
mChipMockBase.chipModeId = chipMode;
return mStatusOk;
}
}
private class GetXxxIfaceNamesAnswer extends MockAnswerUtil.AnswerWithArguments {
private ChipMockBase mChipMockBase;
GetXxxIfaceNamesAnswer(ChipMockBase chipMockBase) {
mChipMockBase = chipMockBase;
}
public void answer(IWifiChip.getStaIfaceNamesCallback cb) {
cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.STA));
}
public void answer(IWifiChip.getApIfaceNamesCallback cb) {
cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.AP));
}
public void answer(IWifiChip.getP2pIfaceNamesCallback cb) {
cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.P2P));
}
public void answer(IWifiChip.getNanIfaceNamesCallback cb) {
cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.NAN));
}
}
private class GetXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments {
private ChipMockBase mChipMockBase;
GetXxxIfaceAnswer(ChipMockBase chipMockBase) {
mChipMockBase = chipMockBase;
}
public void answer(String name, IWifiChip.getStaIfaceCallback cb) {
IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.STA).get(name);
cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiStaIface) iface);
}
public void answer(String name, IWifiChip.getApIfaceCallback cb) {
IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.AP).get(name);
cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiApIface) iface);
}
public void answer(String name, IWifiChip.getP2pIfaceCallback cb) {
IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.P2P).get(name);
cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiP2pIface) iface);
}
public void answer(String name, IWifiChip.getNanIfaceCallback cb) {
IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.NAN).get(name);
cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiNanIface) iface);
}
}
private class CreateXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments {
private ChipMockBase mChipMockBase;
private WifiStatus mStatus;
private IWifiIface mWifiIface;
CreateXxxIfaceAnswer(ChipMockBase chipMockBase, WifiStatus status, IWifiIface wifiIface) {
mChipMockBase = chipMockBase;
mStatus = status;
mWifiIface = wifiIface;
}
private void addInterfaceInfo(int type) {
if (mStatus.code == WifiStatusCode.SUCCESS) {
try {
mChipMockBase.interfaceNames.get(type).add(getName(mWifiIface));
mChipMockBase.interfacesByName.get(type).put(getName(mWifiIface), mWifiIface);
} catch (Exception e) {
// do nothing
}
}
}
public void answer(IWifiChip.createStaIfaceCallback cb) {
cb.onValues(mStatus, (IWifiStaIface) mWifiIface);
addInterfaceInfo(IfaceType.STA);
}
public void answer(IWifiChip.createApIfaceCallback cb) {
cb.onValues(mStatus, (IWifiApIface) mWifiIface);
addInterfaceInfo(IfaceType.AP);
}
public void answer(IWifiChip.createP2pIfaceCallback cb) {
cb.onValues(mStatus, (IWifiP2pIface) mWifiIface);
addInterfaceInfo(IfaceType.P2P);
}
public void answer(IWifiChip.createNanIfaceCallback cb) {
cb.onValues(mStatus, (IWifiNanIface) mWifiIface);
addInterfaceInfo(IfaceType.NAN);
}
}
private class RemoveXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments {
private ChipMockBase mChipMockBase;
private int mType;
RemoveXxxIfaceAnswer(ChipMockBase chipMockBase, int type) {
mChipMockBase = chipMockBase;
mType = type;
}
private WifiStatus removeIface(int type, String ifname) {
try {
if (!mChipMockBase.interfaceNames.get(type).remove(ifname)) {
return mStatusFail;
}
if (mChipMockBase.interfacesByName.get(type).remove(ifname) == null) {
return mStatusFail;
}
} catch (Exception e) {
return mStatusFail;
}
return mStatusOk;
}
public WifiStatus answer(String ifname) {
return removeIface(mType, ifname);
}
}
private class GetNameAnswer extends MockAnswerUtil.AnswerWithArguments {
private String mName;
GetNameAnswer(String name) {
mName = name;
}
public void answer(IWifiIface.getNameCallback cb) {
cb.onValues(mStatusOk, mName);
}
}
private class GetTypeAnswer extends MockAnswerUtil.AnswerWithArguments {
private int mType;
GetTypeAnswer(int type) {
mType = type;
}
public void answer(IWifiIface.getTypeCallback cb) {
cb.onValues(mStatusOk, mType);
}
}
// chip configuration
private class ChipMockBase {
public IWifiChip chip;
public int chipId;
public boolean chipModeValid = false;
public int chipModeId = -1000;
public Map<Integer, ArrayList<String>> interfaceNames = new HashMap<>();
public Map<Integer, Map<String, IWifiIface>> interfacesByName = new HashMap<>();
public ArrayList<IWifiChip.ChipMode> availableModes;
void initialize() throws Exception {
chip = mock(IWifiChip.class);
interfaceNames.put(IfaceType.STA, new ArrayList<>());
interfaceNames.put(IfaceType.AP, new ArrayList<>());
interfaceNames.put(IfaceType.P2P, new ArrayList<>());
interfaceNames.put(IfaceType.NAN, new ArrayList<>());
interfacesByName.put(IfaceType.STA, new HashMap<>());
interfacesByName.put(IfaceType.AP, new HashMap<>());
interfacesByName.put(IfaceType.P2P, new HashMap<>());
interfacesByName.put(IfaceType.NAN, new HashMap<>());
when(chip.registerEventCallback(any(IWifiChipEventCallback.class))).thenReturn(
mStatusOk);
when(chip.configureChip(anyInt())).thenAnswer(new ConfigureChipAnswer(this));
doAnswer(new GetIdAnswer(this)).when(chip).getId(any(IWifiChip.getIdCallback.class));
doAnswer(new GetModeAnswer(this)).when(chip).getMode(
any(IWifiChip.getModeCallback.class));
GetXxxIfaceNamesAnswer getXxxIfaceNamesAnswer = new GetXxxIfaceNamesAnswer(this);
doAnswer(getXxxIfaceNamesAnswer).when(chip).getStaIfaceNames(
any(IWifiChip.getStaIfaceNamesCallback.class));
doAnswer(getXxxIfaceNamesAnswer).when(chip).getApIfaceNames(
any(IWifiChip.getApIfaceNamesCallback.class));
doAnswer(getXxxIfaceNamesAnswer).when(chip).getP2pIfaceNames(
any(IWifiChip.getP2pIfaceNamesCallback.class));
doAnswer(getXxxIfaceNamesAnswer).when(chip).getNanIfaceNames(
any(IWifiChip.getNanIfaceNamesCallback.class));
GetXxxIfaceAnswer getXxxIfaceAnswer = new GetXxxIfaceAnswer(this);
doAnswer(getXxxIfaceAnswer).when(chip).getStaIface(anyString(),
any(IWifiChip.getStaIfaceCallback.class));
doAnswer(getXxxIfaceAnswer).when(chip).getApIface(anyString(),
any(IWifiChip.getApIfaceCallback.class));
doAnswer(getXxxIfaceAnswer).when(chip).getP2pIface(anyString(),
any(IWifiChip.getP2pIfaceCallback.class));
doAnswer(getXxxIfaceAnswer).when(chip).getNanIface(anyString(),
any(IWifiChip.getNanIfaceCallback.class));
doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.STA)).when(chip).removeStaIface(
anyString());
doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.AP)).when(chip).removeApIface(
anyString());
doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.P2P)).when(chip).removeP2pIface(
anyString());
doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.NAN)).when(chip).removeNanIface(
anyString());
}
}
// emulate baseline/legacy config:
// mode: STA + NAN || P2P
// mode: NAN
private class BaselineChip extends ChipMockBase {
static final int STA_CHIP_MODE_ID = 0;
static final int AP_CHIP_MODE_ID = 1;
void initialize() throws Exception {
super.initialize();
// chip Id configuration
ArrayList<Integer> chipIds;
chipId = 10;
chipIds = new ArrayList<>();
chipIds.add(chipId);
doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds(
any(IWifi.getChipIdsCallback.class));
doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(10),
any(IWifi.getChipCallback.class));
// initialize dummy chip modes
IWifiChip.ChipMode cm;
IWifiChip.ChipIfaceCombination cic;
IWifiChip.ChipIfaceCombinationLimit cicl;
// Mode 0: 1xSTA + 1x{P2P,NAN}
// Mode 1: 1xAP
availableModes = new ArrayList<>();
cm = new IWifiChip.ChipMode();
cm.id = STA_CHIP_MODE_ID;
cic = new IWifiChip.ChipIfaceCombination();
cicl = new IWifiChip.ChipIfaceCombinationLimit();
cicl.maxIfaces = 1;
cicl.types.add(IfaceType.STA);
cic.limits.add(cicl);
cicl = new IWifiChip.ChipIfaceCombinationLimit();
cicl.maxIfaces = 1;
cicl.types.add(IfaceType.P2P);
cicl.types.add(IfaceType.NAN);
cic.limits.add(cicl);
cm.availableCombinations.add(cic);
availableModes.add(cm);
cm = new IWifiChip.ChipMode();
cm.id = AP_CHIP_MODE_ID;
cic = new IWifiChip.ChipIfaceCombination();
cicl = new IWifiChip.ChipIfaceCombinationLimit();
cicl.maxIfaces = 1;
cicl.types.add(IfaceType.AP);
cic.limits.add(cicl);
cm.availableCombinations.add(cic);
availableModes.add(cm);
doAnswer(new GetAvailableModesAnswer(this)).when(chip)
.getAvailableModes(any(IWifiChip.getAvailableModesCallback.class));
}
}
}