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

Commit 2ba1a478 authored by Kevin Rocard's avatar Kevin Rocard
Browse files

Put usb stream into standby on disconnection if offloading



If usb headset was disconnected then reconnected while some music was
playing and that the music stopped playing during the disconnection,
the usb driver was never closed.

Unpluging and repluging an usb audio device without closing the usb
driver (uac_usb_close) leaves the usb driver "not in a right state".

The user effect is that sound is no longer played by the usb device.

This patch avoids the issue by putting the usb offload
stream in standby if the device is disconnected.
This lets the usb driver be closed when disconnecting the usb device.

Bug: 37551929
Test: Mir dongle with headset attached. Play music.
      Remove headset from dongle, music pauses.
      Re-insert headset into dongle, wait 5 seconds, press play.
Test: Disconnect reconnect USB during hangout call, modem call, play
      music, youtube and video in chrome
Change-Id: I492f44f106a7e78dd03069d7d796a09831b6f3c9
Signed-off-by: default avatarKevin Rocard <krocard@google.com>
parent 2cfb8392
Loading
Loading
Loading
Loading
+26 −5
Original line number Diff line number Diff line
@@ -2058,16 +2058,13 @@ static int out_set_format(struct audio_stream *stream __unused, audio_format_t f
    return -ENOSYS;
}

static int out_standby(struct audio_stream *stream)
/* must be called with out->lock locked */
static int out_standby_l(struct audio_stream *stream)
{
    struct stream_out *out = (struct stream_out *)stream;
    struct audio_device *adev = out->dev;
    bool do_stop = true;

    ALOGV("%s: enter: usecase(%d: %s)", __func__,
          out->usecase, use_case_table[out->usecase]);

    lock_output_stream(out);
    if (!out->standby) {
        if (adev->adm_deregister_stream)
            adev->adm_deregister_stream(adev->adm_data, out->handle);
@@ -2096,6 +2093,18 @@ static int out_standby(struct audio_stream *stream)
        }
        pthread_mutex_unlock(&adev->lock);
    }
    return 0;
}

static int out_standby(struct audio_stream *stream)
{
    struct stream_out *out = (struct stream_out *)stream;

    ALOGV("%s: enter: usecase(%d: %s)", __func__,
          out->usecase, use_case_table[out->usecase]);

    lock_output_stream(out);
    out_standby_l(stream);
    pthread_mutex_unlock(&out->lock);
    ALOGV("%s: exit", __func__);
    return 0;
@@ -2202,7 +2211,19 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
    ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
    if (ret >= 0) {
        val = atoi(value);

        lock_output_stream(out);

        // The usb driver needs to be closed after usb device disconnection
        // otherwise audio is no longer played on the new usb devices.
        // By forcing the stream in standby, the usb stack refcount drops to 0
        // and the driver is closed.
        if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
                audio_is_usb_out_device(out->devices)) {
            ALOGD("%s() putting the usb device in standby after disconnection", __func__);
            out_standby_l(&out->stream.common);
        }

        pthread_mutex_lock(&adev->lock);

        /*