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

Commit 96798efe authored by Paul McLean's avatar Paul McLean Committed by Android (Google) Code Review
Browse files

Merge "Support for simultaneous USB Audio Devices connect/disconnect"

parents 0c3e78c9 0a8f0692
Loading
Loading
Loading
Loading
+141 −45
Original line number Diff line number Diff line
@@ -22,46 +22,58 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Vector;
import java.util.ArrayList;

/**
 * @hide Retrieves information from an ALSA "cards" file.
 */
public class AlsaCardsParser {
    private static final String TAG = "AlsaCardsParser";
    protected static final boolean DEBUG = true;

    private static LineTokenizer tokenizer_ = new LineTokenizer(" :[]");
    private static LineTokenizer mTokenizer = new LineTokenizer(" :[]");

    private ArrayList<AlsaCardRecord> mCardRecords = new ArrayList<AlsaCardRecord>();

    public class AlsaCardRecord {
        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;

        public AlsaCardRecord() {}

        public boolean parse(String line, int lineIndex) {
            int tokenIndex = 0;
            int delimIndex = 0;

            if (lineIndex == 0) {
                // line # (skip)
                tokenIndex = tokenizer_.nextToken(line, tokenIndex);
                delimIndex = tokenizer_.nextDelimiter(line, tokenIndex);
                tokenIndex = mTokenizer.nextToken(line, tokenIndex);
                delimIndex = mTokenizer.nextDelimiter(line, tokenIndex);

                // mCardNum
                mCardNum = Integer.parseInt(line.substring(tokenIndex, delimIndex));

                // mField1
                tokenIndex = tokenizer_.nextToken(line, delimIndex);
                delimIndex = tokenizer_.nextDelimiter(line, tokenIndex);
                tokenIndex = mTokenizer.nextToken(line, delimIndex);
                delimIndex = mTokenizer.nextDelimiter(line, tokenIndex);
                mField1 = line.substring(tokenIndex, delimIndex);

                // mCardName
                tokenIndex = tokenizer_.nextToken(line, delimIndex);
                // delimIndex = tokenizer_.nextDelimiter(line, tokenIndex);
                tokenIndex = mTokenizer.nextToken(line, delimIndex);
                mCardName = line.substring(tokenIndex);

                // done
              } else if (lineIndex == 1) {
                  tokenIndex = tokenizer_.nextToken(line, 0);
                  tokenIndex = mTokenizer.nextToken(line, 0);
                  if (tokenIndex != -1) {
                      mCardDescription = line.substring(tokenIndex);
                      mIsUsb = mCardDescription.contains(kUsbCardKeyStr);
                  }
            }

@@ -73,10 +85,14 @@ public class AlsaCardsParser {
        }
    }

    private Vector<AlsaCardRecord> cardRecords_ = new Vector<AlsaCardRecord>();
    public AlsaCardsParser() {}

