/*
 * Copyright (C) 2017 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.usb.descriptors;

import android.hardware.usb.UsbDevice;
import android.util.Log;

import java.util.ArrayList;

/**
 * @hide
 * Class for parsing a binary stream of USB Descriptors.
 */
public final class UsbDescriptorParser {
    private static final String TAG = "UsbDescriptorParser";
    public static final boolean DEBUG = false;

    private final String mDeviceAddr;

    private static final int MS_MIDI_1_0 = 0x0100;
    private static final int MS_MIDI_2_0 = 0x0200;

    // Descriptor Objects
    private static final int DESCRIPTORS_ALLOC_SIZE = 128;
    private final ArrayList<UsbDescriptor> mDescriptors;

    private UsbDeviceDescriptor mDeviceDescriptor;
    private UsbConfigDescriptor mCurConfigDescriptor;
    private UsbInterfaceDescriptor mCurInterfaceDescriptor;
    private UsbEndpointDescriptor mCurEndpointDescriptor;

    // The AudioClass spec implemented by the AudioClass Interfaces
    // This may well be different than the overall USB Spec.
    // Obtained from the first AudioClass Header descriptor.
    private int mACInterfacesSpec = UsbDeviceDescriptor.USBSPEC_1_0;

    // The VideoClass spec implemented by the VideoClass Interfaces
    // This may well be different than the overall USB Spec.
    // Obtained from the first VidieoClass Header descriptor.
    private int mVCInterfacesSpec = UsbDeviceDescriptor.USBSPEC_1_0;

    /**
     * Connect this parser to an existing set of already parsed descriptors.
     * This is useful for reporting.
     */
    public UsbDescriptorParser(String deviceAddr, ArrayList<UsbDescriptor> descriptors) {
        mDeviceAddr = deviceAddr;
        mDescriptors = descriptors;
        //TODO some error checking here....
        mDeviceDescriptor = (UsbDeviceDescriptor) descriptors.get(0);
    }

    /**
     * Connect this parser to an byte array containing unparsed (raw) device descriptors
     * to be parsed (and parse them). Useful for parsing a stored descriptor buffer.
     */
    public UsbDescriptorParser(String deviceAddr, byte[] rawDescriptors) {
        mDeviceAddr = deviceAddr;
        mDescriptors = new ArrayList<UsbDescriptor>(DESCRIPTORS_ALLOC_SIZE);
        parseDescriptors(rawDescriptors);
    }

    public String getDeviceAddr() {
        return mDeviceAddr;
    }

    /**
     * @return the USB Spec value associated with the Device descriptor for the
     * descriptors stream being parsed.
     *
     * @throws IllegalArgumentException
     */
    public int getUsbSpec() {
        if (mDeviceDescriptor != null) {
            return mDeviceDescriptor.getSpec();
        } else {
            throw new IllegalArgumentException();
        }
    }

    public void setACInterfaceSpec(int spec) {
        mACInterfacesSpec = spec;
    }

    public int getACInterfaceSpec() {
        return mACInterfacesSpec;
    }

    public void setVCInterfaceSpec(int spec) {
        mVCInterfacesSpec = spec;
    }

    public int getVCInterfaceSpec() {
        return mVCInterfacesSpec;
    }

    private class UsbDescriptorsStreamFormatException extends Exception {
        String mMessage;
        UsbDescriptorsStreamFormatException(String message) {
            mMessage = message;
        }

        public String toString() {
            return "Descriptor Stream Format Exception: " + mMessage;
        }
    }

    /**
     * The probability (as returned by getHeadsetProbability() at which we conclude
     * the peripheral is a headset.
     */
    private static final float IN_HEADSET_TRIGGER = 0.75f;
    private static final float OUT_HEADSET_TRIGGER = 0.75f;

