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

Commit 998fc295 authored by Jeremy Wu's avatar Jeremy Wu
Browse files

UsbAlsaManager: wait for device address on usb added

Currently, when a USB audio device is attached, the framework scans all
available cards in `/proc/asound/cards` and uses this information to
further query and determine if the corresponding device is registered in
`/dev/snd/`.

However, there is some delay in the update of available cards, so in
this CL we wait until the scan results actually include some card that
has the corresponding address.

Bug: 378826805
Flag: com.android.server.usb.flags.wait_for_alsa_scan_results_if_has_audio_interface
Test: plug usb audio device multiple times
Change-Id: I718e5f7874856f0e0037459b29ebe1238e129c46
parent 40af2bbb
Loading
Loading
Loading
Loading
+79 −12
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import android.util.Slog;
import com.android.internal.alsa.AlsaCardsParser;
import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.server.usb.descriptors.UsbDescriptorParser;
import com.android.server.usb.flags.Flags;

import libcore.io.IoUtils;

@@ -294,15 +295,32 @@ public final class UsbAlsaManager {
            UsbDescriptorParser parser) {
        if (DEBUG) {
            Slog.d(TAG, "usbDeviceAdded(): " + usbDevice.getManufacturerName()
                    + " nm:" + usbDevice.getProductName());
                    + " nm:" + usbDevice.getProductName()
                    + " hasAudioInterface: " + parser.hasAudioInterface());
        }

        AlsaCardsParser.AlsaCardRecord cardRec = null;

        if (Flags.waitForAlsaScanResultsIfHasAudioInterface()) {
            if (!parser.hasAudioInterface()) {
                return;
            }

            waitForAlsaDeviceAddress(deviceAddress, true /*isAdded*/);

            // Find the ALSA spec for this device address
            cardRec = mCardsParser.findCardNumFor(deviceAddress);

            if (cardRec == null) {
                Slog.e(TAG, "usbDeviceAdded(): cannot find sound card for " + deviceAddress);
                return;
            }
        } else {
            // Scan the Alsa File Space
            mCardsParser.scan();

            // Find the ALSA spec for this device address
        AlsaCardsParser.AlsaCardRecord cardRec =
                mCardsParser.findCardNumFor(deviceAddress);
            cardRec = mCardsParser.findCardNumFor(deviceAddress);
            if (cardRec == null) {
                if (parser.hasAudioInterface()) {
                    Slog.e(TAG, "usbDeviceAdded(): cannot find sound card for " + deviceAddress);
@@ -311,6 +329,7 @@ public final class UsbAlsaManager {
            }

            waitForAlsaDevice(cardRec.getCardNum(), true /*isAdded*/);
        }

        // Add it to the devices list
        boolean hasInput = parser.hasInput()
@@ -417,7 +436,11 @@ public final class UsbAlsaManager {
        UsbAlsaDevice alsaDevice = removeAlsaDevice(deviceAddress);
        Slog.i(TAG, "USB Audio Device Removed: " + alsaDevice);
        if (alsaDevice != null) {
            if (Flags.waitForAlsaScanResultsIfHasAudioInterface()) {
                waitForAlsaDeviceAddress(deviceAddress, false /*isAdded*/);
            } else {
                waitForAlsaDevice(alsaDevice.getCardNum(), false /*isAdded*/);
            }
            deselectAlsaDevice(alsaDevice);
            if (IS_MULTI_MODE) {
                selectDefaultDevice(alsaDevice.getOutputDeviceType());
@@ -464,6 +487,50 @@ public final class UsbAlsaManager {
        }
   }

    private boolean waitForAlsaDeviceAddress(String addr, boolean isAdded) {
        if (DEBUG) {
            Slog.e(TAG, "waitForAlsaDeviceAddress(" + addr + ")");
        }

        // This value was empirically determined.
        final int kWaitTimeMs = 2500;

        synchronized (mAlsaCards) {
            final long timeoutMs = SystemClock.elapsedRealtime() + kWaitTimeMs;

            do {
                mCardsParser.scan();

                AlsaCardsParser.AlsaCardRecord cardRec =
                        mCardsParser.findCardNumFor(addr);

                if (isAdded && (cardRec != null)) {
                    if (mAlsaCards.contains(cardRec.getCardNum())) {
                        return true;
                    }
                }

                // Consider removed if can't be probed by the parser as
                // it's not as time sensitive for the removal case.
                if (!isAdded && (cardRec == null)) {
                    return true;
                }

                long waitTimeMs = timeoutMs - SystemClock.elapsedRealtime();
                if (waitTimeMs <= 0) {
                    Slog.e(TAG, "waitForAlsaDeviceAddress(" + addr + ") timeout");
                    return false;
                }

                try {
                    mAlsaCards.wait(waitTimeMs);
                } catch (InterruptedException e) {
                    Slog.d(TAG, "usb: InterruptedException while waiting for ALSA file.");
                }
            } while (true);
        }
    }

    private boolean waitForAlsaDevice(int card, boolean isAdded) {
        if (DEBUG) {
            Slog.e(TAG, "waitForAlsaDevice(c:" + card + ")");