    public void scan() {
          cardRecords_.clear();
        if (DEBUG) {
            Slog.i(TAG, "AlsaCardsParser.scan()");
        }
        mCardRecords = new ArrayList<AlsaCardRecord>();

        final String cardsFilePath = "/proc/asound/cards";
        File cardsFile = new File(cardsFilePath);
        try {
@@ -85,9 +101,18 @@ public class AlsaCardsParser {
            String line = "";
            while ((line = bufferedReader.readLine()) != null) {
                AlsaCardRecord cardRecord = new AlsaCardRecord();
                if (DEBUG) {
                    Slog.i(TAG, "  " + line);
                }
                cardRecord.parse(line, 0);
                  cardRecord.parse(line = bufferedReader.readLine(), 1);
                  cardRecords_.add(cardRecord);

                line = bufferedReader.readLine();
                if (DEBUG) {
                    Slog.i(TAG, "  " + line);
                }
                cardRecord.parse(line, 1);

                mCardRecords.add(cardRecord);
            }
            reader.close();
        } catch (FileNotFoundException e) {
@@ -97,20 +122,91 @@ public class AlsaCardsParser {
        }
    }

    public ArrayList<AlsaCardRecord> getScanRecords() {
        return mCardRecords;
    }

    public AlsaCardRecord getCardRecordAt(int index) {
          return cardRecords_.get(index);
        return mCardRecords.get(index);
    }

    public AlsaCardRecord getCardRecordFor(int cardNum) {
        for (AlsaCardRecord rec : mCardRecords) {
            if (rec.mCardNum == cardNum) {
                return rec;
            }
        }

        return null;
    }

    public int getNumCardRecords() {
          return cardRecords_.size();
        return mCardRecords.size();
    }

    public void Log() {
      int numCardRecs = getNumCardRecords();
      for (int index = 0; index < numCardRecs; ++index) {
          Slog.w(TAG, "usb:" + getCardRecordAt(index).textFormat());
    public boolean isCardUsb(int cardNum) {
        for (AlsaCardRecord rec : mCardRecords) {
            if (rec.mCardNum == cardNum) {
                return rec.mIsUsb;
            }
        }

    public AlsaCardsParser() {}
        return false;
    }

    // return -1 if none found
    public int getDefaultUsbCard() {
        // Choose the most-recently added EXTERNAL card
        // or return the first added EXTERNAL card?
        for (AlsaCardRecord rec : mCardRecords) {
            if (rec.mIsUsb) {
                return rec.mCardNum;
            }
        }

        return -1;
    }

    public int getDefaultCard() {
        // return an external card if possible
        int card = getDefaultUsbCard();

        if (card < 0 && getNumCardRecords() > 0) {
            // otherwise return the (internal) card with the highest number
            card = getCardRecordAt(getNumCardRecords() - 1).mCardNum;
        }
        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
    //
    public void Log(String heading) {
        if (DEBUG) {
            Slog.i(TAG, heading);
            for (AlsaCardRecord cardRec : mCardRecords) {
                Slog.i(TAG, cardRec.textFormat());
            }
        }
    }
}
+39 −33
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Vector;
import java.util.ArrayList;

/**
 * @hide
@@ -29,6 +29,7 @@ import java.util.Vector;
 */
public class AlsaDevicesParser {
    private static final String TAG = "AlsaDevicesParser";
    protected static final boolean DEBUG = false;

    private static final int kIndex_CardDeviceField = 5;
    private static final int kStartIndex_CardNum = 6;
@@ -58,8 +59,7 @@ public class AlsaDevicesParser {
        int mDeviceType = kDeviceType_Unknown;
        int mDeviceDir = kDeviceDir_Unknown;

        public AlsaDeviceRecord() {
        }
        public AlsaDeviceRecord() {}

        public boolean parse(String line) {
            // "0123456789012345678901234567890"
@@ -176,38 +176,27 @@ public class AlsaDevicesParser {
        }
    }

    private Vector<AlsaDeviceRecord>
            deviceRecords_ = new Vector<AlsaDeviceRecord>();

    private boolean isLineDeviceRecord(String line) {
        return line.charAt(kIndex_CardDeviceField) == '[';
    }

    public AlsaDevicesParser() {
    }
    private ArrayList<AlsaDeviceRecord> mDeviceRecords = new ArrayList<AlsaDeviceRecord>();

    public int getNumDeviceRecords() {
        return deviceRecords_.size();
    }
    public AlsaDevicesParser() {}

    public AlsaDeviceRecord getDeviceRecordAt(int index) {
        return deviceRecords_.get(index);
    }

    public void Log() {
        int numDevRecs = getNumDeviceRecords();
        for (int index = 0; index < numDevRecs; ++index) {
            Slog.w(TAG, "usb:" + getDeviceRecordAt(index).textFormat());
        }
    //
    // Access
    //
    public int getDefaultDeviceNum(int card) {
        // TODO - This (obviously) isn't sufficient. Revisit.
        return 0;
    }

    //
    // Predicates
    //
   public boolean hasPlaybackDevices() {
        return mHasPlaybackDevices;
    }

    public boolean hasPlaybackDevices(int card) {
        for (int index = 0; index < deviceRecords_.size(); index++) {
            AlsaDeviceRecord deviceRecord = deviceRecords_.get(index);
        for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
            if (deviceRecord.mCardNum == card &&
                deviceRecord.mDeviceType == AlsaDeviceRecord.kDeviceType_Audio &&
                deviceRecord.mDeviceDir == AlsaDeviceRecord.kDeviceDir_Playback) {
@@ -222,8 +211,7 @@ public class AlsaDevicesParser {
    }

    public boolean hasCaptureDevices(int card) {
        for (int index = 0; index < deviceRecords_.size(); index++) {
            AlsaDeviceRecord deviceRecord = deviceRecords_.get(index);
        for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
            if (deviceRecord.mCardNum == card &&
                deviceRecord.mDeviceType == AlsaDeviceRecord.kDeviceType_Audio &&
                deviceRecord.mDeviceDir == AlsaDeviceRecord.kDeviceDir_Capture) {
@@ -238,8 +226,7 @@ public class AlsaDevicesParser {
    }

    public boolean hasMIDIDevices(int card) {
        for (int index = 0; index < deviceRecords_.size(); index++) {
            AlsaDeviceRecord deviceRecord = deviceRecords_.get(index);
        for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
            if (deviceRecord.mCardNum == card &&
                deviceRecord.mDeviceType == AlsaDeviceRecord.kDeviceType_MIDI) {
                return true;
@@ -248,8 +235,15 @@ public class AlsaDevicesParser {
        return false;
    }

    //
    // Process
    //
    private boolean isLineDeviceRecord(String line) {
        return line.charAt(kIndex_CardDeviceField) == '[';
    }

    public void scan() {
        deviceRecords_.clear();
        mDeviceRecords.clear();

        final String devicesFilePath = "/proc/asound/devices";
        File devicesFile = new File(devicesFilePath);
@@ -261,7 +255,7 @@ public class AlsaDevicesParser {
                if (isLineDeviceRecord(line)) {
                    AlsaDeviceRecord deviceRecord = new AlsaDeviceRecord();
                    deviceRecord.parse(line);
                    deviceRecords_.add(deviceRecord);
                    mDeviceRecords.add(deviceRecord);
                }
            }
            reader.close();
@@ -271,5 +265,17 @@ public class AlsaDevicesParser {
            e.printStackTrace();
        }
    }

    //
    // Loging
    //
    public void Log(String heading) {
        if (DEBUG) {
            Slog.i(TAG, heading);
            for (AlsaDeviceRecord deviceRecord : mDeviceRecords) {
                Slog.i(TAG, deviceRecord.textFormat());
            }
        }
    }
} // class AlsaDevicesParser
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.os.Parcelable;
public class UsbDevice implements Parcelable {

    private static final String TAG = "UsbDevice";
    private static final boolean DEBUG = false;

    private final String mName;
    private final String mManufacturerName;
+6 −2
Original line number Diff line number Diff line
@@ -4979,9 +4979,13 @@ public class AudioService extends IAudioService.Stub {
                boolean hasPlayback = intent.getBooleanExtra("hasPlayback", false);
                boolean hasCapture = intent.getBooleanExtra("hasCapture", false);
                boolean hasMIDI = intent.getBooleanExtra("hasMIDI", false);
                int deviceClass = intent.getIntExtra("class", 0);

                String params = (alsaCard == -1 && alsaDevice == -1 ? ""
                                    : "card=" + alsaCard + ";device=" + alsaDevice);
                String params = (alsaCard == -1 && alsaDevice == -1
                        ? ""
                        : "card=" + alsaCard +
                          ";device=" + alsaDevice +
                          ";class=" + Integer.toHexString(deviceClass));

                // Playback Device
                if (hasPlayback) {
+159 −81
Original line number Diff line number Diff line
@@ -37,46 +37,33 @@ import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.ArrayList;

/**
 * UsbAlsaManager manages USB audio and MIDI devices.
 */
public class UsbAlsaManager {
    private static final String TAG = UsbAlsaManager.class.getSimpleName();
    private static final boolean DEBUG = false;
    private static final boolean DEBUG = true;

    private static final String ALSA_DIRECTORY = "/dev/snd/";

    private final Context mContext;
    private IMidiManager mMidiManager;

    private final class AudioDevice {
        public int mCard;
        public int mDevice;
        public boolean mHasPlayback;
        public boolean mHasCapture;
        public boolean mHasMIDI;
    private final AlsaCardsParser mCardsParser = new AlsaCardsParser();
    private final AlsaDevicesParser mDevicesParser = new AlsaDevicesParser();

        public AudioDevice(int card, int device,
                boolean hasPlayback, boolean hasCapture, boolean hasMidi) {
            mCard = card;
            mDevice = device;
            mHasPlayback = hasPlayback;
            mHasCapture = hasCapture;
            mHasMIDI = hasMidi;
        }
    // 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.

        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("AudioDevice: [card: " + mCard);
            sb.append(", device: " + mDevice);
            sb.append(", hasPlayback: " + mHasPlayback);
            sb.append(", hasCapture: " + mHasCapture);
            sb.append(", hasMidi: " + mHasMIDI);
            sb.append("]");
            return sb.toString();
        }
    }
    private final HashMap<UsbDevice,UsbAudioDevice>
        mAudioDevices = new HashMap<UsbDevice,UsbAudioDevice>();

    private final HashMap<String,AlsaDevice>
        mAlsaDevices = new HashMap<String,AlsaDevice>();

    private UsbAudioDevice mSelectedAudioDevice = null;

    private final class AlsaDevice {
        public static final int TYPE_UNKNOWN = 0;
@@ -112,12 +99,6 @@ public class UsbAlsaManager {
        }
    }

    private final HashMap<UsbDevice,AudioDevice> mAudioDevices
            = new HashMap<UsbDevice,AudioDevice>();

    private final HashMap<String,AlsaDevice> mAlsaDevices
            = new HashMap<String,AlsaDevice>();

    private final FileObserver mAlsaObserver = new FileObserver(ALSA_DIRECTORY,
            FileObserver.CREATE | FileObserver.DELETE) {
        public void onEvent(int event, String path) {
@@ -134,6 +115,9 @@ public class UsbAlsaManager {

    /* package */ UsbAlsaManager(Context context) {
        mContext = context;

        // initial scan
        mCardsParser.scan();
    }

    public void systemReady() {
@@ -149,9 +133,15 @@ public class UsbAlsaManager {
    }

    // Broadcasts the arrival/departure of a USB audio interface
    // audioDevice - the AudioDevice that was added or removed
    // audioDevice - the UsbAudioDevice that was added or removed
    // enabled - if true, we're connecting a device (it's arrived), else disconnecting
    private void sendDeviceNotification(AudioDevice audioDevice, boolean enabled) {
    private void sendDeviceNotification(UsbAudioDevice audioDevice, boolean enabled) {
        if (DEBUG) {
            Slog.d(TAG, "sendDeviceNotification(enabled:" + enabled +
                    " c:" + audioDevice.mCard +
                    " d:" + audioDevice.mDevice + ")");
        }

        // send a sticky broadcast containing current USB state
        Intent intent = new Intent(AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG);
        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
@@ -162,6 +152,7 @@ public class UsbAlsaManager {
        intent.putExtra("hasPlayback", audioDevice.mHasPlayback);
        intent.putExtra("hasCapture", audioDevice.mHasCapture);
        intent.putExtra("hasMIDI", audioDevice.mHasMIDI);
        intent.putExtra("class", audioDevice.mDeviceClass);
        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
    }

@@ -241,6 +232,81 @@ public class UsbAlsaManager {
        }
    }

    /*
     * Select the default device of the specified card.
     */
    /* package */ boolean selectCard(int card) {
        if (DEBUG) {
            Slog.d(TAG, "selectCard() card:" + card);
        }
        if (!mCardsParser.isCardUsb(card)) {
            // Don't. AudioPolicyManager has logic for falling back to internal devices.
            return false;
        }

        if (mSelectedAudioDevice != null) {
            if (mSelectedAudioDevice.mCard == card) {
                // Nothing to do here.
                return false;
            }
            // "disconnect" the AudioPolicyManager from the previously selected device.
            sendDeviceNotification(mSelectedAudioDevice, false);
            mSelectedAudioDevice = null;
        }

        mDevicesParser.scan();
        int device = mDevicesParser.getDefaultDeviceNum(card);

        boolean hasPlayback = mDevicesParser.hasPlaybackDevices(card);
        boolean hasCapture = mDevicesParser.hasCaptureDevices(card);
        boolean hasMidi = mDevicesParser.hasMIDIDevices(card);
        int deviceClass =
            (mCardsParser.isCardUsb(card)
                ? UsbAudioDevice.kAudioDeviceClass_External
                : UsbAudioDevice.kAudioDeviceClass_Internal) |
            UsbAudioDevice.kAudioDeviceMeta_Alsa;

        // Playback device file needed/present?
        if (hasPlayback && (waitForAlsaDevice(card, device, AlsaDevice.TYPE_PLAYBACK) == null)) {
            return false;
        }

        // Capture device file needed/present?
        if (hasCapture && (waitForAlsaDevice(card, device, AlsaDevice.TYPE_CAPTURE) == null)) {
            return false;
        }
        //TODO - seems to me that we need to decouple the above tests for audio
        // from the one below for MIDI.

        // MIDI device file needed/present?
        AlsaDevice midiDevice = null;
        if (hasMidi) {
            midiDevice = waitForAlsaDevice(card, device, AlsaDevice.TYPE_MIDI);
        }

        if (DEBUG) {
            Slog.d(TAG, "usb: hasPlayback:" + hasPlayback + " hasCapture:" + hasCapture);
        }

        mSelectedAudioDevice =
                new UsbAudioDevice(card, device, hasPlayback, hasCapture, hasMidi, deviceClass);
        mSelectedAudioDevice.mDeviceName = mCardsParser.getCardRecordFor(card).mCardName;
        mSelectedAudioDevice.mDeviceDescription =
                mCardsParser.getCardRecordFor(card).mCardDescription;

        sendDeviceNotification(mSelectedAudioDevice, true);

        return true;
    }

    /* package */ boolean selectDefaultDevice() {
        if (DEBUG) {
            Slog.d(TAG, "UsbAudioManager.selectDefaultDevice()");
        }
        mCardsParser.scan();
        return selectCard(mCardsParser.getDefaultCard());
    }

    /* package */ void deviceAdded(UsbDevice usbDevice) {
       if (DEBUG) {
          Slog.d(TAG, "deviceAdded(): " + usbDevice);
@@ -263,56 +329,28 @@ public class UsbAlsaManager {
            return;
        }

        //TODO(pmclean) The "Parser" objects inspect files in "/proc/asound" which we presume is
        // present, unlike the waitForAlsaDevice() which waits on a file in /dev/snd. It is not
        // clear why this works, or that it can be relied on going forward.  Needs further
        // research.
        AlsaCardsParser cardsParser = new AlsaCardsParser();
        cardsParser.scan();
        // cardsParser.Log();

        // But we need to parse the device to determine its capabilities.
        AlsaDevicesParser devicesParser = new AlsaDevicesParser();
        devicesParser.scan();
        // devicesParser.Log();

        // The protocol for now will be to select the last-connected (highest-numbered)
        // Alsa Card.
        int card = cardsParser.getNumCardRecords() - 1;
        int device = 0;

        boolean hasPlayback = devicesParser.hasPlaybackDevices(card);
        boolean hasCapture = devicesParser.hasCaptureDevices(card);
        boolean hasMidi = devicesParser.hasMIDIDevices(card);

        // Playback device file needed/present?
        if (hasPlayback &&
            waitForAlsaDevice(card, device, AlsaDevice.TYPE_PLAYBACK) == null) {
            return;
        }

        // Capture device file needed/present?
        if (hasCapture &&
            waitForAlsaDevice(card, device, AlsaDevice.TYPE_CAPTURE) == null) {
            return;
        }
        ArrayList<AlsaCardsParser.AlsaCardRecord> prevScanRecs = mCardsParser.getScanRecords();
        mCardsParser.scan();

        // MIDI device file needed/present?
        if (hasMidi) {
            midiDevice = waitForAlsaDevice(card, device, AlsaDevice.TYPE_MIDI);
        int addedCard = -1;
        ArrayList<AlsaCardsParser.AlsaCardRecord>
            newScanRecs = mCardsParser.getNewCardRecords(prevScanRecs);
        if (newScanRecs.size() > 0) {
            // This is where we select the just connected device
            // NOTE - to switch to prefering the first-connected device, just always
            // take the else clause below.
            addedCard = newScanRecs.get(0).mCardNum;
        } else {
            addedCard = mCardsParser.getDefaultUsbCard();
        }

        if (DEBUG) {
            Slog.d(TAG,
                    "usb: hasPlayback:" + hasPlayback +
                    " hasCapture:" + hasCapture +
                    " hasMidi:" + hasMidi);
        // If the default isn't a USB device, let the existing "select internal mechanism"
        // handle the selection.
        if (mCardsParser.isCardUsb(addedCard)) {
            selectCard(addedCard);
            mAudioDevices.put(usbDevice, mSelectedAudioDevice);
        }

        AudioDevice audioDevice = new AudioDevice(card, device, hasPlayback, hasCapture, hasMidi);
        mAudioDevices.put(usbDevice, audioDevice);
        sendDeviceNotification(audioDevice, true);

        if (midiDevice != null && mMidiManager != null) {
            try {
                mMidiManager.alsaDeviceAdded(midiDevice.mCard, midiDevice.mDevice, usbDevice);
@@ -327,7 +365,7 @@ public class UsbAlsaManager {
          Slog.d(TAG, "deviceRemoved(): " + device);
        }

        AudioDevice audioDevice = mAudioDevices.remove(device);
        UsbAudioDevice audioDevice = mAudioDevices.remove(device);
        if (audioDevice != null) {
            if (audioDevice.mHasPlayback || audioDevice.mHasPlayback) {
                sendDeviceNotification(audioDevice, false);
@@ -340,12 +378,52 @@ public class UsbAlsaManager {
                }
            }
        }

        mSelectedAudioDevice = null;

        // if there any external devices left, select one of them
        selectDefaultDevice();
    }

    //
    // Devices List
    //
    public ArrayList<UsbAudioDevice> getConnectedDevices() {
        ArrayList<UsbAudioDevice> devices = new ArrayList<UsbAudioDevice>(mAudioDevices.size());
        for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
            devices.add(entry.getValue());
        }
        return devices;
    }

    //
    // Logging
    //
    public void dump(FileDescriptor fd, PrintWriter pw) {
        pw.println("  USB AudioDevices:");
        for (UsbDevice device : mAudioDevices.keySet()) {
            pw.println("    " + device.getDeviceName() + ": " + mAudioDevices.get(device));
        }
    }

    public void logDevicesList(String title) {
      if (DEBUG) {
          for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
              Slog.i(TAG, "UsbDevice-------------------");
              Slog.i(TAG, "" + (entry != null ? entry.getKey() : "[none]"));
              Slog.i(TAG, "UsbAudioDevice--------------");
              Slog.i(TAG, "" + entry.getValue());
          }
      }
  }

  // This logs a more terse (and more readable) version of the devices list
  public void logDevices(String title) {
      if (DEBUG) {
          Slog.i(TAG, title);
          for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
              Slog.i(TAG, entry.getValue().toShortString());
          }
      }
  }
}
Loading