summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/WifiLogger.java38
-rw-r--r--service/java/com/android/server/wifi/WifiLoggerHal.java52
-rw-r--r--service/java/com/android/server/wifi/WifiNative.java30
-rw-r--r--service/java/com/android/server/wifi/util/FrameParser.java531
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiLoggerTest.java147
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java322
-rw-r--r--tests/wifitests/src/com/android/server/wifi/util/FrameParserTest.java160
7 files changed, 1062 insertions, 218 deletions
diff --git a/service/java/com/android/server/wifi/WifiLogger.java b/service/java/com/android/server/wifi/WifiLogger.java
index 6d7b608a8..047794f98 100644
--- a/service/java/com/android/server/wifi/WifiLogger.java
+++ b/service/java/com/android/server/wifi/WifiLogger.java
@@ -29,6 +29,7 @@ import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
+import java.lang.StringBuilder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Calendar;
@@ -137,7 +138,7 @@ class WifiLogger extends BaseWifiLogger {
startLoggingAllExceptPerPacketBuffers();
}
- if (verboseEnabled && !mWifiNative.startPktFateMonitoring()) {
+ if (!mWifiNative.startPktFateMonitoring()) {
Log.e(TAG, "Failed to start packet fate monitoring");
}
}
@@ -178,10 +179,6 @@ class WifiLogger extends BaseWifiLogger {
@Override
synchronized void reportConnectionFailure() {
- if (!isVerboseLoggingEnabled()) {
- return;
- }
-
mPacketFatesForLastFailure = fetchPacketFates();
}
@@ -631,14 +628,16 @@ class WifiLogger extends BaseWifiLogger {
}
private void dumpPacketFates(PrintWriter pw) {
- dumpPacketFatesInternal(pw, "Last failed connection fates", mPacketFatesForLastFailure);
+ dumpPacketFatesInternal(pw, "Last failed connection fates", mPacketFatesForLastFailure,
+ isVerboseLoggingEnabled());
if (DBG) {
- dumpPacketFatesInternal(pw, "Latest fates", fetchPacketFates());
+ dumpPacketFatesInternal(pw, "Latest fates", fetchPacketFates(),
+ isVerboseLoggingEnabled());
}
}
- private static void dumpPacketFatesInternal(
- PrintWriter pw, String description, ArrayList<WifiNative.FateReport> fates) {
+ private static void dumpPacketFatesInternal(PrintWriter pw, String description,
+ ArrayList<WifiNative.FateReport> fates, boolean verbose) {
if (fates == null) {
pw.format("No fates fetched for \"%s\"\n", description);
return;
@@ -649,14 +648,25 @@ class WifiLogger extends BaseWifiLogger {
return;
}
- int i = 0;
pw.format("--------------------- %s ----------------------\n", description);
+
+ StringBuilder verboseOutput = new StringBuilder();
+ pw.print(WifiNative.FateReport.getTableHeader());
for (WifiNative.FateReport fate : fates) {
- pw.format("Frame number: %d\n", i + 1);
- pw.print(fate);
- pw.print("\n");
- ++i;
+ pw.print(fate.toTableRowString());
+ if (verbose) {
+ // Important: only print Personally Identifiable Information (PII) if verbose
+ // logging is turned on.
+ verboseOutput.append(fate.toVerboseStringWithPiiAllowed());
+ verboseOutput.append("\n");
+ }
+ }
+
+ if (verbose) {
+ pw.format("\n>>> VERBOSE PACKET FATE DUMP <<<\n\n");
+ pw.print(verboseOutput.toString());
}
+
pw.println("--------------------------------------------------------------------");
}
}
diff --git a/service/java/com/android/server/wifi/WifiLoggerHal.java b/service/java/com/android/server/wifi/WifiLoggerHal.java
index 1d542b87d..ce3640182 100644
--- a/service/java/com/android/server/wifi/WifiLoggerHal.java
+++ b/service/java/com/android/server/wifi/WifiLoggerHal.java
@@ -16,34 +16,34 @@
package com.android.server.wifi;
-class WifiLoggerHal {
+public class WifiLoggerHal {
// Must match wifi_logger.h
- static final int MAX_FATE_LOG_LEN = 32;
+ public static final int MAX_FATE_LOG_LEN = 32;
- static final byte FRAME_TYPE_UNKNOWN = 0;
- static final byte FRAME_TYPE_ETHERNET_II = 1;
- static final byte FRAME_TYPE_80211_MGMT = 2;
+ public static final byte FRAME_TYPE_UNKNOWN = 0;
+ public static final byte FRAME_TYPE_ETHERNET_II = 1;
+ public static final byte FRAME_TYPE_80211_MGMT = 2;
- static final byte TX_PKT_FATE_ACKED = 0;
- static final byte TX_PKT_FATE_SENT = 1;
- static final byte TX_PKT_FATE_FW_QUEUED = 2;
- static final byte TX_PKT_FATE_FW_DROP_INVALID = 3;
- static final byte TX_PKT_FATE_FW_DROP_NOBUFS = 4;
- static final byte TX_PKT_FATE_FW_DROP_OTHER = 5;
- static final byte TX_PKT_FATE_DRV_QUEUED = 6;
- static final byte TX_PKT_FATE_DRV_DROP_INVALID = 7;
- static final byte TX_PKT_FATE_DRV_DROP_NOBUFS = 9;
- static final byte TX_PKT_FATE_DRV_DROP_OTHER = 10;
+ public static final byte TX_PKT_FATE_ACKED = 0;
+ public static final byte TX_PKT_FATE_SENT = 1;
+ public static final byte TX_PKT_FATE_FW_QUEUED = 2;
+ public static final byte TX_PKT_FATE_FW_DROP_INVALID = 3;
+ public static final byte TX_PKT_FATE_FW_DROP_NOBUFS = 4;
+ public static final byte TX_PKT_FATE_FW_DROP_OTHER = 5;
+ public static final byte TX_PKT_FATE_DRV_QUEUED = 6;
+ public static final byte TX_PKT_FATE_DRV_DROP_INVALID = 7;
+ public static final byte TX_PKT_FATE_DRV_DROP_NOBUFS = 9;
+ public static final byte TX_PKT_FATE_DRV_DROP_OTHER = 10;
- static final byte RX_PKT_FATE_SUCCESS = 0;
- static final byte RX_PKT_FATE_FW_QUEUED = 1;
- static final byte RX_PKT_FATE_FW_DROP_FILTER = 2;
- static final byte RX_PKT_FATE_FW_DROP_INVALID = 3;
- static final byte RX_PKT_FATE_FW_DROP_NOBUFS = 4;
- static final byte RX_PKT_FATE_FW_DROP_OTHER = 5;
- static final byte RX_PKT_FATE_DRV_QUEUED = 6;
- static final byte RX_PKT_FATE_DRV_DROP_FILTER = 7;
- static final byte RX_PKT_FATE_DRV_DROP_INVALID = 8;
- static final byte RX_PKT_FATE_DRV_DROP_NOBUFS = 9;
- static final byte RX_PKT_FATE_DRV_DROP_OTHER = 10;
+ public static final byte RX_PKT_FATE_SUCCESS = 0;
+ public static final byte RX_PKT_FATE_FW_QUEUED = 1;
+ public static final byte RX_PKT_FATE_FW_DROP_FILTER = 2;
+ public static final byte RX_PKT_FATE_FW_DROP_INVALID = 3;
+ public static final byte RX_PKT_FATE_FW_DROP_NOBUFS = 4;
+ public static final byte RX_PKT_FATE_FW_DROP_OTHER = 5;
+ public static final byte RX_PKT_FATE_DRV_QUEUED = 6;
+ public static final byte RX_PKT_FATE_DRV_DROP_FILTER = 7;
+ public static final byte RX_PKT_FATE_DRV_DROP_INVALID = 8;
+ public static final byte RX_PKT_FATE_DRV_DROP_NOBUFS = 9;
+ public static final byte RX_PKT_FATE_DRV_DROP_OTHER = 10;
}
diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java
index f6381b929..c07350d2f 100644
--- a/service/java/com/android/server/wifi/WifiNative.java
+++ b/service/java/com/android/server/wifi/WifiNative.java
@@ -50,6 +50,7 @@ import com.android.server.connectivity.KeepalivePacketData;
import com.android.server.wifi.hotspot2.NetworkDetail;
import com.android.server.wifi.hotspot2.SupplicantBridge;
import com.android.server.wifi.hotspot2.Utils;
+import com.android.server.wifi.util.FrameParser;
import com.android.server.wifi.util.InformationElementUtil;
import libcore.util.HexEncoding;
@@ -2638,21 +2639,44 @@ public class WifiNative {
mFrameBytes = frameBytes;
}
- @Override
- public String toString() {
+ public String toTableRowString() {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ FrameParser parser = new FrameParser(mFrameType, mFrameBytes);
+ pw.format("%-15s %-9s %-32s %-12s %s\n",
+ mDriverTimestampUSec, directionToString(), fateToString(),
+ parser.mMostSpecificProtocolString, parser.mTypeString);
+ return sw.toString();
+ }
+
+ public String toVerboseStringWithPiiAllowed() {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
+ FrameParser parser = new FrameParser(mFrameType, mFrameBytes);
pw.format("Frame direction: %s\n", directionToString());
pw.format("Frame timestamp: %d\n", mDriverTimestampUSec);
pw.format("Frame fate: %s\n", fateToString());
pw.format("Frame type: %s\n", frameTypeToString(mFrameType));
+ pw.format("Frame protocol: %s\n", parser.mMostSpecificProtocolString);
+ pw.format("Frame protocol type: %s\n", parser.mTypeString);
pw.format("Frame length: %d\n", mFrameBytes.length);
pw.append("Frame bytes");
- pw.append(HexDump.dumpHexString(mFrameBytes));
+ pw.append(HexDump.dumpHexString(mFrameBytes)); // potentially contains PII
pw.append("\n");
return sw.toString();
}
+ /* Returns a header to match the output of toTableRowString(). */
+ public static String getTableHeader() {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ pw.format("\n%-15s %-9s %-32s %-12s %s\n",
+ "Timestamp", "Direction", "Fate", "Protocol", "Type");
+ pw.format("%-15s %-9s %-32s %-12s %s\n",
+ "---------", "---------", "----", "--------", "----");
+ return sw.toString();
+ }
+
protected abstract String directionToString();
protected abstract String fateToString();
diff --git a/service/java/com/android/server/wifi/util/FrameParser.java b/service/java/com/android/server/wifi/util/FrameParser.java
new file mode 100644
index 000000000..165ebbb89
--- /dev/null
+++ b/service/java/com/android/server/wifi/util/FrameParser.java
@@ -0,0 +1,531 @@
+/*
+ * 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.util;
+
+import android.util.Log;
+
+import com.android.server.wifi.WifiLoggerHal;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * This class parses the raw bytes of a network frame, and stores the parsed information in its
+ * public fields.
+ */
+public class FrameParser {
+ /**
+ * Note: When adding constants derived from network protocol specifications, please encode
+ * these constants the same way as the relevant specification, for ease of comparison.
+ */
+
+ private static final String TAG = "FrameParser";
+
+ /* These fields hold the information parsed from this frame. */
+ public String mMostSpecificProtocolString = "N/A";
+ public String mTypeString = "N/A";
+
+ /**
+ * Parses the contents of a given network frame.
+ *
+ * @param frameType The type of the frame, as defined in
+ * {@link com.android.server.wifi.WifiLoggerHal}.
+ * @param frameBytes The raw bytes of the frame to be parsed.
+ */
+ public FrameParser(byte frameType, byte[] frameBytes) {
+ try {
+ ByteBuffer frameBuffer = ByteBuffer.wrap(frameBytes);
+ frameBuffer.order(ByteOrder.BIG_ENDIAN);
+ if (frameType == WifiLoggerHal.FRAME_TYPE_ETHERNET_II) {
+ parseEthernetFrame(frameBuffer);
+ } else if (frameType == WifiLoggerHal.FRAME_TYPE_80211_MGMT) {
+ parseManagementFrame(frameBuffer);
+ }
+ } catch (BufferUnderflowException | IllegalArgumentException e) {
+ Log.e(TAG, "Dissection aborted mid-frame: " + e);
+ }
+ }
+
+ /**
+ * Read one byte into a form that can easily be compared against, or output as, an integer
+ * in the range (0, 255).
+ */
+ private static short getUnsignedByte(ByteBuffer data) {
+ return (short) (data.get() & 0x00ff);
+ }
+ /**
+ * Read two bytes into a form that can easily be compared against, or output as, an integer
+ * in the range (0, 65535).
+ */
+ private static int getUnsignedShort(ByteBuffer data) {
+ return (data.getShort() & 0xffff);
+ }
+
+ private static final int ETHERNET_SRC_MAC_ADDR_LEN = 6;
+ private static final int ETHERNET_DST_MAC_ADDR_LEN = 6;
+ private static final short ETHERTYPE_IP_V4 = (short) 0x0800;
+ private static final short ETHERTYPE_ARP = (short) 0x0806;
+ private static final short ETHERTYPE_IP_V6 = (short) 0x86dd;
+ private static final short ETHERTYPE_EAPOL = (short) 0x888e;
+
+ private void parseEthernetFrame(ByteBuffer data) {
+ mMostSpecificProtocolString = "Ethernet";
+ data.position(data.position() + ETHERNET_SRC_MAC_ADDR_LEN + ETHERNET_DST_MAC_ADDR_LEN);
+ short etherType = data.getShort();
+ switch (etherType) {
+ case ETHERTYPE_IP_V4:
+ parseIpv4Packet(data);
+ return;
+ case ETHERTYPE_ARP:
+ parseArpPacket(data);
+ return;
+ case ETHERTYPE_IP_V6:
+ parseIpv6Packet(data);
+ return;
+ case ETHERTYPE_EAPOL:
+ parseEapolPacket(data);
+ return;
+ default:
+ return;
+ }
+ }
+
+ private static final byte IP_V4_VERSION_BYTE_MASK = (byte) 0b11110000;
+ private static final byte IP_V4_IHL_BYTE_MASK = (byte) 0b00001111;
+ private static final byte IP_V4_ADDR_LEN = 4;
+ private static final byte IP_V4_DSCP_AND_ECN_LEN = 1;
+ private static final byte IP_V4_TOTAL_LEN_LEN = 2;
+ private static final byte IP_V4_ID_LEN = 2;
+ private static final byte IP_V4_FLAGS_AND_FRAG_OFFSET_LEN = 2;
+ private static final byte IP_V4_TTL_LEN = 1;
+ private static final byte IP_V4_HEADER_CHECKSUM_LEN = 2;
+ private static final byte IP_V4_SRC_ADDR_LEN = 4;
+ private static final byte IP_V4_DST_ADDR_LEN = 4;
+ private static final byte IP_PROTO_ICMP = 1;
+ private static final byte IP_PROTO_TCP = 6;
+ private static final byte IP_PROTO_UDP = 17;
+ private static final byte BYTES_PER_QUAD = 4;
+
+ private void parseIpv4Packet(ByteBuffer data) {
+ mMostSpecificProtocolString = "IPv4";
+ data.mark();
+ byte versionAndHeaderLen = data.get();
+ int version = (versionAndHeaderLen & IP_V4_VERSION_BYTE_MASK) >> 4;
+ if (version != 4) {
+ Log.e(TAG, "IPv4 header: Unrecognized protocol version " + version);
+ return;
+ }
+
+ data.position(data.position() + IP_V4_DSCP_AND_ECN_LEN + IP_V4_TOTAL_LEN_LEN
+ + IP_V4_ID_LEN + IP_V4_FLAGS_AND_FRAG_OFFSET_LEN + IP_V4_TTL_LEN);
+ short protocolNumber = getUnsignedByte(data);
+ data.position(data.position() + IP_V4_HEADER_CHECKSUM_LEN + IP_V4_SRC_ADDR_LEN
+ + IP_V4_DST_ADDR_LEN);
+
+ int headerLen = (versionAndHeaderLen & IP_V4_IHL_BYTE_MASK) * BYTES_PER_QUAD;
+ data.reset(); // back to start of IPv4 header
+ data.position(data.position() + headerLen);
+
+ switch (protocolNumber) {
+ case IP_PROTO_ICMP:
+ parseIcmpPacket(data);
+ break;
+ case IP_PROTO_TCP:
+ parseTcpPacket(data);
+ break;
+ case IP_PROTO_UDP:
+ parseUdpPacket(data);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private static final byte TCP_SRC_PORT_LEN = 2;
+ private static final int HTTPS_PORT = 443;
+ private static final Set<Integer> HTTP_PORTS = new HashSet<>();
+ static {
+ HTTP_PORTS.add(80);
+ HTTP_PORTS.add(3128);
+ HTTP_PORTS.add(3132);
+ HTTP_PORTS.add(5985);
+ HTTP_PORTS.add(8080);
+ HTTP_PORTS.add(8088);
+ HTTP_PORTS.add(11371);
+ HTTP_PORTS.add(1900);
+ HTTP_PORTS.add(2869);
+ HTTP_PORTS.add(2710);
+ }
+
+ private void parseTcpPacket(ByteBuffer data) {
+ mMostSpecificProtocolString = "TCP";
+ data.position(data.position() + TCP_SRC_PORT_LEN);
+ int dstPort = getUnsignedShort(data);
+
+ if (dstPort == HTTPS_PORT) {
+ mTypeString = "HTTPS";
+ } else if (HTTP_PORTS.contains(dstPort)) {
+ mTypeString = "HTTP";
+ }
+ }
+
+ private static final byte UDP_PORT_BOOTPS = 67;
+ private static final byte UDP_PORT_BOOTPC = 68;
+ private static final byte UDP_PORT_NTP = 123;
+ private static final byte UDP_CHECKSUM_LEN = 2;
+
+ private void parseUdpPacket(ByteBuffer data) {
+ mMostSpecificProtocolString = "UDP";
+ int srcPort = getUnsignedShort(data);
+ int dstPort = getUnsignedShort(data);
+ int length = getUnsignedShort(data);
+
+ data.position(data.position() + UDP_CHECKSUM_LEN);
+ if ((srcPort == UDP_PORT_BOOTPC && dstPort == UDP_PORT_BOOTPS)
+ || (srcPort == UDP_PORT_BOOTPS && dstPort == UDP_PORT_BOOTPC)) {
+ parseDhcpPacket(data);
+ return;
+ }
+ if (srcPort == UDP_PORT_NTP || dstPort == UDP_PORT_NTP) {
+ mMostSpecificProtocolString = "NTP";
+ return;
+ }
+ }
+
+ private static final byte BOOTP_OPCODE_LEN = 1;
+ private static final byte BOOTP_HWTYPE_LEN = 1;
+ private static final byte BOOTP_HWADDR_LEN_LEN = 1;
+ private static final byte BOOTP_HOPCOUNT_LEN = 1;
+ private static final byte BOOTP_TRANSACTION_ID_LEN = 4;
+ private static final byte BOOTP_ELAPSED_SECONDS_LEN = 2;
+ private static final byte BOOTP_FLAGS_LEN = 2;
+ private static final byte BOOTP_CLIENT_HWADDR_LEN = 16;
+ private static final byte BOOTP_SERVER_HOSTNAME_LEN = 64;
+ private static final short BOOTP_BOOT_FILENAME_LEN = 128;
+ private static final byte BOOTP_MAGIC_COOKIE_LEN = 4;
+ private static final short DHCP_OPTION_TAG_PAD = 0;
+ private static final short DHCP_OPTION_TAG_MESSAGE_TYPE = 53;
+ private static final short DHCP_OPTION_TAG_END = 255;
+
+ private void parseDhcpPacket(ByteBuffer data) {
+ mMostSpecificProtocolString = "DHCP";
+ data.position(data.position() + BOOTP_OPCODE_LEN + BOOTP_HWTYPE_LEN + BOOTP_HWADDR_LEN_LEN
+ + BOOTP_HOPCOUNT_LEN + BOOTP_TRANSACTION_ID_LEN + BOOTP_ELAPSED_SECONDS_LEN
+ + BOOTP_FLAGS_LEN + IP_V4_ADDR_LEN * 4 + BOOTP_CLIENT_HWADDR_LEN
+ + BOOTP_SERVER_HOSTNAME_LEN + BOOTP_BOOT_FILENAME_LEN + BOOTP_MAGIC_COOKIE_LEN);
+ while (data.remaining() > 0) {
+ short dhcpOptionTag = getUnsignedByte(data);
+ if (dhcpOptionTag == DHCP_OPTION_TAG_PAD) {
+ continue;
+ }
+ if (dhcpOptionTag == DHCP_OPTION_TAG_END) {
+ break;
+ }
+ short dhcpOptionLen = getUnsignedByte(data);
+ switch (dhcpOptionTag) {
+ case DHCP_OPTION_TAG_MESSAGE_TYPE:
+ if (dhcpOptionLen != 1) {
+ Log.e(TAG, "DHCP option len: " + dhcpOptionLen + " (expected |1|)");
+ return;
+ }
+ mTypeString = decodeDhcpMessageType(getUnsignedByte(data));
+ return;
+ default:
+ data.position(data.position() + dhcpOptionLen);
+ }
+ }
+ }
+
+ private static final byte DHCP_MESSAGE_TYPE_DISCOVER = 1;
+ private static final byte DHCP_MESSAGE_TYPE_OFFER = 2;
+ private static final byte DHCP_MESSAGE_TYPE_REQUEST = 3;
+ private static final byte DHCP_MESSAGE_TYPE_DECLINE = 4;
+ private static final byte DHCP_MESSAGE_TYPE_ACK = 5;
+ private static final byte DHCP_MESSAGE_TYPE_NAK = 6;
+ private static final byte DHCP_MESSAGE_TYPE_RELEASE = 7;
+ private static final byte DHCP_MESSAGE_TYPE_INFORM = 8;
+
+ private static String decodeDhcpMessageType(short messageType) {
+ switch (messageType) {
+ case DHCP_MESSAGE_TYPE_DISCOVER:
+ return "Discover";
+ case DHCP_MESSAGE_TYPE_OFFER:
+ return "Offer";
+ case DHCP_MESSAGE_TYPE_REQUEST:
+ return "Request";
+ case DHCP_MESSAGE_TYPE_DECLINE:
+ return "Decline";
+ case DHCP_MESSAGE_TYPE_ACK:
+ return "Ack";
+ case DHCP_MESSAGE_TYPE_NAK:
+ return "Nak";
+ case DHCP_MESSAGE_TYPE_RELEASE:
+ return "Release";
+ case DHCP_MESSAGE_TYPE_INFORM:
+ return "Inform";
+ default:
+ return "Unknown type " + messageType;
+ }
+ }
+
+ private static final byte ICMP_TYPE_ECHO_REPLY = 0;
+ private static final byte ICMP_TYPE_DEST_UNREACHABLE = 3;
+ private static final byte ICMP_TYPE_REDIRECT = 5;
+ private static final byte ICMP_TYPE_ECHO_REQUEST = 8;
+
+ private void parseIcmpPacket(ByteBuffer data) {
+ mMostSpecificProtocolString = "ICMP";
+ short messageType = getUnsignedByte(data);
+ switch (messageType) {
+ case ICMP_TYPE_ECHO_REPLY:
+ mTypeString = "Echo Reply";
+ return;
+ case ICMP_TYPE_DEST_UNREACHABLE:
+ mTypeString = "Destination Unreachable";
+ return;
+ case ICMP_TYPE_REDIRECT:
+ mTypeString = "Redirect";
+ return;
+ case ICMP_TYPE_ECHO_REQUEST:
+ mTypeString = "Echo Request";
+ return;
+ default:
+ mTypeString = "Type " + messageType;
+ return;
+ }
+ }
+
+ private static final byte ARP_HWTYPE_LEN = 2;
+ private static final byte ARP_PROTOTYPE_LEN = 2;
+ private static final byte ARP_HWADDR_LEN_LEN = 1;
+ private static final byte ARP_PROTOADDR_LEN_LEN = 1;
+ private static final byte ARP_OPCODE_REQUEST = 1;
+ private static final byte ARP_OPCODE_REPLY = 2;
+
+ private void parseArpPacket(ByteBuffer data) {
+ mMostSpecificProtocolString = "ARP";
+ data.position(data.position() + ARP_HWTYPE_LEN + ARP_PROTOTYPE_LEN + ARP_HWADDR_LEN_LEN
+ + ARP_PROTOADDR_LEN_LEN);
+ int opCode = getUnsignedShort(data);
+ switch (opCode) {
+ case ARP_OPCODE_REQUEST:
+ mTypeString = "Request";
+ break;
+ case ARP_OPCODE_REPLY:
+ mTypeString = "Reply";
+ break;
+ default:
+ mTypeString = "Operation " + opCode;
+ }
+ }
+
+ private static final byte IP_V6_PAYLOAD_LENGTH_LEN = 2;
+ private static final byte IP_V6_HOP_LIMIT_LEN = 1;
+ private static final byte IP_V6_ADDR_LEN = 16;
+ private static final byte IP_V6_HEADER_TYPE_HOP_BY_HOP_OPTION = 0;
+ private static final byte IP_V6_HEADER_TYPE_ICMP_V6 = 58;
+ private static final byte BYTES_PER_OCT = 8;
+
+ private void parseIpv6Packet(ByteBuffer data) {
+ mMostSpecificProtocolString = "IPv6";
+ int versionClassAndLabel = data.getInt();
+ int version = (versionClassAndLabel & 0xf0000000) >> 28;
+ if (version != 6) {
+ Log.e(TAG, "IPv6 header: invalid IP version " + version);
+ return;
+ }
+ data.position(data.position() + IP_V6_PAYLOAD_LENGTH_LEN);
+
+ short nextHeaderType = getUnsignedByte(data);
+ data.position(data.position() + IP_V6_HOP_LIMIT_LEN + IP_V6_ADDR_LEN * 2);
+ while (nextHeaderType == IP_V6_HEADER_TYPE_HOP_BY_HOP_OPTION) {
+ int thisHeaderLen;
+ data.mark();
+ nextHeaderType = getUnsignedByte(data);
+ thisHeaderLen = (getUnsignedByte(data) + 1) * BYTES_PER_OCT;
+ data.reset(); // back to start of this header
+ data.position(data.position() + thisHeaderLen);
+ }
+ switch (nextHeaderType) {
+ case IP_V6_HEADER_TYPE_ICMP_V6:
+ parseIcmpV6Packet(data);
+ return;
+ default:
+ mTypeString = "Option/Protocol " + nextHeaderType;
+ return;
+ }
+ }
+
+ private static final short ICMP_V6_TYPE_ECHO_REQUEST = 128;
+ private static final short ICMP_V6_TYPE_ECHO_REPLY = 129;
+ private static final short ICMP_V6_TYPE_ROUTER_SOLICITATION = 133;
+ private static final short ICMP_V6_TYPE_ROUTER_ADVERTISEMENT = 134;
+ private static final short ICMP_V6_TYPE_NEIGHBOR_SOLICITATION = 135;
+ private static final short ICMP_V6_TYPE_NEIGHBOR_ADVERTISEMENT = 136;
+ private static final short ICMP_V6_TYPE_MULTICAST_LISTENER_DISCOVERY = 143;
+
+ private void parseIcmpV6Packet(ByteBuffer data) {
+ mMostSpecificProtocolString = "ICMPv6";
+ short icmpV6Type = getUnsignedByte(data);
+ switch (icmpV6Type) {
+ case ICMP_V6_TYPE_ECHO_REQUEST:
+ mTypeString = "Echo Request";
+ return;
+ case ICMP_V6_TYPE_ECHO_REPLY:
+ mTypeString = "Echo Reply";
+ return;
+ case ICMP_V6_TYPE_ROUTER_SOLICITATION:
+ mTypeString = "Router Solicitation";
+ return;
+ case ICMP_V6_TYPE_ROUTER_ADVERTISEMENT:
+ mTypeString = "Router Advertisement";
+ return;
+ case ICMP_V6_TYPE_NEIGHBOR_SOLICITATION:
+ mTypeString = "Neighbor Solicitation";
+ return;
+ case ICMP_V6_TYPE_NEIGHBOR_ADVERTISEMENT:
+ mTypeString = "Neighbor Advertisement";
+ return;
+ case ICMP_V6_TYPE_MULTICAST_LISTENER_DISCOVERY:
+ mTypeString = "MLDv2 report";
+ return;
+ default:
+ mTypeString = "Type " + icmpV6Type;
+ return;
+ }
+ }
+
+ private static final byte EAPOL_TYPE_KEY = 3;
+ private static final byte EAPOL_KEY_DESCRIPTOR_RSN_KEY = 2;
+ private static final byte EAPOL_LENGTH_LEN = 2;
+ private static final short WPA_KEY_INFO_FLAG_PAIRWISE = (short) 1 << 3; // bit 4
+ private static final short WPA_KEY_INFO_FLAG_INSTALL = (short) 1 << 6; // bit 7
+ private static final short WPA_KEY_INFO_FLAG_MIC = (short) 1 << 8; // bit 9
+ private static final byte WPA_KEYLEN_LEN = 2;
+ private static final byte WPA_REPLAY_COUNTER_LEN = 8;
+ private static final byte WPA_KEY_NONCE_LEN = 32;
+ private static final byte WPA_KEY_IV_LEN = 16;
+ private static final byte WPA_KEY_RECEIVE_SEQUENCE_COUNTER_LEN = 8;
+ private static final byte WPA_KEY_IDENTIFIER_LEN = 8;
+ private static final byte WPA_KEY_MIC_LEN = 16;
+
+ private void parseEapolPacket(ByteBuffer data) {
+ mMostSpecificProtocolString = "EAPOL";
+ short eapolVersion = getUnsignedByte(data);
+ if (eapolVersion < 1 || eapolVersion > 2) {
+ Log.e(TAG, "Unrecognized EAPOL version " + eapolVersion);
+ return;
+ }
+
+ short eapolType = getUnsignedByte(data);
+ if (eapolType != EAPOL_TYPE_KEY) {
+ Log.e(TAG, "Unrecognized EAPOL type " + eapolType);
+ return;
+ }
+
+ data.position(data.position() + EAPOL_LENGTH_LEN);
+ short eapolKeyDescriptorType = getUnsignedByte(data);
+ if (eapolKeyDescriptorType != EAPOL_KEY_DESCRIPTOR_RSN_KEY) {
+ Log.e(TAG, "Unrecognized key descriptor " + eapolKeyDescriptorType);
+ return;
+ }
+
+ short wpaKeyInfo = data.getShort();
+ if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_PAIRWISE) == 0) {
+ mTypeString = "Group Key";
+ } else {
+ mTypeString = "Pairwise Key";
+ }
+
+ // See goo.gl/tu8AQC for details.
+ if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_MIC) == 0) {
+ mTypeString += " message 1/4";
+ return;
+ }
+
+ if ((wpaKeyInfo & WPA_KEY_INFO_FLAG_INSTALL) != 0) {
+ mTypeString += " message 3/4";
+ return;
+ }
+
+ data.position(data.position() + WPA_KEYLEN_LEN + WPA_REPLAY_COUNTER_LEN
+ + WPA_KEY_NONCE_LEN + WPA_KEY_IV_LEN + WPA_KEY_RECEIVE_SEQUENCE_COUNTER_LEN
+ + WPA_KEY_IDENTIFIER_LEN + WPA_KEY_MIC_LEN);
+ int wpaKeyDataLen = getUnsignedShort(data);
+ if (wpaKeyDataLen > 0) {
+ mTypeString += " message 2/4";
+ } else {
+ mTypeString += " message 4/4";
+ }
+ }
+
+ private static final byte IEEE_80211_FRAME_CTRL_TYPE_MGMT = 0x00;
+ private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_REQ = 0x00;
+ private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_RESP = 0x01;
+ private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_REQ = 0x04;
+ private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_RESP = 0x05;
+ private static final byte IEEE_80211_FRAME_CTRL_SUBTYPE_AUTH = 0x0b;
+
+ private static byte parseIeee80211FrameCtrlVersion(byte b) {
+ return (byte) (b & 0b00000011);
+ }
+ private static byte parseIeee80211FrameCtrlType(byte b) {
+ return (byte) ((b & 0b00001100) >> 2);
+ }
+ private static byte parseIeee80211FrameCtrlSubtype(byte b) {
+ return (byte) ((b & 0b11110000) >> 4);
+ }
+ private void parseManagementFrame(ByteBuffer data) {
+ mMostSpecificProtocolString = "802.11 Mgmt";
+ byte frameControlField = data.get();
+ byte ieee80211Version = parseIeee80211FrameCtrlVersion(frameControlField);
+ if (ieee80211Version != 0) {
+ Log.e(TAG, "Unrecognized 802.11 version " + ieee80211Version);
+ return;
+ }
+
+ byte ieee80211FrameType = parseIeee80211FrameCtrlType(frameControlField);
+ if (ieee80211FrameType != IEEE_80211_FRAME_CTRL_TYPE_MGMT) {
+ Log.e(TAG, "Unexpected frame type " + ieee80211FrameType);
+ return;
+ }
+
+ byte ieee80211FrameSubtype = parseIeee80211FrameCtrlSubtype(frameControlField);
+ switch (ieee80211FrameSubtype) {
+ case IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_REQ:
+ mTypeString = "Association Request";
+ return;
+ case IEEE_80211_FRAME_CTRL_SUBTYPE_ASSOC_RESP:
+ mTypeString = "Association Response";
+ return;
+ case IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_REQ:
+ mTypeString = "Probe Request";
+ return;
+ case IEEE_80211_FRAME_CTRL_SUBTYPE_PROBE_RESP:
+ mTypeString = "Probe Response";
+ return;
+ case IEEE_80211_FRAME_CTRL_SUBTYPE_AUTH:
+ mTypeString = "Authentication";
+ return;
+ default:
+ mTypeString = "Unexpected subtype " + ieee80211FrameSubtype;
+ return;
+ }
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiLoggerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiLoggerTest.java
index 6f68187a9..64bb880fe 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiLoggerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiLoggerTest.java
@@ -80,6 +80,7 @@ public class WifiLoggerTest {
when(mWifiNative.readKernelLog()).thenReturn("");
mWifiLogger = new WifiLogger(mWsm, mWifiNative);
+ mWifiNative.enableVerboseLogging(0);
}
/**
@@ -138,14 +139,14 @@ public class WifiLoggerTest {
}
/**
- * Verifies that, when verbose mode is not enabled, startLogging() does not
+ * Verifies that, when verbose mode is not enabled, startLogging() calls
* startPktFateMonitoring().
*/
@Test
- public void startLoggingIgnoresPacketFateWithoutVerboseMode() {
+ public void startLoggingStartsPacketFateWithoutVerboseMode() {
final boolean verbosityToggle = false;
mWifiLogger.startLogging(verbosityToggle);
- verify(mWifiNative, never()).startPktFateMonitoring();
+ verify(mWifiNative).startPktFateMonitoring();
}
/**
@@ -160,16 +161,16 @@ public class WifiLoggerTest {
}
/**
- * Verifies that, when verbose mode is not enabled, reportConnectionFailure() does not
- * fetch packet fates.
+ * Verifies that, when verbose mode is not enabled, reportConnectionFailure() still
+ * fetches packet fates.
*/
@Test
public void reportConnectionFailureIsIgnoredWithoutVerboseMode() {
final boolean verbosityToggle = false;
mWifiLogger.startLogging(verbosityToggle);
mWifiLogger.reportConnectionFailure();
- verify(mWifiNative, never()).getTxPktFates(anyObject());
- verify(mWifiNative, never()).getRxPktFates(anyObject());
+ verify(mWifiNative).getTxPktFates(anyObject());
+ verify(mWifiNative).getRxPktFates(anyObject());
}
/**
@@ -266,16 +267,16 @@ public class WifiLoggerTest {
"--------------------------------------------------------------------"));
}
- /**
- * Verifies that dump() shows both TX, and RX, fates.
- */
- @Test
- public void dumpShowsTxAndRxFates() {
- final boolean verbosityToggle = true;
- mWifiLogger.startLogging(verbosityToggle);
+ private String getDumpString(boolean verbose) {
+ mWifiLogger.startLogging(verbose);
+ mWifiNative.enableVerboseLogging(verbose ? 1 : 0);
when(mWifiNative.getTxPktFates(anyObject())).then(new AnswerWithArguments() {
public boolean answer(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]
);
@@ -285,6 +286,10 @@ public class WifiLoggerTest {
when(mWifiNative.getRxPktFates(anyObject())).then(new AnswerWithArguments() {
public boolean answer(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]
);
@@ -296,10 +301,41 @@ public class WifiLoggerTest {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
mWifiLogger.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"});
+ return sw.toString();
+ }
- String fateDumpString = sw.toString();
- assertTrue(fateDumpString.contains("Frame direction: TX"));
- assertTrue(fateDumpString.contains("Frame direction: RX"));
+ /**
+ * 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(dumpString.contains("0 TX"));
+ assertTrue(dumpString.contains("1 RX"));
+ assertTrue(dumpString.contains("2 TX"));
+ assertTrue(dumpString.contains("3 RX"));
+ 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(dumpString.contains("0 TX"));
+ assertTrue(dumpString.contains("1 RX"));
+ assertTrue(dumpString.contains("2 TX"));
+ assertTrue(dumpString.contains("3 RX"));
+ assertTrue(dumpString.contains("VERBOSE PACKET FATE DUMP"));
+ assertTrue(dumpString.contains("Frame bytes"));
}
/**
@@ -309,53 +345,40 @@ public class WifiLoggerTest {
@Test
public void dumpIsSortedByTimestamp() {
final boolean verbosityToggle = true;
- mWifiLogger.startLogging(verbosityToggle);
- when(mWifiNative.getTxPktFates(anyObject())).then(new AnswerWithArguments() {
- public boolean answer(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(anyObject())).then(new AnswerWithArguments() {
- public boolean answer(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;
- }
- });
- mWifiLogger.reportConnectionFailure();
-
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- mWifiLogger.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"});
-
- String fateDumpString = sw.toString();
- assertTrue(fateDumpString.contains(
- "Frame number: 1\nFrame direction: TX\nFrame timestamp: 0\n"));
- assertTrue(fateDumpString.contains(
- "Frame number: 2\nFrame direction: RX\nFrame timestamp: 1\n"));
- assertTrue(fateDumpString.contains(
- "Frame number: 3\nFrame direction: TX\nFrame timestamp: 2\n"));
- assertTrue(fateDumpString.contains(
- "Frame number: 4\nFrame direction: RX\nFrame timestamp: 3\n"));
+ String dumpString = getDumpString(verbosityToggle);
+ assertTrue(dumpString.contains(WifiNative.FateReport.getTableHeader()));
+ int expected_index_of_frame_0 = dumpString.indexOf("0 TX");
+ int expected_index_of_frame_1 = dumpString.indexOf("1 RX");
+ int expected_index_of_frame_2 = dumpString.indexOf("2 TX");
+ int expected_index_of_frame_3 = dumpString.indexOf("3 RX");
+ assertFalse(-1 == expected_index_of_frame_0);
+ assertFalse(-1 == expected_index_of_frame_1);
+ assertFalse(-1 == expected_index_of_frame_2);
+ assertFalse(-1 == expected_index_of_frame_3);
+ assertTrue(expected_index_of_frame_0 < expected_index_of_frame_1);
+ assertTrue(expected_index_of_frame_1 < expected_index_of_frame_2);
+ assertTrue(expected_index_of_frame_2 < expected_index_of_frame_3);
+
+ 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, if verbose is disabled after fetching fates, the dump does not include
- * fates.
+ * verbose fate logs.
*/
@Test
public void dumpOmitsFatesIfVerboseIsDisabledAfterFetch() {
@@ -391,8 +414,8 @@ public class WifiLoggerTest {
mWifiLogger.dump(new FileDescriptor(), pw, new String[]{"bogus", "args"});
String fateDumpString = sw.toString();
- assertFalse(fateDumpString.contains("Frame direction: TX"));
- assertFalse(fateDumpString.contains("Frame direction: RX"));
+ assertFalse(fateDumpString.contains("VERBOSE PACKET FATE DUMP"));
+ assertFalse(fateDumpString.contains("Frame bytes"));
}
/** Verifies that the default size of our ring buffers is small. */
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
index 29cb3e5b5..5fa20d05c 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNativeTest.java
@@ -50,6 +50,68 @@ public class WifiNativeTest {
private static final String NETWORK_EXTRAS_SERIALIZED =
"\"%7B%22key2%22%3A%22value2%22%2C%22key1%22%3A%22value1%22%7D\"";
+ private static final long FATE_REPORT_DRIVER_TIMESTAMP_USEC = 12345;
+ private static final byte[] FATE_REPORT_FRAME_BYTES = new byte[] {
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 0, 1, 2, 3, 4, 5, 6, 7};
+ private static final WifiNative.TxFateReport TX_FATE_REPORT = new WifiNative.TxFateReport(
+ WifiLoggerHal.TX_PKT_FATE_SENT,
+ FATE_REPORT_DRIVER_TIMESTAMP_USEC,
+ WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
+ FATE_REPORT_FRAME_BYTES
+ );
+ private static final WifiNative.RxFateReport RX_FATE_REPORT = new WifiNative.RxFateReport(
+ WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,
+ FATE_REPORT_DRIVER_TIMESTAMP_USEC,
+ WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
+ FATE_REPORT_FRAME_BYTES
+ );
+ private static final FrameTypeMapping[] FRAME_TYPE_MAPPINGS = new FrameTypeMapping[] {
+ new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_UNKNOWN, "unknown", "N/A"),
+ new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, "data", "Ethernet"),
+ new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_80211_MGMT, "802.11 management",
+ "802.11 Mgmt"),
+ new FrameTypeMapping((byte) 42, "42", "N/A")
+ };
+ private static final FateMapping[] TX_FATE_MAPPINGS = new FateMapping[] {
+ new FateMapping(WifiLoggerHal.TX_PKT_FATE_ACKED, "acked"),
+ new FateMapping(WifiLoggerHal.TX_PKT_FATE_SENT, "sent"),
+ new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_QUEUED, "firmware queued"),
+ new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID,
+ "firmware dropped (invalid frame)"),
+ new FateMapping(
+ WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS, "firmware dropped (no bufs)"),
+ new FateMapping(
+ WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"),
+ new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED, "driver queued"),
+ new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID,
+ "driver dropped (invalid frame)"),
+ new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS,
+ "driver dropped (no bufs)"),
+ new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"),
+ new FateMapping((byte) 42, "42")
+ };
+ private static final FateMapping[] RX_FATE_MAPPINGS = new FateMapping[] {
+ new FateMapping(WifiLoggerHal.RX_PKT_FATE_SUCCESS, "success"),
+ new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_QUEUED, "firmware queued"),
+ new FateMapping(
+ WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER, "firmware dropped (filter)"),
+ new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,
+ "firmware dropped (invalid frame)"),
+ new FateMapping(
+ WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS, "firmware dropped (no bufs)"),
+ new FateMapping(
+ WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"),
+ new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED, "driver queued"),
+ new FateMapping(
+ WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER, "driver dropped (filter)"),
+ new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID,
+ "driver dropped (invalid frame)"),
+ new FateMapping(
+ WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS, "driver dropped (no bufs)"),
+ new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"),
+ new FateMapping((byte) 42, "42")
+ };
+
private WifiNative mWifiNative;
@Before
@@ -89,18 +151,16 @@ public class WifiNativeTest {
*/
@Test
public void testTxFateReportCtorSetsFields() {
- long driverTimestampUSec = 12345;
- byte[] frameBytes = new byte[] {'a', 'b', 0, 'c'};
WifiNative.TxFateReport fateReport = new WifiNative.TxFateReport(
WifiLoggerHal.TX_PKT_FATE_SENT, // non-zero value
- driverTimestampUSec,
+ FATE_REPORT_DRIVER_TIMESTAMP_USEC,
WifiLoggerHal.FRAME_TYPE_ETHERNET_II, // non-zero value
- frameBytes
+ FATE_REPORT_FRAME_BYTES
);
assertEquals(WifiLoggerHal.TX_PKT_FATE_SENT, fateReport.mFate);
- assertEquals(driverTimestampUSec, fateReport.mDriverTimestampUSec);
+ assertEquals(FATE_REPORT_DRIVER_TIMESTAMP_USEC, fateReport.mDriverTimestampUSec);
assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, fateReport.mFrameType);
- assertArrayEquals(frameBytes, fateReport.mFrameBytes);
+ assertArrayEquals(FATE_REPORT_FRAME_BYTES, fateReport.mFrameBytes);
}
/**
@@ -108,27 +168,27 @@ public class WifiNativeTest {
*/
@Test
public void testRxFateReportCtorSetsFields() {
- long driverTimestampUSec = 12345;
- byte[] frameBytes = new byte[] {'a', 'b', 0, 'c'};
WifiNative.RxFateReport fateReport = new WifiNative.RxFateReport(
WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, // non-zero value
- driverTimestampUSec,
+ FATE_REPORT_DRIVER_TIMESTAMP_USEC,
WifiLoggerHal.FRAME_TYPE_ETHERNET_II, // non-zero value
- frameBytes
+ FATE_REPORT_FRAME_BYTES
);
assertEquals(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID, fateReport.mFate);
- assertEquals(driverTimestampUSec, fateReport.mDriverTimestampUSec);
+ assertEquals(FATE_REPORT_DRIVER_TIMESTAMP_USEC, fateReport.mDriverTimestampUSec);
assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, fateReport.mFrameType);
- assertArrayEquals(frameBytes, fateReport.mFrameBytes);
+ assertArrayEquals(FATE_REPORT_FRAME_BYTES, fateReport.mFrameBytes);
}
// Support classes for test{Tx,Rx}FateReportToString.
private static class FrameTypeMapping {
byte mTypeNumber;
- String mExpectedText;
- FrameTypeMapping(byte typeNumber, String expectedText) {
+ String mExpectedTypeText;
+ String mExpectedProtocolText;
+ FrameTypeMapping(byte typeNumber, String expectedTypeText, String expectedProtocolText) {
this.mTypeNumber = typeNumber;
- this.mExpectedText = expectedText;
+ this.mExpectedTypeText = expectedTypeText;
+ this.mExpectedProtocolText = expectedProtocolText;
}
}
private static class FateMapping {
@@ -141,138 +201,174 @@ public class WifiNativeTest {
}
/**
- * Verifies that TxFateReport.toString() includes the information we care about.
+ * Verifies that FateReport.getTableHeader() prints the right header.
*/
@Test
- public void testTxFateReportToString() {
- long driverTimestampUSec = 12345;
- byte[] frameBytes = new byte[] {
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 0, 1, 2, 3, 4, 5, 6, 7};
- WifiNative.TxFateReport fateReport = new WifiNative.TxFateReport(
- WifiLoggerHal.TX_PKT_FATE_SENT,
- driverTimestampUSec,
- WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
- frameBytes
- );
+ public void testFateReportTableHeader() {
+ String header = WifiNative.FateReport.getTableHeader();
+ assertTrue(header.contains(
+ "Timestamp Direction Fate Protocol Type\n"));
+ assertTrue(header.contains(
+ "--------- --------- ---- -------- ----\n"));
+ }
+
+ /**
+ * Verifies that TxFateReport.toTableRowString() includes the information we care about.
+ */
+ @Test
+ public void testTxFateReportToTableRowString() {
+ WifiNative.TxFateReport fateReport = TX_FATE_REPORT;
+
+ String tableRowFateString = fateReport.toTableRowString();
+ assertTrue(tableRowFateString.contains("" + FATE_REPORT_DRIVER_TIMESTAMP_USEC));
+ assertTrue(tableRowFateString.contains("TX"));
+ assertTrue(tableRowFateString.contains("sent"));
+ assertTrue(tableRowFateString.contains("Ethernet"));
+ assertTrue(tableRowFateString.contains("N/A"));
+
+ for (FrameTypeMapping frameTypeMapping : FRAME_TYPE_MAPPINGS) {
+ fateReport = new WifiNative.TxFateReport(
+ WifiLoggerHal.TX_PKT_FATE_SENT,
+ FATE_REPORT_DRIVER_TIMESTAMP_USEC,
+ frameTypeMapping.mTypeNumber,
+ FATE_REPORT_FRAME_BYTES
+ );
+ tableRowFateString = fateReport.toTableRowString();
+ assertTrue(tableRowFateString.contains("" + FATE_REPORT_DRIVER_TIMESTAMP_USEC));
+ assertTrue(tableRowFateString.contains("TX"));
+ assertTrue(tableRowFateString.contains("sent"));
+ assertTrue(tableRowFateString.contains(frameTypeMapping.mExpectedProtocolText));
+ assertTrue(tableRowFateString.contains("N/A"));
+ }
+
+ for (FateMapping fateMapping : TX_FATE_MAPPINGS) {
+ fateReport = new WifiNative.TxFateReport(
+ fateMapping.mFateNumber,
+ FATE_REPORT_DRIVER_TIMESTAMP_USEC,
+ WifiLoggerHal.FRAME_TYPE_80211_MGMT,
+ FATE_REPORT_FRAME_BYTES
+ );
+ tableRowFateString = fateReport.toTableRowString();
+ assertTrue(tableRowFateString.contains("" + FATE_REPORT_DRIVER_TIMESTAMP_USEC));
+ assertTrue(tableRowFateString.contains("TX"));
+ assertTrue(tableRowFateString.contains(fateMapping.mExpectedText));
+ assertTrue(tableRowFateString.contains("802.11 Mgmt"));
+ assertTrue(tableRowFateString.contains("N/A"));
+ }
+ }
+
+ /**
+ * Verifies that TxFateReport.toVerboseStringWithPiiAllowed() includes the information we care
+ * about.
+ */
+ @Test
+ public void testTxFateReportToVerboseStringWithPiiAllowed() {
+ WifiNative.TxFateReport fateReport = TX_FATE_REPORT;
- String fateString = fateReport.toString();
- assertTrue(fateString.contains("Frame direction: TX"));
- assertTrue(fateString.contains("Frame timestamp: 12345"));
- assertTrue(fateString.contains("Frame fate: sent"));
- assertTrue(fateString.contains("Frame type: data"));
- assertTrue(fateString.contains("Frame length: 16"));
- assertTrue(fateString.contains(
+ String verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
+ assertTrue(verboseFateString.contains("Frame direction: TX"));
+ assertTrue(verboseFateString.contains("Frame timestamp: 12345"));
+ assertTrue(verboseFateString.contains("Frame fate: sent"));
+ assertTrue(verboseFateString.contains("Frame type: data"));
+ assertTrue(verboseFateString.contains("Frame protocol: Ethernet"));
+ assertTrue(verboseFateString.contains("Frame protocol type: N/A"));
+ assertTrue(verboseFateString.contains("Frame length: 16"));
+ assertTrue(verboseFateString.contains(
"61 62 63 64 65 66 67 68 00 01 02 03 04 05 06 07")); // hex dump
// TODO(quiche): uncomment this, once b/27975149 is fixed.
- // assertTrue(fateString.contains("abcdefgh........")); // hex dump
-
- FrameTypeMapping[] frameTypeMappings = new FrameTypeMapping[] {
- new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_UNKNOWN, "unknown"),
- new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, "data"),
- new FrameTypeMapping(WifiLoggerHal.FRAME_TYPE_80211_MGMT, "802.11 management"),
- new FrameTypeMapping((byte) 42, "42")
- };
- for (FrameTypeMapping frameTypeMapping : frameTypeMappings) {
+ // assertTrue(verboseFateString.contains("abcdefgh........")); // hex dump
+
+ for (FrameTypeMapping frameTypeMapping : FRAME_TYPE_MAPPINGS) {
fateReport = new WifiNative.TxFateReport(
WifiLoggerHal.TX_PKT_FATE_SENT,
- driverTimestampUSec,
+ FATE_REPORT_DRIVER_TIMESTAMP_USEC,
frameTypeMapping.mTypeNumber,
- frameBytes
+ FATE_REPORT_FRAME_BYTES
);
- assertTrue(fateReport.toString().contains(
- "Frame type: " + frameTypeMapping.mExpectedText));
+ verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
+ assertTrue(verboseFateString.contains("Frame type: "
+ + frameTypeMapping.mExpectedTypeText));
}
- FateMapping[] fateMappings = new FateMapping[] {
- new FateMapping(WifiLoggerHal.TX_PKT_FATE_ACKED, "acked"),
- new FateMapping(WifiLoggerHal.TX_PKT_FATE_SENT, "sent"),
- new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_QUEUED, "firmware queued"),
- new FateMapping(WifiLoggerHal.TX_PKT_FATE_FW_DROP_INVALID,
- "firmware dropped (invalid frame)"),
- new FateMapping(
- WifiLoggerHal.TX_PKT_FATE_FW_DROP_NOBUFS, "firmware dropped (no bufs)"),
- new FateMapping(
- WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"),
- new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED, "driver queued"),
- new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_INVALID,
- "driver dropped (invalid frame)"),
- new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_NOBUFS,
- "driver dropped (no bufs)"),
- new FateMapping(WifiLoggerHal.TX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"),
- new FateMapping((byte) 42, "42")
- };
- for (FateMapping fateMapping : fateMappings) {
+ for (FateMapping fateMapping : TX_FATE_MAPPINGS) {
fateReport = new WifiNative.TxFateReport(
fateMapping.mFateNumber,
- driverTimestampUSec,
+ FATE_REPORT_DRIVER_TIMESTAMP_USEC,
WifiLoggerHal.FRAME_TYPE_80211_MGMT,
- frameBytes
+ FATE_REPORT_FRAME_BYTES
);
- assertTrue(fateReport.toString().contains("Frame fate: " + fateMapping.mExpectedText));
+ verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
+ assertTrue(verboseFateString.contains("Frame fate: " + fateMapping.mExpectedText));
}
}
/**
- * Verifies that RxFateReport.toString() includes the information we care about.
+ * Verifies that RxFateReport.toTableRowString() includes the information we care about.
*/
@Test
- public void testRxFateReportToString() {
- long driverTimestampUSec = 67890;
- byte[] frameBytes = new byte[] {
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 0, 1, 2, 3, 4, 5, 6, 7};
- WifiNative.RxFateReport fateReport = new WifiNative.RxFateReport(
- WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,
- driverTimestampUSec,
- WifiLoggerHal.FRAME_TYPE_ETHERNET_II,
- frameBytes
- );
+ public void testRxFateReportToTableRowString() {
+ WifiNative.RxFateReport fateReport = RX_FATE_REPORT;
+
+ String tableRowFateString = fateReport.toTableRowString();
+ assertTrue(tableRowFateString.contains("" + FATE_REPORT_DRIVER_TIMESTAMP_USEC));
+ assertTrue(tableRowFateString.contains("RX"));
+ assertTrue(tableRowFateString.contains("firmware dropped (invalid frame)"));
+ assertTrue(tableRowFateString.contains("Ethernet"));
+ assertTrue(tableRowFateString.contains("N/A"));
- String fateString = fateReport.toString();
- assertTrue(fateString.contains("Frame direction: RX"));
- assertTrue(fateString.contains("Frame timestamp: 67890"));
- assertTrue(fateString.contains("Frame fate: firmware dropped (invalid frame)"));
- assertTrue(fateString.contains("Frame type: data"));
- assertTrue(fateString.contains("Frame length: 16"));
- assertTrue(fateString.contains(
+ // FrameTypeMappings omitted, as they're the same as for TX.
+
+ for (FateMapping fateMapping : RX_FATE_MAPPINGS) {
+ fateReport = new WifiNative.RxFateReport(
+ fateMapping.mFateNumber,
+ FATE_REPORT_DRIVER_TIMESTAMP_USEC,
+ WifiLoggerHal.FRAME_TYPE_80211_MGMT,
+ FATE_REPORT_FRAME_BYTES
+ );
+ tableRowFateString = fateReport.toTableRowString();
+ assertTrue(tableRowFateString.contains("" + FATE_REPORT_DRIVER_TIMESTAMP_USEC));
+ assertTrue(tableRowFateString.contains("RX"));
+ assertTrue(tableRowFateString.contains(fateMapping.mExpectedText));
+ assertTrue(tableRowFateString.contains("802.11 Mgmt"));
+ assertTrue(tableRowFateString.contains("N/A"));
+ }
+ }
+
+ /**
+ * Verifies that RxFateReport.toVerboseStringWithPiiAllowed() includes the information we care
+ * about.
+ */
+ @Test
+ public void testRxFateReportToVerboseStringWithPiiAllowed() {
+ WifiNative.RxFateReport fateReport = RX_FATE_REPORT;
+
+ String verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
+ assertTrue(verboseFateString.contains("Frame direction: RX"));
+ assertTrue(verboseFateString.contains("Frame timestamp: 12345"));
+ assertTrue(verboseFateString.contains("Frame fate: firmware dropped (invalid frame)"));
+ assertTrue(verboseFateString.contains("Frame type: data"));
+ assertTrue(verboseFateString.contains("Frame protocol: Ethernet"));
+ assertTrue(verboseFateString.contains("Frame protocol type: N/A"));
+ assertTrue(verboseFateString.contains("Frame length: 16"));
+ assertTrue(verboseFateString.contains(
"61 62 63 64 65 66 67 68 00 01 02 03 04 05 06 07")); // hex dump
// TODO(quiche): uncomment this, once b/27975149 is fixed.
- // assertTrue(fateString.contains("abcdefgh........")); // hex dump
+ // assertTrue(verboseFateString.contains("abcdefgh........")); // hex dump
// FrameTypeMappings omitted, as they're the same as for TX.
- FateMapping[] fateMappings = new FateMapping[] {
- new FateMapping(WifiLoggerHal.RX_PKT_FATE_SUCCESS, "success"),
- new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_QUEUED, "firmware queued"),
- new FateMapping(
- WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER, "firmware dropped (filter)"),
- new FateMapping(WifiLoggerHal.RX_PKT_FATE_FW_DROP_INVALID,
- "firmware dropped (invalid frame)"),
- new FateMapping(
- WifiLoggerHal.RX_PKT_FATE_FW_DROP_NOBUFS, "firmware dropped (no bufs)"),
- new FateMapping(
- WifiLoggerHal.RX_PKT_FATE_FW_DROP_OTHER, "firmware dropped (other)"),
- new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_QUEUED, "driver queued"),
- new FateMapping(
- WifiLoggerHal.RX_PKT_FATE_DRV_DROP_FILTER, "driver dropped (filter)"),
- new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_INVALID,
- "driver dropped (invalid frame)"),
- new FateMapping(
- WifiLoggerHal.RX_PKT_FATE_DRV_DROP_NOBUFS, "driver dropped (no bufs)"),
- new FateMapping(WifiLoggerHal.RX_PKT_FATE_DRV_DROP_OTHER, "driver dropped (other)"),
- new FateMapping((byte) 42, "42")
- };
- for (FateMapping fateMapping : fateMappings) {
+ for (FateMapping fateMapping : RX_FATE_MAPPINGS) {
fateReport = new WifiNative.RxFateReport(
fateMapping.mFateNumber,
- driverTimestampUSec,
+ FATE_REPORT_DRIVER_TIMESTAMP_USEC,
WifiLoggerHal.FRAME_TYPE_80211_MGMT,
- frameBytes
+ FATE_REPORT_FRAME_BYTES
);
- assertTrue(fateReport.toString().contains("Frame fate: " + fateMapping.mExpectedText));
+ verboseFateString = fateReport.toVerboseStringWithPiiAllowed();
+ assertTrue(verboseFateString.contains("Frame fate: " + fateMapping.mExpectedText));
}
}
-
/**
* Verifies that startPktFateMonitoring returns false when HAL is not started.
*/
diff --git a/tests/wifitests/src/com/android/server/wifi/util/FrameParserTest.java b/tests/wifitests/src/com/android/server/wifi/util/FrameParserTest.java
new file mode 100644
index 000000000..e8e921be4
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/util/FrameParserTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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.util;
+
+import static org.junit.Assert.assertEquals;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.server.wifi.WifiLoggerHal;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.util.FrameParser}.
+ */
+@SmallTest
+public class FrameParserTest {
+
+ private static final byte[] TEST_EAPOL_1_OF_4_FRAME_BYTES = new byte[] {
+ (byte) 0x7C, (byte) 0x7D, (byte) 0x3D, (byte) 0x51, (byte) 0x10, (byte) 0xDC,
+ (byte) 0x08, (byte) 0x96, (byte) 0xD7, (byte) 0x8B, (byte) 0xE3, (byte) 0xFB,
+ (byte) 0x88, (byte) 0x8E, (byte) 0x02, (byte) 0x03, (byte) 0x00, (byte) 0x5F,
+ (byte) 0x02, (byte) 0x00, (byte) 0x8A, (byte) 0x00, (byte) 0x10, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x01, (byte) 0xF2, (byte) 0x0D, (byte) 0xFA, (byte) 0x35, (byte) 0x89,
+ (byte) 0x9C, (byte) 0xA8, (byte) 0x8C, (byte) 0x14, (byte) 0xD9, (byte) 0x3F,
+ (byte) 0xC9, (byte) 0x62, (byte) 0x11, (byte) 0x39, (byte) 0xC3, (byte) 0x34,
+ (byte) 0xE1, (byte) 0x00, (byte) 0x09, (byte) 0xE3, (byte) 0x9C, (byte) 0x0C,
+ (byte) 0x32, (byte) 0xFE, (byte) 0x7F, (byte) 0x79, (byte) 0x29, (byte) 0x3E,
+ (byte) 0x6C, (byte) 0xF2, (byte) 0x57, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
+ private static final byte TEST_EAPOL_1_OF_4_FRAME_TYPE =
+ WifiLoggerHal.FRAME_TYPE_ETHERNET_II;
+ private static final String TEST_EAPOL_1_OF_4_FRAME_PROTOCOL_STRING = "EAPOL";
+ private static final String TEST_EAPOL_1_OF_4_FRAME_TYPE_STRING = "Pairwise Key message 1/4";
+
+ private static final byte[] TEST_EAPOL_2_OF_4_FRAME_BYTES = new byte[] {
+ (byte) 0x08, (byte) 0x96, (byte) 0xD7, (byte) 0x8B, (byte) 0xE3, (byte) 0xFB,
+ (byte) 0x7C, (byte) 0x7D, (byte) 0x3D, (byte) 0x51, (byte) 0x10, (byte) 0xDC,
+ (byte) 0x88, (byte) 0x8E, (byte) 0x01, (byte) 0x03, (byte) 0x00, (byte) 0x75,
+ (byte) 0x02, (byte) 0x01, (byte) 0x0A, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x01, (byte) 0x42, (byte) 0xAE, (byte) 0x33, (byte) 0x61, (byte) 0xF8,
+ (byte) 0x38, (byte) 0x28, (byte) 0x81, (byte) 0x70, (byte) 0xD8, (byte) 0xA5,
+ (byte) 0xDD, (byte) 0x90, (byte) 0xB1, (byte) 0x8E, (byte) 0xEB, (byte) 0x58,
+ (byte) 0xF1, (byte) 0x0A, (byte) 0xE4, (byte) 0xA1, (byte) 0x93, (byte) 0x34,
+ (byte) 0xE1, (byte) 0x4F, (byte) 0x90, (byte) 0x85, (byte) 0xA0, (byte) 0x21,
+ (byte) 0x95, (byte) 0xC8, (byte) 0xD8, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x53,
+ (byte) 0x12, (byte) 0xE4, (byte) 0x97, (byte) 0xBC, (byte) 0xFF, (byte) 0x15,
+ (byte) 0x45, (byte) 0xCF, (byte) 0x4C, (byte) 0xC0, (byte) 0xB8, (byte) 0xBA,
+ (byte) 0x30, (byte) 0x5F, (byte) 0x6C, (byte) 0x00, (byte) 0x16, (byte) 0x30,
+ (byte) 0x14, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC,
+ (byte) 0x04, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC,
+ (byte) 0x04, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC,
+ (byte) 0x02, (byte) 0x80, (byte) 0x00};
+ private static final byte TEST_EAPOL_2_OF_4_FRAME_TYPE =
+ WifiLoggerHal.FRAME_TYPE_ETHERNET_II;
+ private static final String TEST_EAPOL_2_OF_4_FRAME_PROTOCOL_STRING = "EAPOL";
+ private static final String TEST_EAPOL_2_OF_4_FRAME_TYPE_STRING = "Pairwise Key message 2/4";
+
+ private static final byte[] TEST_PROBE_RESPONSE_FRAME_BYTES = new byte[] {
+ (byte) 0x50, (byte) 0x08, (byte) 0x3a, (byte) 0x01, (byte) 0x54, (byte) 0x27,
+ (byte) 0x1e, (byte) 0xf2, (byte) 0xcd, (byte) 0x0f, (byte) 0x10, (byte) 0x6f,
+ (byte) 0x3f, (byte) 0xf6, (byte) 0x89, (byte) 0x0e, (byte) 0x10, (byte) 0x6f,
+ (byte) 0x3f, (byte) 0xf6, (byte) 0x89, (byte) 0x0e, (byte) 0x60, (byte) 0xc4,
+ (byte) 0x4a, (byte) 0xaa, (byte) 0x2a, (byte) 0x0d, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x11, (byte) 0x04,
+ (byte) 0x00, (byte) 0x16, (byte) 0x77, (byte) 0x7a, (byte) 0x72, (byte) 0x5f,
+ (byte) 0x68, (byte) 0x70, (byte) 0x5f, (byte) 0x67, (byte) 0x34, (byte) 0x35,
+ (byte) 0x30, (byte) 0x68, (byte) 0x5f, (byte) 0x67, (byte) 0x5f, (byte) 0x63,
+ (byte) 0x68, (byte) 0x35, (byte) 0x5f, (byte) 0x77, (byte) 0x70, (byte) 0x61,
+ (byte) 0x01, (byte) 0x08, (byte) 0x82, (byte) 0x84, (byte) 0x8b, (byte) 0x96,
+ (byte) 0x0c, (byte) 0x12, (byte) 0x18, (byte) 0x24, (byte) 0x03, (byte) 0x01,
+ (byte) 0x05, (byte) 0x2a, (byte) 0x01, (byte) 0x04, (byte) 0x32, (byte) 0x04,
+ (byte) 0x30, (byte) 0x48, (byte) 0x60, (byte) 0x6c, (byte) 0x30, (byte) 0x18,
+ (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0f, (byte) 0xac, (byte) 0x02,
+ (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x0f, (byte) 0xac, (byte) 0x04,
+ (byte) 0x00, (byte) 0x0f, (byte) 0xac, (byte) 0x02, (byte) 0x01, (byte) 0x00,
+ (byte) 0x00, (byte) 0x0f, (byte) 0xac, (byte) 0x02, (byte) 0x0c, (byte) 0x00,
+ (byte) 0xdd, (byte) 0x18, (byte) 0x00, (byte) 0x50, (byte) 0xf2, (byte) 0x02,
+ (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0xa4,
+ (byte) 0x00, (byte) 0x00, (byte) 0x27, (byte) 0xa4, (byte) 0x00, (byte) 0x00,
+ (byte) 0x42, (byte) 0x43, (byte) 0x5e, (byte) 0x00, (byte) 0x62, (byte) 0x32,
+ (byte) 0x2f, (byte) 0x00, (byte) 0xdd, (byte) 0x70, (byte) 0x00, (byte) 0x50,
+ (byte) 0xf2, (byte) 0x04, (byte) 0x10, (byte) 0x4a, (byte) 0x00, (byte) 0x01,
+ (byte) 0x10, (byte) 0x10, (byte) 0x44, (byte) 0x00, (byte) 0x01, (byte) 0x02,
+ (byte) 0x10, (byte) 0x3b, (byte) 0x00, (byte) 0x01, (byte) 0x03, (byte) 0x10,
+ (byte) 0x47, (byte) 0x00, (byte) 0x10, (byte) 0xf3, (byte) 0x1b, (byte) 0x31,
+ (byte) 0x7f, (byte) 0x8c, (byte) 0x25, (byte) 0x56, (byte) 0x46, (byte) 0xb5,
+ (byte) 0xc9, (byte) 0x5f, (byte) 0x2f, (byte) 0x0b, (byte) 0xcf, (byte) 0x6a,
+ (byte) 0x14, (byte) 0x10, (byte) 0x21, (byte) 0x00, (byte) 0x06, (byte) 0x44,
+ (byte) 0x44, (byte) 0x2d, (byte) 0x57, (byte) 0x52, (byte) 0x54, (byte) 0x10,
+ (byte) 0x23, (byte) 0x00, (byte) 0x0c, (byte) 0x57, (byte) 0x5a, (byte) 0x52,
+ (byte) 0x2d, (byte) 0x48, (byte) 0x50, (byte) 0x2d, (byte) 0x47, (byte) 0x34,
+ (byte) 0x35, (byte) 0x30, (byte) 0x48, (byte) 0x10, (byte) 0x24, (byte) 0x00,
+ (byte) 0x01, (byte) 0x30, (byte) 0x10, (byte) 0x42, (byte) 0x00, (byte) 0x05,
+ (byte) 0x31, (byte) 0x32, (byte) 0x33, (byte) 0x34, (byte) 0x35, (byte) 0x10,
+ (byte) 0x54, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x06, (byte) 0x00,
+ (byte) 0x50, (byte) 0xf2, (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x10,
+ (byte) 0x11, (byte) 0x00, (byte) 0x06, (byte) 0x44, (byte) 0x44, (byte) 0x2d,
+ (byte) 0x57, (byte) 0x52, (byte) 0x54, (byte) 0x10, (byte) 0x08, (byte) 0x00,
+ (byte) 0x02, (byte) 0x01, (byte) 0x04, (byte) 0x10, (byte) 0x3c, (byte) 0x00,
+ (byte) 0x01, (byte) 0x01, (byte) 0x8a, (byte) 0x0e, (byte) 0x06, (byte) 0xcf};
+ private static final byte TEST_PROBE_RESPONSE_FRAME_TYPE = WifiLoggerHal.FRAME_TYPE_80211_MGMT;
+ private static final String TEST_PROBE_RESPONSE_FRAME_PROTOCOL_STRING = "802.11 Mgmt";
+ private static final String TEST_PROBE_RESPONSE_FRAME_TYPE_STRING = "Probe Response";
+
+ /**
+ * Test that a probe response frame is parsed correctly.
+ */
+ @Test
+ public void parseProbeResponseFrame() {
+ FrameParser parser = new FrameParser(
+ TEST_PROBE_RESPONSE_FRAME_TYPE, TEST_PROBE_RESPONSE_FRAME_BYTES);
+ assertEquals(TEST_PROBE_RESPONSE_FRAME_PROTOCOL_STRING, parser.mMostSpecificProtocolString);
+ assertEquals(TEST_PROBE_RESPONSE_FRAME_TYPE_STRING, parser.mTypeString);
+ }
+
+ /**
+ * Test that pairwise EAPOL 1/4 and 2/4 frames are parsed correctly.
+ */
+ @Test
+ public void parseEapolFrames() {
+ FrameParser parser1 = new FrameParser(
+ TEST_EAPOL_1_OF_4_FRAME_TYPE, TEST_EAPOL_1_OF_4_FRAME_BYTES);
+ assertEquals(TEST_EAPOL_1_OF_4_FRAME_PROTOCOL_STRING, parser1.mMostSpecificProtocolString);
+ assertEquals(TEST_EAPOL_1_OF_4_FRAME_TYPE_STRING, parser1.mTypeString);
+
+ FrameParser parser2 = new FrameParser(
+ TEST_EAPOL_2_OF_4_FRAME_TYPE, TEST_EAPOL_2_OF_4_FRAME_BYTES);
+ assertEquals(TEST_EAPOL_2_OF_4_FRAME_PROTOCOL_STRING, parser2.mMostSpecificProtocolString);
+ assertEquals(TEST_EAPOL_2_OF_4_FRAME_TYPE_STRING, parser2.mTypeString);
+ }
+}