blob: 3f2f389c5d2d42c832e7c5628234388dee846720 [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.IWifiChipEventCallback;
import android.hardware.wifi.V1_0.IWifiIface;
import android.hardware.wifi.V1_0.IWifiRttController;
import android.hardware.wifi.V1_0.IWifiRttControllerEventCallback;
import android.hardware.wifi.V1_0.IWifiStaIface;
import android.hardware.wifi.V1_0.IWifiStaIfaceEventCallback;
import android.hardware.wifi.V1_0.IfaceType;
import android.hardware.wifi.V1_0.RttCapabilities;
import android.hardware.wifi.V1_0.RttConfig;
import android.hardware.wifi.V1_0.StaApfPacketFilterCapabilities;
import android.hardware.wifi.V1_0.StaBackgroundScanCapabilities;
import android.hardware.wifi.V1_0.StaBackgroundScanParameters;
import android.hardware.wifi.V1_0.StaLinkLayerIfacePacketStats;
import android.hardware.wifi.V1_0.StaLinkLayerRadioStats;
import android.hardware.wifi.V1_0.StaLinkLayerStats;
import android.hardware.wifi.V1_0.StaScanData;
import android.hardware.wifi.V1_0.StaScanDataFlagMask;
import android.hardware.wifi.V1_0.StaScanResult;
import android.hardware.wifi.V1_0.WifiDebugHostWakeReasonStats;
import android.hardware.wifi.V1_0.WifiDebugPacketFateFrameType;
import android.hardware.wifi.V1_0.WifiDebugRingBufferFlags;
import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus;
import android.hardware.wifi.V1_0.WifiDebugRingBufferVerboseLevel;
import android.hardware.wifi.V1_0.WifiDebugRxPacketFate;
import android.hardware.wifi.V1_0.WifiDebugRxPacketFateReport;
import android.hardware.wifi.V1_0.WifiDebugTxPacketFate;
import android.hardware.wifi.V1_0.WifiDebugTxPacketFateReport;
import android.hardware.wifi.V1_0.WifiInformationElement;
import android.hardware.wifi.V1_0.WifiStatus;
import android.hardware.wifi.V1_0.WifiStatusCode;
import android.net.apf.ApfCapabilities;
import android.net.wifi.RttManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiLinkLayerStats;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiScanner;
import android.net.wifi.WifiSsid;
import android.net.wifi.WifiWakeReasonAndCounts;
import android.os.Looper;
import android.os.RemoteException;
import android.os.test.TestLooper;
import android.util.Pair;
import com.android.server.connectivity.KeepalivePacketData;
import com.android.server.wifi.util.NativeUtil;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
/**
* Unit tests for {@link com.android.server.wifi.WifiVendorHal}.
*/
public class WifiVendorHalTest {
WifiVendorHal mWifiVendorHal;
private WifiStatus mWifiStatusSuccess;
private WifiStatus mWifiStatusFailure;
WifiLog mWifiLog;
@Mock
private HalDeviceManager mHalDeviceManager;
@Mock
private TestLooper mLooper;
@Mock
private WifiVendorHal.HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks;
@Mock
private IWifiApIface mIWifiApIface;
@Mock
private IWifiChip mIWifiChip;
@Mock
private android.hardware.wifi.V1_1.IWifiChip mIWifiChipV11;
@Mock
private IWifiStaIface mIWifiStaIface;
@Mock
private IWifiRttController mIWifiRttController;
private IWifiStaIfaceEventCallback mIWifiStaIfaceEventCallback;
private IWifiChipEventCallback mIWifiChipEventCallback;
@Mock
private WifiNative.VendorHalDeathEventHandler mVendorHalDeathHandler;
/**
* Spy used to return the V1_1 IWifiChip mock object to simulate the 1.1 HAL running on the
* device.
*/
private class WifiVendorHalSpyV1_1 extends WifiVendorHal {
WifiVendorHalSpyV1_1(HalDeviceManager halDeviceManager, Looper looper) {
super(halDeviceManager, looper);
}
@Override
protected android.hardware.wifi.V1_1.IWifiChip getWifiChipForV1_1Mockable() {
return mIWifiChipV11;
}
}
/**
* Identity function to supply a type to its argument, which is a lambda
*/
static Answer<WifiStatus> answerWifiStatus(Answer<WifiStatus> statusLambda) {
return (statusLambda);
}
/**
* Sets up for unit test
*/
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mWifiLog = new FakeWifiLog();
mLooper = new TestLooper();
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);
when(mIWifiChip.registerEventCallback(any(IWifiChipEventCallback.class)))
.thenReturn(mWifiStatusSuccess);
mIWifiStaIfaceEventCallback = null;
when(mIWifiStaIface.registerEventCallback(any(IWifiStaIfaceEventCallback.class)))
.thenAnswer(answerWifiStatus((invocation) -> {
Object[] args = invocation.getArguments();
mIWifiStaIfaceEventCallback = (IWifiStaIfaceEventCallback) args[0];
return (mWifiStatusSuccess);
}));
mIWifiChipEventCallback = null;
when(mIWifiChip.registerEventCallback(any(IWifiChipEventCallback.class)))
.thenAnswer(answerWifiStatus((invocation) -> {
Object[] args = invocation.getArguments();
mIWifiChipEventCallback = (IWifiChipEventCallback) args[0];
return (mWifiStatusSuccess);
}));
when(mIWifiRttController.registerEventCallback(any(IWifiRttControllerEventCallback.class)))
.thenReturn(mWifiStatusSuccess);
// Create the vendor HAL object under test.
mWifiVendorHal = new WifiVendorHal(mHalDeviceManager, mLooper.getLooper());
// Initialize the vendor HAL to capture the registered callback.
mWifiVendorHal.initialize(mVendorHalDeathHandler);
ArgumentCaptor<WifiVendorHal.HalDeviceManagerStatusListener> hdmCallbackCaptor =
ArgumentCaptor.forClass(WifiVendorHal.HalDeviceManagerStatusListener.class);
verify(mHalDeviceManager).registerStatusListener(hdmCallbackCaptor.capture(), any());
mHalDeviceManagerStatusCallbacks = hdmCallbackCaptor.getValue();
}
/**
* Tests the successful starting of HAL in STA mode using
* {@link WifiVendorHal#startVendorHal(boolean)}.
*/
@Test
public void testStartHalSuccessInStaMode() throws Exception {
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(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class));
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() throws Exception {
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() throws Exception {
// 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() throws Exception {
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));
verify(mIWifiStaIface, never())
.registerEventCallback(any(IWifiStaIfaceEventCallback.class));
}
/**
* Tests the failure to start HAL in STA mode using
* {@link WifiVendorHal#startVendorHal(boolean)}.
*/
@Test
public void testStartHalFailureInIfaceCreationInStaMode() throws Exception {
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));
verify(mIWifiStaIface, never())
.registerEventCallback(any(IWifiStaIfaceEventCallback.class));
}
/**
* Tests the failure to start HAL in STA mode using
* {@link WifiVendorHal#startVendorHal(boolean)}.
*/
@Test
public void testStartHalFailureInRttControllerCreationInStaMode() throws Exception {
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(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
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() throws Exception {
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(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
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 testStartHalFailureInStaIfaceCallbackRegistration() throws Exception {
when(mIWifiStaIface.registerEventCallback(any(IWifiStaIfaceEventCallback.class)))
.thenReturn(mWifiStatusFailure);
assertFalse(mWifiVendorHal.startVendorHal(true));
assertFalse(mWifiVendorHal.isHalStarted());
verify(mHalDeviceManager).start();
verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
verify(mHalDeviceManager).stop();
verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
verify(mHalDeviceManager, never()).createRttController(eq(mIWifiStaIface));
verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
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 testStartHalFailureInChipCallbackRegistration() throws Exception {
when(mIWifiChip.registerEventCallback(any(IWifiChipEventCallback.class)))
.thenReturn(mWifiStatusFailure);
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(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class));
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() throws Exception {
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 that enter logs when verbose logging is enabled
*/
@Test
public void testEnterLogging() {
mWifiVendorHal.mLog = spy(mWifiLog);
mWifiVendorHal.enableVerboseLogging(true);
mWifiVendorHal.installPacketFilter(new byte[0]);
verify(mWifiVendorHal.mLog).trace(eq("% filter length %"));
}
/**
* Test that enter does not log when verbose logging is not enabled
*/
@Test
public void testEnterSilenceWhenNotEnabled() {
mWifiVendorHal.mLog = spy(mWifiLog);
mWifiVendorHal.installPacketFilter(new byte[0]);
mWifiVendorHal.enableVerboseLogging(true);
mWifiVendorHal.enableVerboseLogging(false);
mWifiVendorHal.installPacketFilter(new byte[0]);
verify(mWifiVendorHal.mLog, never()).trace(eq("% filter length %"));
}
/**
* Test that boolResult logs a false result
*/
@Test
public void testBoolResultFalse() {
mWifiLog = spy(mWifiLog);
mWifiVendorHal.mLog = mWifiLog;
mWifiVendorHal.mVerboseLog = mWifiLog;
assertFalse(mWifiVendorHal.getBgScanCapabilities(new WifiNative.ScanCapabilities()));
verify(mWifiLog).err("% returns %");
}
/**
* Test that getBgScanCapabilities is hooked up to the HAL correctly
*
* A call before the vendor HAL is started should return a non-null result with version 0
*
* A call after the HAL is started should return the mocked values.
*/
@Test
public void testGetBgScanCapabilities() throws Exception {
StaBackgroundScanCapabilities capabilities = new StaBackgroundScanCapabilities();
capabilities.maxCacheSize = 12;
capabilities.maxBuckets = 34;
capabilities.maxApCachePerScan = 56;
capabilities.maxReportingThreshold = 78;
doAnswer(new AnswerWithArguments() {
public void answer(IWifiStaIface.getBackgroundScanCapabilitiesCallback cb)
throws RemoteException {
cb.onValues(mWifiStatusSuccess, capabilities);
}
}).when(mIWifiStaIface).getBackgroundScanCapabilities(any(
IWifiStaIface.getBackgroundScanCapabilitiesCallback.class));
WifiNative.ScanCapabilities result = new WifiNative.ScanCapabilities();
assertFalse(mWifiVendorHal.getBgScanCapabilities(result)); // should fail - not started
assertTrue(mWifiVendorHal.startVendorHalSta()); // Start the vendor hal
assertTrue(mWifiVendorHal.getBgScanCapabilities(result)); // should succeed
assertEquals(12, result.max_scan_cache_size);
assertEquals(34, result.max_scan_buckets);
assertEquals(56, result.max_ap_cache_per_scan);
assertEquals(78, result.max_scan_reporting_threshold);
}
private void setupValidFrequenciesForBand(ArrayList<Integer> frequencies) throws Exception {
doAnswer(new AnswerWithArguments() {
public void answer(int band, IWifiStaIface.getValidFrequenciesForBandCallback cb)
throws RemoteException {
cb.onValues(mWifiStatusSuccess, frequencies);
}
}).when(mIWifiStaIface).getValidFrequenciesForBand(anyInt(), any(
IWifiStaIface.getValidFrequenciesForBandCallback.class));
doAnswer(new AnswerWithArguments() {
public void answer(int band, IWifiApIface.getValidFrequenciesForBandCallback cb)
throws RemoteException {
cb.onValues(mWifiStatusSuccess, frequencies);
}
}).when(mIWifiApIface).getValidFrequenciesForBand(anyInt(), any(
IWifiApIface.getValidFrequenciesForBandCallback.class));
}
private int[] intArrayFromArrayList(ArrayList<Integer> in) {
int[] ans = new int[in.size()];
int i = 0;
for (Integer e : in) ans[i++] = e;
return ans;
}
/**
* Test that isGetChannelsForBandSupported works in STA mode
*/
@Test
public void testGetChannelsForBandSupportedSta() throws Exception {
ArrayList<Integer> freq = new ArrayList<>();
freq.add(2405);
setupValidFrequenciesForBand(freq);
assertFalse(mWifiVendorHal.isGetChannelsForBandSupported());
assertTrue(mWifiVendorHal.startVendorHalSta());
assertTrue(mWifiVendorHal.isGetChannelsForBandSupported());
}
/**
* Test that isGetChannelsForBandSupported works in AP mode
*/
@Test
public void testGetChannelsForBandSupportedAp() throws Exception {
ArrayList<Integer> freq = new ArrayList<>();
freq.add(2405);
setupValidFrequenciesForBand(freq);
assertFalse(mWifiVendorHal.isGetChannelsForBandSupported());
assertTrue(mWifiVendorHal.startVendorHalAp());
assertTrue(mWifiVendorHal.isGetChannelsForBandSupported());
}
/**
* 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 testStaIfaceFeatureMaskTranslation() {
int caps = (
IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN
| IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS
);
int expected = (
WifiManager.WIFI_FEATURE_SCANNER
| WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
assertEquals(expected, mWifiVendorHal.wifiFeatureMaskFromStaCapabilities(caps));
}
/**
* 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 testChipFeatureMaskTranslation() {
int caps = (
android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.SET_TX_POWER_LIMIT
| android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2D_RTT
| android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.D2AP_RTT
);
int expected = (
WifiManager.WIFI_FEATURE_TX_POWER_LIMIT
| WifiManager.WIFI_FEATURE_D2D_RTT
| WifiManager.WIFI_FEATURE_D2AP_RTT
);
assertEquals(expected, mWifiVendorHal.wifiFeatureMaskFromChipCapabilities(caps));
}
/**
* Test get supported features. Tests whether we coalesce information from different sources
* (IWifiStaIface, IWifiChip and HalDeviceManager) into the bitmask of supported features
* correctly.
*/
@Test
public void testGetSupportedFeatures() throws Exception {
assertTrue(mWifiVendorHal.startVendorHal(true));
int staIfaceHidlCaps = (
IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN
| IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS
);
int chipHidlCaps =
android.hardware.wifi.V1_1.IWifiChip.ChipCapabilityMask.SET_TX_POWER_LIMIT;
Set<Integer> halDeviceManagerSupportedIfaces = new HashSet<Integer>() {{
add(IfaceType.STA);
add(IfaceType.P2P);
}};
int expectedFeatureSet = (
WifiManager.WIFI_FEATURE_SCANNER
| WifiManager.WIFI_FEATURE_LINK_LAYER_STATS
| WifiManager.WIFI_FEATURE_TX_POWER_LIMIT
| WifiManager.WIFI_FEATURE_INFRA
| WifiManager.WIFI_FEATURE_P2P
);
doAnswer(new AnswerWithArguments() {
public void answer(IWifiStaIface.getCapabilitiesCallback cb) throws RemoteException {
cb.onValues(mWifiStatusSuccess, staIfaceHidlCaps);
}
}).when(mIWifiStaIface).getCapabilities(any(IWifiStaIface.getCapabilitiesCallback.class));
doAnswer(new AnswerWithArguments() {
public void answer(IWifiChip.getCapabilitiesCallback cb) throws RemoteException {
cb.onValues(mWifiStatusSuccess, chipHidlCaps);
}
}).when(mIWifiChip).getCapabilities(any(IWifiChip.getCapabilitiesCallback.class));
when(mHalDeviceManager.getSupportedIfaceTypes())
.thenReturn(halDeviceManagerSupportedIfaces);
assertEquals(expectedFeatureSet, mWifiVendorHal.getSupportedFeatureSet());
}
/**
* Test enablement of link layer stats after startup
*
* 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
*
* 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());
}
/**
* Test that the link layer stats fields are populated correctly.
*
* This is done by filling with random values and then using toString on the
* original and converted values, comparing just the numerics in the result.
* This makes the assumption that the fields are in the same order in both string
* representations, which is not quite true. So apply some fixups before the final
* comparison.
*/
@Test
public void testLinkLayerStatsAssignment() throws Exception {
Random r = new Random(1775968256);
StaLinkLayerStats stats = new StaLinkLayerStats();
randomizePacketStats(r, stats.iface.wmeBePktStats);
randomizePacketStats(r, stats.iface.wmeBkPktStats);
randomizePacketStats(r, stats.iface.wmeViPktStats);
randomizePacketStats(r, stats.iface.wmeVoPktStats);
randomizeRadioStats(r, stats.radios);
stats.timeStampInMs = 42; // currently dropped in conversion
String expected = numbersOnly(stats.toString());
WifiLinkLayerStats converted = WifiVendorHal.frameworkFromHalLinkLayerStats(stats);
String actual = numbersOnly(converted.toString());
// Do the required fixups to the both expected and actual
expected = rmValue(expected, stats.radios.get(0).rxTimeInMs);
expected = rmValue(expected, stats.radios.get(0).onTimeInMsForScan);
actual = rmValue(actual, stats.radios.get(0).rxTimeInMs);
actual = rmValue(actual, stats.radios.get(0).onTimeInMsForScan);
actual = actual + "42 ";
// The remaining fields should agree
assertEquals(expected, actual);
}
/** Just the digits with delimiting spaces, please */
private static String numbersOnly(String s) {
return s.replaceAll("[^0-9]+", " ");
}
/** Remove the given value from the space-delimited string, or die trying. */
private static String rmValue(String s, long value) throws Exception {
String ans = s.replaceAll(" " + value + " ", " ");
assertNotEquals(s, ans);
return ans;
}
/**
* Populate packet stats with non-negative random values
*/
private static void randomizePacketStats(Random r, StaLinkLayerIfacePacketStats pstats) {
pstats.rxMpdu = r.nextLong() & 0xFFFFFFFFFFL; // more than 32 bits
pstats.txMpdu = r.nextLong() & 0xFFFFFFFFFFL;
pstats.lostMpdu = r.nextLong() & 0xFFFFFFFFFFL;
pstats.retries = r.nextLong() & 0xFFFFFFFFFFL;
}
/**
* Populate radio stats with non-negative random values
*/
private static void randomizeRadioStats(Random r, ArrayList<StaLinkLayerRadioStats> rstats) {
StaLinkLayerRadioStats rstat = new StaLinkLayerRadioStats();
rstat.onTimeInMs = r.nextInt() & 0xFFFFFF;
rstat.txTimeInMs = r.nextInt() & 0xFFFFFF;
for (int i = 0; i < 4; i++) {
Integer v = r.nextInt() & 0xFFFFFF;
rstat.txTimeInMsPerLevel.add(v);
}
rstat.rxTimeInMs = r.nextInt() & 0xFFFFFF;
rstat.onTimeInMsForScan = r.nextInt() & 0xFFFFFF;
rstats.add(rstat);
}
/**
* Test that getFirmwareVersion() and getDriverVersion() work
*
* Calls before the STA is started are expected to return null.
*/
@Test
public void testVersionGetters() throws Exception {
String firmwareVersion = "fuzzy";
String driverVersion = "dizzy";
IWifiChip.ChipDebugInfo chipDebugInfo = new IWifiChip.ChipDebugInfo();
chipDebugInfo.firmwareDescription = firmwareVersion;
chipDebugInfo.driverDescription = driverVersion;
doAnswer(new AnswerWithArguments() {
public void answer(IWifiChip.requestChipDebugInfoCallback cb) throws RemoteException {
cb.onValues(mWifiStatusSuccess, chipDebugInfo);
}
}).when(mIWifiChip).requestChipDebugInfo(any(IWifiChip.requestChipDebugInfoCallback.class));
assertNull(mWifiVendorHal.getFirmwareVersion());
assertNull(mWifiVendorHal.getDriverVersion());
assertTrue(mWifiVendorHal.startVendorHalSta());
assertEquals(firmwareVersion, mWifiVendorHal.getFirmwareVersion());
assertEquals(driverVersion, mWifiVendorHal.getDriverVersion());
}
/**
* For checkRoundTripIntTranslation lambdas
*/
interface IntForInt {
int translate(int value);
}
/**
* Checks that translation from x to y and back again is the identity function
*
* @param xFromY reverse translator
* @param yFromX forward translator
* @param xLimit non-inclusive upper bound on x (lower bound is zero)
*/
private void checkRoundTripIntTranslation(
IntForInt xFromY, IntForInt yFromX, int xFirst, int xLimit) throws Exception {
int ex = 0;
for (int i = xFirst; i < xLimit; i++) {
assertEquals(i, xFromY.translate(yFromX.translate(i)));
}
try {
yFromX.translate(xLimit);
assertTrue("expected an exception here", false);
} catch (IllegalArgumentException e) {
ex++;
}
try {
xFromY.translate(yFromX.translate(xLimit - 1) + 1);
assertTrue("expected an exception here", false);
} catch (IllegalArgumentException e) {
ex++;
}
assertEquals(2, ex);
}
/**
* Test translations of RTT type
*/
@Test
public void testRttTypeTranslation() throws Exception {
checkRoundTripIntTranslation(
(y) -> WifiVendorHal.halRttTypeFromFrameworkRttType(y),
(x) -> WifiVendorHal.frameworkRttTypeFromHalRttType(x),
1, 3);
}
/**
* Test translations of peer type
*/
@Test
public void testPeerTranslation() throws Exception {
checkRoundTripIntTranslation(
(y) -> WifiVendorHal.halPeerFromFrameworkPeer(y),
(x) -> WifiVendorHal.frameworkPeerFromHalPeer(x),
1, 6);
}
/**
* Test translations of channel width
*/
@Test
public void testChannelWidth() throws Exception {
checkRoundTripIntTranslation(
(y) -> WifiVendorHal.halChannelWidthFromFrameworkChannelWidth(y),
(x) -> WifiVendorHal.frameworkChannelWidthFromHalChannelWidth(x),
0, 5);
}
/**
* Test translations of preamble type mask
*/
@Test
public void testPreambleTranslation() throws Exception {
checkRoundTripIntTranslation(
(y) -> WifiVendorHal.halPreambleFromFrameworkPreamble(y),
(x) -> WifiVendorHal.frameworkPreambleFromHalPreamble(x),
0, 8);
}
/**
* Test translations of bandwidth mask
*/
@Test
public void testBandwidthTranslations() throws Exception {
checkRoundTripIntTranslation(
(y) -> WifiVendorHal.halBwFromFrameworkBw(y),
(x) -> WifiVendorHal.frameworkBwFromHalBw(x),
0, 64);
}
@Test
public void testGetRttStuff() throws Exception {
RttManager.RttParams params = new RttManager.RttParams();
//TODO(b/34901744) populate
RttConfig config = WifiVendorHal.halRttConfigFromFrameworkRttParams(params);
//TODO(b/34901744) check
}
@Test
public void testGetRttCapabilities() throws Exception {
RttCapabilities capabilities = new RttCapabilities();
//TODO(b/34901744) populate
doAnswer(new AnswerWithArguments() {
public void answer(IWifiRttController.getCapabilitiesCallback cb)
throws RemoteException {
cb.onValues(mWifiStatusSuccess, capabilities);
}
}).when(mIWifiRttController).getCapabilities(any(
IWifiRttController.getCapabilitiesCallback.class));
assertNull(mWifiVendorHal.getRttCapabilities());
assertTrue(mWifiVendorHal.startVendorHalSta());
RttManager.RttCapabilities actual = mWifiVendorHal.getRttCapabilities();
//TODO(b/34901744) check
}
//TODO(b/34901744) negative RTT test cases as well.
// e.g. invoke RTT without putting the HAL in the correct mode.
/**
* Test that setScanningMacOui is hooked up to the HAL correctly
*/
@Test
public void testSetScanningMacOui() throws Exception {
byte[] oui = NativeUtil.macAddressOuiToByteArray("DA:A1:19");
byte[] zzz = NativeUtil.macAddressOuiToByteArray("00:00:00");
when(mIWifiStaIface.setScanningMacOui(any())).thenReturn(mWifiStatusSuccess);
assertFalse(mWifiVendorHal.setScanningMacOui(oui)); // expect fail - STA not started
assertTrue(mWifiVendorHal.startVendorHalSta());
assertFalse(mWifiVendorHal.setScanningMacOui(null)); // expect fail - null
assertFalse(mWifiVendorHal.setScanningMacOui(new byte[]{(byte) 1})); // expect fail - len
assertTrue(mWifiVendorHal.setScanningMacOui(oui));
assertTrue(mWifiVendorHal.setScanningMacOui(zzz));
verify(mIWifiStaIface).setScanningMacOui(eq(oui));
verify(mIWifiStaIface).setScanningMacOui(eq(zzz));
}
@Test
public void testStartSendingOffloadedPacket() throws Exception {
byte[] srcMac = NativeUtil.macAddressToByteArray("4007b2088c81");
InetAddress src = InetAddress.parseNumericAddress("192.168.13.13");
InetAddress dst = InetAddress.parseNumericAddress("93.184.216.34");
int slot = 13;
int millis = 16000;
KeepalivePacketData kap = KeepalivePacketData.nattKeepalivePacket(src, 63000, dst, 4500);
when(mIWifiStaIface.startSendingKeepAlivePackets(
anyInt(), any(), anyShort(), any(), any(), anyInt()
)).thenReturn(mWifiStatusSuccess);
assertTrue(mWifiVendorHal.startVendorHalSta());
assertTrue(0 == mWifiVendorHal.startSendingOffloadedPacket(slot, srcMac, kap, millis));
verify(mIWifiStaIface).startSendingKeepAlivePackets(
eq(slot), any(), anyShort(), any(), any(), eq(millis));
}
@Test
public void testStopSendingOffloadedPacket() throws Exception {
int slot = 13;
when(mIWifiStaIface.stopSendingKeepAlivePackets(anyInt())).thenReturn(mWifiStatusSuccess);
assertTrue(mWifiVendorHal.startVendorHalSta());
assertTrue(0 == mWifiVendorHal.stopSendingOffloadedPacket(slot));
verify(mIWifiStaIface).stopSendingKeepAlivePackets(eq(slot));
}
/**
* Test the setup, invocation, and removal of a RSSI event handler
*
*/
@Test
public void testRssiMonitoring() throws Exception {
when(mIWifiStaIface.startRssiMonitoring(anyInt(), anyInt(), anyInt()))
.thenReturn(mWifiStatusSuccess);
when(mIWifiStaIface.stopRssiMonitoring(anyInt()))
.thenReturn(mWifiStatusSuccess);
ArrayList<Byte> breach = new ArrayList<>(10);
byte hi = -21;
byte med = -42;
byte lo = -84;
Byte lower = -88;
WifiNative.WifiRssiEventHandler handler;
handler = ((cur) -> {
breach.add(cur);
});
assertEquals(-1, mWifiVendorHal.startRssiMonitoring(hi, lo, handler)); // not started
assertEquals(-1, mWifiVendorHal.stopRssiMonitoring()); // not started
assertTrue(mWifiVendorHal.startVendorHalSta());
assertEquals(0, mWifiVendorHal.startRssiMonitoring(hi, lo, handler));
int theCmdId = mWifiVendorHal.sRssiMonCmdId;
breach.clear();
mIWifiStaIfaceEventCallback.onRssiThresholdBreached(theCmdId, new byte[6], lower);
assertEquals(breach.get(0), lower);
assertEquals(0, mWifiVendorHal.stopRssiMonitoring());
assertEquals(0, mWifiVendorHal.startRssiMonitoring(hi, lo, handler));
assertEquals(0, mWifiVendorHal.startRssiMonitoring(med, lo, handler)); // replacing works
assertEquals(-1, mWifiVendorHal.startRssiMonitoring(hi, lo, null)); // null handler fails
assertEquals(0, mWifiVendorHal.startRssiMonitoring(hi, lo, handler));
assertEquals(-1, mWifiVendorHal.startRssiMonitoring(lo, hi, handler)); // empty range
}
/**
* Test that getApfCapabilities is hooked up to the HAL correctly
*
* A call before the vendor HAL is started should return a non-null result with version 0
*
* A call after the HAL is started should return the mocked values.
*/
@Test
public void testApfCapabilities() throws Exception {
int myVersion = 33;
int myMaxSize = 1234;
StaApfPacketFilterCapabilities capabilities = new StaApfPacketFilterCapabilities();
capabilities.version = myVersion;
capabilities.maxLength = myMaxSize;
doAnswer(new AnswerWithArguments() {
public void answer(IWifiStaIface.getApfPacketFilterCapabilitiesCallback cb)
throws RemoteException {
cb.onValues(mWifiStatusSuccess, capabilities);
}
}).when(mIWifiStaIface).getApfPacketFilterCapabilities(any(
IWifiStaIface.getApfPacketFilterCapabilitiesCallback.class));
assertEquals(0, mWifiVendorHal.getApfCapabilities().apfVersionSupported);
assertTrue(mWifiVendorHal.startVendorHalSta());
ApfCapabilities actual = mWifiVendorHal.getApfCapabilities();
assertEquals(myVersion, actual.apfVersionSupported);
assertEquals(myMaxSize, actual.maximumApfProgramSize);
assertEquals(android.system.OsConstants.ARPHRD_ETHER, actual.apfPacketFormat);
assertNotEquals(0, actual.apfPacketFormat);
}
/**
* Test that an APF program can be installed.
*/
@Test
public void testInstallApf() throws Exception {
byte[] filter = new byte[] {19, 53, 10};
ArrayList<Byte> expected = new ArrayList<>(3);
for (byte b : filter) expected.add(b);
when(mIWifiStaIface.installApfPacketFilter(anyInt(), any(ArrayList.class)))
.thenReturn(mWifiStatusSuccess);
assertTrue(mWifiVendorHal.startVendorHalSta());
assertTrue(mWifiVendorHal.installPacketFilter(filter));
verify(mIWifiStaIface).installApfPacketFilter(eq(0), eq(expected));
}
/**
* Test that the country code is set in AP mode (when it should be).
*/
@Test
public void testSetCountryCodeHal() throws Exception {
byte[] expected = new byte[]{(byte) 'C', (byte) 'A'};
when(mIWifiApIface.setCountryCode(any()))
.thenReturn(mWifiStatusSuccess);
assertTrue(mWifiVendorHal.startVendorHalAp());
assertFalse(mWifiVendorHal.setCountryCodeHal(null));
assertFalse(mWifiVendorHal.setCountryCodeHal(""));
assertFalse(mWifiVendorHal.setCountryCodeHal("A"));
assertTrue(mWifiVendorHal.setCountryCodeHal("CA")); // Only one expected to succeed
assertFalse(mWifiVendorHal.setCountryCodeHal("ZZZ"));
verify(mIWifiApIface).setCountryCode(eq(expected));
}
/**
* Test that RemoteException is caught and logged.
*/
@Test
public void testRemoteExceptionIsHandled() throws Exception {
mWifiLog = spy(mWifiLog);
mWifiVendorHal.mVerboseLog = mWifiLog;
when(mIWifiApIface.setCountryCode(any()))
.thenThrow(new RemoteException("oops"));
assertTrue(mWifiVendorHal.startVendorHalAp());
assertFalse(mWifiVendorHal.setCountryCodeHal("CA"));
assertFalse(mWifiVendorHal.isHalStarted());
verify(mWifiLog).err(any());
}
/**
* Test that startLoggingToDebugRingBuffer is plumbed to chip
*
* A call before the vendor hal is started should just return false.
* After starting in STA mode, the call should succeed, and pass ther right things down.
*/
@Test
public void testStartLoggingRingBuffer() throws Exception {
when(mIWifiChip.startLoggingToDebugRingBuffer(
any(String.class), anyInt(), anyInt(), anyInt()
)).thenReturn(mWifiStatusSuccess);
assertFalse(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 0, 0, "One"));
assertTrue(mWifiVendorHal.startVendorHalSta());
assertTrue(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 11, 3000, "One"));
verify(mIWifiChip).startLoggingToDebugRingBuffer("One", 1, 11, 3000);
}
/**
* Same test as testStartLoggingRingBuffer, but in AP mode rather than STA.
*/
@Test
public void testStartLoggingRingBufferOnAp() throws Exception {
when(mIWifiChip.startLoggingToDebugRingBuffer(
any(String.class), anyInt(), anyInt(), anyInt()
)).thenReturn(mWifiStatusSuccess);
assertFalse(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 0, 0, "One"));
assertTrue(mWifiVendorHal.startVendorHalAp());
assertTrue(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 11, 3000, "One"));
verify(mIWifiChip).startLoggingToDebugRingBuffer("One", 1, 11, 3000);
}
/**
* Test that getRingBufferStatus gets and translates its stuff correctly
*/
@Test
public void testRingBufferStatus() throws Exception {
WifiDebugRingBufferStatus one = new WifiDebugRingBufferStatus();
one.ringName = "One";
one.flags = WifiDebugRingBufferFlags.HAS_BINARY_ENTRIES;
one.ringId = 5607371;
one.sizeInBytes = 54321;
one.freeSizeInBytes = 42;
one.verboseLevel = WifiDebugRingBufferVerboseLevel.VERBOSE;
String oneExpect = "name: One flag: 1 ringBufferId: 5607371 ringBufferByteSize: 54321"
+ " verboseLevel: 2 writtenBytes: 0 readBytes: 0 writtenRecords: 0";
WifiDebugRingBufferStatus two = new WifiDebugRingBufferStatus();
two.ringName = "Two";
two.flags = WifiDebugRingBufferFlags.HAS_ASCII_ENTRIES
| WifiDebugRingBufferFlags.HAS_PER_PACKET_ENTRIES;
two.ringId = 4512470;
two.sizeInBytes = 300;
two.freeSizeInBytes = 42;
two.verboseLevel = WifiDebugRingBufferVerboseLevel.DEFAULT;
ArrayList<WifiDebugRingBufferStatus> halBufferStatus = new ArrayList<>(2);
halBufferStatus.add(one);
halBufferStatus.add(two);
WifiNative.RingBufferStatus[] actual;
doAnswer(new AnswerWithArguments() {
public void answer(IWifiChip.getDebugRingBuffersStatusCallback cb)
throws RemoteException {
cb.onValues(mWifiStatusSuccess, halBufferStatus);
}
}).when(mIWifiChip).getDebugRingBuffersStatus(any(
IWifiChip.getDebugRingBuffersStatusCallback.class));
assertTrue(mWifiVendorHal.startVendorHalSta());
actual = mWifiVendorHal.getRingBufferStatus();
assertEquals(halBufferStatus.size(), actual.length);
assertEquals(oneExpect, actual[0].toString());
assertEquals(two.ringId, actual[1].ringBufferId);
}
/**
* Test that getRingBufferData calls forceDumpToDebugRingBuffer
*
* Try once before hal start, and twice after (one success, one failure).
*/
@Test
public void testForceRingBufferDump() throws Exception {
when(mIWifiChip.forceDumpToDebugRingBuffer(eq("Gunk"))).thenReturn(mWifiStatusSuccess);
when(mIWifiChip.forceDumpToDebugRingBuffer(eq("Glop"))).thenReturn(mWifiStatusFailure);
assertFalse(mWifiVendorHal.getRingBufferData("Gunk")); // hal not started
assertTrue(mWifiVendorHal.startVendorHalSta());
assertTrue(mWifiVendorHal.getRingBufferData("Gunk")); // mocked call succeeds
assertFalse(mWifiVendorHal.getRingBufferData("Glop")); // mocked call fails
verify(mIWifiChip).forceDumpToDebugRingBuffer("Gunk");
verify(mIWifiChip).forceDumpToDebugRingBuffer("Glop");
}
/**
* Tests the start of packet fate monitoring.
*
* Try once before hal start, and once after (one success, one failure).
*/
@Test
public void testStartPktFateMonitoring() throws Exception {
when(mIWifiStaIface.startDebugPacketFateMonitoring()).thenReturn(mWifiStatusSuccess);
assertFalse(mWifiVendorHal.startPktFateMonitoring());
verify(mIWifiStaIface, never()).startDebugPacketFateMonitoring();
assertTrue(mWifiVendorHal.startVendorHalSta());
assertTrue(mWifiVendorHal.startPktFateMonitoring());
verify(mIWifiStaIface).startDebugPacketFateMonitoring();
}
/**
* Tests the retrieval of tx packet fates.
*
* Try once before hal start, and once after.
*/
@Test
public void testGetTxPktFates() throws Exception {
byte[] frameContentBytes = new byte[30];
new Random().nextBytes(frameContentBytes);
WifiDebugTxPacketFateReport fateReport = new WifiDebugTxPacketFateReport();
fateReport.fate = WifiDebugTxPacketFate.DRV_QUEUED;
fateReport.frameInfo.driverTimestampUsec = new Random().nextLong();
fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.ETHERNET_II;
fateReport.frameInfo.frameContent.addAll(
NativeUtil.byteArrayToArrayList(frameContentBytes));
doAnswer(new AnswerWithArguments() {
public void answer(IWifiStaIface.getDebugTxPacketFatesCallback cb) {
cb.onValues(mWifiStatusSuccess,
new ArrayList<WifiDebugTxPacketFateReport>(Arrays.asList(fateReport)));
}
}).when(mIWifiStaIface)
.getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
WifiNative.TxFateReport[] retrievedFates = new WifiNative.TxFateReport[1];
assertFalse(mWifiVendorHal.getTxPktFates(retrievedFates));
verify(mIWifiStaIface, never())
.getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
assertTrue(mWifiVendorHal.startVendorHalSta());
assertTrue(mWifiVendorHal.getTxPktFates(retrievedFates));
verify(mIWifiStaIface)
.getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
assertEquals(WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED, retrievedFates[0].mFate);
assertEquals(fateReport.frameInfo.driverTimestampUsec,
retrievedFates[0].mDriverTimestampUSec);
assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, retrievedFates[0].mFrameType);
assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes);
}
/**
* Tests the retrieval of tx packet fates when the number of fates retrieved exceeds the
* input array.
*
* Try once before hal start, and once after.
*/
@Test
public void testGetTxPktFatesExceedsInputArrayLength() throws Exception {
byte[] frameContentBytes = new byte[30];
new Random().nextBytes(frameContentBytes);
WifiDebugTxPacketFateReport fateReport = new WifiDebugTxPacketFateReport();
fateReport.fate = WifiDebugTxPacketFate.FW_DROP_OTHER;
fateReport.frameInfo.driverTimestampUsec = new Random().nextLong();
fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.MGMT_80211;
fateReport.frameInfo.frameContent.addAll(
NativeUtil.byteArrayToArrayList(frameContentBytes));
doAnswer(new AnswerWithArguments() {
public void answer(IWifiStaIface.getDebugTxPacketFatesCallback cb) {
cb.onValues(mWifiStatusSuccess,
new ArrayList<WifiDebugTxPacketFateReport>(Arrays.asList(
fateReport, fateReport)));
}
}).when(mIWifiStaIface)
.getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
WifiNative.TxFateReport[] retrievedFates = new WifiNative.TxFateReport[1];
assertFalse(mWifiVendorHal.getTxPktFates(retrievedFates));
verify(mIWifiStaIface, never())
.getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
assertTrue(mWifiVendorHal.startVendorHalSta());
assertTrue(mWifiVendorHal.getTxPktFates(retrievedFates));
verify(mIWifiStaIface)
.getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
assertEquals(WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER, retrievedFates[0].mFate);
assertEquals(fateReport.frameInfo.driverTimestampUsec,
retrievedFates[0].mDriverTimestampUSec);
assertEquals(WifiLoggerHal.FRAME_TYPE_80211_MGMT, retrievedFates[0].mFrameType);
assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes);
}
/**
* Tests the retrieval of rx packet fates.
*
* Try once before hal start, and once after.
*/
@Test
public void testGetRxPktFates() throws Exception {
byte[] frameContentBytes = new byte[30];
new Random().nextBytes(frameContentBytes);
WifiDebugRxPacketFateReport fateReport = new WifiDebugRxPacketFateReport();
fateReport.fate = WifiDebugRxPacketFate.SUCCESS;
fateReport.frameInfo.driverTimestampUsec = new Random().nextLong();
fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.ETHERNET_II;
fateReport.frameInfo.frameContent.addAll(
NativeUtil.byteArrayToArrayList(frameContentBytes));
doAnswer(new AnswerWithArguments() {
public void answer(IWifiStaIface.getDebugRxPacketFatesCallback cb) {
cb.onValues(mWifiStatusSuccess,
new ArrayList<WifiDebugRxPacketFateReport>(Arrays.asList(fateReport)));
}
}).when(mIWifiStaIface)
.getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
WifiNative.RxFateReport[] retrievedFates = new WifiNative.RxFateReport[1];
assertFalse(mWifiVendorHal.getRxPktFates(retrievedFates));
verify(mIWifiStaIface, never())
.getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
assertTrue(mWifiVendorHal.startVendorHalSta());
assertTrue(mWifiVendorHal.getRxPktFates(retrievedFates));
verify(mIWifiStaIface)
.getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
assertEquals(WifiLoggerHal.RX_PKT_FATE_SUCCESS, retrievedFates[0].mFate);
assertEquals(fateReport.frameInfo.driverTimestampUsec,
retrievedFates[0].mDriverTimestampUSec);
assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, retrievedFates[0].mFrameType);
assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes);
}
/**
* Tests the retrieval of rx packet fates when the number of fates retrieved exceeds the
* input array.
*
* Try once before hal start, and once after.
*/
@Test
public void testGetRxPktFatesExceedsInputArrayLength() throws Exception {
byte[] frameContentBytes = new byte[30];
new Random().nextBytes(frameContentBytes);
WifiDebugRxPacketFateReport fateReport = new WifiDebugRxPacketFateReport();
fateReport.fate = WifiDebugRxPacketFate.FW_DROP_FILTER;
fateReport.frameInfo.driverTimestampUsec = new Random().nextLong();
fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.MGMT_80211;
fateReport.frameInfo.frameContent.addAll(
NativeUtil.byteArrayToArrayList(frameContentBytes));
doAnswer(new AnswerWithArguments() {
public void answer(IWifiStaIface.getDebugRxPacketFatesCallback cb) {
cb.onValues(mWifiStatusSuccess,
new ArrayList<WifiDebugRxPacketFateReport>(Arrays.asList(
fateReport, fateReport)));
}
}).when(mIWifiStaIface)
.getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
WifiNative.RxFateReport[] retrievedFates = new WifiNative.RxFateReport[1];
assertFalse(mWifiVendorHal.getRxPktFates(retrievedFates));
verify(mIWifiStaIface, never())
.getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
assertTrue(mWifiVendorHal.startVendorHalSta());
assertTrue(mWifiVendorHal.getRxPktFates(retrievedFates));
verify(mIWifiStaIface)
.getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
assertEquals(WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER, retrievedFates[0].mFate);
assertEquals(fateReport.frameInfo.driverTimestampUsec,
retrievedFates[0].mDriverTimestampUSec);
assertEquals(WifiLoggerHal.FRAME_TYPE_80211_MGMT, retrievedFates[0].mFrameType);
assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes);
}
/**
* Tests the failure to retrieve tx packet fates when the input array is empty.
*/
@Test
public void testGetTxPktFatesEmptyInputArray() throws Exception {
assertTrue(mWifiVendorHal.startVendorHalSta());
assertFalse(mWifiVendorHal.getTxPktFates(new WifiNative.TxFateReport[0]));
verify(mIWifiStaIface, never())
.getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
}
/**
* Tests the failure to retrieve rx packet fates when the input array is empty.
*/
@Test
public void testGetRxPktFatesEmptyInputArray() throws Exception {
assertTrue(mWifiVendorHal.startVendorHalSta());
assertFalse(mWifiVendorHal.getRxPktFates(new WifiNative.RxFateReport[0]));
verify(mIWifiStaIface, never())
.getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
}
/**
* Tests the nd offload enable/disable.
*/
@Test
public void testEnableDisableNdOffload() throws Exception {
when(mIWifiStaIface.enableNdOffload(anyBoolean())).thenReturn(mWifiStatusSuccess);
assertFalse(mWifiVendorHal.configureNeighborDiscoveryOffload(true));
verify(mIWifiStaIface, never()).enableNdOffload(anyBoolean());
assertTrue(mWifiVendorHal.startVendorHalSta());
assertTrue(mWifiVendorHal.configureNeighborDiscoveryOffload(true));
verify(mIWifiStaIface).enableNdOffload(eq(true));
assertTrue(mWifiVendorHal.configureNeighborDiscoveryOffload(false));
verify(mIWifiStaIface).enableNdOffload(eq(false));
}
/**
* Tests the nd offload enable failure.
*/
@Test
public void testEnableNdOffloadFailure() throws Exception {
when(mIWifiStaIface.enableNdOffload(eq(true))).thenReturn(mWifiStatusFailure);
assertTrue(mWifiVendorHal.startVendorHalSta());
assertFalse(mWifiVendorHal.configureNeighborDiscoveryOffload(true));
verify(mIWifiStaIface).enableNdOffload(eq(true));
}
/**
* Tests the retrieval of wlan wake reason stats.
*/
@Test
public void testGetWlanWakeReasonCount() throws Exception {
WifiDebugHostWakeReasonStats stats = new WifiDebugHostWakeReasonStats();
Random rand = new Random();
stats.totalCmdEventWakeCnt = rand.nextInt();
stats.totalDriverFwLocalWakeCnt = rand.nextInt();
stats.totalRxPacketWakeCnt = rand.nextInt();
stats.rxPktWakeDetails.rxUnicastCnt = rand.nextInt();
stats.rxPktWakeDetails.rxMulticastCnt = rand.nextInt();
stats.rxIcmpPkWakeDetails.icmpPkt = rand.nextInt();
stats.rxIcmpPkWakeDetails.icmp6Pkt = rand.nextInt();
stats.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt = rand.nextInt();
stats.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt = rand.nextInt();
doAnswer(new AnswerWithArguments() {
public void answer(IWifiChip.getDebugHostWakeReasonStatsCallback cb) {
cb.onValues(mWifiStatusSuccess, stats);
}
}).when(mIWifiChip).getDebugHostWakeReasonStats(
any(IWifiChip.getDebugHostWakeReasonStatsCallback.class));
assertNull(mWifiVendorHal.getWlanWakeReasonCount());
verify(mIWifiChip, never())
.getDebugHostWakeReasonStats(
any(IWifiChip.getDebugHostWakeReasonStatsCallback.class));
assertTrue(mWifiVendorHal.startVendorHalSta());
WifiWakeReasonAndCounts retrievedStats = mWifiVendorHal.getWlanWakeReasonCount();
verify(mIWifiChip).getDebugHostWakeReasonStats(
any(IWifiChip.getDebugHostWakeReasonStatsCallback.class));
assertNotNull(retrievedStats);
assertEquals(stats.totalCmdEventWakeCnt, retrievedStats.totalCmdEventWake);
assertEquals(stats.totalDriverFwLocalWakeCnt, retrievedStats.totalDriverFwLocalWake);
assertEquals(stats.totalRxPacketWakeCnt, retrievedStats.totalRxDataWake);
assertEquals(stats.rxPktWakeDetails.rxUnicastCnt, retrievedStats.rxUnicast);
assertEquals(stats.rxPktWakeDetails.rxMulticastCnt, retrievedStats.rxMulticast);
assertEquals(stats.rxIcmpPkWakeDetails.icmpPkt, retrievedStats.icmp);
assertEquals(stats.rxIcmpPkWakeDetails.icmp6Pkt, retrievedStats.icmp6);
assertEquals(stats.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt,
retrievedStats.ipv4RxMulticast);
assertEquals(stats.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt,
retrievedStats.ipv6Multicast);
}
/**
* Tests the failure in retrieval of wlan wake reason stats.
*/
@Test
public void testGetWlanWakeReasonCountFailure() throws Exception {
doAnswer(new AnswerWithArguments() {
public void answer(IWifiChip.getDebugHostWakeReasonStatsCallback cb) {
cb.onValues(mWifiStatusFailure, new WifiDebugHostWakeReasonStats());
}
}).when(mIWifiChip).getDebugHostWakeReasonStats(
any(IWifiChip.getDebugHostWakeReasonStatsCallback.class));
// This should work in both AP & STA mode.
assertTrue(mWifiVendorHal.startVendorHalAp());
assertNull(mWifiVendorHal.getWlanWakeReasonCount());
verify(mIWifiChip).getDebugHostWakeReasonStats(
any(IWifiChip.getDebugHostWakeReasonStatsCallback.class));
}
/**
* Test that getFwMemoryDump is properly plumbed
*/
@Test
public void testGetFwMemoryDump() throws Exception {
byte [] sample = NativeUtil.hexStringToByteArray("268c7a3fbfa4661c0bdd6a36");
ArrayList<Byte> halBlob = NativeUtil.byteArrayToArrayList(sample);
doAnswer(new AnswerWithArguments() {
public void answer(IWifiChip.requestFirmwareDebugDumpCallback cb)
throws RemoteException {
cb.onValues(mWifiStatusSuccess, halBlob);
}
}).when(mIWifiChip).requestFirmwareDebugDump(any(
IWifiChip.requestFirmwareDebugDumpCallback.class));
assertTrue(mWifiVendorHal.startVendorHalSta());
assertArrayEquals(sample, mWifiVendorHal.getFwMemoryDump());
}
/**
* Test that getDriverStateDump is properly plumbed
*
* Just for variety, use AP mode here.
*/
@Test
public void testGetDriverStateDump() throws Exception {
byte [] sample = NativeUtil.hexStringToByteArray("e83ff543cf80083e6459d20f");
ArrayList<Byte> halBlob = NativeUtil.byteArrayToArrayList(sample);
doAnswer(new AnswerWithArguments() {
public void answer(IWifiChip.requestDriverDebugDumpCallback cb)
throws RemoteException {
cb.onValues(mWifiStatusSuccess, halBlob);
}
}).when(mIWifiChip).requestDriverDebugDump(any(
IWifiChip.requestDriverDebugDumpCallback.class));
assertTrue(mWifiVendorHal.startVendorHalAp());
assertArrayEquals(sample, mWifiVendorHal.getDriverStateDump());
}
/**
* Test that background scan failure is handled correctly.
*/
@Test
public void testBgScanFailureCallback() throws Exception {
assertTrue(mWifiVendorHal.startVendorHalSta());
assertNotNull(mIWifiStaIfaceEventCallback);
WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
startBgScan(eventHandler);
mIWifiStaIfaceEventCallback.onBackgroundScanFailure(mWifiVendorHal.mScan.cmdId);
verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_FAILED);
}
/**
* Test that background scan failure with wrong id is not reported.
*/
@Test
public void testBgScanFailureCallbackWithInvalidCmdId() throws Exception {
assertTrue(mWifiVendorHal.startVendorHalSta());
assertNotNull(mIWifiStaIfaceEventCallback);
WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
startBgScan(eventHandler);
mIWifiStaIfaceEventCallback.onBackgroundScanFailure(mWifiVendorHal.mScan.cmdId + 1);
verify(eventHandler, never()).onScanStatus(WifiNative.WIFI_SCAN_FAILED);
}
/**
* Test that background scan full results are handled correctly.
*/
@Test
public void testBgScanFullScanResults() throws Exception {
assertTrue(mWifiVendorHal.startVendorHalSta());
assertNotNull(mIWifiStaIfaceEventCallback);
WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
startBgScan(eventHandler);
Pair<StaScanResult, ScanResult> result = createHidlAndFrameworkBgScanResult();
mIWifiStaIfaceEventCallback.onBackgroundFullScanResult(
mWifiVendorHal.mScan.cmdId, 5, result.first);
ArgumentCaptor<ScanResult> scanResultCaptor = ArgumentCaptor.forClass(ScanResult.class);
verify(eventHandler).onFullScanResult(scanResultCaptor.capture(), eq(5));
assertScanResultEqual(result.second, scanResultCaptor.getValue());
}
/**
* Test that background scan results are handled correctly.
*/
@Test
public void testBgScanScanResults() throws Exception {
assertTrue(mWifiVendorHal.startVendorHalSta());
assertNotNull(mIWifiStaIfaceEventCallback);
WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
startBgScan(eventHandler);
Pair<ArrayList<StaScanData>, ArrayList<WifiScanner.ScanData>> data =
createHidlAndFrameworkBgScanDatas();
mIWifiStaIfaceEventCallback.onBackgroundScanResults(
mWifiVendorHal.mScan.cmdId, data.first);
verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
assertScanDatasEqual(
data.second, Arrays.asList(mWifiVendorHal.mScan.latestScanResults));
}
/**
* Test that starting a new background scan when one is active will stop the previous one.
*/
@Test
public void testBgScanReplacement() throws Exception {
when(mIWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(mWifiStatusSuccess);
assertTrue(mWifiVendorHal.startVendorHalSta());
assertNotNull(mIWifiStaIfaceEventCallback);
WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
startBgScan(eventHandler);
int cmdId1 = mWifiVendorHal.mScan.cmdId;
startBgScan(eventHandler);
assertNotEquals(mWifiVendorHal.mScan.cmdId, cmdId1);
verify(mIWifiStaIface, times(2)).startBackgroundScan(anyInt(), any());
verify(mIWifiStaIface).stopBackgroundScan(cmdId1);
}
/**
* Test stopping a background scan.
*/
@Test
public void testBgScanStop() throws Exception {
when(mIWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(mWifiStatusSuccess);
assertTrue(mWifiVendorHal.startVendorHalSta());
assertNotNull(mIWifiStaIfaceEventCallback);
WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
startBgScan(eventHandler);
int cmdId = mWifiVendorHal.mScan.cmdId;
mWifiVendorHal.stopBgScan();
mWifiVendorHal.stopBgScan(); // second call should not do anything
verify(mIWifiStaIface).stopBackgroundScan(cmdId); // Should be called just once
}
/**
* Test pausing and restarting a background scan.
*/
@Test
public void testBgScanPauseAndRestart() throws Exception {
when(mIWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(mWifiStatusSuccess);
assertTrue(mWifiVendorHal.startVendorHalSta());
assertNotNull(mIWifiStaIfaceEventCallback);
WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
startBgScan(eventHandler);
int cmdId = mWifiVendorHal.mScan.cmdId;
mWifiVendorHal.pauseBgScan();
mWifiVendorHal.restartBgScan();
verify(mIWifiStaIface).stopBackgroundScan(cmdId); // Should be called just once
verify(mIWifiStaIface, times(2)).startBackgroundScan(eq(cmdId), any());
}
/**
* Test the handling of log handler set.
*/
@Test
public void testSetLogHandler() throws Exception {
when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess);
WifiNative.WifiLoggerEventHandler eventHandler =
mock(WifiNative.WifiLoggerEventHandler.class);
assertFalse(mWifiVendorHal.setLoggingEventHandler(eventHandler));
verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean());
assertTrue(mWifiVendorHal.startVendorHalSta());
assertTrue(mWifiVendorHal.setLoggingEventHandler(eventHandler));
verify(mIWifiChip).enableDebugErrorAlerts(eq(true));
reset(mIWifiChip);
// Second call should fail.
assertFalse(mWifiVendorHal.setLoggingEventHandler(eventHandler));
verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean());
}
/**
* Test the handling of log handler reset.
*/
@Test
public void testResetLogHandler() throws Exception {
when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess);
when(mIWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(mWifiStatusSuccess);
assertFalse(mWifiVendorHal.resetLogHandler());
verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean());
verify(mIWifiChip, never()).stopLoggingToDebugRingBuffer();
assertTrue(mWifiVendorHal.startVendorHalSta());
// Not set, so this should fail.
assertFalse(mWifiVendorHal.resetLogHandler());
verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean());
verify(mIWifiChip, never()).stopLoggingToDebugRingBuffer();
// Now set and then reset.
assertTrue(mWifiVendorHal.setLoggingEventHandler(
mock(WifiNative.WifiLoggerEventHandler.class)));
assertTrue(mWifiVendorHal.resetLogHandler());
verify(mIWifiChip).enableDebugErrorAlerts(eq(false));
verify(mIWifiChip).stopLoggingToDebugRingBuffer();
reset(mIWifiChip);
// Second reset should fail.
assertFalse(mWifiVendorHal.resetLogHandler());
verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean());
verify(mIWifiChip, never()).stopLoggingToDebugRingBuffer();
}
/**
* Test the handling of alert callback.
*/
@Test
public void testAlertCallback() throws Exception {
when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess);
when(mIWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(mWifiStatusSuccess);
assertTrue(mWifiVendorHal.startVendorHalSta());
assertNotNull(mIWifiChipEventCallback);
int errorCode = 5;
byte[] errorData = new byte[45];
new Random().nextBytes(errorData);
// Randomly raise the HIDL callback before we register for the log callback.
// This should be safely ignored. (Not trigger NPE.)
mIWifiChipEventCallback.onDebugErrorAlert(
errorCode, NativeUtil.byteArrayToArrayList(errorData));
mLooper.dispatchAll();
WifiNative.WifiLoggerEventHandler eventHandler =
mock(WifiNative.WifiLoggerEventHandler.class);
assertTrue(mWifiVendorHal.setLoggingEventHandler(eventHandler));
verify(mIWifiChip).enableDebugErrorAlerts(eq(true));
// Now raise the HIDL callback, this should be properly handled.
mIWifiChipEventCallback.onDebugErrorAlert(
errorCode, NativeUtil.byteArrayToArrayList(errorData));
mLooper.dispatchAll();
verify(eventHandler).onWifiAlert(eq(errorCode), eq(errorData));
// Now stop the logging and invoke the callback. This should be ignored.
reset(eventHandler);
assertTrue(mWifiVendorHal.resetLogHandler());
mIWifiChipEventCallback.onDebugErrorAlert(
errorCode, NativeUtil.byteArrayToArrayList(errorData));
mLooper.dispatchAll();
verify(eventHandler, never()).onWifiAlert(anyInt(), anyObject());
}
/**
* Test the handling of ring buffer callback.
*/
@Test
public void testRingBufferDataCallback() throws Exception {
when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess);
when(mIWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(mWifiStatusSuccess);
assertTrue(mWifiVendorHal.startVendorHalSta());
assertNotNull(mIWifiChipEventCallback);
byte[] errorData = new byte[45];
new Random().nextBytes(errorData);
// Randomly raise the HIDL callback before we register for the log callback.
// This should be safely ignored. (Not trigger NPE.)
mIWifiChipEventCallback.onDebugRingBufferDataAvailable(
new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData));
mLooper.dispatchAll();
WifiNative.WifiLoggerEventHandler eventHandler =
mock(WifiNative.WifiLoggerEventHandler.class);
assertTrue(mWifiVendorHal.setLoggingEventHandler(eventHandler));
verify(mIWifiChip).enableDebugErrorAlerts(eq(true));
// Now raise the HIDL callback, this should be properly handled.
mIWifiChipEventCallback.onDebugRingBufferDataAvailable(
new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData));
mLooper.dispatchAll();
verify(eventHandler).onRingBufferData(
any(WifiNative.RingBufferStatus.class), eq(errorData));
// Now stop the logging and invoke the callback. This should be ignored.
reset(eventHandler);
assertTrue(mWifiVendorHal.resetLogHandler());
mIWifiChipEventCallback.onDebugRingBufferDataAvailable(
new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData));
mLooper.dispatchAll();
verify(eventHandler, never()).onRingBufferData(anyObject(), anyObject());
}
/**
* Test the handling of Vendor HAL death.
*/
@Test
public void testVendorHalDeath() {
// Invoke the HAL device manager status callback with ready set to false to indicate the
// death of the HAL.
when(mHalDeviceManager.isReady()).thenReturn(false);
mHalDeviceManagerStatusCallbacks.onStatusChanged();
verify(mVendorHalDeathHandler).onDeath();
}
/**
* Test the new setTxPowerLimit HIDL method invocation. This should return failure if the
* HAL service is exposing the 1.0 interface.
*/
@Test
public void testSetTxPowerLimit() throws RemoteException {
int powerLevelInDbm = -45;
assertTrue(mWifiVendorHal.startVendorHal(true));
// Should fail because we exposed the 1.0 IWifiChip.
assertFalse(mWifiVendorHal.setTxPowerLimit(powerLevelInDbm));
verify(mIWifiChipV11, never()).setTxPowerLimit(eq(powerLevelInDbm));
mWifiVendorHal.stopVendorHal();
// Now expose the 1.1 IWifiChip.
mWifiVendorHal = new WifiVendorHalSpyV1_1(mHalDeviceManager, mLooper.getLooper());
when(mIWifiChipV11.setTxPowerLimit(anyInt())).thenReturn(mWifiStatusSuccess);
assertTrue(mWifiVendorHal.startVendorHal(true));
assertTrue(mWifiVendorHal.setTxPowerLimit(powerLevelInDbm));
verify(mIWifiChipV11).setTxPowerLimit(eq(powerLevelInDbm));
mWifiVendorHal.stopVendorHal();
}
/**
* Test the new setTxPowerLimit HIDL method invocation. This should return failure if the
* HAL service is exposing the 1.0 interface.
*/
@Test
public void testResetTxPowerLimit() throws RemoteException {
assertTrue(mWifiVendorHal.startVendorHal(true));
// Should fail because we exposed the 1.0 IWifiChip.
assertFalse(mWifiVendorHal.resetTxPowerLimit());
verify(mIWifiChipV11, never()).resetTxPowerLimit();
mWifiVendorHal.stopVendorHal();
// Now expose the 1.1 IWifiChip.
mWifiVendorHal = new WifiVendorHalSpyV1_1(mHalDeviceManager, mLooper.getLooper());
when(mIWifiChipV11.resetTxPowerLimit()).thenReturn(mWifiStatusSuccess);
assertTrue(mWifiVendorHal.startVendorHal(true));
assertTrue(mWifiVendorHal.resetTxPowerLimit());
verify(mIWifiChipV11).resetTxPowerLimit();
mWifiVendorHal.stopVendorHal();
}
private void startBgScan(WifiNative.ScanEventHandler eventHandler) throws Exception {
when(mIWifiStaIface.startBackgroundScan(
anyInt(), any(StaBackgroundScanParameters.class))).thenReturn(mWifiStatusSuccess);
WifiNative.ScanSettings settings = new WifiNative.ScanSettings();
settings.num_buckets = 1;
WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings();
bucketSettings.bucket = 0;
bucketSettings.period_ms = 16000;
bucketSettings.report_events = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;
settings.buckets = new WifiNative.BucketSettings[] {bucketSettings};
assertTrue(mWifiVendorHal.startBgScan(settings, eventHandler));
}
// Create a pair of HIDL scan result and its corresponding framework scan result for
// comparison.
private Pair<StaScanResult, ScanResult> createHidlAndFrameworkBgScanResult() {
StaScanResult staScanResult = new StaScanResult();
Random random = new Random();
byte[] ssid = new byte[8];
random.nextBytes(ssid);
staScanResult.ssid.addAll(NativeUtil.byteArrayToArrayList(ssid));
random.nextBytes(staScanResult.bssid);
staScanResult.frequency = 2432;
staScanResult.rssi = -45;
staScanResult.timeStampInUs = 5;
WifiInformationElement ie1 = new WifiInformationElement();
byte[] ie1_data = new byte[56];
random.nextBytes(ie1_data);
ie1.id = 1;
ie1.data.addAll(NativeUtil.byteArrayToArrayList(ie1_data));
staScanResult.informationElements.add(ie1);
// Now create the corresponding Scan result structure.
ScanResult scanResult = new ScanResult();
scanResult.SSID = NativeUtil.encodeSsid(staScanResult.ssid);
scanResult.BSSID = NativeUtil.macAddressFromByteArray(staScanResult.bssid);
scanResult.wifiSsid = WifiSsid.createFromByteArray(ssid);
scanResult.frequency = staScanResult.frequency;
scanResult.level = staScanResult.rssi;
scanResult.timestamp = staScanResult.timeStampInUs;
scanResult.bytes = new byte[57];
scanResult.bytes[0] = ie1.id;
System.arraycopy(ie1_data, 0, scanResult.bytes, 1, ie1_data.length);
return Pair.create(staScanResult, scanResult);
}
// Create a pair of HIDL scan datas and its corresponding framework scan datas for
// comparison.
private Pair<ArrayList<StaScanData>, ArrayList<WifiScanner.ScanData>>
createHidlAndFrameworkBgScanDatas() {
ArrayList<StaScanData> staScanDatas = new ArrayList<>();
StaScanData staScanData = new StaScanData();
Pair<StaScanResult, ScanResult> result = createHidlAndFrameworkBgScanResult();
staScanData.results.add(result.first);
staScanData.bucketsScanned = 5;
staScanData.flags = StaScanDataFlagMask.INTERRUPTED;
staScanDatas.add(staScanData);
ArrayList<WifiScanner.ScanData> scanDatas = new ArrayList<>();
ScanResult[] scanResults = new ScanResult[1];
scanResults[0] = result.second;
WifiScanner.ScanData scanData =
new WifiScanner.ScanData(mWifiVendorHal.mScan.cmdId, 1,
staScanData.bucketsScanned, false, scanResults);
scanDatas.add(scanData);
return Pair.create(staScanDatas, scanDatas);
}
private void assertScanResultEqual(ScanResult expected, ScanResult actual) {
assertEquals(expected.SSID, actual.SSID);
assertEquals(expected.wifiSsid.getHexString(), actual.wifiSsid.getHexString());
assertEquals(expected.BSSID, actual.BSSID);
assertEquals(expected.frequency, actual.frequency);
assertEquals(expected.level, actual.level);
assertEquals(expected.timestamp, actual.timestamp);
assertArrayEquals(expected.bytes, actual.bytes);
}
private void assertScanResultsEqual(ScanResult[] expected, ScanResult[] actual) {
assertEquals(expected.length, actual.length);
for (int i = 0; i < expected.length; i++) {
assertScanResultEqual(expected[i], actual[i]);
}
}
private void assertScanDataEqual(WifiScanner.ScanData expected, WifiScanner.ScanData actual) {
assertEquals(expected.getId(), actual.getId());
assertEquals(expected.getFlags(), actual.getFlags());
assertEquals(expected.getBucketsScanned(), actual.getBucketsScanned());
assertScanResultsEqual(expected.getResults(), actual.getResults());
}
private void assertScanDatasEqual(
List<WifiScanner.ScanData> expected, List<WifiScanner.ScanData> actual) {
assertEquals(expected.size(), actual.size());
for (int i = 0; i < expected.size(); i++) {
assertScanDataEqual(expected.get(i), actual.get(i));
}
}
}