    private UsbDescriptor allocDescriptor(ByteStream stream)
            throws UsbDescriptorsStreamFormatException {
        stream.resetReadCount();

        int length = stream.getUnsignedByte();
        byte type = stream.getByte();

        UsbDescriptor.logDescriptorName(type, length);

        UsbDescriptor descriptor = null;
        switch (type) {
            /*
             * Standard
             */
            case UsbDescriptor.DESCRIPTORTYPE_DEVICE:
                descriptor = mDeviceDescriptor = new UsbDeviceDescriptor(length, type);
                break;

            case UsbDescriptor.DESCRIPTORTYPE_CONFIG:
                descriptor = mCurConfigDescriptor = new UsbConfigDescriptor(length, type);
                if (mDeviceDescriptor != null) {
                    mDeviceDescriptor.addConfigDescriptor(mCurConfigDescriptor);
                } else {
                    Log.e(TAG, "Config Descriptor found with no associated Device Descriptor!");
                    throw new UsbDescriptorsStreamFormatException(
                            "Config Descriptor found with no associated Device Descriptor!");
                }
                break;

            case UsbDescriptor.DESCRIPTORTYPE_INTERFACE:
                descriptor = mCurInterfaceDescriptor = new UsbInterfaceDescriptor(length, type);
                if (mCurConfigDescriptor != null) {
                    mCurConfigDescriptor.addInterfaceDescriptor(mCurInterfaceDescriptor);
                } else {
                    Log.e(TAG, "Interface Descriptor found with no associated Config Descriptor!");
                    throw new UsbDescriptorsStreamFormatException(
                            "Interface Descriptor found with no associated Config Descriptor!");
                }
                break;

            case UsbDescriptor.DESCRIPTORTYPE_ENDPOINT:
                descriptor = mCurEndpointDescriptor = new UsbEndpointDescriptor(length, type);
                if (mCurInterfaceDescriptor != null) {
                    mCurInterfaceDescriptor.addEndpointDescriptor(
                            (UsbEndpointDescriptor) descriptor);
                } else {
                    Log.e(TAG,
                            "Endpoint Descriptor found with no associated Interface Descriptor!");
                    throw new UsbDescriptorsStreamFormatException(
                            "Endpoint Descriptor found with no associated Interface Descriptor!");
                }
                break;

            /*
             * HID
             */
            case UsbDescriptor.DESCRIPTORTYPE_HID:
                descriptor = new UsbHIDDescriptor(length, type);
                break;

            /*
             * Other
             */
            case UsbDescriptor.DESCRIPTORTYPE_INTERFACEASSOC:
                descriptor = new UsbInterfaceAssoc(length, type);
                break;

            /*
             * Various Class Specific
             */
            case UsbDescriptor.DESCRIPTORTYPE_CLASSSPECIFIC_INTERFACE:
                if (mCurInterfaceDescriptor != null) {
                    switch (mCurInterfaceDescriptor.getUsbClass()) {
                        case UsbDescriptor.CLASSID_AUDIO:
                            descriptor =
                                    UsbACInterface.allocDescriptor(this, stream, length, type);
                            if (descriptor instanceof UsbMSMidiHeader) {
                                mCurInterfaceDescriptor.setMidiHeaderInterfaceDescriptor(
                                        descriptor);
                            }
                            break;

                        case UsbDescriptor.CLASSID_VIDEO:
                            if (DEBUG) {
                                Log.d(TAG, "  UsbDescriptor.CLASSID_VIDEO");
                            }
                            descriptor =
                                    UsbVCInterface.allocDescriptor(this, stream, length, type);
                            break;

                        case UsbDescriptor.CLASSID_AUDIOVIDEO:
                            if (DEBUG) {
                                Log.d(TAG, "  UsbDescriptor.CLASSID_AUDIOVIDEO");
                            }
                            break;

                        default:
                            Log.w(TAG, "  Unparsed Class-specific");
                            break;
                    }
                }
                break;

            case UsbDescriptor.DESCRIPTORTYPE_CLASSSPECIFIC_ENDPOINT:
                if (mCurInterfaceDescriptor != null) {
                    int subClass = mCurInterfaceDescriptor.getUsbClass();
                    switch (subClass) {
                        case UsbDescriptor.CLASSID_AUDIO: {
                            Byte subType = stream.getByte();
                            if (DEBUG) {
                                Log.d(TAG, "UsbDescriptor.CLASSID_AUDIO type:0x"
                                        + Integer.toHexString(type));
                            }
                            descriptor = UsbACEndpoint.allocDescriptor(this, length, type,
                                    subType);
                        }
                            break;

                        case UsbDescriptor.CLASSID_VIDEO: {
                            Byte subType = stream.getByte();
                            if (DEBUG) {
                                Log.d(TAG, "UsbDescriptor.CLASSID_VIDEO type:0x"
                                        + Integer.toHexString(type));
                            }
                            descriptor = UsbVCEndpoint.allocDescriptor(this, length, type,
                                    subType);
                        }
                            break;

                        case UsbDescriptor.CLASSID_AUDIOVIDEO:
                            if (DEBUG) {
                                Log.d(TAG, "UsbDescriptor.CLASSID_AUDIOVIDEO type:0x"
                                        + Integer.toHexString(type));
                            }
                            break;

                        default:
                            Log.w(TAG, "  Unparsed Class-specific Endpoint:0x"
                                    + Integer.toHexString(subClass));
                            break;
                    }
                    if (mCurEndpointDescriptor != null && descriptor != null) {
                        mCurEndpointDescriptor.setClassSpecificEndpointDescriptor(descriptor);
                    }
                }
                break;

            default:
                break;
        }

        if (descriptor == null) {
            // Unknown Descriptor
            descriptor = new UsbUnknown(length, type);
        }

        return descriptor;
    }

