summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/alsa/AlsaCardsParser.java203
-rw-r--r--core/java/com/android/internal/alsa/AlsaDevicesParser.java22
-rw-r--r--services/usb/java/com/android/server/usb/UsbAlsaDevice.java138
-rw-r--r--services/usb/java/com/android/server/usb/UsbAlsaManager.java480
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java26
-rw-r--r--services/usb/java/com/android/server/usb/UsbHostManager.java17
-rw-r--r--services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java157
7 files changed, 438 insertions, 605 deletions
diff --git a/core/java/com/android/internal/alsa/AlsaCardsParser.java b/core/java/com/android/internal/alsa/AlsaCardsParser.java
index bb75bf6e6fb8..fa8db96781ac 100644
--- a/core/java/com/android/internal/alsa/AlsaCardsParser.java
+++ b/core/java/com/android/internal/alsa/AlsaCardsParser.java
@@ -31,7 +31,9 @@ public class AlsaCardsParser {
private static final String TAG = "AlsaCardsParser";
protected static final boolean DEBUG = false;
- private static final String kCardsFilePath = "/proc/asound/cards";
+ private static final String kAlsaFolderPath = "/proc/asound";
+ private static final String kCardsFilePath = kAlsaFolderPath + "/cards";
+ private static final String kDeviceAddressPrefix = "/dev/bus/usb/";
private static LineTokenizer mTokenizer = new LineTokenizer(" :[]");
@@ -47,14 +49,31 @@ public class AlsaCardsParser {
private static final String TAG = "AlsaCardRecord";
private static final String kUsbCardKeyStr = "at usb-";
- public int mCardNum = -1;
- public String mField1 = "";
- public String mCardName = "";
- public String mCardDescription = "";
- public boolean mIsUsb = false;
+ int mCardNum = -1;
+ String mField1 = "";
+ String mCardName = "";
+ String mCardDescription = "";
+
+ private String mUsbDeviceAddress = null;
public AlsaCardRecord() {}
+ public int getCardNum() {
+ return mCardNum;
+ }
+
+ public String getCardName() {
+ return mCardName;
+ }
+
+ public String getCardDescription() {
+ return mCardDescription;
+ }
+
+ public void setDeviceAddress(String usbDeviceAddress) {
+ mUsbDeviceAddress = usbDeviceAddress;
+ }
+
private boolean parse(String line, int lineIndex) {
int tokenIndex = 0;
int delimIndex = 0;
@@ -87,8 +106,8 @@ public class AlsaCardsParser {
tokenIndex = mTokenizer.nextToken(line, 0);
if (tokenIndex != -1) {
int keyIndex = line.indexOf(kUsbCardKeyStr);
- mIsUsb = keyIndex != -1;
- if (mIsUsb) {
+ boolean isUsb = keyIndex != -1;
+ if (isUsb) {
mCardDescription = line.substring(tokenIndex, keyIndex - 1);
}
}
@@ -97,14 +116,18 @@ public class AlsaCardsParser {
return true;
}
+ boolean isUsb() {
+ return mUsbDeviceAddress != null;
+ }
+
public String textFormat() {
- return mCardName + " : " + mCardDescription;
+ return mCardName + " : " + mCardDescription + " [addr:" + mUsbDeviceAddress + "]";
}
public void log(int listIndex) {
Slog.d(TAG, "" + listIndex +
" [" + mCardNum + " " + mCardName + " : " + mCardDescription +
- " usb:" + mIsUsb);
+ " usb:" + isUsb());
}
}
@@ -112,7 +135,7 @@ public class AlsaCardsParser {
public int scan() {
if (DEBUG) {
- Slog.i(TAG, "AlsaCardsParser.scan()....");
+ Slog.d(TAG, "AlsaCardsParser.scan()....");
}
mCardRecords = new ArrayList<AlsaCardRecord>();
@@ -125,7 +148,7 @@ public class AlsaCardsParser {
while ((line = bufferedReader.readLine()) != null) {
AlsaCardRecord cardRecord = new AlsaCardRecord();
if (DEBUG) {
- Slog.i(TAG, " " + line);
+ Slog.d(TAG, " " + line);
}
cardRecord.parse(line, 0);
@@ -134,10 +157,23 @@ public class AlsaCardsParser {
break;
}
if (DEBUG) {
- Slog.i(TAG, " " + line);
+ Slog.d(TAG, " " + line);
}
cardRecord.parse(line, 1);
+ // scan "usbbus" file
+ int cardNum = cardRecord.mCardNum;
+ String cardFolderPath = kAlsaFolderPath + "/card" + cardNum;
+ File usbbusFile = new File(cardFolderPath + "/usbbus");
+ if (usbbusFile.exists()) {
+ // read it in
+ FileReader usbbusReader = new FileReader(usbbusFile);
+ String deviceAddress = (new BufferedReader(usbbusReader)).readLine();
+ if (deviceAddress != null) {
+ cardRecord.setDeviceAddress(kDeviceAddressPrefix + deviceAddress);
+ }
+ usbbusReader.close();
+ }
mCardRecords.add(cardRecord);
}
reader.close();
@@ -147,14 +183,12 @@ public class AlsaCardsParser {
mScanStatus = SCANSTATUS_EMPTY;
}
} catch (FileNotFoundException e) {
- e.printStackTrace();
mScanStatus = SCANSTATUS_FAIL;
} catch (IOException e) {
- e.printStackTrace();
mScanStatus = SCANSTATUS_FAIL;
}
if (DEBUG) {
- Slog.i(TAG, " status:" + mScanStatus);
+ Slog.d(TAG, " status:" + mScanStatus);
}
return mScanStatus;
}
@@ -163,142 +197,33 @@ public class AlsaCardsParser {
return mScanStatus;
}
- public ArrayList<AlsaCardRecord> getScanRecords() {
- return mCardRecords;
- }
-
- public AlsaCardRecord getCardRecordAt(int index) {
- return mCardRecords.get(index);
- }
-
- public AlsaCardRecord getCardRecordFor(int cardNum) {
- for (AlsaCardRecord rec : mCardRecords) {
- if (rec.mCardNum == cardNum) {
- return rec;
+ public AlsaCardRecord findCardNumFor(String deviceAddress) {
+ for(AlsaCardRecord cardRec : mCardRecords) {
+ if (cardRec.isUsb() && cardRec.mUsbDeviceAddress.equals(deviceAddress)) {
+ return cardRec;
}
}
-
return null;
}
- public int getNumCardRecords() {
- return mCardRecords.size();
- }
-
- public boolean isCardUsb(int cardNum) {
- for (AlsaCardRecord rec : mCardRecords) {
- if (rec.mCardNum == cardNum) {
- return rec.mIsUsb;
- }
- }
-
- return false;
- }
-
- // return -1 if none found
- public int getDefaultUsbCard() {
- // save the current list of devices
- ArrayList<AlsaCardsParser.AlsaCardRecord> prevRecs = mCardRecords;
- if (DEBUG) {
- LogDevices("Previous Devices:", prevRecs);
- }
-
- // get the new list of devices
- if (scan() != SCANSTATUS_SUCCESS) {
- Slog.e(TAG, "Error scanning Alsa cards file.");
- return -1;
- }
-
- if (DEBUG) {
- LogDevices("Current Devices:", mCardRecords);
- }
-
- // Calculate the difference between the old and new device list
- ArrayList<AlsaCardRecord> newRecs = getNewCardRecords(prevRecs);
- if (DEBUG) {
- LogDevices("New Devices:", newRecs);
- }
-
- // Choose the most-recently added EXTERNAL card
- // Check recently added devices
- for (AlsaCardRecord rec : newRecs) {
- if (DEBUG) {
- Slog.d(TAG, rec.mCardName + " card:" + rec.mCardNum + " usb:" + rec.mIsUsb);
- }
- if (rec.mIsUsb) {
- // Found it
- return rec.mCardNum;
- }
- }
-
- // or return the first added EXTERNAL card?
- for (AlsaCardRecord rec : prevRecs) {
- if (DEBUG) {
- Slog.d(TAG, rec.mCardName + " card:" + rec.mCardNum + " usb:" + rec.mIsUsb);
- }
- if (rec.mIsUsb) {
- return rec.mCardNum;
- }
- }
-
- return -1;
- }
-
- public int getDefaultCard() {
- // return an external card if possible
- int card = getDefaultUsbCard();
- if (DEBUG) {
- Slog.d(TAG, "getDefaultCard() default usb card:" + card);
- }
-
- if (card < 0 && getNumCardRecords() > 0) {
- // otherwise return the (internal) card with the highest number
- card = getCardRecordAt(getNumCardRecords() - 1).mCardNum;
- }
- if (DEBUG) {
- Slog.d(TAG, " returns card:" + card);
- }
- return card;
- }
-
- static public boolean hasCardNumber(ArrayList<AlsaCardRecord> recs, int cardNum) {
- for (AlsaCardRecord cardRec : recs) {
- if (cardRec.mCardNum == cardNum) {
- return true;
- }
- }
- return false;
- }
-
- public ArrayList<AlsaCardRecord> getNewCardRecords(ArrayList<AlsaCardRecord> prevScanRecs) {
- ArrayList<AlsaCardRecord> newRecs = new ArrayList<AlsaCardRecord>();
- for (AlsaCardRecord rec : mCardRecords) {
- // now scan to see if this card number is in the previous scan list
- if (!hasCardNumber(prevScanRecs, rec.mCardNum)) {
- newRecs.add(rec);
- }
- }
- return newRecs;
- }
-
//
// Logging
//
private void Log(String heading) {
if (DEBUG) {
- Slog.i(TAG, heading);
+ Slog.d(TAG, heading);
for (AlsaCardRecord cardRec : mCardRecords) {
- Slog.i(TAG, cardRec.textFormat());
+ Slog.d(TAG, cardRec.textFormat());
}
}
}
- static private void LogDevices(String caption, ArrayList<AlsaCardRecord> deviceList) {
- Slog.d(TAG, caption + " ----------------");
- int listIndex = 0;
- for (AlsaCardRecord device : deviceList) {
- device.log(listIndex++);
- }
- Slog.d(TAG, "----------------");
- }
+// static private void LogDevices(String caption, ArrayList<AlsaCardRecord> deviceList) {
+// Slog.d(TAG, caption + " ----------------");
+// int listIndex = 0;
+// for (AlsaCardRecord device : deviceList) {
+// device.log(listIndex++);
+// }
+// Slog.d(TAG, caption + "----------------");
+// }
}
diff --git a/core/java/com/android/internal/alsa/AlsaDevicesParser.java b/core/java/com/android/internal/alsa/AlsaDevicesParser.java
index 15261bafd299..8d92d016be24 100644
--- a/core/java/com/android/internal/alsa/AlsaDevicesParser.java
+++ b/core/java/com/android/internal/alsa/AlsaDevicesParser.java
@@ -27,6 +27,9 @@ import java.util.ArrayList;
* @hide
* Retrieves information from an ALSA "devices" file.
*/
+/*
+ * NOTE: This class is currently not being used, but may be needed in the future.
+ */
public class AlsaDevicesParser {
private static final String TAG = "AlsaDevicesParser";
protected static final boolean DEBUG = false;
@@ -207,12 +210,6 @@ public class AlsaDevicesParser {
//
// Predicates
//
-/*
- public boolean hasPlaybackDevices() {
- return mHasPlaybackDevices;
- }
-*/
-
public boolean hasPlaybackDevices(int card) {
for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
if (deviceRecord.mCardNum == card &&
@@ -224,12 +221,6 @@ public class AlsaDevicesParser {
return false;
}
-/*
- public boolean hasCaptureDevices() {
- return mHasCaptureDevices;
- }
-*/
-
public boolean hasCaptureDevices(int card) {
for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
if (deviceRecord.mCardNum == card &&
@@ -241,12 +232,6 @@ public class AlsaDevicesParser {
return false;
}
-/*
- public boolean hasMIDIDevices() {
- return mHasMIDIDevices;
- }
-*/
-
public boolean hasMIDIDevices(int card) {
for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
if (deviceRecord.mCardNum == card &&
@@ -280,6 +265,7 @@ public class AlsaDevicesParser {
if (isLineDeviceRecord(line)) {
AlsaDeviceRecord deviceRecord = new AlsaDeviceRecord();
deviceRecord.parse(line);
+ Slog.i(TAG, deviceRecord.textFormat());
mDeviceRecords.add(deviceRecord);
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
index 5417d042ca54..74280fff2dfc 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaDevice.java
@@ -17,58 +17,101 @@
package com.android.server.usb;
/**
- * Represents an instance of an Alsa-supported USB peripheral.
+ * Represents the ALSA specification, and attributes of an ALSA device.
*/
public final class UsbAlsaDevice {
private static final String TAG = "UsbAlsaDevice";
protected static final boolean DEBUG = false;
- public final int mCard;
- public final int mDevice;
- public final boolean mHasPlayback;
- public final boolean mHasCapture;
-
- // Device "class" flags
- static final int AUDIO_DEVICE_CLASS_MASK = 0x00FFFFFF;
- static final int AUDIO_DEVICE_CLASS_UNDEFINED = 0x00000000;
- static final int AUDIO_DEVICE_CLASS_INTERNAL = 0x00000001;
- static final int AUDIO_DEVICE_CLASS_EXTERNAL = 0x00000002;
- // Device meta-data flags
- static final int AUDIO_DEVICE_META_MASK = 0xFF000000;
- static final int AUDIO_DEVICE_META_ALSA = 0x80000000;
- // This member is a combination of the above bit-flags
- public final int mDeviceClass;
+ private final int mCardNum;
+ private final int mDeviceNum;
+ private final boolean mHasPlayback;
+ private final boolean mHasCapture;
+
+ private final boolean mIsInputHeadset;
+ private final boolean mIsOutputHeadset;
+
+ private final String mDeviceAddress;
private String mDeviceName = "";
private String mDeviceDescription = "";
- public UsbAlsaDevice(int card, int device,
- boolean hasPlayback, boolean hasCapture, int deviceClass) {
- mCard = card;
- mDevice = device;
+ public UsbAlsaDevice(int card, int device, String deviceAddress,
+ boolean hasPlayback, boolean hasCapture,
+ boolean isInputHeadset, boolean isOutputHeadset) {
+ mCardNum = card;
+ mDeviceNum = device;
+ mDeviceAddress = deviceAddress;
mHasPlayback = hasPlayback;
mHasCapture = hasCapture;
- mDeviceClass = deviceClass;
+ mIsInputHeadset = isInputHeadset;
+ mIsOutputHeadset = isOutputHeadset;
+ }
+
+ /**
+ * @returns the ALSA card number associated with this peripheral.
+ */
+ public int getCardNum() {
+ return mCardNum;
+ }
+
+ /**
+ * @returns the ALSA device number associated with this peripheral.
+ */
+ public int getDeviceNum() {
+ return mDeviceNum;
+ }
+
+ /**
+ * @returns the USB device device address associated with this peripheral.
+ */
+ public String getDeviceAddress() {
+ return mDeviceAddress;
+ }
+
+ /**
+ * @returns true if the device supports playback.
+ */
+ public boolean hasPlayback() {
+ return mHasPlayback;
+ }
+
+ /**
+ * @returns true if the device supports capture (recording).
+ */
+ public boolean hasCapture() {
+ return mHasCapture;
+ }
+
+ /**
+ * @returns true if the device is a headset for purposes of capture.
+ */
+ public boolean isInputHeadset() {
+ return mIsInputHeadset;
+ }
+
+ /**
+ * @returns true if the device is a headset for purposes of playback.
+ */
+ public boolean isOutputHeadset() {
+ return mIsOutputHeadset;
}
/**
* @Override
- * @return a String representation of the object.
+ * @returns a string representation of the object.
*/
public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("UsbAlsaDevice: [card: " + mCard);
- sb.append(", device: " + mDevice);
- sb.append(", name: " + mDeviceName);
- sb.append(", hasPlayback: " + mHasPlayback);
- sb.append(", hasCapture: " + mHasCapture);
- sb.append(", class: 0x" + Integer.toHexString(mDeviceClass) + "]");
- return sb.toString();
+ return "UsbAlsaDevice: [card: " + mCardNum
+ + ", device: " + mDeviceNum
+ + ", name: " + mDeviceName
+ + ", hasPlayback: " + mHasPlayback
+ + ", hasCapture: " + mHasCapture + "]";
}
// called by logDevices
String toShortString() {
- return "[card:" + mCard + " device:" + mDevice + " " + mDeviceName + "]";
+ return "[card:" + mCardNum + " device:" + mDeviceNum + " " + mDeviceName + "]";
}
String getDeviceName() {
@@ -80,5 +123,38 @@ public final class UsbAlsaDevice {
mDeviceDescription = deviceDescription;
}
+ /**
+ * @Override
+ * @returns true if the objects are equivalent.
+ */
+ public boolean equals(Object obj) {
+ if (!(obj instanceof UsbAlsaDevice)) {
+ return false;
+ }
+ UsbAlsaDevice other = (UsbAlsaDevice) obj;
+ return (mCardNum == other.mCardNum
+ && mDeviceNum == other.mDeviceNum
+ && mHasPlayback == other.mHasPlayback
+ && mHasCapture == other.mHasCapture
+ && mIsInputHeadset == other.mIsInputHeadset
+ && mIsOutputHeadset == other.mIsOutputHeadset);
+ }
+
+ /**
+ * @Override
+ * @returns a hash code generated from the object contents.
+ */
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + mCardNum;
+ result = prime * result + mDeviceNum;
+ result = prime * result + (mHasPlayback ? 0 : 1);
+ result = prime * result + (mHasCapture ? 0 : 1);
+ result = prime * result + (mIsInputHeadset ? 0 : 1);
+ result = prime * result + (mIsOutputHeadset ? 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 11517b653838..0a94828e595e 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -10,7 +10,7 @@
* 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 an
+ * See the License for the specific language governing permissions and
* limitations under the License.
*/
@@ -19,28 +19,24 @@ package com.android.server.usb;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
-import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
-import android.hardware.usb.UsbInterface;
import android.media.AudioSystem;
import android.media.IAudioService;
import android.media.midi.MidiDeviceInfo;
import android.os.Bundle;
-import android.os.FileObserver;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemClock;
import android.provider.Settings;
import android.util.Slog;
import com.android.internal.alsa.AlsaCardsParser;
-import com.android.internal.alsa.AlsaDevicesParser;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.audio.AudioService;
+import com.android.server.usb.descriptors.UsbDescriptorParser;
import libcore.io.IoUtils;
-import java.io.File;
+import java.util.ArrayList;
import java.util.HashMap;
/**
@@ -57,107 +53,36 @@ public final class UsbAlsaManager {
private final boolean mHasMidiFeature;
private final AlsaCardsParser mCardsParser = new AlsaCardsParser();
- private final AlsaDevicesParser mDevicesParser = new AlsaDevicesParser();
// this is needed to map USB devices to ALSA Audio Devices, especially to remove an
// ALSA device when we are notified that its associated USB device has been removed.
+ private final ArrayList<UsbAlsaDevice> mAlsaDevices = new ArrayList<UsbAlsaDevice>();
- private final HashMap<UsbDevice, UsbAlsaDevice>
- mAudioDevices = new HashMap<UsbDevice, UsbAlsaDevice>();
-
- private boolean mIsInputHeadset; // as reported by UsbDescriptorParser
- private boolean mIsOutputHeadset; // as reported by UsbDescriptorParser
-
- private final HashMap<UsbDevice,UsbMidiDevice>
- mMidiDevices = new HashMap<UsbDevice,UsbMidiDevice>();
-
- private final HashMap<String,AlsaDevice>
- mAlsaDevices = new HashMap<String,AlsaDevice>();
-
- private UsbAlsaDevice mAccessoryAudioDevice = null;
+ /**
+ * List of connected MIDI devices
+ */
+ private final HashMap<String, UsbMidiDevice>
+ mMidiDevices = new HashMap<String, UsbMidiDevice>();
// UsbMidiDevice for USB peripheral mode (gadget) device
private UsbMidiDevice mPeripheralMidiDevice = null;
- private final class AlsaDevice {
- public static final int TYPE_UNKNOWN = 0;
- public static final int TYPE_PLAYBACK = 1;
- public static final int TYPE_CAPTURE = 2;
- public static final int TYPE_MIDI = 3;
-
- public int mCard;
- public int mDevice;
- public int mType;
-
- public AlsaDevice(int type, int card, int device) {
- mType = type;
- mCard = card;
- mDevice = device;
- }
-
- public boolean equals(Object obj) {
- if (! (obj instanceof AlsaDevice)) {
- return false;
- }
- AlsaDevice other = (AlsaDevice)obj;
- return (mType == other.mType && mCard == other.mCard && mDevice == other.mDevice);
- }
-
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("AlsaDevice: [card: " + mCard);
- sb.append(", device: " + mDevice);
- sb.append(", type: " + mType);
- sb.append("]");
- return sb.toString();
- }
- }
-
- private final FileObserver mAlsaObserver = new FileObserver(ALSA_DIRECTORY,
- FileObserver.CREATE | FileObserver.DELETE) {
- public void onEvent(int event, String path) {
- switch (event) {
- case FileObserver.CREATE:
- alsaFileAdded(path);
- break;
- case FileObserver.DELETE:
- alsaFileRemoved(path);
- break;
- }
- }
- };
-
/* package */ UsbAlsaManager(Context context) {
mContext = context;
mHasMidiFeature = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
-
- // initial scan
- if (mCardsParser.scan() != AlsaCardsParser.SCANSTATUS_SUCCESS) {
- Slog.e(TAG, "Error scanning ASLA cards file.");
- }
}
public void systemReady() {
mAudioService = IAudioService.Stub.asInterface(
ServiceManager.getService(Context.AUDIO_SERVICE));
-
- mAlsaObserver.startWatching();
-
- // add existing alsa devices
- File[] files = new File(ALSA_DIRECTORY).listFiles();
- if (files != null) {
- for (int i = 0; i < files.length; i++) {
- alsaFileAdded(files[i].getName());
- }
- }
}
// Notifies AudioService when a device is added or removed
// audioDevice - the AudioDevice that was added or removed
// enabled - if true, we're connecting a device (it's arrived), else disconnecting
- private void notifyDeviceState(UsbAlsaDevice audioDevice, boolean enabled) {
+ private void notifyDeviceState(UsbAlsaDevice alsaDevice, boolean enabled) {
if (DEBUG) {
- Slog.d(TAG, "notifyDeviceState " + enabled + " " + audioDevice);
+ Slog.d(TAG, "notifyDeviceState " + enabled + " " + alsaDevice);
}
if (mAudioService == null) {
@@ -177,276 +102,151 @@ public final class UsbAlsaManager {
}
int state = (enabled ? 1 : 0);
- int alsaCard = audioDevice.mCard;
- int alsaDevice = audioDevice.mDevice;
- if (alsaCard < 0 || alsaDevice < 0) {
- Slog.e(TAG, "Invalid alsa card or device alsaCard: " + alsaCard +
- " alsaDevice: " + alsaDevice);
+ int cardNum = alsaDevice.getCardNum();
+ int deviceNum = alsaDevice.getDeviceNum();
+ if (cardNum < 0 || deviceNum < 0) {
+ Slog.e(TAG, "Invalid alsa card or device alsaCard: " + cardNum
+ + " alsaDevice: " + deviceNum);
return;
}
- String address = AudioService.makeAlsaAddressString(alsaCard, alsaDevice);
+ String address = AudioService.makeAlsaAddressString(cardNum, deviceNum);
try {
// Playback Device
- if (audioDevice.mHasPlayback) {
- int device;
- if (mIsOutputHeadset) {
- device = AudioSystem.DEVICE_OUT_USB_HEADSET;
- } else {
- device = (audioDevice == mAccessoryAudioDevice
- ? AudioSystem.DEVICE_OUT_USB_ACCESSORY
- : AudioSystem.DEVICE_OUT_USB_DEVICE);
- }
+ if (alsaDevice.hasPlayback()) {
+ int device = alsaDevice.isOutputHeadset()
+ ? AudioSystem.DEVICE_OUT_USB_HEADSET
+ : AudioSystem.DEVICE_OUT_USB_DEVICE;
if (DEBUG) {
Slog.i(TAG, "pre-call device:0x" + Integer.toHexString(device) +
- " addr:" + address + " name:" + audioDevice.getDeviceName());
+ " addr:" + address + " name:" + alsaDevice.getDeviceName());
}
mAudioService.setWiredDeviceConnectionState(
- device, state, address, audioDevice.getDeviceName(), TAG);
+ device, state, address, alsaDevice.getDeviceName(), TAG);
}
// Capture Device
- if (audioDevice.mHasCapture) {
- int device;
- if (mIsInputHeadset) {
- device = AudioSystem.DEVICE_IN_USB_HEADSET;
- } else {
- device = (audioDevice == mAccessoryAudioDevice
- ? AudioSystem.DEVICE_IN_USB_ACCESSORY
- : AudioSystem.DEVICE_IN_USB_DEVICE);
- }
+ if (alsaDevice.hasCapture()) {
+ int device = alsaDevice.isInputHeadset()
+ ? AudioSystem.DEVICE_IN_USB_HEADSET
+ : AudioSystem.DEVICE_IN_USB_DEVICE;
mAudioService.setWiredDeviceConnectionState(
- device, state, address, audioDevice.getDeviceName(), TAG);
+ device, state, address, alsaDevice.getDeviceName(), TAG);
}
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException in setWiredDeviceConnectionState");
}
}
- private AlsaDevice waitForAlsaDevice(int card, int device, int type) {
- if (DEBUG) {
- Slog.e(TAG, "waitForAlsaDevice(c:" + card + " d:" + device + ")");
- }
-
- AlsaDevice testDevice = new AlsaDevice(type, card, device);
-
- // This value was empirically determined.
- final int kWaitTimeMs = 2500;
-
- synchronized(mAlsaDevices) {
- long timeoutMs = SystemClock.elapsedRealtime() + kWaitTimeMs;
- do {
- if (mAlsaDevices.values().contains(testDevice)) {
- return testDevice;
- }
- long waitTimeMs = timeoutMs - SystemClock.elapsedRealtime();
- if (waitTimeMs > 0) {
- try {
- mAlsaDevices.wait(waitTimeMs);
- } catch (InterruptedException e) {
- Slog.d(TAG, "usb: InterruptedException while waiting for ALSA file.");
- }
- }
- } while (timeoutMs > SystemClock.elapsedRealtime());
- }
-
- Slog.e(TAG, "waitForAlsaDevice failed for " + testDevice);
- return null;
- }
-
- private void alsaFileAdded(String name) {
- Slog.i(TAG, "alsaFileAdded(" + name + ")");
- int type = AlsaDevice.TYPE_UNKNOWN;
- int card = -1, device = -1;
-
- if (name.startsWith("pcmC")) {
- if (name.endsWith("p")) {
- type = AlsaDevice.TYPE_PLAYBACK;
- } else if (name.endsWith("c")) {
- type = AlsaDevice.TYPE_CAPTURE;
- }
- } else if (name.startsWith("midiC")) {
- type = AlsaDevice.TYPE_MIDI;
- }
-
- if (type != AlsaDevice.TYPE_UNKNOWN) {
- try {
- int c_index = name.indexOf('C');
- int d_index = name.indexOf('D');
- int end = name.length();
- if (type == AlsaDevice.TYPE_PLAYBACK || type == AlsaDevice.TYPE_CAPTURE) {
- // skip trailing 'p' or 'c'
- end--;
- }
- card = Integer.parseInt(name.substring(c_index + 1, d_index));
- device = Integer.parseInt(name.substring(d_index + 1, end));
- } catch (Exception e) {
- Slog.e(TAG, "Could not parse ALSA file name " + name, e);
- return;
- }
- synchronized(mAlsaDevices) {
- if (mAlsaDevices.get(name) == null) {
- AlsaDevice alsaDevice = new AlsaDevice(type, card, device);
- Slog.d(TAG, "Adding ALSA device " + alsaDevice);
- mAlsaDevices.put(name, alsaDevice);
- mAlsaDevices.notifyAll();
- }
- }
- }
- }
-
- private void alsaFileRemoved(String path) {
- synchronized(mAlsaDevices) {
- AlsaDevice device = mAlsaDevices.remove(path);
- if (device != null) {
- Slog.d(TAG, "ALSA device removed: " + device);
+ private int getAlsaDeviceListIndexFor(String deviceAddress) {
+ for (int index = 0; index < mAlsaDevices.size(); index++) {
+ if (mAlsaDevices.get(index).getDeviceAddress().equals(deviceAddress)) {
+ return index;
}
}
+ return -1;
}
- /*
- * Select the default device of the specified card.
- */
- /* package */ UsbAlsaDevice selectAudioCard(int card) {
- if (DEBUG) {
- Slog.d(TAG, "selectAudioCard() card:" + card
- + " isCardUsb(): " + mCardsParser.isCardUsb(card));
- }
- if (!mCardsParser.isCardUsb(card)) {
- // Don't. AudioPolicyManager has logic for falling back to internal devices.
- return null;
- }
-
- if (mDevicesParser.scan() != AlsaDevicesParser.SCANSTATUS_SUCCESS) {
- Slog.e(TAG, "Error parsing ALSA devices file.");
- return null;
- }
-
- int device = mDevicesParser.getDefaultDeviceNum(card);
-
- boolean hasPlayback = mDevicesParser.hasPlaybackDevices(card);
- boolean hasCapture = mDevicesParser.hasCaptureDevices(card);
- if (DEBUG) {
- Slog.d(TAG, "usb: hasPlayback:" + hasPlayback + " hasCapture:" + hasCapture);
- }
-
- int deviceClass =
- (mCardsParser.isCardUsb(card)
- ? UsbAlsaDevice.AUDIO_DEVICE_CLASS_EXTERNAL
- : UsbAlsaDevice.AUDIO_DEVICE_CLASS_INTERNAL)
- | UsbAlsaDevice.AUDIO_DEVICE_META_ALSA;
-
- // Playback device file needed/present?
- if (hasPlayback && (waitForAlsaDevice(card, device, AlsaDevice.TYPE_PLAYBACK) == null)) {
- return null;
- }
-
- // Capture device file needed/present?
- if (hasCapture && (waitForAlsaDevice(card, device, AlsaDevice.TYPE_CAPTURE) == null)) {
+ private UsbAlsaDevice removeAlsaDeviceFromList(String deviceAddress) {
+ int index = getAlsaDeviceListIndexFor(deviceAddress);
+ if (index > -1) {
+ return mAlsaDevices.remove(index);
+ } else {
return null;
}
-
- UsbAlsaDevice audioDevice =
- new UsbAlsaDevice(card, device, hasPlayback, hasCapture, deviceClass);
- AlsaCardsParser.AlsaCardRecord cardRecord = mCardsParser.getCardRecordFor(card);
- audioDevice.setDeviceNameAndDescription(cardRecord.mCardName, cardRecord.mCardDescription);
-
- notifyDeviceState(audioDevice, true /*enabled*/);
-
- return audioDevice;
}
/* package */ UsbAlsaDevice selectDefaultDevice() {
if (DEBUG) {
Slog.d(TAG, "UsbAudioManager.selectDefaultDevice()");
}
- return selectAudioCard(mCardsParser.getDefaultCard());
+
+ if (mAlsaDevices.size() > 0) {
+ UsbAlsaDevice alsaDevice = mAlsaDevices.get(0);
+ if (DEBUG) {
+ Slog.d(TAG, " alsaDevice:" + alsaDevice);
+ }
+ if (alsaDevice != null) {
+ notifyDeviceState(alsaDevice, true /*enabled*/);
+ }
+ return alsaDevice;
+ } else {
+ return null;
+ }
}
- /* package */ void usbDeviceAdded(UsbDevice usbDevice,
- boolean isInputHeadset, boolean isOutputHeadset) {
+ /* package */ void usbDeviceAdded(String deviceAddress, UsbDevice usbDevice,
+ UsbDescriptorParser parser) {
if (DEBUG) {
- Slog.d(TAG, "deviceAdded(): " + usbDevice.getManufacturerName()
+ Slog.d(TAG, "usbDeviceAdded(): " + usbDevice.getManufacturerName()
+ " nm:" + usbDevice.getProductName());
}
- mIsInputHeadset = isInputHeadset;
- mIsOutputHeadset = isOutputHeadset;
-
- // Is there an audio interface in there?
- boolean isAudioDevice = false;
+ // Scan the Alsa File Space
+ mCardsParser.scan();
- // FIXME - handle multiple configurations?
- int interfaceCount = usbDevice.getInterfaceCount();
- for (int ntrfaceIndex = 0; !isAudioDevice && ntrfaceIndex < interfaceCount;
- ntrfaceIndex++) {
- UsbInterface ntrface = usbDevice.getInterface(ntrfaceIndex);
- if (ntrface.getInterfaceClass() == UsbConstants.USB_CLASS_AUDIO) {
- isAudioDevice = true;
- }
+ // Find the ALSA spec for this device address
+ AlsaCardsParser.AlsaCardRecord cardRec =
+ mCardsParser.findCardNumFor(deviceAddress);
+ if (cardRec == null) {
+ return;
}
+ // Add it to the devices list
+ boolean hasInput = parser.hasInput();
+ boolean hasOutput = parser.hasOutput();
if (DEBUG) {
- Slog.d(TAG, " isAudioDevice: " + isAudioDevice);
- }
- if (!isAudioDevice) {
- return;
+ Slog.d(TAG, "hasInput: " + hasInput + " hasOutput:" + hasOutput);
+ }
+ if (hasInput || hasOutput) {
+ boolean isInputHeadset = parser.isInputHeadset();
+ boolean isOutputHeadset = parser.isOutputHeadset();
+ UsbAlsaDevice alsaDevice =
+ new UsbAlsaDevice(cardRec.getCardNum(), 0 /*device*/, deviceAddress,
+ hasOutput, hasInput, isInputHeadset, isOutputHeadset);
+ alsaDevice.setDeviceNameAndDescription(
+ cardRec.getCardName(), cardRec.getCardDescription());
+ mAlsaDevices.add(0, alsaDevice);
+
+ // Select it
+ if (alsaDevice != null) {
+ notifyDeviceState(alsaDevice, true /*enabled*/);
+ }
}
- int addedCard = mCardsParser.getDefaultUsbCard();
-
- // If the default isn't a USB device, let the existing "select internal mechanism"
- // handle the selection.
+ // look for MIDI devices
+ boolean hasMidi = parser.hasMIDIInterface();
if (DEBUG) {
- Slog.d(TAG, " mCardsParser.isCardUsb(" + addedCard + ") = "
- + mCardsParser.isCardUsb(addedCard));
+ Slog.d(TAG, "hasMidi: " + hasMidi + " mHasMidiFeature:" + mHasMidiFeature);
}
- if (mCardsParser.isCardUsb(addedCard)) {
- UsbAlsaDevice audioDevice = selectAudioCard(addedCard);
- if (audioDevice != null) {
- mAudioDevices.put(usbDevice, audioDevice);
- Slog.i(TAG, "USB Audio Device Added: " + audioDevice);
+ if (hasMidi && mHasMidiFeature) {
+ int device = 0;
+ Bundle properties = new Bundle();
+ String manufacturer = usbDevice.getManufacturerName();
+ String product = usbDevice.getProductName();
+ String version = usbDevice.getVersion();
+ String name;
+ if (manufacturer == null || manufacturer.isEmpty()) {
+ name = product;
+ } else if (product == null || product.isEmpty()) {
+ name = manufacturer;
+ } else {
+ name = manufacturer + " " + product;
}
-
- // look for MIDI devices
-
- // Don't need to call mDevicesParser.scan() because selectAudioCard() does this above.
- // Uncomment this next line if that behavior changes in the fugure.
- // mDevicesParser.scan()
-
- boolean hasMidi = mDevicesParser.hasMIDIDevices(addedCard);
- if (hasMidi && mHasMidiFeature) {
- int device = mDevicesParser.getDefaultDeviceNum(addedCard);
- AlsaDevice alsaDevice = waitForAlsaDevice(addedCard, device, AlsaDevice.TYPE_MIDI);
- if (alsaDevice != null) {
- Bundle properties = new Bundle();
- String manufacturer = usbDevice.getManufacturerName();
- String product = usbDevice.getProductName();
- String version = usbDevice.getVersion();
- String name;
- if (manufacturer == null || manufacturer.isEmpty()) {
- name = product;
- } else if (product == null || product.isEmpty()) {
- name = manufacturer;
- } else {
- name = manufacturer + " " + product;
- }
- properties.putString(MidiDeviceInfo.PROPERTY_NAME, name);
- properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, manufacturer);
- properties.putString(MidiDeviceInfo.PROPERTY_PRODUCT, product);
- properties.putString(MidiDeviceInfo.PROPERTY_VERSION, version);
- properties.putString(MidiDeviceInfo.PROPERTY_SERIAL_NUMBER,
- usbDevice.getSerialNumber());
- properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, alsaDevice.mCard);
- properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, alsaDevice.mDevice);
- properties.putParcelable(MidiDeviceInfo.PROPERTY_USB_DEVICE, usbDevice);
-
- UsbMidiDevice usbMidiDevice = UsbMidiDevice.create(mContext, properties,
- alsaDevice.mCard, alsaDevice.mDevice);
- if (usbMidiDevice != null) {
- mMidiDevices.put(usbDevice, usbMidiDevice);
- }
- }
+ properties.putString(MidiDeviceInfo.PROPERTY_NAME, name);
+ properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, manufacturer);
+ properties.putString(MidiDeviceInfo.PROPERTY_PRODUCT, product);
+ properties.putString(MidiDeviceInfo.PROPERTY_VERSION, version);
+ properties.putString(MidiDeviceInfo.PROPERTY_SERIAL_NUMBER,
+ usbDevice.getSerialNumber());
+ properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, cardRec.getCardNum());
+ properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, 0 /*deviceNum*/);
+ properties.putParcelable(MidiDeviceInfo.PROPERTY_USB_DEVICE, usbDevice);
+
+ UsbMidiDevice usbMidiDevice = UsbMidiDevice.create(mContext, properties,
+ cardRec.getCardNum(), 0 /*device*/);
+ if (usbMidiDevice != null) {
+ mMidiDevices.put(deviceAddress, usbMidiDevice);
}
}
@@ -455,42 +255,31 @@ public final class UsbAlsaManager {
}
}
- /* package */ void usbDeviceRemoved(UsbDevice usbDevice) {
+ /* package */ void usbDeviceRemoved(String deviceAddress/*UsbDevice usbDevice*/) {
if (DEBUG) {
- Slog.d(TAG, "deviceRemoved(): " + usbDevice.getManufacturerName() +
- " " + usbDevice.getProductName());
+ Slog.d(TAG, "deviceRemoved(" + deviceAddress + ")");
}
- UsbAlsaDevice audioDevice = mAudioDevices.remove(usbDevice);
- Slog.i(TAG, "USB Audio Device Removed: " + audioDevice);
- if (audioDevice != null) {
- if (audioDevice.mHasPlayback || audioDevice.mHasCapture) {
- notifyDeviceState(audioDevice, false /*enabled*/);
+ // Audio
+ UsbAlsaDevice alsaDevice = removeAlsaDeviceFromList(deviceAddress);
+ Slog.i(TAG, "USB Audio Device Removed: " + alsaDevice);
+ if (alsaDevice != null) {
+ if (alsaDevice.hasPlayback() || alsaDevice.hasCapture()) {
+ notifyDeviceState(alsaDevice, false /*enabled*/);
// if there any external devices left, select one of them
selectDefaultDevice();
}
}
- UsbMidiDevice usbMidiDevice = mMidiDevices.remove(usbDevice);
+
+ // MIDI
+ UsbMidiDevice usbMidiDevice = mMidiDevices.remove(deviceAddress);
if (usbMidiDevice != null) {
+ Slog.i(TAG, "USB MIDI Device Removed: " + usbMidiDevice);
IoUtils.closeQuietly(usbMidiDevice);
}
}
- /* package */ void setAccessoryAudioState(boolean enabled, int card, int device) {
- if (DEBUG) {
- Slog.d(TAG, "setAccessoryAudioState " + enabled + " " + card + " " + device);
- }
- if (enabled) {
- mAccessoryAudioDevice = new UsbAlsaDevice(card, device, true, false,
- UsbAlsaDevice.AUDIO_DEVICE_CLASS_EXTERNAL);
- notifyDeviceState(mAccessoryAudioDevice, true /*enabled*/);
- } else if (mAccessoryAudioDevice != null) {
- notifyDeviceState(mAccessoryAudioDevice, false /*enabled*/);
- mAccessoryAudioDevice = null;
- }
- }
-
/* package */ void setPeripheralMidiState(boolean enabled, int card, int device) {
if (!mHasMidiFeature) {
return;
@@ -515,34 +304,21 @@ public final class UsbAlsaManager {
}
//
- // Devices List
- //
-/*
- //import java.util.ArrayList;
- public ArrayList<UsbAlsaDevice> getConnectedDevices() {
- ArrayList<UsbAlsaDevice> devices = new ArrayList<UsbAlsaDevice>(mAudioDevices.size());
- for (HashMap.Entry<UsbDevice,UsbAlsaDevice> entry : mAudioDevices.entrySet()) {
- devices.add(entry.getValue());
- }
- return devices;
- }
-*/
-
- //
// Logging
//
// called by UsbService.dump
public void dump(IndentingPrintWriter pw) {
pw.println("Parsers Scan Status:");
pw.println(" Cards Parser: " + mCardsParser.getScanStatus());
- pw.println(" Devices Parser: " + mDevicesParser.getScanStatus());
+// pw.println(" Devices Parser: " + mDevicesParser.getScanStatus());
pw.println("USB Audio Devices:");
- for (UsbDevice device : mAudioDevices.keySet()) {
- pw.println(" " + device.getDeviceName() + ": " + mAudioDevices.get(device));
+ for (UsbAlsaDevice usbAlsaDevice : mAlsaDevices) {
+ pw.println(" " + usbAlsaDevice.getDeviceAddress() + ": " + usbAlsaDevice);
}
pw.println("USB MIDI Devices:");
- for (UsbDevice device : mMidiDevices.keySet()) {
- pw.println(" " + device.getDeviceName() + ": " + mMidiDevices.get(device));
+ for (String deviceAddr : mMidiDevices.keySet()) {
+ UsbMidiDevice midiDevice = mMidiDevices.get(deviceAddr);
+ pw.println(" " + deviceAddr + ": " + midiDevice);
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 55ffea6f252f..a67e7f37f947 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -726,35 +726,9 @@ public class UsbDeviceManager implements ActivityManagerInternal.ScreenObserver
}
private void updateUsbFunctions() {
- updateAudioSourceFunction();
updateMidiFunction();
}
- private void updateAudioSourceFunction() {
- boolean enabled = (mCurrentFunctions & UsbManager.FUNCTION_AUDIO_SOURCE) != 0;
- if (enabled != mAudioSourceEnabled) {
- int card = -1;
- int device = -1;
-
- if (enabled) {
- Scanner scanner = null;
- try {
- scanner = new Scanner(new File(AUDIO_SOURCE_PCM_PATH));
- card = scanner.nextInt();
- device = scanner.nextInt();
- } catch (FileNotFoundException e) {
- Slog.e(TAG, "could not open audio source PCM file", e);
- } finally {
- if (scanner != null) {
- scanner.close();
- }
- }
- }
- mUsbAlsaManager.setAccessoryAudioState(enabled, card, device);
- mAudioSourceEnabled = enabled;
- }
- }
-
private void updateMidiFunction() {
boolean enabled = (mCurrentFunctions & UsbManager.FUNCTION_MIDI) != 0;
if (enabled != mMidiEnabled) {
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index 7a352a4dc69d..58f914773071 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -44,7 +44,7 @@ import java.util.LinkedList;
*/
public class UsbHostManager {
private static final String TAG = UsbHostManager.class.getSimpleName();
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private final Context mContext;
@@ -230,6 +230,7 @@ public class UsbHostManager {
}
private boolean isBlackListed(String deviceAddress) {
+ Slog.i(TAG, "isBlackListed(" + deviceAddress + ")");
int count = mHostBlacklist.length;
for (int i = 0; i < count; i++) {
if (deviceAddress.startsWith(mHostBlacklist[i])) {
@@ -241,6 +242,7 @@ public class UsbHostManager {
/* returns true if the USB device should not be accessible by applications */
private boolean isBlackListed(int clazz, int subClass) {
+ Slog.i(TAG, "isBlackListed(" + clazz + ", " + subClass + ")");
// blacklist hubs
if (clazz == UsbConstants.USB_CLASS_HUB) return true;
@@ -312,13 +314,7 @@ public class UsbHostManager {
usbDeviceConnectionHandler);
}
- // Headset?
- boolean isInputHeadset = parser.isInputHeadset();
- boolean isOutputHeadset = parser.isOutputHeadset();
- Slog.i(TAG, "---- isHeadset[in: " + isInputHeadset
- + " , out: " + isOutputHeadset + "]");
-
- mUsbAlsaManager.usbDeviceAdded(newDevice, isInputHeadset, isOutputHeadset);
+ mUsbAlsaManager.usbDeviceAdded(deviceAddress, newDevice, parser);
// Tracking
addConnectionRecord(deviceAddress, ConnectionRecord.CONNECT,
@@ -343,10 +339,13 @@ public class UsbHostManager {
/* Called from JNI in monitorUsbHostBus to report USB device removal */
@SuppressWarnings("unused")
private void usbDeviceRemoved(String deviceAddress) {
+ if (DEBUG) {
+ Slog.d(TAG, "usbDeviceRemoved(" + deviceAddress + ") - start");
+ }
synchronized (mLock) {
UsbDevice device = mDevices.remove(deviceAddress);
if (device != null) {
- mUsbAlsaManager.usbDeviceRemoved(device);
+ mUsbAlsaManager.usbDeviceRemoved(deviceAddress/*device*/);
mSettingsManager.usbDeviceRemoved(device);
getCurrentUserSettings().usbDeviceRemoved(device);
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 7a1e9e2f9896..297a6eab4a78 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
@@ -26,7 +26,7 @@ import java.util.ArrayList;
*/
public final class UsbDescriptorParser {
private static final String TAG = "UsbDescriptorParser";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private final String mDeviceAddr;
@@ -358,50 +358,93 @@ public final class UsbDescriptorParser {
return list;
}
+ /*
+ * Attribute predicates
+ */
/**
* @hide
*/
- public boolean hasHIDDescriptor() {
- ArrayList<UsbDescriptor> descriptors =
- getInterfaceDescriptorsForClass(UsbDescriptor.CLASSID_HID);
- return !descriptors.isEmpty();
+ 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));
+ }
+ if ((type >= UsbTerminalTypes.TERMINAL_IN_UNDEFINED
+ && type <= UsbTerminalTypes.TERMINAL_IN_PROC_MIC_ARRAY)
+ || (type >= UsbTerminalTypes.TERMINAL_BIDIR_UNDEFINED
+ && type <= UsbTerminalTypes.TERMINAL_BIDIR_SKRPHONE_CANCEL)
+ || (type == UsbTerminalTypes.TERMINAL_USB_STREAMING)) {
+ 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 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 interfaceDescr = (UsbInterfaceDescriptor) descriptor;
- if (interfaceDescr.getUsbSubclass() == UsbDescriptor.AUDIO_MIDISTREAMING) {
- return true;
+ 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));
+ }
+ if ((type >= UsbTerminalTypes.TERMINAL_OUT_UNDEFINED
+ && type <= UsbTerminalTypes.TERMINAL_OUT_LFSPEAKER)
+ || (type >= UsbTerminalTypes.TERMINAL_BIDIR_UNDEFINED
+ && type <= UsbTerminalTypes.TERMINAL_BIDIR_SKRPHONE_CANCEL)) {
+ hasOutput = true;
+ break;
}
} else {
- Log.w(TAG, "Undefined Audio Class Interface l: " + descriptor.getLength()
+ Log.w(TAG, "Undefined Audio Input terminal l: " + descriptor.getLength()
+ " t:0x" + Integer.toHexString(descriptor.getType()));
}
}
- return false;
+ if (DEBUG) {
+ Log.d(TAG, "hasOutput() = " + hasOutput);
+ }
+ return hasOutput;
}
/**
* @hide
*/
- public float getInputHeadsetProbability() {
- if (hasMIDIInterface()) {
- return 0.0f;
- }
-
- float probability = 0.0f;
- ArrayList<UsbDescriptor> acDescriptors;
-
- // Look for a microphone
+ public boolean hasMic() {
boolean hasMic = false;
- acDescriptors = getACInterfaceDescriptors(UsbACInterface.ACI_INPUT_TERMINAL,
+
+ ArrayList<UsbDescriptor> acDescriptors =
+ getACInterfaceDescriptors(UsbACInterface.ACI_INPUT_TERMINAL,
UsbACInterface.AUDIO_AUDIOCONTROL);
for (UsbDescriptor descriptor : acDescriptors) {
if (descriptor instanceof UsbACTerminal) {
@@ -418,18 +461,23 @@ public final class UsbDescriptorParser {
+ " t:0x" + Integer.toHexString(descriptor.getType()));
}
}
+ return hasMic;
+ }
- // Look for a "speaker"
+ /**
+ * @hide
+ */
+ public boolean hasSpeaker() {
boolean hasSpeaker = false;
- acDescriptors =
+
+ 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_OUT_HEADPHONES
|| outDescr.getTerminalType() == UsbTerminalTypes.TERMINAL_BIDIR_HEADSET) {
hasSpeaker = true;
break;
@@ -440,6 +488,55 @@ public final class UsbDescriptorParser {
}
}
+ return hasSpeaker;
+ }
+
+ /**
+ * @hide
+ */
+ public boolean hasHIDDescriptor() {
+ ArrayList<UsbDescriptor> descriptors =
+ getInterfaceDescriptorsForClass(UsbDescriptor.CLASSID_HID);
+ 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 interfaceDescr = (UsbInterfaceDescriptor) descriptor;
+ if (interfaceDescr.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 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;
}