diff options
5 files changed, 69 insertions, 24 deletions
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index 0961fcb31ace..2dd6bf575579 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -1360,6 +1360,9 @@ public class AudioDeviceInventory { case AudioSystem.DEVICE_OUT_USB_HEADSET: connType = AudioRoutesInfo.MAIN_USB; break; + case AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET: + connType = AudioRoutesInfo.MAIN_DOCK_SPEAKERS; + break; } synchronized (mCurAudioRoutes) { diff --git a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java index 9d4db003a297..85b1de5478e1 100644 --- a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java +++ b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java @@ -41,6 +41,7 @@ public final class UsbAlsaDevice { private final boolean mIsInputHeadset; private final boolean mIsOutputHeadset; + private final boolean mIsDock; private boolean mSelected = false; private int mOutputState; @@ -53,7 +54,7 @@ public final class UsbAlsaDevice { public UsbAlsaDevice(IAudioService audioService, int card, int device, String deviceAddress, boolean hasOutput, boolean hasInput, - boolean isInputHeadset, boolean isOutputHeadset) { + boolean isInputHeadset, boolean isOutputHeadset, boolean isDock) { mAudioService = audioService; mCardNum = card; mDeviceNum = device; @@ -62,31 +63,32 @@ public final class UsbAlsaDevice { mHasInput = hasInput; mIsInputHeadset = isInputHeadset; mIsOutputHeadset = isOutputHeadset; + mIsDock = isDock; } /** - * @returns the ALSA card number associated with this peripheral. + * @return the ALSA card number associated with this peripheral. */ public int getCardNum() { return mCardNum; } /** - * @returns the ALSA device number associated with this peripheral. + * @return the ALSA device number associated with this peripheral. */ public int getDeviceNum() { return mDeviceNum; } /** - * @returns the USB device device address associated with this peripheral. + * @return the USB device device address associated with this peripheral. */ public String getDeviceAddress() { return mDeviceAddress; } /** - * @returns the ALSA card/device address string. + * @return the ALSA card/device address string. */ public String getAlsaCardDeviceString() { if (mCardNum < 0 || mDeviceNum < 0) { @@ -98,35 +100,42 @@ public final class UsbAlsaDevice { } /** - * @returns true if the device supports output. + * @return true if the device supports output. */ public boolean hasOutput() { return mHasOutput; } /** - * @returns true if the device supports input (recording). + * @return true if the device supports input (recording). */ public boolean hasInput() { return mHasInput; } /** - * @returns true if the device is a headset for purposes of input. + * @return true if the device is a headset for purposes of input. */ public boolean isInputHeadset() { return mIsInputHeadset; } /** - * @returns true if the device is a headset for purposes of output. + * @return true if the device is a headset for purposes of output. */ public boolean isOutputHeadset() { return mIsOutputHeadset; } /** - * @returns true if input jack is detected or jack detection is not supported. + * @return true if the device is a USB dock. + */ + public boolean isDock() { + return mIsDock; + } + + /** + * @return true if input jack is detected or jack detection is not supported. */ private synchronized boolean isInputJackConnected() { if (mJackDetector == null) { @@ -136,7 +145,7 @@ public final class UsbAlsaDevice { } /** - * @returns true if input jack is detected or jack detection is not supported. + * @return true if input jack is detected or jack detection is not supported. */ private synchronized boolean isOutputJackConnected() { if (mJackDetector == null) { @@ -190,9 +199,10 @@ public final class UsbAlsaDevice { try { // Output Device if (mHasOutput) { - int device = mIsOutputHeadset - ? AudioSystem.DEVICE_OUT_USB_HEADSET - : AudioSystem.DEVICE_OUT_USB_DEVICE; + int device = mIsDock ? AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET + : (mIsOutputHeadset + ? AudioSystem.DEVICE_OUT_USB_HEADSET + : AudioSystem.DEVICE_OUT_USB_DEVICE); if (DEBUG) { Slog.d(TAG, "pre-call device:0x" + Integer.toHexString(device) + " addr:" + alsaCardDeviceString @@ -231,7 +241,7 @@ public final class UsbAlsaDevice { /** * @Override - * @returns a string representation of the object. + * @return a string representation of the object. */ public synchronized String toString() { return "UsbAlsaDevice: [card: " + mCardNum @@ -273,7 +283,7 @@ public final class UsbAlsaDevice { /** * @Override - * @returns true if the objects are equivalent. + * @return true if the objects are equivalent. */ public boolean equals(Object obj) { if (!(obj instanceof UsbAlsaDevice)) { @@ -285,12 +295,13 @@ public final class UsbAlsaDevice { && mHasOutput == other.mHasOutput && mHasInput == other.mHasInput && mIsInputHeadset == other.mIsInputHeadset - && mIsOutputHeadset == other.mIsOutputHeadset); + && mIsOutputHeadset == other.mIsOutputHeadset + && mIsDock == other.mIsDock); } /** * @Override - * @returns a hash code generated from the object contents. + * @return a hash code generated from the object contents. */ public int hashCode() { final int prime = 31; @@ -301,6 +312,7 @@ public final class UsbAlsaDevice { result = prime * result + (mHasInput ? 0 : 1); result = prime * result + (mIsInputHeadset ? 0 : 1); result = prime * result + (mIsOutputHeadset ? 0 : 1); + result = prime * result + (mIsDock ? 0 : 1); return result; } diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java index 0aa62c53e269..22b110fee5e7 100644 --- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java +++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java @@ -237,6 +237,7 @@ public final class UsbAlsaManager { if (hasInput || hasOutput) { boolean isInputHeadset = parser.isInputHeadset(); boolean isOutputHeadset = parser.isOutputHeadset(); + boolean isDock = parser.isDock(); if (mAudioService == null) { Slog.e(TAG, "no AudioService"); @@ -246,7 +247,7 @@ public final class UsbAlsaManager { UsbAlsaDevice alsaDevice = new UsbAlsaDevice(mAudioService, cardRec.getCardNum(), 0 /*device*/, deviceAddress, hasOutput, hasInput, - isInputHeadset, isOutputHeadset); + isInputHeadset, isOutputHeadset, isDock); if (alsaDevice != null) { alsaDevice.setDeviceNameAndDescription( cardRec.getCardName(), cardRec.getCardDescription()); diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java index f33001c9241e..5befe52ea13a 100644 --- a/services/usb/java/com/android/server/usb/UsbHostManager.java +++ b/services/usb/java/com/android/server/usb/UsbHostManager.java @@ -155,7 +155,7 @@ public class UsbHostManager { pw.println("manfacturer:0x" + Integer.toHexString(deviceDescriptor.getVendorID()) + " product:" + Integer.toHexString(deviceDescriptor.getProductID())); pw.println("isHeadset[in: " + parser.isInputHeadset() - + " , out: " + parser.isOutputHeadset() + "]"); + + " , out: " + parser.isOutputHeadset() + "], isDock: " + parser.isDock()); } else { pw.println(formatTime() + " Disconnect " + mDeviceAddress); } @@ -169,9 +169,8 @@ public class UsbHostManager { UsbDescriptorsTree descriptorTree = new UsbDescriptorsTree(); descriptorTree.parse(parser); descriptorTree.report(new TextReportCanvas(parser, stringBuilder)); - stringBuilder.append("isHeadset[in: " + parser.isInputHeadset() - + " , out: " + parser.isOutputHeadset() + "]"); + + " , out: " + parser.isOutputHeadset() + "], isDock: " + parser.isDock()); pw.println(stringBuilder.toString()); } else { pw.println(formatTime() + " Disconnect " + mDeviceAddress); @@ -188,9 +187,8 @@ public class UsbHostManager { descriptor.report(canvas); } pw.println(stringBuilder.toString()); - pw.println("isHeadset[in: " + parser.isInputHeadset() - + " , out: " + parser.isOutputHeadset() + "]"); + + " , out: " + parser.isOutputHeadset() + "], isDock: " + parser.isDock()); } else { pw.println(formatTime() + " Disconnect " + mDeviceAddress); } diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java index 7250a071835d..38ce6cb65506 100644 --- a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java +++ b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java @@ -785,4 +785,35 @@ public final class UsbDescriptorParser { return getOutputHeadsetProbability() >= 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; + } + } |