    public UsbDeviceDescriptor getDeviceDescriptor() {
        return mDeviceDescriptor;
    }

    public UsbInterfaceDescriptor getCurInterface() {
        return mCurInterfaceDescriptor;
    }

    /**
     * @hide
     */
    public void parseDescriptors(byte[] descriptors) {
        ByteStream stream = new ByteStream(descriptors);
        while (stream.available() > 0) {
            UsbDescriptor descriptor = null;
            try {
                descriptor = allocDescriptor(stream);
            } catch (Exception ex) {
                Log.e(TAG, "Exception allocating USB descriptor.", ex);
            }

            if (descriptor != null) {
                // Parse
                try {
                    descriptor.parseRawDescriptors(stream);

                    // Clean up
                    descriptor.postParse(stream);
                } catch (Exception ex) {
                    // Clean up, compute error status
                    descriptor.postParse(stream);

                    // Report
                    Log.w(TAG, "Exception parsing USB descriptors. type:0x" + descriptor.getType()
                            + " status:" + descriptor.getStatus());
                    if (DEBUG) {
                        // Show full stack trace if debugging
                        Log.e(TAG, "Exception parsing USB descriptors.", ex);
                    }
                    StackTraceElement[] stackElems = ex.getStackTrace();
                    if (stackElems.length > 0) {
                        Log.i(TAG, "  class:" + stackElems[0].getClassName()
                                    + " @ " + stackElems[0].getLineNumber());
                    }
                    if (stackElems.length > 1) {
                        Log.i(TAG, "  class:" + stackElems[1].getClassName()
                                + " @ " + stackElems[1].getLineNumber());
                    }

                    // Finish up
                    descriptor.setStatus(UsbDescriptor.STATUS_PARSE_EXCEPTION);
                } finally {
                    mDescriptors.add(descriptor);
                }
            }
        }
        if (DEBUG) {
            Log.d(TAG, "parseDescriptors() - end " + mDescriptors.size() + " descriptors.");
        }
    }

    public byte[] getRawDescriptors() {
        return getRawDescriptors_native(mDeviceAddr);
    }

    private native byte[] getRawDescriptors_native(String deviceAddr);

    /**
     * @hide
     */
    public String getDescriptorString(int stringId) {
        return getDescriptorString_native(mDeviceAddr, stringId);
    }

    private native String getDescriptorString_native(String deviceAddr, int stringId);

    public int getParsingSpec() {
        return mDeviceDescriptor != null ? mDeviceDescriptor.getSpec() : 0;
    }

    public ArrayList<UsbDescriptor> getDescriptors() {
        return mDescriptors;
    }

    /**
     * @hide
     */
    public UsbDevice.Builder toAndroidUsbDeviceBuilder() {
        if (mDeviceDescriptor == null) {
            Log.e(TAG, "toAndroidUsbDevice() ERROR - No Device Descriptor");
            return null;
        }

        UsbDevice.Builder builder = mDeviceDescriptor.toAndroid(this);
        if (builder == null) {
            Log.e(TAG, "toAndroidUsbDevice() ERROR Creating Device");
        }
        return builder;
    }

    /**
     * @hide
     */
    public ArrayList<UsbDescriptor> getDescriptors(byte type) {
        ArrayList<UsbDescriptor> list = new ArrayList<UsbDescriptor>();
        for (UsbDescriptor descriptor : mDescriptors) {
            if (descriptor.getType() == type) {
                list.add(descriptor);
            }
        }
        return list;
    }

    /**
     * @hide
     */
    public ArrayList<UsbDescriptor> getInterfaceDescriptorsForClass(int usbClass) {
        ArrayList<UsbDescriptor> list = new ArrayList<UsbDescriptor>();
        for (UsbDescriptor descriptor : mDescriptors) {
            // ensure that this isn't an unrecognized DESCRIPTORTYPE_INTERFACE
            if (descriptor.getType() == UsbDescriptor.DESCRIPTORTYPE_INTERFACE) {
                if (descriptor instanceof UsbInterfaceDescriptor) {
                    UsbInterfaceDescriptor intrDesc = (UsbInterfaceDescriptor) descriptor;
                    if (intrDesc.getUsbClass() == usbClass) {
                        list.add(descriptor);
                    }
                } else {
                    Log.w(TAG, "Unrecognized Interface l: " + descriptor.getLength()
                            + " t:0x" + Integer.toHexString(descriptor.getType()));
                }
            }
        }
        return list;
    }

