Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f25c4eb7 authored by Paul McLean's avatar Paul McLean
Browse files

Adding ability to control how the USB data is dumped.

Also added tracing to android.UsbDevice creation.

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

Change-Id: I2ec05dfa9c544d0c50ee59e3b990e9010cbe0aa0
parent 7310f4f3
Loading
Loading
Loading
Loading
+117 −33
Original line number Diff line number Diff line
@@ -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,10 +294,16 @@ public class UsbHostManager {
            if (parser.parseDescriptors(descriptors)) {

                UsbDevice newDevice = parser.toAndroidUsbDevice();
                if (newDevice == null) {
                    Slog.e(TAG, "Couldn't create UsbDevice object.");
                    // Tracking
                    addConnectionRecord(deviceAddress, ConnectionRecord.CONNECT_BADDEVICE,
                            parser.getRawDescriptors());
                } else {
                    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.
                    // 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);
@@ -264,8 +323,12 @@ public class UsbHostManager {
                    // 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,19 +409,36 @@ 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);
            }

        }

        mUsbAlsaManager.dump(pw);
    }

    /**
     * Dump various descriptor data.
     */
    public void dumpDescriptors(IndentingPrintWriter pw, String[] args) {
        if (mLastConnect != null) {
            pw.println("Last Connected USB Device:");
                mLastConnect.dumpLong(pw);
            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.");
        }

        mUsbAlsaManager.dump(pw);
    }

    private native void monitorUsbHostBus();
+16 −8
Original line number Diff line number Diff line
@@ -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);
+8 −0
Original line number Diff line number Diff line
@@ -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);
        }
+7 −2
Original line number Diff line number Diff line
@@ -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;
    }

    /**
+13 −0
Original line number Diff line number Diff line
@@ -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);
        }
Loading