Snap for 6456462 from 2acbffca7a55680e2c5f0907798ddf69b04240a3 to mainline-release

Change-Id: I0ee7892e8bd609139d61ad8a2c7d7ba3cdc78b4d
diff --git a/audio/audio_hw.c b/audio/audio_hw.c
index af9d7d6..d145b42 100644
--- a/audio/audio_hw.c
+++ b/audio/audio_hw.c
@@ -49,6 +49,11 @@
 #include "audio_hw.h"
 #include "audio_aec.h"
 
+static int adev_get_mic_mute(const struct audio_hw_device* dev, bool* state);
+static int adev_get_microphones(const struct audio_hw_device* dev,
+                                struct audio_microphone_characteristic_t* mic_array,
+                                size_t* mic_count);
+
 static int get_audio_output_port(audio_devices_t devices) {
     /* Prefer HDMI, default to internal speaker */
     int port = PORT_INTERNAL_SPEAKER;
@@ -391,8 +396,12 @@
 static void get_mic_characteristics(struct audio_microphone_characteristic_t* mic_data,
                                     size_t* mic_count) {
     *mic_count = 1;
-    strcpy(mic_data->device_id, "builtin_mic");
-    strcpy(mic_data->address, "top");
+    memset(mic_data, 0, sizeof(struct audio_microphone_characteristic_t));
+    strlcpy(mic_data->device_id, "builtin_mic", AUDIO_MICROPHONE_ID_MAX_LEN - 1);
+    strlcpy(mic_data->address, "top", AUDIO_DEVICE_MAX_ADDRESS_LEN - 1);
+    memset(mic_data->channel_mapping, AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED,
+           sizeof(mic_data->channel_mapping));
+    mic_data->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
     mic_data->sensitivity = -37.0;
     mic_data->max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
     mic_data->min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
@@ -460,6 +469,25 @@
     return buffer_size;
 }
 
+static int in_get_active_microphones(const struct audio_stream_in* stream,
+                                     struct audio_microphone_characteristic_t* mic_array,
+                                     size_t* mic_count) {
+    ALOGV("in_get_active_microphones");
+    if ((mic_array == NULL) || (mic_count == NULL)) {
+        return -EINVAL;
+    }
+    struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
+    struct audio_hw_device* dev = (struct audio_hw_device*)in->dev;
+    bool mic_muted = false;
+    adev_get_mic_mute(dev, &mic_muted);
+    if ((in->source == AUDIO_SOURCE_ECHO_REFERENCE) || mic_muted) {
+        *mic_count = 0;
+        return 0;
+    }
+    adev_get_microphones(dev, mic_array, mic_count);
+    return 0;
+}
+
 static int do_input_standby(struct alsa_stream_in *in)
 {
     struct alsa_audio_device *adev = in->dev;
@@ -503,6 +531,7 @@
     for (idx = 0; idx < mic_count; idx++) {
         dprintf(fd, "  Microphone: %zd\n", idx);
         dprintf(fd, "    Address: %s\n", mic_array[idx].address);
+        dprintf(fd, "    Device: %d\n", mic_array[idx].device);
         dprintf(fd, "    Sensitivity (dB): %.2f\n", mic_array[idx].sensitivity);
     }
 
@@ -621,7 +650,9 @@
 exit:
     pthread_mutex_unlock(&in->lock);
 
-    if (adev->mic_mute) {
+    bool mic_muted = false;
+    adev_get_mic_mute((struct audio_hw_device*)adev, &mic_muted);
+    if (mic_muted) {
         memset(buffer, 0, bytes);
     }
 
@@ -631,7 +662,7 @@
     } else {
         /* Process AEC if available */
         /* TODO move to a separate thread */
-        if (!adev->mic_mute) {
+        if (!mic_muted) {
             info.bytes = bytes;
             int aec_ret = process_aec(adev->aec, buffer, &info);
             if (aec_ret) {
@@ -802,6 +833,9 @@
                                 struct audio_microphone_characteristic_t* mic_array,
                                 size_t* mic_count) {
     ALOGV("adev_get_microphones");
+    if ((mic_array == NULL) || (mic_count == NULL)) {
+        return -EINVAL;
+    }
     get_mic_characteristics(mic_array, mic_count);
     return 0;
 }
@@ -815,7 +849,7 @@
 static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
 {
     ALOGV("adev_set_voice_volume: %f", volume);
-    return 0;
+    return -ENOSYS;
 }
 
 static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
@@ -852,7 +886,9 @@
 {
     ALOGV("adev_set_mic_mute: %d",state);
     struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
+    pthread_mutex_lock(&adev->lock);
     adev->mic_mute = state;
+    pthread_mutex_unlock(&adev->lock);
     return 0;
 }
 
@@ -860,7 +896,9 @@
 {
     ALOGV("adev_get_mic_mute");
     struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
+    pthread_mutex_lock(&adev->lock);
     *state = adev->mic_mute;
+    pthread_mutex_unlock(&adev->lock);
     return 0;
 }
 
@@ -909,6 +947,7 @@
     in->stream.read = in_read;
     in->stream.get_input_frames_lost = in_get_input_frames_lost;
     in->stream.get_capture_position = in_get_capture_position;
+    in->stream.get_active_microphones = in_get_active_microphones;
 
     in->config.channels = CHANNEL_STEREO;
     if (source == AUDIO_SOURCE_ECHO_REFERENCE) {
diff --git a/audio/audio_policy_configuration.xml b/audio/audio_policy_configuration.xml
index f0f5294..7cfb4f6 100644
--- a/audio/audio_policy_configuration.xml
+++ b/audio/audio_policy_configuration.xml
@@ -81,7 +81,8 @@
                     <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                              samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                 </devicePort>
-                <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
+                <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source"
+                            address="top">
                     <profile name="" format="AUDIO_FORMAT_PCM_32_BIT"
                              samplingRates="16000"
                              channelMasks="AUDIO_CHANNEL_IN_STEREO"/>