    /**
     * @hide
     */
    public ArrayList<UsbDescriptor> getACInterfaceDescriptors(byte subtype, int subclass) {
        ArrayList<UsbDescriptor> list = new ArrayList<UsbDescriptor>();
        for (UsbDescriptor descriptor : mDescriptors) {
            if (descriptor.getType() == UsbDescriptor.DESCRIPTORTYPE_CLASSSPECIFIC_INTERFACE) {
                // ensure that this isn't an unrecognized DESCRIPTORTYPE_CLASSSPECIFIC_INTERFACE
                if (descriptor instanceof UsbACInterface) {
                    UsbACInterface acDescriptor = (UsbACInterface) descriptor;
                    if (acDescriptor.getSubtype() == subtype
                            && acDescriptor.getSubclass() == subclass) {
                        list.add(descriptor);
                    }
                } else {
                    Log.w(TAG, "Unrecognized Audio Interface len: " + descriptor.getLength()
                            + " type:0x" + Integer.toHexString(descriptor.getType()));
                }
            }
        }
        return list;
    }

    /*
     * Attribute predicates
     */
    /**
     * @hide
     */
    public boolean hasInput() {
        if (DEBUG) {
            Log.d(TAG, "---- hasInput()");
        }
        ArrayList<UsbDescriptor> acDescriptors =
                getACInterfaceDescriptors(UsbACInterface.ACI_INPUT_TERMINAL,
                UsbACInterface.AUDIO_AUDIOCONTROL);
        boolean hasInput = false;
        for (UsbDescriptor descriptor : acDescriptors) {
            if (descriptor instanceof UsbACTerminal) {
                UsbACTerminal inDescr = (UsbACTerminal) descriptor;
                // Check for input and bi-directional terminal types
                int type = inDescr.getTerminalType();
                if (DEBUG) {
                    Log.d(TAG, "  type:0x" + Integer.toHexString(type));
                }
                int terminalCategory = type & ~0xFF;
                if (terminalCategory != UsbTerminalTypes.TERMINAL_USB_UNDEFINED
                        && terminalCategory != UsbTerminalTypes.TERMINAL_OUT_UNDEFINED) {
                    // If not explicitly a USB connection or output, it could be an input.
                    hasInput = true;
                    break;
                }
            } else {
                Log.w(TAG, "Undefined Audio Input terminal l: " + descriptor.getLength()
                        + " t:0x" + Integer.toHexString(descriptor.getType()));
            }
        }

        if (DEBUG) {
            Log.d(TAG, "hasInput() = " + hasInput);
        }
        return hasInput;
    }

    /**
     * @hide
     */
    public boolean hasOutput() {
        if (DEBUG) {
            Log.d(TAG, "---- hasOutput()");
        }
        ArrayList<UsbDescriptor> acDescriptors =
                getACInterfaceDescriptors(UsbACInterface.ACI_OUTPUT_TERMINAL,
                UsbACInterface.AUDIO_AUDIOCONTROL);
        boolean hasOutput = false;
        for (UsbDescriptor descriptor : acDescriptors) {
            if (descriptor instanceof UsbACTerminal) {
                UsbACTerminal outDescr = (UsbACTerminal) descriptor;
                // Check for output and bi-directional terminal types
                int type = outDescr.getTerminalType();
                if (DEBUG) {
                    Log.d(TAG, "  type:0x" + Integer.toHexString(type));
                }
                int terminalCategory = type & ~0xFF;
                if (terminalCategory != UsbTerminalTypes.TERMINAL_USB_UNDEFINED
                        && terminalCategory != UsbTerminalTypes.TERMINAL_IN_UNDEFINED) {
                    // If not explicitly a USB connection or input, it could be an output.
                    hasOutput = true;
                    break;
                }
            } else {
                Log.w(TAG, "Undefined Audio Input terminal l: " + descriptor.getLength()
                        + " t:0x" + Integer.toHexString(descriptor.getType()));
            }
        }
        if (DEBUG) {
            Log.d(TAG, "hasOutput() = " + hasOutput);
        }
        return hasOutput;
    }

    /**
     * @hide
     */
    public boolean hasMic() {
        boolean hasMic = false;

        ArrayList<UsbDescriptor> acDescriptors =
                getACInterfaceDescriptors(UsbACInterface.ACI_INPUT_TERMINAL,
                UsbACInterface.AUDIO_AUDIOCONTROL);
        for (UsbDescriptor descriptor : acDescriptors) {
            if (descriptor instanceof UsbACTerminal) {
                UsbACTerminal inDescr = (UsbACTerminal) descriptor;
                if (inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_IN_MIC
                        || inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_BIDIR_HEADSET
                        || inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_BIDIR_UNDEFINED
                        || inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_EXTERN_LINE) {
                    hasMic = true;
                    break;
                }
            } else {
                Log.w(TAG, "Undefined Audio Input terminal l: " + descriptor.getLength()
                        + " t:0x" + Integer.toHexString(descriptor.getType()));
            }
        }
        return hasMic;
    }

