blob: eedaebdc0cf0190be0babd61805c7c45025d3a59 [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 android.app.test.MockAnswerUtil.AnswerWithArguments;
import android.hardware.wifi.V1_0.IWifiApIface;
import android.hardware.wifi.V1_0.IWifiChip;
import android.hardware.wifi.V1_0.IWifiIface;
import android.hardware.wifi.V1_0.IWifiRttController;
import android.hardware.wifi.V1_0.IWifiStaIface;
import android.hardware.wifi.V1_0.WifiStatus;
import android.hardware.wifi.V1_0.WifiStatusCode;
import android.net.wifi.WifiManager;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import android.os.HandlerThread;
import android.os.Looper;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
/**
* Unit tests for {@link com.android.server.wifi.WifiVendorHal}.
*/
public class WifiVendorHalTest {
WifiVendorHal mWifiVendorHal;
private WifiStatus mWifiStatusSuccess;
private WifiStatus mWifiStatusFailure;
@Mock
private HalDeviceManager mHalDeviceManager;
@Mock
private HandlerThread mWifiStateMachineHandlerThread;
@Mock
private WifiVendorHal.HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks;
@Mock
private IWifiApIface mIWifiApIface;
@Mock
private IWifiChip mIWifiChip;
@Mock
private IWifiStaIface mIWifiStaIface;
@Mock
private IWifiRttController mIWifiRttController;
/**
* Sets up for unit test
*/
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mWifiStatusSuccess = new WifiStatus();
mWifiStatusSuccess.code = WifiStatusCode.SUCCESS;
mWifiStatusFailure = new WifiStatus();
mWifiStatusFailure.code = WifiStatusCode.ERROR_UNKNOWN;
mWifiStatusFailure.description = "I don't even know what a Mock Turtle is.";
when(mIWifiStaIface.enableLinkLayerStatsCollection(false)).thenReturn(mWifiStatusSuccess);
// Setup the HalDeviceManager mock's start/stop behaviour. This can be overridden in
// individual tests, if needed.
doAnswer(new AnswerWithArguments() {
public boolean answer() {
when(mHalDeviceManager.isReady()).thenReturn(true);
when(mHalDeviceManager.isStarted()).thenReturn(true);
mHalDeviceManagerStatusCallbacks.onStatusChanged();
return true;
}
}).when(mHalDeviceManager).start();
doAnswer(new AnswerWithArguments() {
public void answer() {
when(mHalDeviceManager.isReady()).thenReturn(true);
when(mHalDeviceManager.isStarted()).thenReturn(false);
mHalDeviceManagerStatusCallbacks.onStatusChanged();
}
}).when(mHalDeviceManager).stop();
when(mHalDeviceManager.createStaIface(eq(null), eq(null)))
.thenReturn(mIWifiStaIface);
when(mHalDeviceManager.createApIface(eq(null), eq(null)))
.thenReturn(mIWifiApIface);
when(mHalDeviceManager.getChip(any(IWifiIface.class)))
.thenReturn(mIWifiChip);
when(mHalDeviceManager.createRttController(any(IWifiIface.class)))
.thenReturn(mIWifiRttController);
// Create the vendor HAL object under test.
mWifiVendorHal = new WifiVendorHal(mHalDeviceManager, mWifiStateMachineHandlerThread);
// Initialize the vendor HAL to capture the registered callback.
mWifiVendorHal.initialize();
ArgumentCaptor<WifiVendorHal.HalDeviceManagerStatusListener> callbackCaptor =
ArgumentCaptor.forClass(WifiVendorHal.HalDeviceManagerStatusListener.class);
verify(mHalDeviceManager).registerStatusListener(
callbackCaptor.capture(), any(Looper.class));
mHalDeviceManagerStatusCallbacks = callbackCaptor.getValue();
}
/**
* Test that parsing a typical colon-delimited MAC adddress works
*/
@Test
public void testTypicalHexParse() throws Exception {
byte[] sixBytes = new byte[6];
mWifiVendorHal.parseUnquotedMacStrToByteArray("61:52:43:34:25:16", sixBytes);
Assert.assertArrayEquals(new byte[]{0x61, 0x52, 0x43, 0x34, 0x25, 0x16}, sixBytes);
}
/**
* Tests the successful starting of HAL in STA mode using
* {@link WifiVendorHal#startVendorHal(boolean)}.
*/
@Test
public void testStartHalSuccessInStaMode() {
assertTrue(mWifiVendorHal.startVendorHal(true));
assertTrue(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
verify(mHalDeviceManager).getChip(eq(mIWifiStaIface));
verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
verify(mHalDeviceManager).isReady();
verify(mHalDeviceManager).isStarted();
verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
}
/**
* Tests the successful starting of HAL in AP mode using
* {@link WifiVendorHal#startVendorHal(boolean)}.
*/
@Test
public void testStartHalSuccessInApMode() {
assertTrue(mWifiVendorHal.startVendorHal(false));
assertTrue(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
verify(mHalDeviceManager).createApIface(eq(null), eq(null));
verify(mHalDeviceManager).getChip(eq(mIWifiApIface));
verify(mHalDeviceManager).isReady();
verify(mHalDeviceManager).isStarted();
verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
}
/**
* Tests the failure to start HAL in STA mode using
* {@link WifiVendorHal#startVendorHal(boolean)}.
*/
@Test
public void testStartHalFailureInStaMode() {
// No callbacks are invoked in this case since the start itself failed. So, override
// default AnswerWithArguments that we setup.
doAnswer(new AnswerWithArguments() {
public boolean answer() {
return false;
}
}).when(mHalDeviceManager).start();
assertFalse(mWifiVendorHal.startVendorHal(true));
assertFalse(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
}
/**
* Tests the failure to start HAL in STA mode using
* {@link WifiVendorHal#startVendorHal(boolean)}.
*/
@Test
public void testStartHalFailureInIfaceCreationInStaMode() {
when(mHalDeviceManager.createStaIface(eq(null), eq(null))).thenReturn(null);
assertFalse(mWifiVendorHal.startVendorHal(true));
assertFalse(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
verify(mHalDeviceManager).stop();
verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
}
/**
* Tests the failure to start HAL in STA mode using
* {@link WifiVendorHal#startVendorHal(boolean)}.
*/
@Test
public void testStartHalFailureInRttControllerCreationInStaMode() {
when(mHalDeviceManager.createRttController(any(IWifiIface.class))).thenReturn(null);
assertFalse(mWifiVendorHal.startVendorHal(true));
assertFalse(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
verify(mHalDeviceManager).stop();
verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
}
/**
* Tests the failure to start HAL in STA mode using
* {@link WifiVendorHal#startVendorHal(boolean)}.
*/
@Test
public void testStartHalFailureInChipGetInStaMode() {
when(mHalDeviceManager.getChip(any(IWifiIface.class))).thenReturn(null);
assertFalse(mWifiVendorHal.startVendorHal(true));
assertFalse(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
verify(mHalDeviceManager).getChip(any(IWifiIface.class));
verify(mHalDeviceManager).stop();
verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
}
/**
* Tests the failure to start HAL in STA mode using
* {@link WifiVendorHal#startVendorHal(boolean)}.
*/
@Test
public void testStartHalFailureInApMode() {
when(mHalDeviceManager.createApIface(eq(null), eq(null))).thenReturn(null);
assertFalse(mWifiVendorHal.startVendorHal(false));
assertFalse(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
verify(mHalDeviceManager).createApIface(eq(null), eq(null));
verify(mHalDeviceManager).stop();
verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
}
/**
* Tests the stopping of HAL in STA mode using
* {@link WifiVendorHal#stopVendorHal()}.
*/
@Test
public void testStopHalInStaMode() {
assertTrue(mWifiVendorHal.startVendorHal(true));
assertTrue(mWifiVendorHal.isHalStarted());
mWifiVendorHal.stopVendorHal();
assertFalse(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
verify(mHalDeviceManager).stop();
verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
verify(mHalDeviceManager).getChip(eq(mIWifiStaIface));
verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
verify(mHalDeviceManager, times(2)).isReady();
verify(mHalDeviceManager, times(2)).isStarted();
verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
}
/**
* Tests the stopping of HAL in AP mode using
* {@link WifiVendorHal#stopVendorHal()}.
*/
@Test
public void testStopHalInApMode() {
assertTrue(mWifiVendorHal.startVendorHal(false));
assertTrue(mWifiVendorHal.isHalStarted());
mWifiVendorHal.stopVendorHal();
assertFalse(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
verify(mHalDeviceManager).stop();
verify(mHalDeviceManager).createApIface(eq(null), eq(null));
verify(mHalDeviceManager).getChip(eq(mIWifiApIface));
verify(mHalDeviceManager, times(2)).isReady();
verify(mHalDeviceManager, times(2)).isStarted();
verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
}
/**
* Test translation to WifiManager.WIFI_FEATURE_*
*
* Just do a spot-check with a few feature bits here; since the code is table-
* driven we don't have to work hard to exercise all of it.
*/
@Test
public void testFeatureMaskTranslation() {
int caps = (
IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN
| IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS
);
int expected = (
WifiManager.WIFI_FEATURE_INFRA
| WifiManager.WIFI_FEATURE_SCANNER
| WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
assertEquals(expected, mWifiVendorHal.wifiFeatureMaskFromStaCapabilities(caps));
}
/**
* Test enablement of link layer stats after startup
* <p>
* Request link layer stats before HAL start
* - should not make it to the HAL layer
* Start the HAL in STA mode
* Request link layer stats twice more
* - enable request should make it to the HAL layer
* - HAL layer should have been called to make the requests (i.e., two calls total)
*/
@Test
public void testLinkLayerStatsEnableAfterStartup() throws Exception {
doNothing().when(mIWifiStaIface).getLinkLayerStats(any());
assertNull(mWifiVendorHal.getWifiLinkLayerStats());
assertTrue(mWifiVendorHal.startVendorHalSta());
assertTrue(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
mWifiVendorHal.getWifiLinkLayerStats();
mWifiVendorHal.getWifiLinkLayerStats();
verify(mIWifiStaIface).enableLinkLayerStatsCollection(false); // mLinkLayerStatsDebug
verify(mIWifiStaIface, times(2)).getLinkLayerStats(any());
}
/**
* Test that link layer stats are not enabled and harmless in AP mode
* <p>
* Start the HAL in AP mode
* - stats should not be enabled
* Request link layer stats
* - HAL layer should have been called to make the request
*/
@Test
public void testLinkLayerStatsNotEnabledAndHarmlessInApMode() throws Exception {
doNothing().when(mIWifiStaIface).getLinkLayerStats(any());
assertTrue(mWifiVendorHal.startVendorHalAp());
assertTrue(mWifiVendorHal.isHalStarted());
assertNull(mWifiVendorHal.getWifiLinkLayerStats());
verify(mHalDeviceManager).start();
verify(mIWifiStaIface, never()).enableLinkLayerStatsCollection(false);
verify(mIWifiStaIface, never()).getLinkLayerStats(any());
}
// TODO(b/34900534) add test for correct MOVE CORRESPONDING of fields
}