audio: added support for dual mic capture.

Added support for simultaneous capture from front and back
mics.

Noise suppression is turned off when capturing from front and back
mics and the input source is voice recognition.

Change-Id: I1750f2634bfa75f611dfded0ca21a295c752a836
diff --git a/audio/audio_hw.c b/audio/audio_hw.c
index daaaf26..461c1c4 100644
--- a/audio/audio_hw.c
+++ b/audio/audio_hw.c
@@ -137,6 +137,7 @@
     int es305_mode;
     int hdmi_drv_fd;
     struct bubble_level *bubble_level;
+    audio_channel_mask_t in_channel_mask;
 
     struct stream_out *outputs[OUTPUT_TOTAL];
 };
@@ -180,6 +181,7 @@
     uint16_t ramp_vol;
     uint16_t ramp_step;
     size_t  ramp_frames;
+    audio_channel_mask_t channel_mask;
 
     struct audio_device *dev;
 };
@@ -535,6 +537,10 @@
             new_es305_preset =
                 route_configs[input_source_id][output_device_id]->es305_preset[adev->es305_mode];
         }
+        // disable noise suppression when capturing front and back mic for voice recognition
+        if ((adev->input_source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
+                (adev->in_channel_mask != AUDIO_CHANNEL_IN_FRONT_BACK))
+            new_es305_preset = -1;
     } else {
         if (output_device_id != OUT_DEVICE_NONE) {
             output_route =
@@ -811,13 +817,15 @@
         in->frames_in = pcm_config_in.period_size;
 
         /* Do stereo to mono conversion in place by discarding right channel */
-        for (i = 1; i < in->frames_in; i++)
-            in->buffer[i] = in->buffer[i * 2];
+        if (in->channel_mask == AUDIO_CHANNEL_IN_MONO)
+            for (i = 1; i < in->frames_in; i++)
+                in->buffer[i] = in->buffer[i * 2];
     }
 
     buffer->frame_count = (buffer->frame_count > in->frames_in) ?
                                 in->frames_in : buffer->frame_count;
-    buffer->i16 = in->buffer + (pcm_config_in.period_size - in->frames_in);
+    buffer->i16 = in->buffer +
+            (pcm_config_in.period_size - in->frames_in) * popcount(in->channel_mask);
 
     return in->read_status;
 
@@ -1180,7 +1188,9 @@
 
 static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
 {
-    return AUDIO_CHANNEL_IN_MONO;
+    struct stream_in *in = (struct stream_in *)stream;
+
+    return in->channel_mask;
 }
 
 
@@ -1303,11 +1313,20 @@
 
     frames = (frames < in->ramp_frames) ? frames : in->ramp_frames;
 
-    for (i = 0; i < frames; i++)
-    {
-        buffer[i] = (int16_t)((buffer[i] * vol) >> 16);
-        vol += step;
-    }
+    if (in->channel_mask == AUDIO_CHANNEL_IN_MONO)
+        for (i = 0; i < frames; i++)
+        {
+            buffer[i] = (int16_t)((buffer[i] * vol) >> 16);
+            vol += step;
+        }
+    else
+        for (i = 0; i < frames; i++)
+        {
+            buffer[2*i] = (int16_t)((buffer[2*i] * vol) >> 16);
+            buffer[2*i + 1] = (int16_t)((buffer[2*i + 1] * vol) >> 16);
+            vol += step;
+        }
+
 
     in->ramp_vol = vol;
     in->ramp_frames -= frames;
@@ -1605,7 +1624,8 @@
     *stream_in = NULL;
 
     /* Respond with a request for mono if a different format is given. */
-    if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
+    if (config->channel_mask != AUDIO_CHANNEL_IN_MONO &&
+            config->channel_mask != AUDIO_CHANNEL_IN_FRONT_BACK) {
         config->channel_mask = AUDIO_CHANNEL_IN_MONO;
         return -EINVAL;
     }
@@ -1636,6 +1656,7 @@
     in->input_source = AUDIO_SOURCE_DEFAULT;
     in->device = devices;
     in->io_handle = handle;
+    in->channel_mask = config->channel_mask;
 
     in->buffer = malloc(pcm_config_in.period_size * pcm_config_in.channels
                                                * audio_stream_frame_size(&in->stream.common));
@@ -1651,7 +1672,7 @@
 
         ret = create_resampler(pcm_config_in.rate,
                                in->requested_rate,
-                               1,
+                               popcount(in->channel_mask),
                                RESAMPLER_QUALITY_DEFAULT,
                                &in->buf_provider,
                                &in->resampler);
diff --git a/audio_policy.conf b/audio_policy.conf
index 73bf4ba..1f827cc 100644
--- a/audio_policy.conf
+++ b/audio_policy.conf
@@ -47,7 +47,7 @@
     inputs {
       primary {
         sampling_rates 8000|11025|16000|22050|32000|44100|48000
-        channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
+        channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO|AUDIO_CHANNEL_IN_FRONT_BACK
         formats AUDIO_FORMAT_PCM_16_BIT
         devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_WIRED_HEADSET
       }