Loading services/usb/java/com/android/server/usb/descriptors/UsbACTerminal.java +7 −0 Original line number Original line Diff line number Diff line Loading @@ -48,6 +48,13 @@ public abstract class UsbACTerminal extends UsbACInterface { return mAssocTerminal; return mAssocTerminal; } } public boolean isInputTerminal() { return mTerminalType == UsbTerminalTypes.TERMINAL_IN_MIC || mTerminalType == UsbTerminalTypes.TERMINAL_BIDIR_HEADSET || mTerminalType == UsbTerminalTypes.TERMINAL_BIDIR_UNDEFINED || mTerminalType == UsbTerminalTypes.TERMINAL_EXTERN_LINE; } @Override @Override public int parseRawDescriptors(ByteStream stream) { public int parseRawDescriptors(ByteStream stream) { mTerminalID = stream.getByte(); mTerminalID = stream.getByte(); Loading services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java +43 −19 Original line number Original line Diff line number Diff line Loading @@ -524,27 +524,21 @@ public final class UsbDescriptorParser { * @hide * @hide */ */ public boolean hasMic() { public boolean hasMic() { boolean hasMic = false; ArrayList<UsbDescriptor> acDescriptors = ArrayList<UsbDescriptor> acDescriptors = getACInterfaceDescriptors(UsbACInterface.ACI_INPUT_TERMINAL, getACInterfaceDescriptors(UsbACInterface.ACI_INPUT_TERMINAL, UsbACInterface.AUDIO_AUDIOCONTROL); UsbACInterface.AUDIO_AUDIOCONTROL); for (UsbDescriptor descriptor : acDescriptors) { for (UsbDescriptor descriptor : acDescriptors) { if (descriptor instanceof UsbACTerminal) { if (descriptor instanceof UsbACTerminal) { UsbACTerminal inDescr = (UsbACTerminal) descriptor; UsbACTerminal inDescr = (UsbACTerminal) descriptor; if (inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_IN_MIC if (inDescr.isInputTerminal()) { || inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_BIDIR_HEADSET return true; || inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_BIDIR_UNDEFINED || inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_EXTERN_LINE) { hasMic = true; break; } } } else { } else { Log.w(TAG, "Undefined Audio Input terminal l: " + descriptor.getLength() Log.w(TAG, "Undefined Audio Input terminal l: " + descriptor.getLength() + " t:0x" + Integer.toHexString(descriptor.getType())); + " t:0x" + Integer.toHexString(descriptor.getType())); } } } } return hasMic; return false; } } /** /** Loading Loading @@ -913,19 +907,21 @@ public final class UsbDescriptorParser { float probability = 0.0f; float probability = 0.0f; // Look for a microphone boolean hasMic = hasMic(); // Look for a "speaker" // Look for a "speaker" boolean hasSpeaker = hasSpeaker(); boolean hasSpeaker = hasSpeaker(); if (hasMic && hasSpeaker) { if (hasMic()) { if (hasSpeaker) { probability += 0.75f; probability += 0.75f; } } if (hasHIDInterface()) { if (hasMic && hasHIDInterface()) { probability += 0.25f; probability += 0.25f; } } if (getMaximumInputChannelCount() > 1) { // A headset is more likely to only support mono capture. probability -= 0.25f; } } return probability; return probability; } } Loading @@ -935,9 +931,11 @@ public final class UsbDescriptorParser { * headset. The probability range is between 0.0f (definitely NOT a headset) and * 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 * 1.0f (definitely IS a headset). A probability of 0.75f seems sufficient * to count on the peripheral being a headset. * to count on the peripheral being a headset. * To align with the output device type, only treat the device as input headset if it is * an output headset. */ */ public boolean isInputHeadset() { public boolean isInputHeadset() { return getInputHeadsetProbability() >= IN_HEADSET_TRIGGER; return getInputHeadsetProbability() >= IN_HEADSET_TRIGGER && isOutputHeadset(); } } // TODO: Up/Downmix process descriptor is not yet parsed, which may affect the result here. // TODO: Up/Downmix process descriptor is not yet parsed, which may affect the result here. Loading @@ -952,6 +950,32 @@ public final class UsbDescriptorParser { return maxChannelCount; return maxChannelCount; } } private int getMaximumInputChannelCount() { int maxChannelCount = 0; ArrayList<UsbDescriptor> acDescriptors = getACInterfaceDescriptors(UsbACInterface.ACI_INPUT_TERMINAL, UsbACInterface.AUDIO_AUDIOCONTROL); for (UsbDescriptor descriptor : acDescriptors) { if (!(descriptor instanceof UsbACTerminal)) { continue; } UsbACTerminal inDescr = (UsbACTerminal) descriptor; if (!inDescr.isInputTerminal()) { continue; } // For an input terminal, it should at lease has 1 channel. // Comparing the max channel count with 1 here in case the USB device doesn't report // audio channel cluster. maxChannelCount = Math.max(maxChannelCount, 1); if (!(descriptor instanceof UsbAudioChannelCluster)) { continue; } maxChannelCount = Math.max(maxChannelCount, ((UsbAudioChannelCluster) descriptor).getChannelCount()); } return maxChannelCount; } /** /** * @hide * @hide */ */ Loading Loading
services/usb/java/com/android/server/usb/descriptors/UsbACTerminal.java +7 −0 Original line number Original line Diff line number Diff line Loading @@ -48,6 +48,13 @@ public abstract class UsbACTerminal extends UsbACInterface { return mAssocTerminal; return mAssocTerminal; } } public boolean isInputTerminal() { return mTerminalType == UsbTerminalTypes.TERMINAL_IN_MIC || mTerminalType == UsbTerminalTypes.TERMINAL_BIDIR_HEADSET || mTerminalType == UsbTerminalTypes.TERMINAL_BIDIR_UNDEFINED || mTerminalType == UsbTerminalTypes.TERMINAL_EXTERN_LINE; } @Override @Override public int parseRawDescriptors(ByteStream stream) { public int parseRawDescriptors(ByteStream stream) { mTerminalID = stream.getByte(); mTerminalID = stream.getByte(); Loading
services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java +43 −19 Original line number Original line Diff line number Diff line Loading @@ -524,27 +524,21 @@ public final class UsbDescriptorParser { * @hide * @hide */ */ public boolean hasMic() { public boolean hasMic() { boolean hasMic = false; ArrayList<UsbDescriptor> acDescriptors = ArrayList<UsbDescriptor> acDescriptors = getACInterfaceDescriptors(UsbACInterface.ACI_INPUT_TERMINAL, getACInterfaceDescriptors(UsbACInterface.ACI_INPUT_TERMINAL, UsbACInterface.AUDIO_AUDIOCONTROL); UsbACInterface.AUDIO_AUDIOCONTROL); for (UsbDescriptor descriptor : acDescriptors) { for (UsbDescriptor descriptor : acDescriptors) { if (descriptor instanceof UsbACTerminal) { if (descriptor instanceof UsbACTerminal) { UsbACTerminal inDescr = (UsbACTerminal) descriptor; UsbACTerminal inDescr = (UsbACTerminal) descriptor; if (inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_IN_MIC if (inDescr.isInputTerminal()) { || inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_BIDIR_HEADSET return true; || inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_BIDIR_UNDEFINED || inDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_EXTERN_LINE) { hasMic = true; break; } } } else { } else { Log.w(TAG, "Undefined Audio Input terminal l: " + descriptor.getLength() Log.w(TAG, "Undefined Audio Input terminal l: " + descriptor.getLength() + " t:0x" + Integer.toHexString(descriptor.getType())); + " t:0x" + Integer.toHexString(descriptor.getType())); } } } } return hasMic; return false; } } /** /** Loading Loading @@ -913,19 +907,21 @@ public final class UsbDescriptorParser { float probability = 0.0f; float probability = 0.0f; // Look for a microphone boolean hasMic = hasMic(); // Look for a "speaker" // Look for a "speaker" boolean hasSpeaker = hasSpeaker(); boolean hasSpeaker = hasSpeaker(); if (hasMic && hasSpeaker) { if (hasMic()) { if (hasSpeaker) { probability += 0.75f; probability += 0.75f; } } if (hasHIDInterface()) { if (hasMic && hasHIDInterface()) { probability += 0.25f; probability += 0.25f; } } if (getMaximumInputChannelCount() > 1) { // A headset is more likely to only support mono capture. probability -= 0.25f; } } return probability; return probability; } } Loading @@ -935,9 +931,11 @@ public final class UsbDescriptorParser { * headset. The probability range is between 0.0f (definitely NOT a headset) and * 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 * 1.0f (definitely IS a headset). A probability of 0.75f seems sufficient * to count on the peripheral being a headset. * to count on the peripheral being a headset. * To align with the output device type, only treat the device as input headset if it is * an output headset. */ */ public boolean isInputHeadset() { public boolean isInputHeadset() { return getInputHeadsetProbability() >= IN_HEADSET_TRIGGER; return getInputHeadsetProbability() >= IN_HEADSET_TRIGGER && isOutputHeadset(); } } // TODO: Up/Downmix process descriptor is not yet parsed, which may affect the result here. // TODO: Up/Downmix process descriptor is not yet parsed, which may affect the result here. Loading @@ -952,6 +950,32 @@ public final class UsbDescriptorParser { return maxChannelCount; return maxChannelCount; } } private int getMaximumInputChannelCount() { int maxChannelCount = 0; ArrayList<UsbDescriptor> acDescriptors = getACInterfaceDescriptors(UsbACInterface.ACI_INPUT_TERMINAL, UsbACInterface.AUDIO_AUDIOCONTROL); for (UsbDescriptor descriptor : acDescriptors) { if (!(descriptor instanceof UsbACTerminal)) { continue; } UsbACTerminal inDescr = (UsbACTerminal) descriptor; if (!inDescr.isInputTerminal()) { continue; } // For an input terminal, it should at lease has 1 channel. // Comparing the max channel count with 1 here in case the USB device doesn't report // audio channel cluster. maxChannelCount = Math.max(maxChannelCount, 1); if (!(descriptor instanceof UsbAudioChannelCluster)) { continue; } maxChannelCount = Math.max(maxChannelCount, ((UsbAudioChannelCluster) descriptor).getChannelCount()); } return maxChannelCount; } /** /** * @hide * @hide */ */ Loading