summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChloe Dai <chloedai@google.com>2022-01-13 10:32:39 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2022-01-13 10:32:39 +0000
commita00dbb0b9ce02ef09f37d3caed0ad05d36b63542 (patch)
tree20983da7a06d782bad53788acbf1265b3bf7ea1c /src
parent133d44c80c1723d9d1abe6151f902412b44fc39f (diff)
parentf84e6e7f9d0a854c6cf9e4d488b143fe0d05a74f (diff)
downloadNfc-a00dbb0b9ce02ef09f37d3caed0ad05d36b63542.tar.gz
Merge "Add routing table dumping function to dumpsys nfc"
Diffstat (limited to 'src')
-rw-r--r--src/com/android/nfc/DeviceHost.java11
-rw-r--r--src/com/android/nfc/NfcService.java5
-rw-r--r--src/com/android/nfc/RoutingTableParser.java193
3 files changed, 209 insertions, 0 deletions
diff --git a/src/com/android/nfc/DeviceHost.java b/src/com/android/nfc/DeviceHost.java
index 4ffbe824..a42c1484 100644
--- a/src/com/android/nfc/DeviceHost.java
+++ b/src/com/android/nfc/DeviceHost.java
@@ -19,6 +19,7 @@ package com.android.nfc;
import android.annotation.Nullable;
import android.nfc.NdefMessage;
import android.os.Bundle;
+
import java.io.FileDescriptor;
import java.io.IOException;
@@ -264,6 +265,16 @@ public interface DeviceHost {
public String getNfaStorageDir();
/**
+ * Get the committed listen mode routing configuration
+ */
+ byte[] getRoutingTable();
+
+ /**
+ * Get the Max Routing Table size from cache
+ */
+ int getMaxRoutingTableSize();
+
+ /**
* Start or stop RF polling
*/
void startStopPolling(boolean enable);
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index 7ae0660a..4b6c0906 100644
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -322,6 +322,7 @@ public class NfcService implements DeviceHostListener {
TagService mNfcTagService;
NfcAdapterService mNfcAdapter;
NfcDtaService mNfcDtaService;
+ RoutingTableParser mRoutingTableParser;
boolean mIsDebugBuild;
boolean mIsHceCapable;
boolean mIsHceFCapable;
@@ -469,6 +470,7 @@ public class NfcService implements DeviceHostListener {
mNfcTagService = new TagService();
mNfcAdapter = new NfcAdapterService();
+ mRoutingTableParser = new RoutingTableParser();
Log.i(TAG, "Starting NFC service");
sService = this;
@@ -3420,6 +3422,9 @@ public class NfcService implements DeviceHostListener {
mCardEmulationManager.dump(fd, pw, args);
}
mNfcDispatcher.dump(fd, pw, args);
+ if (mState == NfcAdapter.STATE_ON) {
+ mRoutingTableParser.dump(mDeviceHost, pw);
+ }
copyNativeCrashLogsIfAny(pw);
pw.flush();
mDeviceHost.dump(fd);
diff --git a/src/com/android/nfc/RoutingTableParser.java b/src/com/android/nfc/RoutingTableParser.java
new file mode 100644
index 00000000..d2c7f1ad
--- /dev/null
+++ b/src/com/android/nfc/RoutingTableParser.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2021 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.nfc;
+
+import android.os.SystemProperties;
+import java.util.Locale;
+import android.util.Log;
+
+import java.io.PrintWriter;
+
+/**
+* Parse the Routing Table from the last backup lmrt cmd and dump it with a clear typography
+*/
+public class RoutingTableParser {
+ static final boolean DBG = SystemProperties.getBoolean("persist.nfc.debug_enabled", false);
+ private static final String TAG = "RoutingTableParser";
+
+ private String getTechStr(int value) {
+ String[] tech_mask_list = {
+ "TECHNOLOGY_A", "TECHNOLOGY_B", "TECHNOLOGY_F", "TECHNOLOGY_V"
+ };
+
+ if (value > tech_mask_list.length) {
+ return "UNSUPPORTED_TECH";
+ }
+ return tech_mask_list[value];
+ }
+
+ private String getProtoStr(int value) {
+ 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) {
+ return "UNSUPPORTED_PROTO";
+ }
+ return proto_mask_list[value];
+ }
+
+ 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]);
+ }
+
+ if (Aid.length() == 0) {
+ return "Empty_AID";
+ }
+ return "AID_" + Aid;
+ }
+
+ 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]);
+ }
+ return "SYSTEMCODE_" + SystemCode;
+ }
+
+ private String getBlockCtrlStr(int mask) {
+ if ((mask & 0x40) != 0) {
+ return "True";
+ }
+ return "False";
+ }
+
+ private String getPrefixSubsetStr(int mask) {
+ String prefix_subset_str = "";
+ if ((mask & 0x10) != 0) {
+ prefix_subset_str += "Prefix ";
+ }
+ if ((mask & 0x20) != 0) {
+ prefix_subset_str += "Subset";
+ }
+ if (prefix_subset_str.equals("")){
+ return "Exact";
+ }
+ return prefix_subset_str;
+ }
+
+ private String formatRow(String entry, String eeId,
+ String pwrState, String blkCtrl, String extra) {
+ String fmt = "\t%-36s\t%8s\t%-11s\t%-10s\t%-10s";
+ 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;
+
+ 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]);
+
+ pw.println(formatRow(entry, eeId, pwrState, blkCtrl, ""));
+ }
+
+ private void dumpProtoEntry(byte[] rt, int rtSize, PrintWriter pw, int offset) {
+ if (offset + 4 >= rtSize) return;
+
+ 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]);
+
+ pw.println(formatRow(entry, eeId, pwrState, blkCtrl, ""));
+ }
+
+ private void dumpAidEntry(byte[] rt, int rtSize, PrintWriter pw, int offset) {
+ if (offset + 4 + rt[offset + 1] - 2 >= rtSize) 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);
+
+ pw.println(formatRow(entry, eeId, pwrState, blkCtrl, extra));
+ }
+
+ private void dumpSystemEntry(byte[] rt, int rtSize, PrintWriter pw, int offset) {
+ if (offset + 4 + rt[offset + 1] - 2 >= rtSize) return;
+
+ 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);
+
+ pw.println(formatRow(entry, eeId, pwrState, blkCtrl, ""));
+ }
+
+ /**
+ * Get Routing Table from the last backup lmrt cmd and dump it
+ */
+ public void dump(DeviceHost dh, PrintWriter pw) {
+ int offset = 0;
+ byte[] rt = dh.getRoutingTable();
+ int maxSize = dh.getMaxRoutingTableSize();
+
+ logRoutingTableRawData(rt);
+
+ pw.println("--- dumpRoutingTable: start ---");
+ pw.println(String.format(Locale.US, "RoutingTableSize: %d/%d", rt.length, maxSize));
+ 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;
+ }
+
+ pw.println("--- dumpRoutingTable: end ---");
+ }
+
+ 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]);
+ }
+ Log.d(TAG, String.format("RoutingTableSize: %d", lmrt_cmd.length));
+ Log.d(TAG, String.format("RoutingTable: %s", lmrt_str));
+ }
+}