summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorchloedai <chloedai@google.com>2022-01-22 05:13:53 +0000
committerchloedai <chloedai@google.com>2022-01-24 15:42:32 +0000
commit4ddeec28de7ecd4fb9bbe589577328f5c8072c9b (patch)
tree173dae0cbf06a1f32aae732736272a631d1e7409 /src
parenta00dbb0b9ce02ef09f37d3caed0ad05d36b63542 (diff)
downloadNfc-4ddeec28de7ecd4fb9bbe589577328f5c8072c9b.tar.gz
Refine the code and add atests for RoutingTableParser
Bug: 215808326 Test: atest NfcRoutingTableParseTest Change-Id: Idf2b98401d2d324c7babe5f6031a18a100f24b11
Diffstat (limited to 'src')
-rw-r--r--src/com/android/nfc/RoutingTableParser.java284
1 files changed, 205 insertions, 79 deletions
diff --git a/src/com/android/nfc/RoutingTableParser.java b/src/com/android/nfc/RoutingTableParser.java
index d2c7f1ad..9174c244 100644
--- a/src/com/android/nfc/RoutingTableParser.java
+++ b/src/com/android/nfc/RoutingTableParser.java
@@ -17,10 +17,12 @@
package com.android.nfc;
import android.os.SystemProperties;
-import java.util.Locale;
import android.util.Log;
import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Vector;
/**
* Parse the Routing Table from the last backup lmrt cmd and dump it with a clear typography
@@ -28,57 +30,92 @@ import java.io.PrintWriter;
public class RoutingTableParser {
static final boolean DBG = SystemProperties.getBoolean("persist.nfc.debug_enabled", false);
private static final String TAG = "RoutingTableParser";
+ private static int sRoutingTableSize = 0;
+ private static int sRoutingTableMaxSize = 0;
+ private static Vector<RoutingEntryInfo> sRoutingTable = new Vector<RoutingEntryInfo>(0);
+
+ // Entry types
+ static final byte TYPE_TECHNOLOGY = 0;
+ static final byte TYPE_PROTOCOL = 1;
+ static final byte TYPE_AID = 2;
+ static final byte TYPE_SYSTEMCODE = 3;
+ static final byte TYPE_UNSUPPORTED = 4;
+
+ // Commit status
+ static final int STATS_HOST_OK = 0;
+ static final int STATS_OFFHOST_OK = 1;
+ static final int STATS_NOT_FOUND = 2;
- private String getTechStr(int value) {
+ private interface GetEntryStr {
+ String getEntryStr(byte[] entry);
+ }
+
+ private GetEntryStr[] mGetEntryStrFuncs = new GetEntryStr[] {
+ new GetEntryStr() { public String getEntryStr(byte[] entry) {
+ return getTechStr(entry); } },
+ new GetEntryStr() { public String getEntryStr(byte[] entry) {
+ return getProtoStr(entry); } },
+ new GetEntryStr() { public String getEntryStr(byte[] entry) {
+ return getAidStr(entry); } },
+ new GetEntryStr() { public String getEntryStr(byte[] entry) {
+ return getSystemCodeStr(entry); } },
+ };
+
+ private String getTechStr(byte[] tech) {
String[] tech_mask_list = {
"TECHNOLOGY_A", "TECHNOLOGY_B", "TECHNOLOGY_F", "TECHNOLOGY_V"
};
- if (value > tech_mask_list.length) {
+ if (tech[0] > tech_mask_list.length) {
return "UNSUPPORTED_TECH";
}
- return tech_mask_list[value];
+ return tech_mask_list[tech[0]];
}
- private String getProtoStr(int value) {
+ private String getProtoStr(byte[] proto) {
String[] proto_mask_list = {
"PROTOCOL_UNDETERMINED", "PROTOCOL_T1T", "PROTOCOL_T2T", "PROTOCOL_T3T",
"PROTOCOL_ISO_DEP", "PROTOCOL_NFC_DEP", "PROTOCOL_T5T", "PROTOCOL_NDEF"
};
- if (value > proto_mask_list.length) {
+ if (proto[0] > proto_mask_list.length) {
return "UNSUPPORTED_PROTO";
}
- return proto_mask_list[value];
+ return proto_mask_list[proto[0]];
}
- private String getAidStr(byte[] rt, int offset, int aidLen) {
- String Aid = "";
- for (int i = 0; i < aidLen; i++) {
- Aid += String.format("%02X", rt[offset + i]);
+ private String getAidStr(byte[] aid) {
+ String aidStr = "";
+
+ for (byte b : aid) {
+ aidStr += String.format("%02X", b);
}
- if (Aid.length() == 0) {
+ if (aidStr.length() == 0) {
return "Empty_AID";
}
- return "AID_" + Aid;
+ return "AID_" + aidStr;
}
- private String getSystemCodeStr(byte[] rt, int offset, int scLen) {
- String SystemCode = "";
- for (int i = 0; i < scLen; i++) {
- SystemCode += String.format("%02X", rt[offset + i]);
+ private String getSystemCodeStr(byte[] sc) {
+ String systemCodeStr = "";
+ for (byte b : sc) {
+ systemCodeStr += String.format("%02X", b);
}
- return "SYSTEMCODE_" + SystemCode;
+ return "SYSTEMCODE_" + systemCodeStr;
}
- private String getBlockCtrlStr(int mask) {
+ private String getBlockCtrlStr(byte mask) {
if ((mask & 0x40) != 0) {
return "True";
}
return "False";
}
- private String getPrefixSubsetStr(int mask) {
+ private String getPrefixSubsetStr(byte mask, byte type) {
+ if (type != TYPE_AID) {
+ return "";
+ }
+
String prefix_subset_str = "";
if ((mask & 0x10) != 0) {
prefix_subset_str += "Prefix ";
@@ -98,84 +135,172 @@ public class RoutingTableParser {
return String.format(fmt, entry, eeId, pwrState, blkCtrl, extra);
}
- private void dumpTechEntry(byte[] rt, int rtSize, PrintWriter pw, int offset) {
- if (offset + 4 >= rtSize) return;
+ private class RoutingEntryInfo {
+ public final byte mQualifier;
+ public final byte mType;
+ public final byte mNfceeId;
+ public final byte mPowerState;
+ public final byte[] mEntry;
+
+ private RoutingEntryInfo(byte qualifier, byte type, byte eeId, byte pwrState,
+ byte[] entry) {
+ mQualifier = qualifier;
+ mType = type;
+ mNfceeId = eeId;
+ mPowerState = pwrState;
+ mEntry = entry;
+ }
- String blkCtrl = getBlockCtrlStr(rt[offset] & 0xF0);
- String eeId = String.format("0x%02X", rt[offset + 2]);
- String pwrState = String.format("0x%02X", rt[offset + 3]);
- String entry = getTechStr(rt[offset + 4]);
+ private void dump(PrintWriter pw) {
+ String blkCtrl = getBlockCtrlStr(mQualifier);
+ String eeId = String.format("0x%02X", mNfceeId);
+ String pwrState = String.format("0x%02X", mPowerState);
+ String entry = mGetEntryStrFuncs[mType].getEntryStr(mEntry);
+ String extra = getPrefixSubsetStr(mQualifier, mType);
- pw.println(formatRow(entry, eeId, pwrState, blkCtrl, ""));
+ pw.println(formatRow(entry, eeId, pwrState, blkCtrl, extra));
+ }
}
- private void dumpProtoEntry(byte[] rt, int rtSize, PrintWriter pw, int offset) {
- if (offset + 4 >= rtSize) return;
+ private boolean validateEntryInfo(byte type, byte[] entry) {
+ switch(type) {
+ case TYPE_TECHNOLOGY:
+ if (entry.length != 1) return false;
+ break;
+ case TYPE_PROTOCOL:
+ if (entry.length != 1) return false;
+ break;
+ case TYPE_AID:
+ if (entry.length > 16) return false;
+ break;
+ case TYPE_SYSTEMCODE:
+ if (entry.length != 2) return false;
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
- String blkCtrl = getBlockCtrlStr(rt[offset] & 0xF0);
- String eeId = String.format("0x%02X", rt[offset + 2]);
- String pwrState = String.format("0x%02X", rt[offset + 3]);
- String entry = getProtoStr(rt[offset + 4]);
+ /**
+ * Check commit status by inputting type and entry
+ */
+ public int getCommitStatus(byte type, byte[] entry) {
+ if (!validateEntryInfo(type, entry)) return STATS_NOT_FOUND;
- pw.println(formatRow(entry, eeId, pwrState, blkCtrl, ""));
+ for (RoutingEntryInfo routingEntry : sRoutingTable) {
+ if (routingEntry.mType != type) {
+ continue;
+ }
+ if (Arrays.equals(routingEntry.mEntry, entry)) {
+ return routingEntry.mNfceeId == 0x00 ? STATS_HOST_OK : STATS_OFFHOST_OK;
+ }
+ if (routingEntry.mType != TYPE_AID) {
+ continue;
+ }
+ if ((routingEntry.mQualifier & 0x10) != 0
+ && entry.length > routingEntry.mEntry.length) {
+ int ptr = 0;
+ while (entry[ptr] == routingEntry.mEntry[ptr]) {
+ ptr += 1;
+ }
+ if (ptr == routingEntry.mEntry.length) {
+ return routingEntry.mNfceeId == 0x00 ? STATS_HOST_OK : STATS_OFFHOST_OK;
+ }
+ }
+ if ((routingEntry.mQualifier & 0x20) != 0
+ && entry.length < routingEntry.mEntry.length) {
+ int ptr = 0;
+ while (entry[ptr] == routingEntry.mEntry[ptr]) {
+ ptr += 1;
+ }
+ if (ptr == entry.length) {
+ return routingEntry.mNfceeId == 0x00 ? STATS_HOST_OK : STATS_OFFHOST_OK;
+ }
+ }
+ }
+ return STATS_NOT_FOUND;
}
- private void dumpAidEntry(byte[] rt, int rtSize, PrintWriter pw, int offset) {
- if (offset + 4 + rt[offset + 1] - 2 >= rtSize) return;
+ private void addRoutingEntry(byte[] rt, int offset) {
+ if (offset + 1 >= rt.length) return;
+ int valueLength = rt[offset + 1];
+
+ // Qualifier-Type(1 byte) + Length(1 byte) + Value(valueLength bytes)
+ if (offset + 2 + valueLength > rt.length) return;
- String blkCtrl = getBlockCtrlStr(rt[offset] & 0xF0);
- String extra = getPrefixSubsetStr(rt[offset] & 0xF0);
- String eeId = String.format("0x%02X", rt[offset + 2]);
- String pwrState = String.format("0x%02X", rt[offset + 3]);
- String entry = getAidStr(rt, offset + 4, rt[offset + 1] - 2);
+ byte qualifier = (byte) (rt[offset] & 0xF0);
+ byte type = (byte) (rt[offset] & 0x0F);
+ byte eeId = rt[offset + 2];
+ byte pwrState = rt[offset + 3];
+ byte[] entry = new byte[valueLength - 2];
+ for (int i = 0; i < valueLength - 2; i++) {
+ entry[i] = rt[offset + 4 + i];
+ }
- pw.println(formatRow(entry, eeId, pwrState, blkCtrl, extra));
+ if (type == TYPE_SYSTEMCODE && (entry.length & 1) == 0 && entry.length <= 64) {
+ for (int i = 0; i < entry.length; i += 2) {
+ byte[] sc_entry = {entry[i], entry[i + 1]};
+ sRoutingTable.add(new RoutingEntryInfo(qualifier, type, eeId, pwrState, sc_entry));
+ }
+ } else if (validateEntryInfo(type, entry)) {
+ sRoutingTable.add(new RoutingEntryInfo(qualifier, type, eeId, pwrState, entry));
+ }
}
- private void dumpSystemEntry(byte[] rt, int rtSize, PrintWriter pw, int offset) {
- if (offset + 4 + rt[offset + 1] - 2 >= rtSize) return;
+ /**
+ * Parse the raw data of routing table
+ */
+ public void parse(byte[] rt) {
+ int offset = 0;
+
+ logRoutingTableRawData(rt);
+
+ sRoutingTable.clear();
+ while (offset < rt.length) {
+ byte type = (byte) (rt[offset] & 0x0F);
+ if (type >= TYPE_UNSUPPORTED) {
+ // Unrecognizable entry type
+ Log.e(TAG, String.format("Unrecognizable entry type: 0x%02X, stop parsing", type));
+ return;
+ }
+ if (offset + 1 >= rt.length) {
+ // Buffer overflow
+ Log.e(TAG, String.format("Wrong tlv length, stop parsing"));
+ return;
+ }
+ // Qualifier-Type(1 byte) + Length(1 byte) + Value(valueLength bytes)
+ int tlvLength = rt[offset + 1] + 2;
- String blkCtrl = getBlockCtrlStr(rt[offset] & 0xF0);
- String eeId = String.format("0x%02X", rt[offset + 2]);
- String pwrState = String.format("0x%02X", rt[offset + 3]);
- String entry = getSystemCodeStr(rt, offset + 4, rt[offset + 1] - 2);
+ addRoutingEntry(rt, offset);
- pw.println(formatRow(entry, eeId, pwrState, blkCtrl, ""));
+ offset += tlvLength;
+ }
}
/**
- * Get Routing Table from the last backup lmrt cmd and dump it
+ * Get Routing Table from the last backup lmrt cmd and parse it
*/
- public void dump(DeviceHost dh, PrintWriter pw) {
- int offset = 0;
+ public void update(DeviceHost dh) {
+ sRoutingTableMaxSize = dh.getMaxRoutingTableSize();
byte[] rt = dh.getRoutingTable();
- int maxSize = dh.getMaxRoutingTableSize();
+ sRoutingTableSize = rt.length;
+ parse(rt);
+ }
- logRoutingTableRawData(rt);
+ /**
+ * Get Routing Table from the last backup lmrt cmd and dump it
+ */
+ public void dump(DeviceHost dh, PrintWriter pw) {
+ update(dh);
pw.println("--- dumpRoutingTable: start ---");
- pw.println(String.format(Locale.US, "RoutingTableSize: %d/%d", rt.length, maxSize));
+ pw.println(String.format(Locale.US, "RoutingTableSize: %d/%d",
+ sRoutingTableSize, sRoutingTableMaxSize));
pw.println(formatRow("Entry", "NFCEE_ID", "Power State", "Block Ctrl", "Extra Info"));
- while (offset < rt.length) {
- int type = rt[offset] & 0x0F;
- if (type == 0x00) {
- // Technology-based routing entry
- dumpTechEntry(rt, rt.length, pw, offset);
- } else if (type == 0x01) {
- // Protocol-based routing entry
- dumpProtoEntry(rt, rt.length, pw, offset);
- } else if (type == 0x02) {
- // AID-based routing entry
- dumpAidEntry(rt, rt.length, pw, offset);
- } else if (type == 0x03) {
- // System Code-based routing entry
- dumpSystemEntry(rt, rt.length, pw, offset);
- } else {
- // Unrecognizable entry type
- Log.d(TAG, String.format("Unrecognizable entry type: 0x%02X, stop parsing", type));
- break;
- }
- offset += rt[offset+1] + 2;
+
+ for (RoutingEntryInfo routingEntry : sRoutingTable) {
+ routingEntry.dump(pw);
}
pw.println("--- dumpRoutingTable: end ---");
@@ -184,10 +309,11 @@ public class RoutingTableParser {
private void logRoutingTableRawData(byte[] lmrt_cmd) {
if (!DBG) return;
String lmrt_str = "";
- for (int i = 0; i < lmrt_cmd.length; i++) {
- lmrt_str += String.format("%02X ", lmrt_cmd[i]);
+
+ for (byte b : lmrt_cmd) {
+ lmrt_str += String.format("%02X ", b);
}
- Log.d(TAG, String.format("RoutingTableSize: %d", lmrt_cmd.length));
- Log.d(TAG, String.format("RoutingTable: %s", lmrt_str));
+ Log.i(TAG, String.format("RoutingTableSize: %d", lmrt_cmd.length));
+ Log.i(TAG, String.format("RoutingTable: %s", lmrt_str));
}
}