hal: Fix audio playback issue on USB headset

- Start music playback on USB headset. The playback is stopped
  after 3sec.
- A touch tone is played through low latency output path,  while
  selecting the song in the music app. This output goes to standy
  after 3sec. So the disable_snd_device() is called to reduce the
  ref count on usb headset device by 1. At this point the music
  playback (deep-buffer path) is still active. But the current
  implementation has uncondtionally calls usb_stop_playback()
  which results music playback to stop.
- Fix by ensuring the usb_stop_playback is called only when the
  device ref count goes to 0.
- Fix related minor stabilty issues

Change-Id: I979423458738e68da45973751cd918d4c1a924ea
CRs-Fixed: 572048
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 59e7c86..74217b7 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -285,15 +285,6 @@
 
     adev->snd_dev_ref_cnt[snd_device]--;
 
-    /* exit usb play back thread */
-    if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
-       SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
-        audio_extn_usb_stop_playback();
-
-    /* exit usb capture thread */
-    if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
-        audio_extn_usb_stop_capture(adev);
-
     if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
         ALOGE("%s: Invalid sound device returned", __func__);
         return -EINVAL;
@@ -302,7 +293,17 @@
     if (adev->snd_dev_ref_cnt[snd_device] == 0) {
         ALOGV("%s: snd_device(%d: %s)", __func__,
               snd_device, device_name);
+        /* exit usb play back thread */
+        if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
+           SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
+            audio_extn_usb_stop_playback();
+
+        /* exit usb capture thread */
+        if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
+            audio_extn_usb_stop_capture(adev);
+
         audio_route_reset_path(adev->audio_route, device_name);
+
         if (update_mixer)
             audio_route_update_mixer(adev->audio_route);
     }
@@ -1094,9 +1095,18 @@
                                   audio_format_t format,
                                   int channel_count)
 {
-    if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
+    int ret = 0;
 
-    if ((channel_count < 1) || (channel_count > 6)) return -EINVAL;
+    if (format != AUDIO_FORMAT_PCM_16_BIT) ret = -EINVAL;
+
+    switch (channel_count) {
+    case 1:
+    case 2:
+    case 6:
+        break;
+    default:
+        ret = -EINVAL;
+    }
 
     switch (sample_rate) {
     case 8000:
@@ -1110,10 +1120,10 @@
     case 48000:
         break;
     default:
-        return -EINVAL;
+        ret = -EINVAL;
     }
 
-    return 0;
+    return ret;
 }
 
 static size_t get_input_buffer_size(uint32_t sample_rate,
@@ -2214,7 +2224,7 @@
 {
     struct audio_device *adev = (struct audio_device *)dev;
     struct stream_in *in;
-    int ret, buffer_size, frame_size;
+    int ret = 0, buffer_size, frame_size;
     int channel_count = popcount(config->channel_mask);
 
     ALOGV("%s: enter", __func__);
@@ -2251,9 +2261,17 @@
     in->config = pcm_config_audio_capture;
     in->config.rate = config->sample_rate;
 
-    if (audio_extn_ssr_get_enabled()&& channel_count == 6) {
-        if(audio_extn_ssr_init(adev, in))
-            ALOGE("%s: audio_extn_ssr_init failed", __func__);
+    if (channel_count == 6) {
+        if(audio_extn_ssr_get_enabled()) {
+            if(audio_extn_ssr_init(adev, in)) {
+                ALOGE("%s: audio_extn_ssr_init failed", __func__);
+                ret = -EINVAL;
+                goto err_open;
+            }
+        } else {
+            ret = -EINVAL;
+            goto err_open;
+        }
     } else {
         in->config.channels = channel_count;
         frame_size = audio_stream_frame_size((struct audio_stream *)in);
@@ -2265,7 +2283,7 @@
 
     *stream_in = &in->stream;
     ALOGV("%s: exit", __func__);
-    return 0;
+    return ret;
 
 err_open:
     free(in);