blob: e72f80887483f2398dfb655991a87cfd1793ef67 [file] [log] [blame]
/*
* Copyright (C) 2016 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 org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.AdditionalMatchers.gt;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.contains;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.test.MockAnswerUtil.AnswerWithArguments;
import android.content.Context;
import android.os.BugreportManager;
import androidx.test.filters.SmallTest;
import com.android.wifi.resources.R;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import java.io.ByteArrayInputStream;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.regex.Pattern;
/**
* Unit tests for {@link WifiDiagnostics}.
*/
@SmallTest
public class WifiDiagnosticsTest extends WifiBaseTest {
@Mock WifiNative mWifiNative;
@Mock BuildProperties mBuildProperties;
@Mock Context mContext;
@Mock WifiInjector mWifiInjector;
@Mock DeviceConfigFacade mDeviceConfigFacade;
@Spy FakeWifiLog mLog;
@Mock LastMileLogger mLastMileLogger;
@Mock Runtime mJavaRuntime;
@Mock Process mExternalProcess;
@Mock WifiMetrics mWifiMetrics;
@Mock Clock mClock;
@Mock BugreportManager mBugreportManager;
@Mock WifiScoreCard mWifiScoreCard;
private long mBootTimeMs = 0L;
MockResources mResources;
WifiDiagnostics mWifiDiagnostics;
private static final String FAKE_RING_BUFFER_NAME = "fake-ring-buffer";
private static final String STA_IF_NAME = "wlan0";
private static final String AP_IF_NAME = "wlan1";
private static final int SMALL_RING_BUFFER_SIZE_KB = 32;
private static final int LARGE_RING_BUFFER_SIZE_KB = 1024;
private static final int BYTES_PER_KBYTE = 1024;
private static final int ALERT_REASON_CODE = 1;
private static final byte[] ALERT_DATA = {0 , 4, 5};
/** Mock resource for fatal firmware alert list */
private static final int[] FATAL_FW_ALERT_LIST = {256, 257, 258};
/** Mock a non fatal firmware alert */
private static final int NON_FATAL_FW_ALERT = 0;
private static final int BUG_REPORT_MIN_WINDOW_MS = 3600_000;
private WifiNative.RingBufferStatus mFakeRbs;
/**
* Returns the data that we would dump in a bug report, for our ring buffer.
* @return a 2-D byte array, where the first dimension is the record number, and the second
* dimension is the byte index within that record.
*/
private final byte[][] getLoggerRingBufferData() throws Exception {
return mWifiDiagnostics.getBugReports().get(0).ringBuffers.get(FAKE_RING_BUFFER_NAME);
}
/**
* Initializes common state (e.g. mocks) needed by test cases.
*/
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mFakeRbs = new WifiNative.RingBufferStatus();
mFakeRbs.name = FAKE_RING_BUFFER_NAME;
WifiNative.RingBufferStatus[] ringBufferStatuses = new WifiNative.RingBufferStatus[] {
mFakeRbs
};
when(mWifiNative.getRingBufferStatus()).thenReturn(ringBufferStatuses);
when(mBuildProperties.isEngBuild()).thenReturn(false);
when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
when(mBuildProperties.isUserBuild()).thenReturn(true);
when(mExternalProcess.getInputStream()).thenReturn(new ByteArrayInputStream(new byte[0]));
when(mExternalProcess.getErrorStream()).thenReturn(new ByteArrayInputStream(new byte[0]));
when(mJavaRuntime.exec(anyString())).thenReturn(mExternalProcess);
mResources = new MockResources();
mResources.setInteger(R.integer.config_wifi_logger_ring_buffer_default_size_limit_kb,
SMALL_RING_BUFFER_SIZE_KB);
mResources.setInteger(R.integer.config_wifi_logger_ring_buffer_verbose_size_limit_kb,
LARGE_RING_BUFFER_SIZE_KB);
mResources.setIntArray(R.array.config_wifi_fatal_firmware_alert_error_code_list,
FATAL_FW_ALERT_LIST);
mResources.setBoolean(R.bool.config_wifi_diagnostics_bugreport_enabled, true);
when(mContext.getResources()).thenReturn(mResources);
when(mContext.getSystemService(BugreportManager.class)).thenReturn(mBugreportManager);
when(mWifiInjector.makeLog(anyString())).thenReturn(mLog);
when(mWifiInjector.getJavaRuntime()).thenReturn(mJavaRuntime);
when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
when(mWifiInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
when(mWifiInjector.getWifiScoreCard()).thenReturn(mWifiScoreCard);
when(mDeviceConfigFacade.getBugReportMinWindowMs()).thenReturn(BUG_REPORT_MIN_WINDOW_MS);
// needed to for the loop in WifiDiagnostics.readLogcatStreamLinesWithTimeout().
doAnswer(new AnswerWithArguments() {
public long answer() throws Exception {
mBootTimeMs += WifiDiagnostics.LOGCAT_READ_TIMEOUT_MILLIS / 2;
return mBootTimeMs;
}
}).when(mClock).getElapsedSinceBootMillis();
mWifiDiagnostics = new WifiDiagnostics(
mContext, mWifiInjector, mWifiNative, mBuildProperties, mLastMileLogger, mClock);
mWifiNative.enableVerboseLogging(0);
}
/** Verifies that startLogging() registers a logging event handler. */
@Test
public void startLoggingRegistersLogEventHandler() throws Exception {
mWifiDiagnostics.enableVerboseLogging(false);
mWifiDiagnostics.startLogging(STA_IF_NAME);
verify(mWifiNative).setLoggingEventHandler(anyObject());
}
/**
* Verifies that a failure to set the logging event handler does not prevent a future
* startLogging() from setting the logging event handler.
*/
@Test
public void startLoggingRegistersLogEventHandlerIfPriorAttemptFailed()
throws Exception {
final boolean verbosityToggle = false; // even default mode registers handler
when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(false);
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
verify(mWifiNative).setLoggingEventHandler(anyObject());
mWifiDiagnostics.stopLogging(STA_IF_NAME);
reset(mWifiNative);
when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true);
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
verify(mWifiNative).setLoggingEventHandler(anyObject());
}
/** Verifies that startLogging() does not make redundant calls to setLoggingEventHandler(). */
@Test
public void startLoggingDoesNotRegisterLogEventHandlerIfPriorAttemptSucceeded()
throws Exception {
when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true);
mWifiDiagnostics.enableVerboseLogging(false);
mWifiDiagnostics.startLogging(STA_IF_NAME);
verify(mWifiNative).setLoggingEventHandler(anyObject());
reset(mWifiNative);
mWifiDiagnostics.enableVerboseLogging(false);
mWifiDiagnostics.startLogging(STA_IF_NAME);
verify(mWifiNative, never()).setLoggingEventHandler(anyObject());
}
/**
* Verifies that startLogging() restarts HAL ringbuffers.
*
* Specifically: verifies that startLogging()
* a) stops any ring buffer logging that might be already running,
* b) instructs WifiNative to enable ring buffers of the appropriate log level.
*/
@Test
public void startLoggingStopsAndRestartsRingBufferLoggingInVerboseMode() throws Exception {
final boolean verbosityToggle = true;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
verify(mWifiNative).startLoggingRingBuffer(
eq(WifiDiagnostics.VERBOSE_NO_LOG), anyInt(), anyInt(), anyInt(),
eq(FAKE_RING_BUFFER_NAME));
verify(mWifiNative).startLoggingRingBuffer(
eq(WifiDiagnostics.VERBOSE_LOG_WITH_WAKEUP), anyInt(), anyInt(), anyInt(),
eq(FAKE_RING_BUFFER_NAME));
}
@Test
public void startLoggingStopsAndThenStartRingBufferLoggingInNormalMode() throws Exception {
final boolean verbosityToggle = false;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
verify(mWifiNative).startLoggingRingBuffer(
eq(WifiDiagnostics.VERBOSE_NO_LOG), anyInt(), anyInt(), anyInt(),
eq(FAKE_RING_BUFFER_NAME));
verify(mWifiNative).startLoggingRingBuffer(
gt(WifiDiagnostics.VERBOSE_NO_LOG), anyInt(), anyInt(), anyInt(),
anyString());
}
/** Verifies that, if a log handler was registered, then stopLogging() resets it. */
@Test
public void stopLoggingResetsLogHandlerIfHandlerWasRegistered() throws Exception {
final boolean verbosityToggle = false; // even default mode registers handler
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true);
mWifiDiagnostics.startLogging(STA_IF_NAME);
reset(mWifiNative);
mWifiDiagnostics.stopLogging(STA_IF_NAME);
verify(mWifiNative).resetLogHandler();
}
/** Verifies that, if a log handler is not registered, stopLogging() skips resetLogHandler(). */
@Test
public void stopLoggingOnlyResetsLogHandlerIfHandlerWasRegistered() throws Exception {
mWifiDiagnostics.stopLogging(STA_IF_NAME);
verify(mWifiNative, never()).resetLogHandler();
}
/** Verifies that stopLogging() remembers that we've reset the log handler. */
@Test
public void multipleStopLoggingCallsOnlyResetLogHandlerOnce() throws Exception {
final boolean verbosityToggle = false; // even default mode registers handler
when(mWifiNative.setLoggingEventHandler(anyObject())).thenReturn(true);
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
reset(mWifiNative);
when(mWifiNative.resetLogHandler()).thenReturn(true);
mWifiDiagnostics.stopLogging(STA_IF_NAME);
verify(mWifiNative).resetLogHandler();
reset(mWifiNative);
mWifiDiagnostics.stopLogging(STA_IF_NAME);
verify(mWifiNative, never()).resetLogHandler();
}
/**
* Verifies that we capture ring-buffer data.
*/
@Test
public void canCaptureAndStoreRingBufferData() throws Exception {
final boolean verbosityToggle = false;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE];
mWifiDiagnostics.onRingBufferData(mFakeRbs, data);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
byte[][] ringBufferData = getLoggerRingBufferData();
assertEquals(1, ringBufferData.length);
assertArrayEquals(data, ringBufferData[0]);
}
/**
* Verifies that we discard extraneous ring-buffer data.
*/
@Ignore("TODO(b/36811399): re-enabled this @Test")
@Test
public void loggerDiscardsExtraneousData() throws Exception {
final boolean verbosityToggle = false;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
final byte[] data1 = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE];
final byte[] data2 = {1, 2, 3};
mWifiDiagnostics.onRingBufferData(mFakeRbs, data1);
mWifiDiagnostics.onRingBufferData(mFakeRbs, data2);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
byte[][] ringBufferData = getLoggerRingBufferData();
assertEquals(1, ringBufferData.length);
assertArrayEquals(data2, ringBufferData[0]);
}
// Verifies that startPktFateMonitoring(any()) reports failure to start packet fate
@Test
public void startPktFateMonitoringReportsStartFailures() {
when(mWifiNative.startPktFateMonitoring(any())).thenReturn(false);
mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
verify(mLog).wC(contains("Failed"));
}
/**
* Verifies that, when verbose mode is not enabled,
* reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED) still fetches packet fates.
*/
@Test
public void reportConnectionFailureIsIgnoredWithoutVerboseMode() {
final boolean verbosityToggle = false;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
verify(mWifiNative).getTxPktFates(any(), anyObject());
verify(mWifiNative).getRxPktFates(any(), anyObject());
}
/**
* Verifies that, when verbose mode is enabled, reportConnectionFailure() fetches packet fates.
*/
@Test
public void reportConnectionFailureFetchesFatesInVerboseMode() {
final boolean verbosityToggle = true;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
verify(mWifiNative).getTxPktFates(any(), anyObject());
verify(mWifiNative).getRxPktFates(any(), anyObject());
}
@Test
public void reportConnectionEventPropagatesStartToLastMileLogger() {
final boolean verbosityToggle = false;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_STARTED);
verify(mLastMileLogger).reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_STARTED);
}
@Test
public void reportConnectionEventPropagatesSuccessToLastMileLogger() {
final boolean verbosityToggle = false;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED);
verify(mLastMileLogger).reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_SUCCEEDED);
}
@Test
public void reportConnectionEventPropagatesFailureToLastMileLogger() {
final boolean verbosityToggle = false;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
verify(mLastMileLogger).reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
}
/**
* Verifies that we are propagating the CONNECTION_EVENT_TIMEOUT event to LastMileLogger.
*/
@Test
public void reportConnectionEventPropagatesTimeoutToLastMileLogger() {
final boolean verbosityToggle = true;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_TIMEOUT);
verify(mLastMileLogger).reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_TIMEOUT);
}
/**
* Verifies that we try to fetch TX fates, even if fetching RX fates failed.
*/
@Test
public void loggerFetchesTxFatesEvenIfFetchingRxFatesFails() {
final boolean verbosityToggle = true;
when(mWifiNative.getRxPktFates(any(), anyObject())).thenReturn(false);
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
verify(mWifiNative).getTxPktFates(any(), anyObject());
verify(mWifiNative).getRxPktFates(any(), anyObject());
}
/**
* Verifies that we try to fetch RX fates, even if fetching TX fates failed.
*/
@Test
public void loggerFetchesRxFatesEvenIfFetchingTxFatesFails() {
final boolean verbosityToggle = true;
when(mWifiNative.getTxPktFates(any(), anyObject())).thenReturn(false);
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
verify(mWifiNative).getTxPktFates(any(), anyObject());
verify(mWifiNative).getRxPktFates(any(), anyObject());
}
/** Verifies that dump() fetches the latest fates. */
@Test
public void dumpFetchesFates() {
final boolean verbosityToggle = false;
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"});
verify(mWifiNative).getTxPktFates(any(), anyObject());
verify(mWifiNative).getRxPktFates(any(), anyObject());
}
/**
* Verifies that dump() doesn't crash, or generate garbage, in the case where we haven't fetched
* any fates.
*/
@Test
public void dumpSucceedsWhenNoFatesHaveNotBeenFetched() {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"});
String fateDumpString = sw.toString();
assertTrue(fateDumpString.contains("Last failed"));
// Verify dump terminator is present
assertTrue(fateDumpString.contains(
"--------------------------------------------------------------------"));
}
/**
* Verifies that dump() doesn't crash, or generate garbage, in the case where the fates that
* the HAL-provided fates are empty.
*/
@Test
public void dumpSucceedsWhenFatesHaveBeenFetchedButAreEmpty() {
final boolean verbosityToggle = true;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
verify(mWifiNative).getTxPktFates(any(), anyObject());
verify(mWifiNative).getRxPktFates(any(), anyObject());
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"});
String fateDumpString = sw.toString();
assertTrue(fateDumpString.contains("Last failed"));
// Verify dump terminator is present
assertTrue(fateDumpString.contains(
"--------------------------------------------------------------------"));
}
private String getDumpString(boolean verbose) {
mWifiDiagnostics.enableVerboseLogging(verbose);
mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiNative.enableVerboseLogging(verbose ? 1 : 0);
when(mWifiNative.getTxPktFates(any(), anyObject())).then(new AnswerWithArguments() {
public boolean answer(String ifaceName, WifiNative.TxFateReport[] fates) {
fates[0] = new WifiNative.TxFateReport(
WifiLoggerHal.TX_PKT_FATE_ACKED, 2, WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
new byte[0]
);
fates[1] = new WifiNative.TxFateReport(
WifiLoggerHal.TX_PKT_FATE_ACKED, 0, WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
new byte[0]
);
return true;
}
});
when(mWifiNative.getRxPktFates(any(), anyObject())).then(new AnswerWithArguments() {
public boolean answer(String ifaceName, WifiNative.RxFateReport[] fates) {
fates[0] = new WifiNative.RxFateReport(
WifiLoggerHal.RX_PKT_FATE_SUCCESS, 3, WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
new byte[0]
);
fates[1] = new WifiNative.RxFateReport(
WifiLoggerHal.RX_PKT_FATE_SUCCESS, 1, WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
new byte[0]
);
return true;
}
});
mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"});
return sw.toString();
}
/**
* Verifies that dump() shows both TX, and RX fates in only table form, when verbose
* logging is not enabled.
*/
@Test
public void dumpShowsTxAndRxFates() {
final boolean verbosityToggle = false;
String dumpString = getDumpString(verbosityToggle);
assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader()));
assertTrue(Pattern.compile("0 .* TX ").matcher(dumpString).find());
assertTrue(Pattern.compile("1 .* RX ").matcher(dumpString).find());
assertTrue(Pattern.compile("2 .* TX ").matcher(dumpString).find());
assertTrue(Pattern.compile("3 .* RX ").matcher(dumpString).find());
assertFalse(dumpString.contains("VERBOSE PACKET FATE DUMP"));
assertFalse(dumpString.contains("Frame bytes"));
}
/**
* Verifies that dump() shows both TX, and RX fates in table and verbose forms, when verbose
* logging is enabled.
*/
@Test
public void dumpShowsTxAndRxFatesVerbose() {
final boolean verbosityToggle = true;
String dumpString = getDumpString(verbosityToggle);
assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader()));
assertTrue(Pattern.compile("0 .* TX ").matcher(dumpString).find());
assertTrue(Pattern.compile("1 .* RX ").matcher(dumpString).find());
assertTrue(Pattern.compile("2 .* TX ").matcher(dumpString).find());
assertTrue(Pattern.compile("3 .* RX ").matcher(dumpString).find());
assertTrue(dumpString.contains("VERBOSE PACKET FATE DUMP"));
assertTrue(dumpString.contains("Frame bytes"));
}
/**
* Verifies that dump() outputs frames in timestamp order, even though the HAL provided the
* data out-of-order (order is specified in getDumpString()).
*/
@Test
public void dumpIsSortedByTimestamp() {
final boolean verbosityToggle = true;
String dumpString = getDumpString(verbosityToggle);
assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader()));
assertTrue(Pattern.compile(
"0 .* TX .*\n" +
"1 .* RX .*\n" +
"2 .* TX .*\n" +
"3 .* RX "
).matcher(dumpString).find());
int expected_index_of_verbose_frame_0 = dumpString.indexOf(
"Frame direction: TX\nFrame timestamp: 0\n");
int expected_index_of_verbose_frame_1 = dumpString.indexOf(
"Frame direction: RX\nFrame timestamp: 1\n");
int expected_index_of_verbose_frame_2 = dumpString.indexOf(
"Frame direction: TX\nFrame timestamp: 2\n");
int expected_index_of_verbose_frame_3 = dumpString.indexOf(
"Frame direction: RX\nFrame timestamp: 3\n");
assertFalse(-1 == expected_index_of_verbose_frame_0);
assertFalse(-1 == expected_index_of_verbose_frame_1);
assertFalse(-1 == expected_index_of_verbose_frame_2);
assertFalse(-1 == expected_index_of_verbose_frame_3);
assertTrue(expected_index_of_verbose_frame_0 < expected_index_of_verbose_frame_1);
assertTrue(expected_index_of_verbose_frame_1 < expected_index_of_verbose_frame_2);
assertTrue(expected_index_of_verbose_frame_2 < expected_index_of_verbose_frame_3);
}
/** Verifies that eng builds do not show fate detail outside of verbose mode. */
@Test
public void dumpOmitsFateDetailInEngBuildsOutsideOfVerboseMode() throws Exception {
final boolean verbosityToggle = false;
when(mBuildProperties.isEngBuild()).thenReturn(true);
when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
when(mBuildProperties.isUserBuild()).thenReturn(false);
String dumpString = getDumpString(verbosityToggle);
assertFalse(dumpString.contains("VERBOSE PACKET FATE DUMP"));
assertFalse(dumpString.contains("Frame bytes"));
}
/** Verifies that userdebug builds do not show fate detail outside of verbose mode. */
@Test
public void dumpOmitsFateDetailInUserdebugBuildsOutsideOfVerboseMode() throws Exception {
final boolean verbosityToggle = false;
when(mBuildProperties.isUserdebugBuild()).thenReturn(true);
when(mBuildProperties.isEngBuild()).thenReturn(false);
when(mBuildProperties.isUserBuild()).thenReturn(false);
String dumpString = getDumpString(verbosityToggle);
assertFalse(dumpString.contains("VERBOSE PACKET FATE DUMP"));
assertFalse(dumpString.contains("Frame bytes"));
}
/**
* Verifies that, if verbose is disabled after fetching fates, the dump does not include
* verbose fate logs.
*/
@Test
public void dumpOmitsFatesIfVerboseIsDisabledAfterFetch() {
final boolean verbosityToggle = true;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startPktFateMonitoring(STA_IF_NAME);
when(mWifiNative.getTxPktFates(any(), anyObject())).then(new AnswerWithArguments() {
public boolean answer(String ifaceName, WifiNative.TxFateReport[] fates) {
fates[0] = new WifiNative.TxFateReport(
WifiLoggerHal.TX_PKT_FATE_ACKED, 0, WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
new byte[0]
);
return true;
}
});
when(mWifiNative.getRxPktFates(any(), anyObject())).then(new AnswerWithArguments() {
public boolean answer(String ifaceName, WifiNative.RxFateReport[] fates) {
fates[0] = new WifiNative.RxFateReport(
WifiLoggerHal.RX_PKT_FATE_SUCCESS, 1, WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
new byte[0]
);
return true;
}
});
mWifiDiagnostics.reportConnectionEvent(WifiDiagnostics.CONNECTION_EVENT_FAILED);
verify(mWifiNative).getTxPktFates(any(), anyObject());
verify(mWifiNative).getRxPktFates(any(), anyObject());
final boolean newVerbosityToggle = false;
mWifiDiagnostics.enableVerboseLogging(newVerbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"});
String fateDumpString = sw.toString();
assertFalse(fateDumpString.contains("VERBOSE PACKET FATE DUMP"));
assertFalse(fateDumpString.contains("Frame bytes"));
}
/** Verifies that the default size of our ring buffers is small. */
@Ignore("TODO(b/36811399): re-enable this @Test")
@Test
public void ringBufferSizeIsSmallByDefault() throws Exception {
final boolean verbosityToggle = false;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.onRingBufferData(
mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
assertEquals(0, getLoggerRingBufferData().length);
}
/** Verifies that we use small ring buffers by default, on userdebug builds. */
@Ignore("TODO(b/36811399): re-enable this @Test")
@Test
public void ringBufferSizeIsSmallByDefaultOnUserdebugBuilds() throws Exception {
final boolean verbosityToggle = false;
when(mBuildProperties.isUserdebugBuild()).thenReturn(true);
when(mBuildProperties.isEngBuild()).thenReturn(false);
when(mBuildProperties.isUserBuild()).thenReturn(false);
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.onRingBufferData(
mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
assertEquals(0, getLoggerRingBufferData().length);
}
/** Verifies that we use small ring buffers by default, on eng builds. */
@Ignore("TODO(b/36811399): re-enable this @Test")
@Test
public void ringBufferSizeIsSmallByDefaultOnEngBuilds() throws Exception {
final boolean verbosityToggle = false;
when(mBuildProperties.isEngBuild()).thenReturn(true);
when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
when(mBuildProperties.isUserBuild()).thenReturn(false);
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.onRingBufferData(
mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
assertEquals(0, getLoggerRingBufferData().length);
}
/** Verifies that we use large ring buffers when initially started in verbose mode. */
@Test
public void ringBufferSizeIsLargeInVerboseMode() throws Exception {
final boolean verbosityToggle = true;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.onRingBufferData(
mFakeRbs, new byte[LARGE_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
assertEquals(1, getLoggerRingBufferData().length);
}
/** Verifies that we use large ring buffers when switched from normal to verbose mode. */
@Test
public void startLoggingGrowsRingBuffersIfNeeded() throws Exception {
mWifiDiagnostics.enableVerboseLogging(false /* verbose disabled */);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.onRingBufferData(
mFakeRbs, new byte[LARGE_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE]);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
assertEquals(1, getLoggerRingBufferData().length);
}
/** Verifies that we use small ring buffers when switched from verbose to normal mode. */
@Ignore("TODO(b/36811399): re-enabled this @Test")
@Test
public void startLoggingShrinksRingBuffersIfNeeded() throws Exception {
mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.onRingBufferData(
mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]);
// Existing data is nuked (too large).
mWifiDiagnostics.enableVerboseLogging(false /* verbose disabled */);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
assertEquals(0, getLoggerRingBufferData().length);
// New data must obey limit as well.
mWifiDiagnostics.onRingBufferData(
mFakeRbs, new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE + 1]);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
assertEquals(0, getLoggerRingBufferData().length);
}
/**
* Verifies that we capture a bugreport & store alert data when WifiNative invokes
* the alert callback.
*/
@Test
public void onWifiAlertCapturesBugreportAndLogsMetrics() throws Exception {
mWifiDiagnostics.onWifiAlert(ALERT_REASON_CODE, ALERT_DATA);
assertEquals(1, mWifiDiagnostics.getAlertReports().size());
WifiDiagnostics.BugReport alertReport = mWifiDiagnostics.getAlertReports().get(0);
assertEquals(ALERT_REASON_CODE, alertReport.errorCode);
assertArrayEquals(ALERT_DATA, alertReport.alertData);
verify(mWifiMetrics).logFirmwareAlert(ALERT_REASON_CODE);
verify(mWifiScoreCard).noteFirmwareAlert(ALERT_REASON_CODE);
}
/** Verifies that we skip the firmware and driver dumps if verbose is not enabled. */
@Test
public void captureBugReportSkipsFirmwareAndDriverDumpsByDefault() {
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
verify(mWifiNative, never()).getFwMemoryDump();
verify(mWifiNative, never()).getDriverStateDump();
}
/** Verifies that we capture the firmware and driver dumps if verbose is enabled. */
@Test
public void captureBugReportTakesFirmwareAndDriverDumpsInVerboseMode() {
mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
verify(mWifiNative).getFwMemoryDump();
verify(mWifiNative).getDriverStateDump();
}
/** Verifies that the dump includes driver state, if driver state was provided by HAL. */
@Test
public void dumpIncludesDriverStateDumpIfAvailable() {
when(mWifiNative.getDriverStateDump()).thenReturn(new byte[]{0, 1, 2});
mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
verify(mWifiNative).getDriverStateDump();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{});
assertTrue(sw.toString().contains(WifiDiagnostics.DRIVER_DUMP_SECTION_HEADER));
}
/** Verifies that the dump skips driver state, if driver state was not provided by HAL. */
@Test
public void dumpOmitsDriverStateDumpIfUnavailable() {
mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
verify(mWifiNative).getDriverStateDump();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{});
assertFalse(sw.toString().contains(WifiDiagnostics.DRIVER_DUMP_SECTION_HEADER));
}
/** Verifies that the dump omits driver state, if verbose was disabled after capture. */
@Test
public void dumpOmitsDriverStateDumpIfVerboseDisabledAfterCapture() {
when(mWifiNative.getDriverStateDump()).thenReturn(new byte[]{0, 1, 2});
mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
verify(mWifiNative).getDriverStateDump();
mWifiDiagnostics.enableVerboseLogging(false /* verbose disabled */);
mWifiDiagnostics.startLogging(STA_IF_NAME);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{});
assertFalse(sw.toString().contains(WifiDiagnostics.DRIVER_DUMP_SECTION_HEADER));
}
/** Verifies that the dump includes firmware dump, if firmware dump was provided by HAL. */
@Test
public void dumpIncludesFirmwareMemoryDumpIfAvailable() {
when(mWifiNative.getFwMemoryDump()).thenReturn(new byte[]{0, 1, 2});
mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
verify(mWifiNative).getFwMemoryDump();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{});
assertTrue(sw.toString().contains(WifiDiagnostics.FIRMWARE_DUMP_SECTION_HEADER));
}
/** Verifies that the dump skips firmware memory, if firmware memory was not provided by HAL. */
@Test
public void dumpOmitsFirmwareMemoryDumpIfUnavailable() {
mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
verify(mWifiNative).getFwMemoryDump();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{});
assertFalse(sw.toString().contains(WifiDiagnostics.FIRMWARE_DUMP_SECTION_HEADER));
}
/** Verifies that the dump omits firmware memory, if verbose was disabled after capture. */
@Test
public void dumpOmitsFirmwareMemoryDumpIfVerboseDisabledAfterCapture() {
when(mWifiNative.getFwMemoryDump()).thenReturn(new byte[]{0, 1, 2});
mWifiDiagnostics.enableVerboseLogging(true /* verbose enabled */);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
verify(mWifiNative).getFwMemoryDump();
mWifiDiagnostics.enableVerboseLogging(false /* verbose disabled */);
mWifiDiagnostics.startLogging(STA_IF_NAME);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
mWifiDiagnostics.dump(new FileDescriptor(), pw, new String[]{});
assertFalse(sw.toString().contains(WifiDiagnostics.FIRMWARE_DUMP_SECTION_HEADER));
}
@Test
public void dumpRequestsLastMileLoggerDump() {
mWifiDiagnostics.dump(
new FileDescriptor(), new PrintWriter(new StringWriter()), new String[]{});
verify(mLastMileLogger).dump(anyObject());
}
@Test
public void takeBugReportCallsActivityManagerOnUserDebug() {
when(mBuildProperties.isUserBuild()).thenReturn(false);
mWifiDiagnostics.takeBugReport("", "");
verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any());
}
@Test
public void takeBugReportSwallowsExceptions() {
when(mBuildProperties.isUserBuild()).thenReturn(false);
doThrow(new RuntimeException()).when(mBugreportManager).requestBugreport(
any(), any(), any());
mWifiDiagnostics.takeBugReport("", "");
verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any());
}
@Test
public void takeBugReportDoesNothingOnUserBuild() {
when(mBuildProperties.isUserBuild()).thenReturn(true);
mWifiDiagnostics.takeBugReport("", "");
verify(mBugreportManager, never()).requestBugreport(any(), any(), any());
}
@Test
public void tryTakeBugReportTwiceWithInsufficientTimeGap() {
when(mBuildProperties.isUserBuild()).thenReturn(false);
// 1st attempt should succeed
when(mClock.getWallClockMillis()).thenReturn(10L);
mWifiDiagnostics.takeBugReport("", "");
verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any());
// 2nd attempt should fail
when(mClock.getWallClockMillis()).thenReturn(BUG_REPORT_MIN_WINDOW_MS - 20L);
mWifiDiagnostics.takeBugReport("", "");
verify(mBugreportManager, times(1)).requestBugreport(any(), any(), any());
}
@Test
public void takeBugReportDoesNothingWhenConfigOverlayDisabled() {
when(mBuildProperties.isUserBuild()).thenReturn(false);
mResources.setBoolean(R.bool.config_wifi_diagnostics_bugreport_enabled, false);
mWifiDiagnostics = new WifiDiagnostics(
mContext, mWifiInjector, mWifiNative, mBuildProperties, mLastMileLogger, mClock);
mWifiDiagnostics.takeBugReport("", "");
verify(mBugreportManager, never()).requestBugreport(any(), any(), any());
}
/** Verifies that we flush HAL ringbuffer when capture bugreport. */
@Test
public void captureBugReportFlushRingBufferData() {
when(mBuildProperties.isUserBuild()).thenReturn(false);
when(mWifiNative.flushRingBufferData()).thenReturn(true);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
verify(mWifiNative).flushRingBufferData();
}
/** Verifies that we flush HAL ringbuffer when detecting fatal firmware alert. */
@Test
public void captureAlertFlushRingBufferData() {
when(mBuildProperties.isUserBuild()).thenReturn(false);
when(mWifiNative.flushRingBufferData()).thenReturn(true);
/** captureAlertData with mock fatal firmware alert*/
mWifiDiagnostics.captureAlertData(FATAL_FW_ALERT_LIST[0], ALERT_DATA);
verify(mWifiNative).flushRingBufferData();
}
/** Verifies that we don't flush HAL ringbuffer when detecting non fatal firmware alert. */
@Test
public void captureNonAlertFlushRingBufferData() {
when(mBuildProperties.isUserBuild()).thenReturn(false);
when(mWifiNative.flushRingBufferData()).thenReturn(true);
/** captureAlertData with mock non fatal firmware alert*/
mWifiDiagnostics.captureAlertData(NON_FATAL_FW_ALERT, ALERT_DATA);
verify(mWifiNative, never()).flushRingBufferData();
}
/**
* Verifies that we can capture ring-buffer data in SoftAp mode
*/
@Test
public void canCaptureAndStoreRingBufferDataInSoftApMode() throws Exception {
final boolean verbosityToggle = false;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(AP_IF_NAME);
final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE];
mWifiDiagnostics.onRingBufferData(mFakeRbs, data);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
byte[][] ringBufferData = getLoggerRingBufferData();
assertEquals(1, ringBufferData.length);
assertArrayEquals(data, ringBufferData[0]);
}
/**
* Verifies that we capture ring-buffer data in Station + SoftAp
* Concurrency mode.
*/
@Test
public void canCaptureAndStoreRingBufferDataInConcurrencyMode() throws Exception {
final boolean verbosityToggle = false;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.startLogging(AP_IF_NAME);
final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE];
mWifiDiagnostics.onRingBufferData(mFakeRbs, data);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
byte[][] ringBufferData = getLoggerRingBufferData();
assertEquals(1, ringBufferData.length);
assertArrayEquals(data, ringBufferData[0]);
}
/**
* Verifies that we can continue to capture ring-buffer data
* after WiFi station is turned off in concurrency mode.
*/
@Test
public void canCaptureAndStoreRingBufferDataAfterStaIsTurnedOffInConcurrencyMode()
throws Exception {
final boolean verbosityToggle = false;
final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE];
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.startLogging(AP_IF_NAME);
mWifiDiagnostics.onRingBufferData(mFakeRbs, data);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
byte[][] ringBufferData0 = getLoggerRingBufferData();
assertEquals(1, ringBufferData0.length);
assertArrayEquals(data, ringBufferData0[0]);
mWifiDiagnostics.stopLogging(STA_IF_NAME);
mWifiDiagnostics.onRingBufferData(mFakeRbs, data);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
byte[][] ringBufferData1 = getLoggerRingBufferData();
assertEquals(1, ringBufferData1.length);
assertArrayEquals(data, ringBufferData1[0]);
}
/**
* Verifies that we can continue to capture ring-buffer data
* after SoftAp is turned off in concurrency mode.
*/
@Test
public void canCaptureAndStoreRingBufferDataAfterSoftApIsTurnedOffInConcurrencyMode()
throws Exception {
final boolean verbosityToggle = false;
final byte[] data = new byte[SMALL_RING_BUFFER_SIZE_KB * BYTES_PER_KBYTE];
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
mWifiDiagnostics.startLogging(STA_IF_NAME);
mWifiDiagnostics.startLogging(AP_IF_NAME);
mWifiDiagnostics.onRingBufferData(mFakeRbs, data);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
byte[][] ringBufferData0 = getLoggerRingBufferData();
assertEquals(1, ringBufferData0.length);
assertArrayEquals(data, ringBufferData0[0]);
mWifiDiagnostics.stopLogging(AP_IF_NAME);
mWifiDiagnostics.onRingBufferData(mFakeRbs, data);
mWifiDiagnostics.captureBugReportData(WifiDiagnostics.REPORT_REASON_NONE);
byte[][] ringBufferData1 = getLoggerRingBufferData();
assertEquals(1, ringBufferData1.length);
assertArrayEquals(data, ringBufferData1[0]);
}
/** Verifies that stoplogging on both the interfaces clean up
* all the resources.
*/
@Test
public void verifyStopLoggingOnAllInterfacesClearTheResources() throws Exception {
final boolean verbosityToggle = false;
mWifiDiagnostics.enableVerboseLogging(verbosityToggle);
when(mWifiNative.setLoggingEventHandler(any())).thenReturn(true);
when(mWifiNative.resetLogHandler()).thenReturn(true);
mWifiDiagnostics.startLogging(STA_IF_NAME);
verify(mWifiNative).setLoggingEventHandler(any());
mWifiDiagnostics.startLogging(AP_IF_NAME);
mWifiDiagnostics.stopLogging(STA_IF_NAME);
verify(mWifiNative, never()).resetLogHandler();
mWifiDiagnostics.stopLogging(AP_IF_NAME);
verify(mWifiNative).resetLogHandler();
}
}