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: Kevin Rocard <krocard@google.com>
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 5b5a434..0ff581d 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -2058,16 +2058,13 @@
     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 @@
         }
         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 @@
     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);
 
         /*