OSDN Git Service

Adding ability to control how the USB data is dumped.
authorPaul McLean <pmclean@google.com>
Mon, 11 Dec 2017 15:36:41 +0000 (08:36 -0700)
committerPaul McLean <pmclean@google.com>
Wed, 13 Dec 2017 20:33:40 +0000 (13:33 -0700)
Also added tracing to android.UsbDevice creation.

Test: Try each dump command with CALYX Pat USB DAC & Dragonfly Red USB DAC

Change-Id: I2ec05dfa9c544d0c50ee59e3b990e9010cbe0aa0

services/usb/java/com/android/server/usb/UsbHostManager.java
services/usb/java/com/android/server/usb/UsbService.java
services/usb/java/com/android/server/usb/descriptors/UsbConfigDescriptor.java
services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java
services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
services/usb/java/com/android/server/usb/descriptors/UsbInterfaceDescriptor.java

index e76d211..7a352a4 100644 (file)
@@ -28,6 +28,7 @@ import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.usb.descriptors.UsbDescriptor;
 import com.android.server.usb.descriptors.UsbDescriptorParser;
 import com.android.server.usb.descriptors.UsbDeviceDescriptor;
 import com.android.server.usb.descriptors.report.TextReportCanvas;
@@ -84,7 +85,10 @@ public class UsbHostManager {
         String mDeviceAddress;
 
         static final int CONNECT = 0;
-        static final int DISCONNECT = 1;
+        static final int CONNECT_BADPARSE = 1;
+        static final int CONNECT_BADDEVICE = 2;
+        static final int DISCONNECT = -1;
+
         final int mMode;
         final byte[] mDescriptors;
 
@@ -100,8 +104,8 @@ public class UsbHostManager {
         }
 
         void dumpShort(IndentingPrintWriter pw) {
-            if (mMode == CONNECT) {
-                pw.println(formatTime() + " Connect " + mDeviceAddress);
+            if (mMode != DISCONNECT) {
+                pw.println(formatTime() + " Connect " + mDeviceAddress + " mode:" + mMode);
                 UsbDescriptorParser parser = new UsbDescriptorParser(mDeviceAddress, mDescriptors);
 
                 UsbDeviceDescriptor deviceDescriptor = parser.getDeviceDescriptor();
@@ -115,9 +119,9 @@ public class UsbHostManager {
             }
         }
 
-        void dumpLong(IndentingPrintWriter pw) {
-            if (mMode == CONNECT) {
-                pw.println(formatTime() + " Connect " + mDeviceAddress);
+        void dumpTree(IndentingPrintWriter pw) {
+            if (mMode != DISCONNECT) {
+                pw.println(formatTime() + " Connect " + mDeviceAddress + " mode:" + mMode);
                 UsbDescriptorParser parser = new UsbDescriptorParser(mDeviceAddress, mDescriptors);
                 StringBuilder stringBuilder = new StringBuilder();
                 UsbDescriptorsTree descriptorTree = new UsbDescriptorsTree();
@@ -131,6 +135,55 @@ public class UsbHostManager {
                 pw.println(formatTime() + " Disconnect " + mDeviceAddress);
             }
         }
+
+        void dumpList(IndentingPrintWriter pw) {
+            if (mMode != DISCONNECT) {
+                pw.println(formatTime() + " Connect " + mDeviceAddress + " mode:" + mMode);
+                UsbDescriptorParser parser = new UsbDescriptorParser(mDeviceAddress, mDescriptors);
+                StringBuilder stringBuilder = new StringBuilder();
+                TextReportCanvas canvas = new TextReportCanvas(parser, stringBuilder);
+                for (UsbDescriptor descriptor : parser.getDescriptors()) {
+                    descriptor.report(canvas);
+                }
+                pw.println(stringBuilder.toString());
+
+                pw.println("isHeadset[in: " + parser.isInputHeadset()
+                        + " , out: " + parser.isOutputHeadset() + "]");
+            } else {
+                pw.println(formatTime() + " Disconnect " + mDeviceAddress);
+            }
+        }
+
+        private static final int kDumpBytesPerLine = 16;
+
+        void dumpRaw(IndentingPrintWriter pw) {
+            if (mMode != DISCONNECT) {
+                pw.println(formatTime() + " Connect " + mDeviceAddress + " mode:" + mMode);
+                int length = mDescriptors.length;
+                pw.println("Raw Descriptors " + length + " bytes");
+                int dataOffset = 0;
+                for (int line = 0; line < length / kDumpBytesPerLine; line++) {
+                    StringBuilder sb = new StringBuilder();
+                    for (int offset = 0; offset < kDumpBytesPerLine; offset++) {
+                        sb.append("0x")
+                            .append(String.format("0x%02X", mDescriptors[dataOffset++]))
+                            .append(" ");
+                    }
+                    pw.println(sb.toString());
+                }
+
+                // remainder
+                StringBuilder sb = new StringBuilder();
+                while (dataOffset < length) {
+                    sb.append("0x")
+                        .append(String.format("0x%02X", mDescriptors[dataOffset++]))
+                        .append(" ");
+                }
+                pw.println(sb.toString());
+            } else {
+                pw.println(formatTime() + " Disconnect " + mDeviceAddress);
+            }
+        }
     }
 
     /*
@@ -205,7 +258,7 @@ public class UsbHostManager {
         ConnectionRecord rec =
                 new ConnectionRecord(deviceAddress, mode, rawDescriptors);
         mConnections.add(rec);
-        if (mode == ConnectionRecord.CONNECT) {
+        if (mode != ConnectionRecord.DISCONNECT) {
             mLastConnect = rec;
         }
     }
@@ -241,31 +294,41 @@ public class UsbHostManager {
             if (parser.parseDescriptors(descriptors)) {
 
                 UsbDevice newDevice = parser.toAndroidUsbDevice();
-                mDevices.put(deviceAddress, newDevice);
-
-                // It is fine to call this only for the current user as all broadcasts are sent to
-                // all profiles of the user and the dialogs should only show once.
-                ComponentName usbDeviceConnectionHandler = getUsbDeviceConnectionHandler();
-                if (usbDeviceConnectionHandler == null) {
-                    getCurrentUserSettings().deviceAttached(newDevice);
+                if (newDevice == null) {
+                    Slog.e(TAG, "Couldn't create UsbDevice object.");
+                    // Tracking
+                    addConnectionRecord(deviceAddress, ConnectionRecord.CONNECT_BADDEVICE,
+                            parser.getRawDescriptors());
                 } else {
-                    getCurrentUserSettings().deviceAttachedForFixedHandler(newDevice,
-                            usbDeviceConnectionHandler);
+                    mDevices.put(deviceAddress, newDevice);
+
+                    // It is fine to call this only for the current user as all broadcasts are
+                    // sent to all profiles of the user and the dialogs should only show once.
+                    ComponentName usbDeviceConnectionHandler = getUsbDeviceConnectionHandler();
+                    if (usbDeviceConnectionHandler == null) {
+                        getCurrentUserSettings().deviceAttached(newDevice);
+                    } else {
+                        getCurrentUserSettings().deviceAttachedForFixedHandler(newDevice,
+                                usbDeviceConnectionHandler);
+                    }
+
+                    // Headset?
+                    boolean isInputHeadset = parser.isInputHeadset();
+                    boolean isOutputHeadset = parser.isOutputHeadset();
+                    Slog.i(TAG, "---- isHeadset[in: " + isInputHeadset
+                            + " , out: " + isOutputHeadset + "]");
+
+                    mUsbAlsaManager.usbDeviceAdded(newDevice, isInputHeadset, isOutputHeadset);
+
+                    // Tracking
+                    addConnectionRecord(deviceAddress, ConnectionRecord.CONNECT,
+                            parser.getRawDescriptors());
                 }
-
-                // Headset?
-                boolean isInputHeadset = parser.isInputHeadset();
-                boolean isOutputHeadset = parser.isOutputHeadset();
-                Slog.i(TAG, "---- isHeadset[in: " + isInputHeadset
-                        + " , out: " + isOutputHeadset + "]");
-
-                mUsbAlsaManager.usbDeviceAdded(newDevice, isInputHeadset, isOutputHeadset);
-
-                // Tracking
-                addConnectionRecord(deviceAddress, ConnectionRecord.CONNECT,
-                        parser.getRawDescriptors());
             } else {
                 Slog.e(TAG, "Error parsing USB device descriptors for " + deviceAddress);
+                // Tracking
+                addConnectionRecord(deviceAddress, ConnectionRecord.CONNECT_BADPARSE,
+                        parser.getRawDescriptors());
                 return false;
             }
         }
@@ -330,7 +393,11 @@ public class UsbHostManager {
         }
     }
 
-    public void dump(IndentingPrintWriter pw) {
+    /**
+     * Dump out various information about the state of USB device connections.
+     *
+     */
+    public void dump(IndentingPrintWriter pw, String[] args) {
         pw.println("USB Host State:");
         synchronized (mHandlerLock) {
             if (mUsbDeviceConnectionHandler != null) {
@@ -342,21 +409,38 @@ public class UsbHostManager {
                 pw.println("  " + name + ": " + mDevices.get(name));
             }
 
+            // Connections
             pw.println("" + mNumConnects + " total connects/disconnects");
             pw.println("Last " + mConnections.size() + " connections/disconnections");
             for (ConnectionRecord rec : mConnections) {
                 rec.dumpShort(pw);
             }
 
-            if (mLastConnect != null) {
-                pw.println("Last Connected USB Device:");
-                mLastConnect.dumpLong(pw);
-            }
         }
 
         mUsbAlsaManager.dump(pw);
     }
 
+    /**
+     * Dump various descriptor data.
+     */
+    public void dumpDescriptors(IndentingPrintWriter pw, String[] args) {
+        if (mLastConnect != null) {
+            pw.println("Last Connected USB Device:");
+            if (args.length <= 1 || args[1].equals("-dump-short")) {
+                mLastConnect.dumpShort(pw);
+            } else if (args[1].equals("-dump-tree")) {
+                mLastConnect.dumpTree(pw);
+            } else if (args[1].equals("-dump-list")) {
+                mLastConnect.dumpList(pw);
+            }  else if (args[1].equals("-dump-raw")) {
+                mLastConnect.dumpRaw(pw);
+            }
+        } else {
+            pw.println("No USB Devices have been connected.");
+        }
+    }
+
     private native void monitorUsbHostBus();
     private native ParcelFileDescriptor nativeOpenDevice(String deviceAddress);
 }
index 17de83f..8554cf7 100644 (file)
@@ -496,7 +496,7 @@ public class UsbService extends IUsbManager.Stub {
                     mDeviceManager.dump(pw);
                 }
                 if (mHostManager != null) {
-                    mHostManager.dump(pw);
+                    mHostManager.dump(pw, args);
                 }
                 if (mPortManager != null) {
                     mPortManager.dump(pw);
@@ -504,7 +504,7 @@ public class UsbService extends IUsbManager.Stub {
                 mAlsaManager.dump(pw);
 
                 mSettingsManager.dump(pw);
-            } else if (args.length == 4 && "set-port-roles".equals(args[0])) {
+            } else if ("set-port-roles".equals(args[0]) && args.length == 4) {
                 final String portId = args[1];
                 final int powerRole;
                 switch (args[2]) {
@@ -546,7 +546,7 @@ public class UsbService extends IUsbManager.Stub {
                     pw.println();
                     mPortManager.dump(pw);
                 }
-            } else if (args.length == 3 && "add-port".equals(args[0])) {
+            } else if ("add-port".equals(args[0]) && args.length == 3) {
                 final String portId = args[1];
                 final int supportedModes;
                 switch (args[2]) {
@@ -571,7 +571,7 @@ public class UsbService extends IUsbManager.Stub {
                     pw.println();
                     mPortManager.dump(pw);
                 }
-            } else if (args.length == 5 && "connect-port".equals(args[0])) {
+            } else if ("connect-port".equals(args[0]) && args.length == 5) {
                 final String portId = args[1];
                 final int mode;
                 final boolean canChangeMode = args[2].endsWith("?");
@@ -618,30 +618,32 @@ public class UsbService extends IUsbManager.Stub {
                     pw.println();
                     mPortManager.dump(pw);
                 }
-            } else if (args.length == 2 && "disconnect-port".equals(args[0])) {
+            } else if ("disconnect-port".equals(args[0]) && args.length == 2) {
                 final String portId = args[1];
                 if (mPortManager != null) {
                     mPortManager.disconnectSimulatedPort(portId, pw);
                     pw.println();
                     mPortManager.dump(pw);
                 }
-            } else if (args.length == 2 && "remove-port".equals(args[0])) {
+            } else if ("remove-port".equals(args[0]) && args.length == 2) {
                 final String portId = args[1];
                 if (mPortManager != null) {
                     mPortManager.removeSimulatedPort(portId, pw);
                     pw.println();
                     mPortManager.dump(pw);
                 }
-            } else if (args.length == 1 && "reset".equals(args[0])) {
+            } else if ("reset".equals(args[0]) && args.length == 1) {
                 if (mPortManager != null) {
                     mPortManager.resetSimulation(pw);
                     pw.println();
                     mPortManager.dump(pw);
                 }
-            } else if (args.length == 1 && "ports".equals(args[0])) {
+            } else if ("ports".equals(args[0]) && args.length == 1) {
                 if (mPortManager != null) {
                     mPortManager.dump(pw);
                 }
+            } else if ("dump-descriptors".equals(args[0])) {
+                mHostManager.dumpDescriptors(pw, args);
             } else {
                 pw.println("Dump current USB state or issue command:");
                 pw.println("  ports");
@@ -678,6 +680,12 @@ public class UsbService extends IUsbManager.Stub {
                 pw.println("  dumpsys usb add-port \"matrix\" ufp");
                 pw.println("  dumpsys usb connect-port \"matrix\" ufp sink device");
                 pw.println("  dumpsys usb reset");
+                pw.println();
+                pw.println("Example USB device descriptors:");
+                pw.println("  dumpsys usb dump-descriptors -dump-short");
+                pw.println("  dumpsys usb dump-descriptors -dump-tree");
+                pw.println("  dumpsys usb dump-descriptors -dump-list");
+                pw.println("  dumpsys usb dump-descriptors -dump-raw");
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
index 993778f..639aa4e 100644 (file)
@@ -17,6 +17,7 @@ package com.android.server.usb.descriptors;
 
 import android.hardware.usb.UsbConfiguration;
 import android.hardware.usb.UsbInterface;
+import android.util.Log;
 
 import com.android.server.usb.descriptors.report.ReportCanvas;
 
@@ -29,6 +30,7 @@ import java.util.ArrayList;
  */
 public final class UsbConfigDescriptor extends UsbDescriptor {
     private static final String TAG = "UsbConfigDescriptor";
+    private static final boolean DEBUG = false;
 
     private int mTotalLength;    // 2:2 Total length in bytes of data returned
     private byte mNumInterfaces; // 4:1 Number of Interfaces
@@ -77,10 +79,16 @@ public final class UsbConfigDescriptor extends UsbDescriptor {
     }
 
     UsbConfiguration toAndroid(UsbDescriptorParser parser) {
+        if (DEBUG) {
+            Log.d(TAG, "  toAndroid()");
+        }
         String name = parser.getDescriptorString(mConfigIndex);
         UsbConfiguration config = new
                 UsbConfiguration(mConfigValue, name, mAttribs, mMaxPower);
         UsbInterface[] interfaces = new UsbInterface[mInterfaceDescriptors.size()];
+        if (DEBUG) {
+            Log.d(TAG, "    " + mInterfaceDescriptors.size() + " interfaces.");
+        }
         for (int index = 0; index < mInterfaceDescriptors.size(); index++) {
             interfaces[index] = mInterfaceDescriptors.get(index).toAndroid(parser);
         }
index 78c7fdc..7a1e9e2 100644 (file)
@@ -26,7 +26,7 @@ import java.util.ArrayList;
  */
 public final class UsbDescriptorParser {
     private static final String TAG = "UsbDescriptorParser";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;
 
     private final String mDeviceAddr;
 
@@ -289,10 +289,15 @@ public final class UsbDescriptorParser {
      */
     public UsbDevice toAndroidUsbDevice() {
         if (mDeviceDescriptor == null) {
+            Log.e(TAG, "toAndroidUsbDevice() ERROR - No Device Descriptor");
             return null;
         }
 
-        return mDeviceDescriptor.toAndroid(this);
+        UsbDevice device = mDeviceDescriptor.toAndroid(this);
+        if (device == null) {
+            Log.e(TAG, "toAndroidUsbDevice() ERROR Creating Device");
+        }
+        return device;
     }
 
     /**
index 8e7f0fd..e31e3a3 100644 (file)
@@ -17,6 +17,7 @@ package com.android.server.usb.descriptors;
 
 import android.hardware.usb.UsbConfiguration;
 import android.hardware.usb.UsbDevice;
+import android.util.Log;
 
 import com.android.server.usb.descriptors.report.ReportCanvas;
 import com.android.server.usb.descriptors.report.UsbStrings;
@@ -30,6 +31,7 @@ import java.util.ArrayList;
  */
 public final class UsbDeviceDescriptor extends UsbDescriptor {
     private static final String TAG = "UsbDeviceDescriptor";
+    private static final boolean DEBUG = false;
 
     public static final int USBSPEC_1_0 = 0x0100;
     public static final int USBSPEC_1_1 = 0x0110;
@@ -113,19 +115,30 @@ public final class UsbDeviceDescriptor extends UsbDescriptor {
      * @hide
      */
     public UsbDevice toAndroid(UsbDescriptorParser parser) {
+        if (DEBUG) {
+            Log.d(TAG, "toAndroid()");
+        }
+
         String mfgName = parser.getDescriptorString(mMfgIndex);
         String prodName = parser.getDescriptorString(mProductIndex);
+        if (DEBUG) {
+            Log.d(TAG, "  mfgName:" + mfgName + " prodName:" + prodName);
+        }
 
         // Create version string in "%.%" format
         String versionString =
                 Integer.toString(mDeviceRelease >> 8) + "." + (mDeviceRelease & 0xFF);
         String serialStr = parser.getDescriptorString(mSerialNum);
+        if (DEBUG) {
+            Log.d(TAG, "  versionString:" + versionString + " serialStr:" + serialStr);
+        }
 
         UsbDevice device = new UsbDevice(parser.getDeviceAddr(), mVendorID, mProductID,
                 mDevClass, mDevSubClass,
                 mProtocol, mfgName, prodName,
                 versionString, serialStr);
         UsbConfiguration[] configs = new UsbConfiguration[mConfigDescriptors.size()];
+        Log.d(TAG, "  " + configs.length + " configs");
         for (int index = 0; index < mConfigDescriptors.size(); index++) {
             configs[index] = mConfigDescriptors.get(index).toAndroid(parser);
         }
index 1130238..4da31ea 100644 (file)
@@ -16,6 +16,7 @@
 package com.android.server.usb.descriptors;
 
 import android.hardware.usb.UsbEndpoint;
+import android.util.Log;
 
 import com.android.server.usb.descriptors.report.ReportCanvas;
 
@@ -26,6 +27,7 @@ import com.android.server.usb.descriptors.report.ReportCanvas;
  */
 public class UsbEndpointDescriptor extends UsbDescriptor {
     private static final String TAG = "UsbEndpointDescriptor";
+    private static final boolean DEBUG = false;
 
     public static final int MASK_ENDPOINT_ADDRESS = 0b000000000001111;
     public static final int MASK_ENDPOINT_DIRECTION = (byte) 0b0000000010000000;
@@ -108,6 +110,12 @@ public class UsbEndpointDescriptor extends UsbDescriptor {
     }
 
     /* package */ UsbEndpoint toAndroid(UsbDescriptorParser parser) {
+        if (DEBUG) {
+            Log.d(TAG, "toAndroid() type:"
+                    + Integer.toHexString(mAttributes & MASK_ATTRIBS_TRANSTYPE)
+                    + " sync:" + Integer.toHexString(mAttributes & MASK_ATTRIBS_SYNCTYPE)
+                    + " usage:" + Integer.toHexString(mAttributes & MASK_ATTRIBS_USEAGE));
+        }
         return new UsbEndpoint(mEndpointAddress, mAttributes, mPacketSize, mInterval);
     }
 
index d87b1af..632e3dc 100644 (file)
@@ -17,6 +17,7 @@ package com.android.server.usb.descriptors;
 
 import android.hardware.usb.UsbEndpoint;
 import android.hardware.usb.UsbInterface;
+import android.util.Log;
 
 import com.android.server.usb.descriptors.report.ReportCanvas;
 import com.android.server.usb.descriptors.report.UsbStrings;
@@ -30,6 +31,7 @@ import java.util.ArrayList;
  */
 public class UsbInterfaceDescriptor extends UsbDescriptor {
     private static final String TAG = "UsbInterfaceDescriptor";
+    private static final boolean DEBUG = false;
 
     protected int mInterfaceNumber;   // 2:1 Number of Interface
     protected byte mAlternateSetting; // 3:1 Value used to select alternative setting
@@ -93,6 +95,11 @@ public class UsbInterfaceDescriptor extends UsbDescriptor {
     }
 
     UsbInterface toAndroid(UsbDescriptorParser parser) {
+        if (DEBUG) {
+            Log.d(TAG, "toAndroid() class:" + Integer.toHexString(mUsbClass)
+                    + " subclass:" + Integer.toHexString(mUsbSubclass)
+                    + " " + mEndpointDescriptors.size() + " endpoints.");
+        }
         String name = parser.getDescriptorString(mDescrIndex);
         UsbInterface ntrface = new UsbInterface(
                 mInterfaceNumber, mAlternateSetting, name, mUsbClass, mUsbSubclass, mProtocol);