    /**
     * @hide
     */
    public boolean hasSpeaker() {
        boolean hasSpeaker = false;

        ArrayList<UsbDescriptor> acDescriptors =
                getACInterfaceDescriptors(UsbACInterface.ACI_OUTPUT_TERMINAL,
                        UsbACInterface.AUDIO_AUDIOCONTROL);
        for (UsbDescriptor descriptor : acDescriptors) {
            if (descriptor instanceof UsbACTerminal) {
                UsbACTerminal outDescr = (UsbACTerminal) descriptor;
                if (outDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_OUT_SPEAKER
                        || outDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_OUT_HEADPHONES
                        || outDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_BIDIR_HEADSET) {
                    hasSpeaker = true;
                    break;
                }
            } else {
                Log.w(TAG, "Undefined Audio Output terminal l: " + descriptor.getLength()
                        + " t:0x" + Integer.toHexString(descriptor.getType()));
            }
        }

        return hasSpeaker;
    }

    /**
     *@ hide
     */
    public boolean hasAudioInterface() {
        ArrayList<UsbDescriptor> descriptors =
                getInterfaceDescriptorsForClass(UsbDescriptor.CLASSID_AUDIO);
        return !descriptors.isEmpty();
    }

    /**
     * Returns true only if there is a terminal whose subtype and terminal type are the same as
     * the given values.
     * @hide
     */
    public boolean hasAudioTerminal(int subType, int terminalType) {
        for (UsbDescriptor descriptor : mDescriptors) {
            if (descriptor instanceof UsbACTerminal) {
                if (((UsbACTerminal) descriptor).getSubclass() == UsbDescriptor.AUDIO_AUDIOCONTROL
                        && ((UsbACTerminal) descriptor).getSubtype() == subType
                        && ((UsbACTerminal) descriptor).getTerminalType() == terminalType) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Returns true only if there is an interface whose subtype is the same as the given one and
     * terminal type is different from the given one.
     * @hide
     */
    public boolean hasAudioTerminalExcludeType(int subType, int excludedTerminalType) {
        for (UsbDescriptor descriptor : mDescriptors) {
            if (descriptor instanceof UsbACTerminal) {
                if (((UsbACTerminal) descriptor).getSubclass() == UsbDescriptor.AUDIO_AUDIOCONTROL
                        && ((UsbACTerminal) descriptor).getSubtype() == subType
                        && ((UsbACTerminal) descriptor).getTerminalType() != excludedTerminalType) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * @hide
     */
    public boolean hasAudioPlayback() {
        return hasAudioTerminalExcludeType(
                UsbACInterface.ACI_OUTPUT_TERMINAL, UsbTerminalTypes.TERMINAL_USB_STREAMING)
                && hasAudioTerminal(
                        UsbACInterface.ACI_INPUT_TERMINAL, UsbTerminalTypes.TERMINAL_USB_STREAMING);
    }

    /**
     * @hide
     */
    public boolean hasAudioCapture() {
        return hasAudioTerminalExcludeType(
                UsbACInterface.ACI_INPUT_TERMINAL, UsbTerminalTypes.TERMINAL_USB_STREAMING)
                && hasAudioTerminal(
                        UsbACInterface.ACI_OUTPUT_TERMINAL,
                        UsbTerminalTypes.TERMINAL_USB_STREAMING);
    }

    /**
     * @hide
     */
    public boolean hasVideoCapture() {
        for (UsbDescriptor descriptor : mDescriptors) {
            if (descriptor instanceof UsbVCInputTerminal) {
                return true;
            }
        }
        return false;
    }

    /**
     * @hide
     */
    public boolean hasVideoPlayback() {
        for (UsbDescriptor descriptor : mDescriptors) {
            if (descriptor instanceof UsbVCOutputTerminal) {
                return true;
            }
        }
        return false;
    }

    /**
     * @hide
     */
    public boolean hasHIDInterface() {
        ArrayList<UsbDescriptor> descriptors =
                getInterfaceDescriptorsForClass(UsbDescriptor.CLASSID_HID);
        return !descriptors.isEmpty();
    }

    /**
     * @hide
     */
    public boolean hasStorageInterface() {
        ArrayList<UsbDescriptor> descriptors =
                getInterfaceDescriptorsForClass(UsbDescriptor.CLASSID_STORAGE);
        return !descriptors.isEmpty();
    }

    /**
     * @hide
     */
    public boolean hasMIDIInterface() {
        ArrayList<UsbDescriptor> descriptors =
                getInterfaceDescriptorsForClass(UsbDescriptor.CLASSID_AUDIO);
        for (UsbDescriptor descriptor : descriptors) {
            // enusure that this isn't an unrecognized interface descriptor
            if (descriptor instanceof UsbInterfaceDescriptor) {
                UsbInterfaceDescriptor interfaceDescriptor = (UsbInterfaceDescriptor) descriptor;
                if (interfaceDescriptor.getUsbSubclass() == UsbDescriptor.AUDIO_MIDISTREAMING) {
                    return true;
                }
            } else {
                Log.w(TAG, "Undefined Audio Class Interface l: " + descriptor.getLength()
                        + " t:0x" + Integer.toHexString(descriptor.getType()));
            }
        }
        return false;
    }

    /**
     * @hide
     */
    public boolean containsUniversalMidiDeviceEndpoint() {
        ArrayList<UsbInterfaceDescriptor> interfaceDescriptors =
                findUniversalMidiInterfaceDescriptors();
        return doesInterfaceContainEndpoint(interfaceDescriptors);
    }

    /**
     * @hide
     */
    public boolean containsLegacyMidiDeviceEndpoint() {
        ArrayList<UsbInterfaceDescriptor> interfaceDescriptors =
                findLegacyMidiInterfaceDescriptors();
        return doesInterfaceContainEndpoint(interfaceDescriptors);
    }

    /**
     * @hide
     */
    public boolean doesInterfaceContainEndpoint(
            ArrayList<UsbInterfaceDescriptor> interfaceDescriptors) {
        int outputCount = 0;
        int inputCount = 0;
        for (int interfaceIndex = 0; interfaceIndex < interfaceDescriptors.size();
                interfaceIndex++) {
            UsbInterfaceDescriptor interfaceDescriptor = interfaceDescriptors.get(interfaceIndex);
            for (int endpointIndex = 0; endpointIndex < interfaceDescriptor.getNumEndpoints();
                    endpointIndex++) {
                UsbEndpointDescriptor endpoint =
                        interfaceDescriptor.getEndpointDescriptor(endpointIndex);
                // 0 is output, 1 << 7 is input.
                if (endpoint.getDirection() == 0) {
                    outputCount++;
                } else {
                    inputCount++;
                }
            }
        }
        return (outputCount > 0) || (inputCount > 0);
    }

    /**
     * @hide
     */
    public ArrayList<UsbInterfaceDescriptor> findUniversalMidiInterfaceDescriptors() {
        return findMidiInterfaceDescriptors(MS_MIDI_2_0);
    }

    /**
     * @hide
     */
    public ArrayList<UsbInterfaceDescriptor> findLegacyMidiInterfaceDescriptors() {
        return findMidiInterfaceDescriptors(MS_MIDI_1_0);
    }

    /**
     * @hide
     */
    private ArrayList<UsbInterfaceDescriptor> findMidiInterfaceDescriptors(int type) {
        int count = 0;
        ArrayList<UsbDescriptor> descriptors =
                getInterfaceDescriptorsForClass(UsbDescriptor.CLASSID_AUDIO);
        ArrayList<UsbInterfaceDescriptor> midiInterfaces =
                new ArrayList<UsbInterfaceDescriptor>();

        for (UsbDescriptor descriptor : descriptors) {
            // ensure that this isn't an unrecognized interface descriptor
            if (descriptor instanceof UsbInterfaceDescriptor) {
                UsbInterfaceDescriptor interfaceDescriptor = (UsbInterfaceDescriptor) descriptor;
                if (interfaceDescriptor.getUsbSubclass() == UsbDescriptor.AUDIO_MIDISTREAMING) {
                    UsbDescriptor midiHeaderDescriptor =
                            interfaceDescriptor.getMidiHeaderInterfaceDescriptor();
                    if (midiHeaderDescriptor != null) {
                        if (midiHeaderDescriptor instanceof UsbMSMidiHeader) {
                            UsbMSMidiHeader midiHeader =
                                    (UsbMSMidiHeader) midiHeaderDescriptor;
                            if (midiHeader.getMidiStreamingClass() == type) {
                                midiInterfaces.add(interfaceDescriptor);
                            }
                        }
                    }
                }
            } else {
                Log.w(TAG, "Undefined Audio Class Interface l: " + descriptor.getLength()
                        + " t:0x" + Integer.toHexString(descriptor.getType()));
            }
        }
        return midiInterfaces;
    }

    /**
     * @hide
     */
    public int calculateMidiInterfaceDescriptorsCount() {
        int count = 0;
        ArrayList<UsbDescriptor> descriptors =
                getInterfaceDescriptorsForClass(UsbDescriptor.CLASSID_AUDIO);
        for (UsbDescriptor descriptor : descriptors) {
            // ensure that this isn't an unrecognized interface descriptor
            if (descriptor instanceof UsbInterfaceDescriptor) {
                UsbInterfaceDescriptor interfaceDescriptor = (UsbInterfaceDescriptor) descriptor;
                if (interfaceDescriptor.getUsbSubclass() == UsbDescriptor.AUDIO_MIDISTREAMING) {
                    UsbDescriptor midiHeaderDescriptor =
                            interfaceDescriptor.getMidiHeaderInterfaceDescriptor();
                    if (midiHeaderDescriptor != null) {
                        if (midiHeaderDescriptor instanceof UsbMSMidiHeader) {
                            UsbMSMidiHeader midiHeader =
                                    (UsbMSMidiHeader) midiHeaderDescriptor;
                            count++;
                        }
                    }
                }
            } else {
                Log.w(TAG, "Undefined Audio Class Interface l: " + descriptor.getLength()
                        + " t:0x" + Integer.toHexString(descriptor.getType()));
            }
        }
        return count;
    }

    /**
     * @hide
     */
    private int calculateNumLegacyMidiPorts(boolean isOutput) {
        // Only look at the first config.
        UsbConfigDescriptor configDescriptor = null;
        for (UsbDescriptor descriptor : mDescriptors) {
            if (descriptor.getType() == UsbDescriptor.DESCRIPTORTYPE_CONFIG) {
                if (descriptor instanceof UsbConfigDescriptor) {
                    configDescriptor = (UsbConfigDescriptor) descriptor;
                    break;
                } else {
                    Log.w(TAG, "Unrecognized Config l: " + descriptor.getLength()
                            + " t:0x" + Integer.toHexString(descriptor.getType()));
                }
            }
        }
        if (configDescriptor == null) {
            Log.w(TAG, "Config not found");
            return 0;
        }

        ArrayList<UsbInterfaceDescriptor> legacyMidiInterfaceDescriptors =
                new ArrayList<UsbInterfaceDescriptor>();
        for (UsbInterfaceDescriptor interfaceDescriptor
                : configDescriptor.getInterfaceDescriptors()) {
            if (interfaceDescriptor.getUsbClass() == UsbDescriptor.CLASSID_AUDIO) {
                if (interfaceDescriptor.getUsbSubclass() == UsbDescriptor.AUDIO_MIDISTREAMING) {
                    UsbDescriptor midiHeaderDescriptor =
                            interfaceDescriptor.getMidiHeaderInterfaceDescriptor();
                    if (midiHeaderDescriptor != null) {
                        if (midiHeaderDescriptor instanceof UsbMSMidiHeader) {
                            UsbMSMidiHeader midiHeader =
                                    (UsbMSMidiHeader) midiHeaderDescriptor;
                            if (midiHeader.getMidiStreamingClass() == MS_MIDI_1_0) {
                                legacyMidiInterfaceDescriptors.add(interfaceDescriptor);
                            }
                        }
                    }
                }
            }
        }

        int count = 0;
        for (UsbInterfaceDescriptor interfaceDescriptor : legacyMidiInterfaceDescriptors) {
            for (int i = 0; i < interfaceDescriptor.getNumEndpoints(); i++) {
                UsbEndpointDescriptor endpoint =
                        interfaceDescriptor.getEndpointDescriptor(i);
                // 0 is output, 1 << 7 is input.
                if ((endpoint.getDirection() == 0) == isOutput) {
                    UsbDescriptor classSpecificEndpointDescriptor =
                            endpoint.getClassSpecificEndpointDescriptor();
                    if (classSpecificEndpointDescriptor != null
                            && (classSpecificEndpointDescriptor instanceof UsbACMidi10Endpoint)) {
                        UsbACMidi10Endpoint midiEndpoint =
                                (UsbACMidi10Endpoint) classSpecificEndpointDescriptor;
                        count += midiEndpoint.getNumJacks();
                    }
                }
            }
        }
        return count;
    }

    /**
     * @hide
     */
    public int calculateNumLegacyMidiInputs() {
        return calculateNumLegacyMidiPorts(false /*isOutput*/);
    }

    /**
     * @hide
     */
    public int calculateNumLegacyMidiOutputs() {
        return calculateNumLegacyMidiPorts(true /*isOutput*/);
    }

    /**
     * @hide
     */
    public float getInputHeadsetProbability() {
        if (hasMIDIInterface()) {
            return 0.0f;
        }

        float probability = 0.0f;

        // Look for a microphone
        boolean hasMic = hasMic();

        // Look for a "speaker"
        boolean hasSpeaker = hasSpeaker();

        if (hasMic && hasSpeaker) {
            probability += 0.75f;
        }

        if (hasMic && hasHIDInterface()) {
            probability += 0.25f;
        }

        return probability;
    }

    /**
     * getInputHeadsetProbability() reports a probability of a USB Input peripheral being a
     * headset. The probability range is between 0.0f (definitely NOT a headset) and
     * 1.0f (definitely IS a headset). A probability of 0.75f seems sufficient
     * to count on the peripheral being a headset.
     */
    public boolean isInputHeadset() {
        return getInputHeadsetProbability() >= IN_HEADSET_TRIGGER;
    }

    // TODO: Up/Downmix process descriptor is not yet parsed, which may affect the result here.
    private int getMaximumChannelCount() {
        int maxChannelCount = 0;
        for (UsbDescriptor descriptor : mDescriptors) {
            if (descriptor instanceof UsbAudioChannelCluster) {
                maxChannelCount = Math.max(maxChannelCount,
                        ((UsbAudioChannelCluster) descriptor).getChannelCount());
            }
        }
        return maxChannelCount;
    }

    /**
     * @hide
     */
    public float getOutputHeadsetLikelihood() {
        if (hasMIDIInterface()) {
            return 0.0f;
        }

        float likelihood = 0.0f;
        ArrayList<UsbDescriptor> acDescriptors;

        // Look for a "speaker"
        boolean hasSpeaker = false;
        boolean hasAssociatedInputTerminal = false;
        boolean hasHeadphoneOrHeadset = false;
        acDescriptors =
                getACInterfaceDescriptors(UsbACInterface.ACI_OUTPUT_TERMINAL,
                        UsbACInterface.AUDIO_AUDIOCONTROL);
        for (UsbDescriptor descriptor : acDescriptors) {
            if (descriptor instanceof UsbACTerminal) {
                UsbACTerminal outDescr = (UsbACTerminal) descriptor;
                if (outDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_OUT_SPEAKER) {
                    hasSpeaker = true;
                    if (outDescr.getAssocTerminal() != 0x0) {
                        hasAssociatedInputTerminal = true;
                    }
                } else if (outDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_OUT_HEADPHONES
                        || outDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_BIDIR_HEADSET) {
                    hasHeadphoneOrHeadset = true;
                }
            } else {
                Log.w(TAG, "Undefined Audio Output terminal l: " + descriptor.getLength()
                        + " t:0x" + Integer.toHexString(descriptor.getType()));
            }
        }

        if (hasHeadphoneOrHeadset) {
            likelihood += 0.75f;
        } else if (hasSpeaker) {
            // The device only reports output terminal as speaker. Try to figure out if the device
            // is a headset or not by checking if it has associated input terminal and if multiple
            // channels are supported or not.
            likelihood += 0.5f;
            if (hasAssociatedInputTerminal) {
                likelihood += 0.25f;
            }
            if (getMaximumChannelCount() > 2) {
                // When multiple channels are supported, it is less likely to be a headset.
                likelihood -= 0.25f;
            }
        }

        if ((hasHeadphoneOrHeadset || hasSpeaker) && hasHIDInterface()) {
            likelihood += 0.25f;
        }

        return likelihood;
    }

    /**
     * getOutputHeadsetProbability() reports a probability of a USB Output peripheral being a
     * headset. The probability range is between 0.0f (definitely NOT a headset) and
     * 1.0f (definitely IS a headset). A probability of 0.75f seems sufficient
     * to count on the peripheral being a headset.
     */
    public boolean isOutputHeadset() {
        return getOutputHeadsetLikelihood() >= OUT_HEADSET_TRIGGER;
    }

    /**
     * isDock() indicates if the connected USB output peripheral is a docking station with
     * audio output.
     * A valid audio dock must declare only one audio output control terminal of type
     * TERMINAL_EXTERN_DIGITAL.
     */
    public boolean isDock() {
        if (hasMIDIInterface() || hasHIDInterface()) {
            return false;
        }

        ArrayList<UsbDescriptor> acDescriptors =
                getACInterfaceDescriptors(UsbACInterface.ACI_OUTPUT_TERMINAL,
                        UsbACInterface.AUDIO_AUDIOCONTROL);

        if (acDescriptors.size() != 1) {
            return false;
        }

        if (acDescriptors.get(0) instanceof UsbACTerminal) {
            UsbACTerminal outDescr = (UsbACTerminal) acDescriptors.get(0);
            if (outDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_EXTERN_DIGITAL) {
                return true;
            }
        } else {
            Log.w(TAG, "Undefined Audio Output terminal l: " + acDescriptors.get(0).getLength()
                    + " t:0x" + Integer.toHexString(acDescriptors.get(0).getType()));
        }
        return false;
    }

}
