Merge "Workaround: Do not send command to a disconnected usb subsystem" into oc-dr1-dev
am: 2cfb8392cb

Change-Id: Icdf69b557873f8983b2671e76e076f0370f83791
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 36a8ba5..c7d6768 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -82,6 +82,7 @@
 #define audio_extn_usb_get_max_channels(dir)                           (0)
 #define audio_extn_usb_get_max_bit_width(dir)                          (0)
 #define audio_extn_usb_sup_sample_rates(t, s, l)                       (0)
+#define audio_extn_usb_alive(adev)                                     (false)
 #else
 void audio_extn_usb_init(void *adev);
 void audio_extn_usb_deinit();
@@ -98,6 +99,7 @@
 int audio_extn_usb_get_max_channels(bool is_playback);
 int audio_extn_usb_get_max_bit_width(bool is_playback);
 int audio_extn_usb_sup_sample_rates(bool is_playback, uint32_t *sr, uint32_t l);
+bool audio_extn_usb_alive(int card);
 #endif
 
 
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index 4b81ae2..743ba58 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -305,6 +305,7 @@
         goto done;
     }
 
+    // TODO: figure up if this wait is needed any more
     while (tries--) {
         if (access(path, F_OK) < 0) {
             ALOGW("stream %s doesn't exist retrying\n", path);
@@ -1101,6 +1102,13 @@
     return;
 }
 
+bool audio_extn_usb_alive(int card) {
+    char path[PATH_MAX] = {0};
+    // snprintf should never fail
+    (void) snprintf(path, sizeof(path), "/proc/asound/card%u/stream0", card);
+    return access(path, F_OK) == 0;
+}
+
 void audio_extn_usb_init(void *adev)
 {
     if (usbmod == NULL) {
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index fd32e77..5b5a434 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -2217,6 +2217,19 @@
             val = AUDIO_DEVICE_OUT_SPEAKER;
         }
 
+        audio_devices_t new_dev = val;
+
+        // Workaround: If routing to an non existing usb device, fail gracefully
+        // The routing request will otherwise block during 10 second
+        if (audio_is_usb_out_device(new_dev) && !audio_extn_usb_alive(adev->snd_card)) {
+            ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d",
+                  adev->snd_card);
+            pthread_mutex_unlock(&adev->lock);
+            pthread_mutex_unlock(&out->lock);
+            status = -ENOSYS;
+            goto routing_fail;
+        }
+
         /*
          * select_devices() call below switches all the usecases on the same
          * backend to the new device. Refer to check_and_route_playback_usecases() in
@@ -2235,7 +2248,6 @@
          *       Because select_devices() must be called to switch back the music
          *       playback to headset.
          */
-        audio_devices_t new_dev = val;
         if (new_dev != AUDIO_DEVICE_NONE) {
             bool same_dev = out->devices == new_dev;
             out->devices = new_dev;
@@ -2279,6 +2291,7 @@
         /*handles device and call state changes*/
         audio_extn_extspk_update(adev->extspk);
     }
+    routing_fail:
 
     if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
         parse_compress_metadata(out, parms);
@@ -3125,16 +3138,26 @@
     if (ret >= 0) {
         val = atoi(value);
         if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
-            in->device = val;
-            /* If recording is in progress, change the tx device to new device */
-            if (!in->standby) {
-                ALOGV("update input routing change");
-                // inform adm before actual routing to prevent glitches.
-                if (adev->adm_on_routing_change) {
-                    adev->adm_on_routing_change(adev->adm_data,
-                                                in->capture_handle);
+
+            // Workaround: If routing to an non existing usb device, fail gracefully
+            // The routing request will otherwise block during 10 second
+            if (audio_is_usb_in_device(val) && !audio_extn_usb_alive(adev->snd_card)) {
+                ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d",
+                      adev->snd_card);
+                status = -ENOSYS;
+            } else {
+
+                in->device = val;
+                /* If recording is in progress, change the tx device to new device */
+                if (!in->standby) {
+                    ALOGV("update input routing change");
+                    // inform adm before actual routing to prevent glitches.
+                    if (adev->adm_on_routing_change) {
+                        adev->adm_on_routing_change(adev->adm_data,
+                                                    in->capture_handle);
+                    }
+                    select_devices(adev, in->usecase);
                 }
-                select_devices(adev, in->usecase);
             }
         }
     }