hal: Add support to get active microphones on input stream
Add support to get active microphones on input stream.
Get microphone device id and channel map based on active
usecase and sound device. Active microphone characteristics
are retrieved from platform info using this device id.
Change-Id: I63ec99e70980869097fa896bc4b309fc0583fb3a
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 45cf3ef..217467a 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -5612,6 +5612,36 @@
return 0;
}
+static int in_get_active_microphones(const struct audio_stream_in *stream,
+ struct audio_microphone_characteristic_t *mic_array,
+ size_t *mic_count) {
+ struct stream_in *in = (struct stream_in *)stream;
+ struct audio_device *adev = in->dev;
+ ALOGVV("%s", __func__);
+
+ lock_input_stream(in);
+ pthread_mutex_lock(&adev->lock);
+ int ret = platform_get_active_microphones(adev->platform,
+ audio_channel_count_from_in_mask(in->channel_mask),
+ in->usecase, mic_array, mic_count);
+ pthread_mutex_unlock(&adev->lock);
+ pthread_mutex_unlock(&in->lock);
+
+ return ret;
+}
+
+static int adev_get_microphones(const struct audio_hw_device *dev,
+ struct audio_microphone_characteristic_t *mic_array,
+ size_t *mic_count) {
+ struct audio_device *adev = (struct audio_device *)dev;
+ ALOGVV("%s", __func__);
+
+ pthread_mutex_lock(&adev->lock);
+ int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
+ pthread_mutex_unlock(&adev->lock);
+
+ return ret;
+}
int adev_open_output_stream(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
@@ -6795,6 +6825,7 @@
in->stream.set_gain = in_set_gain;
in->stream.read = in_read;
in->stream.get_input_frames_lost = in_get_input_frames_lost;
+ in->stream.get_active_microphones = in_get_active_microphones;
in->device = devices;
in->source = source;
@@ -7334,6 +7365,7 @@
adev->device.get_audio_port = adev_get_audio_port;
adev->device.set_audio_port_config = adev_set_audio_port_config;
adev->device.dump = adev_dump;
+ adev->device.get_microphones = adev_get_microphones;
/* Set the default route before the PCM stream is opened */
adev->mode = AUDIO_MODE_NORMAL;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 34aa7d1..88abf3b 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -8115,3 +8115,26 @@
return id_string;
}
+
+bool platform_set_microphone_characteristic(void *platform __unused,
+ struct audio_microphone_characteristic_t mic __unused) {
+ return -ENOSYS;
+}
+
+int platform_get_microphones(void *platform __unused,
+ struct audio_microphone_characteristic_t *mic_array __unused,
+ size_t *mic_count __unused) {
+ return -ENOSYS;
+}
+
+bool platform_set_microphone_map(void *platform __unused, snd_device_t in_snd_device __unused,
+ const struct mic_info *info __unused) {
+ return false;
+}
+
+int platform_get_active_microphones(void *platform __unused, unsigned int channels __unused,
+ audio_usecase_t usecase __unused,
+ struct audio_microphone_characteristic_t *mic_array __unused,
+ size_t *mic_count __unused) {
+ return -ENOSYS;
+}
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 8d87a9f..44c37bd 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
* Not a Contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -398,6 +398,8 @@
#define TX_VOICE_FV5ECNS_SM 0x10F09
#define TX_VOICE_FV5ECNS_DM 0x10F0A
+#define AUDIO_MAKE_STRING_FROM_ENUM(X) { #X, X }
+
#define LIB_CSD_CLIENT "libcsd-client.so"
/* CSD-CLIENT related functions */
typedef int (*init_t)();
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 71090ca..480ef13 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -1363,3 +1363,21 @@
{
return -ENOSYS;
}
+
+bool platform_set_microphone_characteristic(void *platform __unused,
+ struct audio_microphone_characteristic_t mic __unused) {
+ return -ENOSYS;
+}
+
+int platform_get_microphones(void *platform __unused,
+ struct audio_microphone_characteristic_t *mic_array __unused,
+ size_t *mic_count __unused) {
+ return -ENOSYS;
+}
+
+int platform_get_active_microphones(void *platform __unused, unsigned int channels __unused,
+ audio_usecase_t usecase __unused,
+ struct audio_microphone_characteristic_t *mic_array __unused,
+ size_t *mic_count __unused) {
+ return -ENOSYS;
+}
diff --git a/hal/msm8960/platform.h b/hal/msm8960/platform.h
index c9ac74a..727f906 100644
--- a/hal/msm8960/platform.h
+++ b/hal/msm8960/platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013 - 2018 The Linux Foundation. All rights reserved.
* Not a contribution.
*
* Copyright (C) 2013 The Android Open Source Project
@@ -166,4 +166,7 @@
#define DEVICE_NAME_MAX_SIZE 128
+#define AUDIO_MAKE_STRING_FROM_ENUM(X) { #X, X }
+
+
#endif // QCOM_AUDIO_PLATFORM_H
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 53e0519..fca14b2 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -210,6 +210,11 @@
static int max_be_dai_names = 0;
static const struct be_dai_name_struct *be_dai_name_table;
+struct snd_device_to_mic_map {
+ struct mic_info microphones[AUDIO_MICROPHONE_MAX_COUNT];
+ size_t mic_count;
+};
+
struct platform_data {
struct audio_device *adev;
bool fluence_in_spkr_mode;
@@ -273,6 +278,10 @@
struct listnode acdb_meta_key_list;
bool use_generic_handset;
struct acdb_init_data_v4 acdb_init_data;
+ uint32_t declared_mic_count;
+ struct audio_microphone_characteristic_t microphones[AUDIO_MICROPHONE_MAX_COUNT];
+ struct snd_device_to_mic_map mic_map[SND_DEVICE_MAX];
+
};
static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
@@ -2092,6 +2101,7 @@
my_data->mono_speaker = SPKR_1;
my_data->speaker_lr_swap = false;
my_data->voice_speaker_stereo = false;
+ my_data->declared_mic_count = 0;
be_dai_name_table = NULL;
@@ -8009,3 +8019,105 @@
return id_string;
}
+
+bool platform_set_microphone_characteristic(void *platform,
+ struct audio_microphone_characteristic_t mic) {
+ struct platform_data *my_data = (struct platform_data *)platform;
+ if (my_data->declared_mic_count >= AUDIO_MICROPHONE_MAX_COUNT) {
+ ALOGE("mic number is more than maximum number");
+ return false;
+ }
+ for (size_t ch = 0; ch < AUDIO_CHANNEL_COUNT_MAX; ch++) {
+ mic.channel_mapping[ch] = AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
+ }
+ my_data->microphones[my_data->declared_mic_count++] = mic;
+ return true;
+}
+
+int platform_get_microphones(void *platform,
+ struct audio_microphone_characteristic_t *mic_array,
+ size_t *mic_count) {
+ struct platform_data *my_data = (struct platform_data *)platform;
+ if (mic_count == NULL) {
+ return -EINVAL;
+ }
+ if (mic_array == NULL) {
+ return -EINVAL;
+ }
+
+ if (*mic_count == 0) {
+ *mic_count = my_data->declared_mic_count;
+ return 0;
+ }
+
+ size_t max_mic_count = *mic_count;
+ size_t actual_mic_count = 0;
+ for (size_t i = 0; i < max_mic_count && i < my_data->declared_mic_count; i++) {
+ mic_array[i] = my_data->microphones[i];
+ actual_mic_count++;
+ }
+ *mic_count = actual_mic_count;
+ return 0;
+}
+
+bool platform_set_microphone_map(void *platform, snd_device_t in_snd_device,
+ const struct mic_info *info) {
+ struct platform_data *my_data = (struct platform_data *)platform;
+ if (in_snd_device < SND_DEVICE_IN_BEGIN || in_snd_device >= SND_DEVICE_IN_END) {
+ ALOGE("%s: Sound device not valid", __func__);
+ return false;
+ }
+ size_t m_count = my_data->mic_map[in_snd_device].mic_count++;
+ if (m_count >= AUDIO_MICROPHONE_MAX_COUNT) {
+ ALOGE("%s: Microphone count is greater than max allowed value", __func__);
+ my_data->mic_map[in_snd_device].mic_count--;
+ return false;
+ }
+ my_data->mic_map[in_snd_device].microphones[m_count] = *info;
+ return true;
+}
+
+int platform_get_active_microphones(void *platform, unsigned int channels,
+ audio_usecase_t uc_id,
+ struct audio_microphone_characteristic_t *mic_array,
+ size_t *mic_count) {
+ struct platform_data *my_data = (struct platform_data *)platform;
+ struct audio_usecase *usecase = get_usecase_from_list(my_data->adev, uc_id);
+ if (mic_count == NULL || mic_array == NULL || usecase == NULL) {
+ return -EINVAL;
+ }
+ size_t max_mic_count = my_data->declared_mic_count;
+ size_t actual_mic_count = 0;
+
+ snd_device_t active_input_snd_device =
+ platform_get_input_snd_device(platform, usecase->stream.in->device);
+ if (active_input_snd_device == SND_DEVICE_NONE) {
+ ALOGI("%s: No active microphones found", __func__);
+ goto end;
+ }
+
+ size_t active_mic_count = my_data->mic_map[active_input_snd_device].mic_count;
+ struct mic_info *m_info = my_data->mic_map[active_input_snd_device].microphones;
+
+ for (size_t i = 0; i < active_mic_count; i++) {
+ unsigned int channels_for_active_mic = channels;
+ if (channels_for_active_mic > m_info[i].channel_count) {
+ channels_for_active_mic = m_info[i].channel_count;
+ }
+ for (size_t j = 0; j < max_mic_count; j++) {
+ if (strcmp(my_data->microphones[j].device_id,
+ m_info[i].device_id) == 0) {
+ mic_array[actual_mic_count] = my_data->microphones[j];
+ for (size_t ch = 0; ch < channels_for_active_mic; ch++) {
+ mic_array[actual_mic_count].channel_mapping[ch] =
+ m_info[i].channel_mapping[ch];
+ }
+ actual_mic_count++;
+ break;
+ }
+ }
+ }
+end:
+ *mic_count = actual_mic_count;
+ return 0;
+}
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index ccbc413..34ab9f6 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -521,6 +521,9 @@
#define TX_VOICE_FV5ECNS_DM 0x10F0A
#define LIB_CSD_CLIENT "libcsd-client.so"
+
+#define AUDIO_MAKE_STRING_FROM_ENUM(X) { #X, X }
+
/* CSD-CLIENT related functions */
typedef int (*init_t)(bool);
typedef int (*deinit_t)();
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 53a4888..226275e 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -51,6 +51,12 @@
uint32_t level;
};
+struct mic_info {
+ char device_id[AUDIO_MICROPHONE_ID_MAX_LEN];
+ size_t channel_count;
+ audio_microphone_channel_mapping_t channel_mapping[AUDIO_CHANNEL_COUNT_MAX];
+};
+
enum {
NATIVE_AUDIO_MODE_SRC = 1,
NATIVE_AUDIO_MODE_TRUE_44_1,
@@ -285,4 +291,16 @@
int *fd, uint32_t *size);
int platform_get_ec_ref_loopback_snd_device(int channel_count);
const char * platform_get_snd_card_name_for_acdb_loader(const char *snd_card_name);
+
+bool platform_set_microphone_characteristic(void *platform,
+ struct audio_microphone_characteristic_t mic);
+bool platform_set_microphone_map(void *platform, snd_device_t in_snd_device,
+ const struct mic_info *info);
+int platform_get_microphones(void *platform,
+ struct audio_microphone_characteristic_t *mic_array,
+ size_t *mic_count);
+int platform_get_active_microphones(void *platform, unsigned int channels,
+ audio_usecase_t usecase,
+ struct audio_microphone_characteristic_t *mic_array,
+ size_t *mic_count);
#endif // AUDIO_PLATFORM_API_H
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 5140911..d27d689 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -62,6 +62,12 @@
CONFIG_PARAMS,
GAIN_LEVEL_MAPPING,
ACDB_METAINFO_KEY,
+ MICROPHONE_CHARACTERISTIC,
+ SND_DEVICES,
+ INPUT_SND_DEVICE,
+ INPUT_SND_DEVICE_TO_MIC_MAPPING,
+ SND_DEV,
+ MIC_INFO,
} section_t;
typedef void (* section_process_fn)(const XML_Char **attr);
@@ -78,6 +84,9 @@
static void process_root(const XML_Char **attr);
static void process_gain_db_to_level_map(const XML_Char **attr);
static void process_acdb_metainfo_key(const XML_Char **attr);
+static void process_microphone_characteristic(const XML_Char **attr);
+static void process_snd_dev(const XML_Char **attr);
+static void process_mic_info(const XML_Char **attr);
static section_process_fn section_table[] = {
[ROOT] = process_root,
@@ -91,6 +100,9 @@
[CONFIG_PARAMS] = process_config_params,
[GAIN_LEVEL_MAPPING] = process_gain_db_to_level_map,
[ACDB_METAINFO_KEY] = process_acdb_metainfo_key,
+ [MICROPHONE_CHARACTERISTIC] = process_microphone_characteristic,
+ [SND_DEV] = process_snd_dev,
+ [MIC_INFO] = process_mic_info,
};
static section_t section;
@@ -103,6 +115,98 @@
static struct platform_info my_data;
+
+struct audio_string_to_enum {
+ const char* name;
+ unsigned int value;
+};
+
+static snd_device_t in_snd_device;
+
+static const struct audio_string_to_enum mic_locations[AUDIO_MICROPHONE_LOCATION_CNT] = {
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_LOCATION_UNKNOWN),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_LOCATION_MAINBODY),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_LOCATION_PERIPHERAL),
+};
+
+static const struct audio_string_to_enum mic_directionalities[AUDIO_MICROPHONE_DIRECTIONALITY_CNT] = {
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_OMNI),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID),
+};
+
+static const struct audio_string_to_enum mic_channel_mapping[AUDIO_MICROPHONE_CHANNEL_MAPPING_CNT] = {
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED),
+};
+
+static const struct audio_string_to_enum device_in_types[] = {
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AMBIENT),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_COMMUNICATION),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_WIRED_HEADSET),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AUX_DIGITAL),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_HDMI),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_VOICE_CALL),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TELEPHONY_RX),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BACK_MIC),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_REMOTE_SUBMIX),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_ACCESSORY),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_DEVICE),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_FM_TUNER),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_TV_TUNER),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LINE),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_SPDIF),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_IP),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUS),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_PROXY),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_USB_HEADSET),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_BLE),
+ AUDIO_MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_DEFAULT),
+};
+
+enum {
+ AUDIO_MICROPHONE_CHARACTERISTIC_NONE = 0u, // 0x0
+ AUDIO_MICROPHONE_CHARACTERISTIC_SENSITIVITY = 1u, // 0x1
+ AUDIO_MICROPHONE_CHARACTERISTIC_MAX_SPL = 2u, // 0x2
+ AUDIO_MICROPHONE_CHARACTERISTIC_MIN_SPL = 4u, // 0x4
+ AUDIO_MICROPHONE_CHARACTERISTIC_ORIENTATION = 8u, // 0x8
+ AUDIO_MICROPHONE_CHARACTERISTIC_GEOMETRIC_LOCATION = 16u, // 0x10
+ AUDIO_MICROPHONE_CHARACTERISTIC_ALL = 31u, /* ((((SENSITIVITY | MAX_SPL) | MIN_SPL)
+ | ORIENTATION) | GEOMETRIC_LOCATION) */
+};
+
+static bool find_enum_by_string(const struct audio_string_to_enum * table, const char * name,
+ int32_t len, unsigned int *value)
+{
+ if (table == NULL) {
+ ALOGE("%s: table is NULL", __func__);
+ return false;
+ }
+
+ if (name == NULL) {
+ ALOGE("null key");
+ return false;
+ }
+
+ for (int i = 0; i < len; i++) {
+ if (!strcmp(table[i].name, name)) {
+ *value = table[i].value;
+ return true;
+ }
+ }
+ return false;
+}
/*
* <audio_platform_info>
* <acdb_ids>
@@ -447,6 +551,291 @@
return;
}
+static void process_microphone_characteristic(const XML_Char **attr) {
+ struct audio_microphone_characteristic_t microphone;
+ uint32_t curIdx = 0;
+
+ if (strcmp(attr[curIdx++], "valid_mask")) {
+ ALOGE("%s: valid_mask not found", __func__);
+ goto done;
+ }
+ uint32_t valid_mask = atoi(attr[curIdx++]);
+
+ if (strcmp(attr[curIdx++], "device_id")) {
+ ALOGE("%s: device_id not found", __func__);
+ goto done;
+ }
+ if (strlen(attr[curIdx]) > AUDIO_MICROPHONE_ID_MAX_LEN) {
+ ALOGE("%s: device_id %s is too long", __func__, attr[curIdx]);
+ goto done;
+ }
+ strcpy(microphone.device_id, attr[curIdx++]);
+
+ if (strcmp(attr[curIdx++], "type")) {
+ ALOGE("%s: device not found", __func__);
+ goto done;
+ }
+ if (!find_enum_by_string(device_in_types, (char*)attr[curIdx++],
+ ARRAY_SIZE(device_in_types), µphone.device)) {
+ ALOGE("%s: type %s in %s not found!",
+ __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
+ goto done;
+ }
+
+ if (strcmp(attr[curIdx++], "address")) {
+ ALOGE("%s: address not found", __func__);
+ goto done;
+ }
+ if (strlen(attr[curIdx]) > AUDIO_DEVICE_MAX_ADDRESS_LEN) {
+ ALOGE("%s, address %s is too long", __func__, attr[curIdx]);
+ goto done;
+ }
+ strcpy(microphone.address, attr[curIdx++]);
+ if (strlen(microphone.address) == 0) {
+ // If the address is empty, populate the address according to device type.
+ if (microphone.device == AUDIO_DEVICE_IN_BUILTIN_MIC) {
+ strcpy(microphone.address, AUDIO_BOTTOM_MICROPHONE_ADDRESS);
+ } else if (microphone.device == AUDIO_DEVICE_IN_BACK_MIC) {
+ strcpy(microphone.address, AUDIO_BACK_MICROPHONE_ADDRESS);
+ }
+ }
+
+ if (strcmp(attr[curIdx++], "location")) {
+ ALOGE("%s: location not found", __func__);
+ goto done;
+ }
+ if (!find_enum_by_string(mic_locations, (char*)attr[curIdx++],
+ AUDIO_MICROPHONE_LOCATION_CNT, µphone.location)) {
+ ALOGE("%s: location %s in %s not found!",
+ __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
+ goto done;
+ }
+
+ if (strcmp(attr[curIdx++], "group")) {
+ ALOGE("%s: group not found", __func__);
+ goto done;
+ }
+ microphone.group = atoi(attr[curIdx++]);
+
+ if (strcmp(attr[curIdx++], "index_in_the_group")) {
+ ALOGE("%s: index_in_the_group not found", __func__);
+ goto done;
+ }
+ microphone.index_in_the_group = atoi(attr[curIdx++]);
+
+ if (strcmp(attr[curIdx++], "directionality")) {
+ ALOGE("%s: directionality not found", __func__);
+ goto done;
+ }
+ if (!find_enum_by_string(mic_directionalities, (char*)attr[curIdx++],
+ AUDIO_MICROPHONE_DIRECTIONALITY_CNT, µphone.directionality)) {
+ ALOGE("%s: directionality %s in %s not found!",
+ __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
+ goto done;
+ }
+
+ if (strcmp(attr[curIdx++], "num_frequency_responses")) {
+ ALOGE("%s: num_frequency_responses not found", __func__);
+ goto done;
+ }
+ microphone.num_frequency_responses = atoi(attr[curIdx++]);
+ if (microphone.num_frequency_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+ ALOGE("%s: num_frequency_responses is too large", __func__);
+ goto done;
+ }
+ if (microphone.num_frequency_responses > 0) {
+ if (strcmp(attr[curIdx++], "frequencies")) {
+ ALOGE("%s: frequencies not found", __func__);
+ goto done;
+ }
+ char *token = strtok((char *)attr[curIdx++], " ");
+ uint32_t num_frequencies = 0;
+ while (token) {
+ microphone.frequency_responses[0][num_frequencies++] = atof(token);
+ if (num_frequencies > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+ ALOGE("%s: num %u of frequency is too large", __func__, num_frequencies);
+ goto done;
+ }
+ token = strtok(NULL, " ");
+ }
+
+ if (strcmp(attr[curIdx++], "responses")) {
+ ALOGE("%s: responses not found", __func__);
+ goto done;
+ }
+ token = strtok((char *)attr[curIdx++], " ");
+ uint32_t num_responses = 0;
+ while (token) {
+ microphone.frequency_responses[1][num_responses++] = atof(token);
+ if (num_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+ ALOGE("%s: num %u of response is too large", __func__, num_responses);
+ goto done;
+ }
+ token = strtok(NULL, " ");
+ }
+
+ if (num_frequencies != num_responses
+ || num_frequencies != microphone.num_frequency_responses) {
+ ALOGE("%s: num of frequency and response not match: %u, %u, %u",
+ __func__, num_frequencies, num_responses, microphone.num_frequency_responses);
+ goto done;
+ }
+ }
+
+ if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_SENSITIVITY) {
+ if (strcmp(attr[curIdx++], "sensitivity")) {
+ ALOGE("%s: sensitivity not found", __func__);
+ goto done;
+ }
+ microphone.sensitivity = atof(attr[curIdx++]);
+ } else {
+ microphone.sensitivity = AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN;
+ }
+
+ if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_MAX_SPL) {
+ if (strcmp(attr[curIdx++], "max_spl")) {
+ ALOGE("%s: max_spl not found", __func__);
+ goto done;
+ }
+ microphone.max_spl = atof(attr[curIdx++]);
+ } else {
+ microphone.max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
+ }
+
+ if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_MIN_SPL) {
+ if (strcmp(attr[curIdx++], "min_spl")) {
+ ALOGE("%s: min_spl not found", __func__);
+ goto done;
+ }
+ microphone.min_spl = atof(attr[curIdx++]);
+ } else {
+ microphone.min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
+ }
+
+ if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_ORIENTATION) {
+ if (strcmp(attr[curIdx++], "orientation")) {
+ ALOGE("%s: orientation not found", __func__);
+ goto done;
+ }
+ char *token = strtok((char *)attr[curIdx++], " ");
+ float orientation[3];
+ uint32_t idx = 0;
+ while (token) {
+ orientation[idx++] = atof(token);
+ if (idx > 3) {
+ ALOGE("%s: orientation invalid", __func__);
+ goto done;
+ }
+ token = strtok(NULL, " ");
+ }
+ if (idx != 3) {
+ ALOGE("%s: orientation invalid", __func__);
+ goto done;
+ }
+ microphone.orientation.x = orientation[0];
+ microphone.orientation.y = orientation[1];
+ microphone.orientation.z = orientation[2];
+ } else {
+ microphone.orientation.x = 0.0f;
+ microphone.orientation.y = 0.0f;
+ microphone.orientation.z = 0.0f;
+ }
+
+ if (valid_mask & AUDIO_MICROPHONE_CHARACTERISTIC_GEOMETRIC_LOCATION) {
+ if (strcmp(attr[curIdx++], "geometric_location")) {
+ ALOGE("%s: geometric_location not found", __func__);
+ goto done;
+ }
+ char *token = strtok((char *)attr[curIdx++], " ");
+ float geometric_location[3];
+ uint32_t idx = 0;
+ while (token) {
+ geometric_location[idx++] = atof(token);
+ if (idx > 3) {
+ ALOGE("%s: geometric_location invalid", __func__);
+ goto done;
+ }
+ token = strtok(NULL, " ");
+ }
+ if (idx != 3) {
+ ALOGE("%s: geometric_location invalid", __func__);
+ goto done;
+ }
+ microphone.geometric_location.x = geometric_location[0];
+ microphone.geometric_location.y = geometric_location[1];
+ microphone.geometric_location.z = geometric_location[2];
+ } else {
+ microphone.geometric_location.x = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
+ microphone.geometric_location.y = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
+ microphone.geometric_location.z = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
+ }
+
+ platform_set_microphone_characteristic(my_data.platform, microphone);
+done:
+ return;
+}
+
+static void process_snd_dev(const XML_Char **attr)
+{
+ uint32_t curIdx = 0;
+ in_snd_device = SND_DEVICE_NONE;
+
+ if (strcmp(attr[curIdx++], "in_snd_device")) {
+ ALOGE("%s: snd_device not found", __func__);
+ return;
+ }
+ in_snd_device = platform_get_snd_device_index((char *)attr[curIdx++]);
+ if (in_snd_device < SND_DEVICE_IN_BEGIN ||
+ in_snd_device >= SND_DEVICE_IN_END) {
+ ALOGE("%s: Sound device not valid", __func__);
+ in_snd_device = SND_DEVICE_NONE;
+ }
+
+ return;
+}
+
+static void process_mic_info(const XML_Char **attr)
+{
+ uint32_t curIdx = 0;
+ struct mic_info microphone;
+
+ memset(µphone.channel_mapping, AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED,
+ sizeof(microphone.channel_mapping));
+
+ if (strcmp(attr[curIdx++], "mic_device_id")) {
+ ALOGE("%s: mic_device_id not found", __func__);
+ goto on_error;
+ }
+ strlcpy(microphone.device_id,
+ (char *)attr[curIdx++], AUDIO_MICROPHONE_ID_MAX_LEN);
+
+ if (strcmp(attr[curIdx++], "channel_mapping")) {
+ ALOGE("%s: channel_mapping not found", __func__);
+ goto on_error;
+ }
+ const char *token = strtok((char *)attr[curIdx++], " ");
+ uint32_t idx = 0;
+ while (token) {
+ if (!find_enum_by_string(mic_channel_mapping, token,
+ AUDIO_MICROPHONE_CHANNEL_MAPPING_CNT,
+ µphone.channel_mapping[idx++])) {
+ ALOGE("%s: channel_mapping %s in %s not found!",
+ __func__, attr[--curIdx], PLATFORM_INFO_XML_PATH);
+ goto on_error;
+ }
+ token = strtok(NULL, " ");
+ }
+ microphone.channel_count = idx;
+
+ platform_set_microphone_map(my_data.platform, in_snd_device,
+ µphone);
+ return;
+on_error:
+ in_snd_device = SND_DEVICE_NONE;
+ return;
+}
+
+
/* process acdb meta info key value */
static void process_acdb_metainfo_key(const XML_Char **attr)
{
@@ -516,6 +905,10 @@
section = GAIN_LEVEL_MAPPING;
} else if(strcmp(tag_name, "acdb_metainfo_key") == 0) {
section = ACDB_METAINFO_KEY;
+ } else if (strcmp(tag_name, "microphone_characteristics") == 0) {
+ section = MICROPHONE_CHARACTERISTIC;
+ } else if (strcmp(tag_name, "snd_devices") == 0) {
+ section = SND_DEVICES;
} else if (strcmp(tag_name, "device") == 0) {
if ((section != ACDB) && (section != AEC) && (section != NS) &&
(section != BACKEND_NAME) && (section != BITWIDTH) &&
@@ -551,21 +944,56 @@
section_process_fn fn = section_table[section];
fn(attr);
- }
- else if (strcmp(tag_name, "aec") == 0) {
+ } else if (strcmp(tag_name, "aec") == 0) {
if (section != MODULE) {
ALOGE("aec tag only supported with MODULE section");
return;
}
section = AEC;
- }
- else if (strcmp(tag_name, "ns") == 0) {
+ } else if (strcmp(tag_name, "ns") == 0) {
if (section != MODULE) {
ALOGE("ns tag only supported with MODULE section");
return;
}
section = NS;
- }
+ } else if (strcmp(tag_name, "microphone") == 0) {
+ if (section != MICROPHONE_CHARACTERISTIC) {
+ ALOGE("microphone tag only supported with MICROPHONE_CHARACTERISTIC section");
+ return;
+ }
+ section_process_fn fn = section_table[MICROPHONE_CHARACTERISTIC];
+ fn(attr);
+ } else if (strcmp(tag_name, "input_snd_device") == 0) {
+ if (section != SND_DEVICES) {
+ ALOGE("input_snd_device tag only supported with SND_DEVICES section");
+ return;
+ }
+ section = INPUT_SND_DEVICE;
+ } else if (strcmp(tag_name, "input_snd_device_mic_mapping") == 0) {
+ if (section != INPUT_SND_DEVICE) {
+ ALOGE("input_snd_device_mic_mapping tag only supported with INPUT_SND_DEVICE section");
+ return;
+ }
+ section = INPUT_SND_DEVICE_TO_MIC_MAPPING;
+ } else if (strcmp(tag_name, "snd_dev") == 0) {
+ if (section != INPUT_SND_DEVICE_TO_MIC_MAPPING) {
+ ALOGE("snd_dev tag only supported with INPUT_SND_DEVICE_TO_MIC_MAPPING section");
+ return;
+ }
+ section_process_fn fn = section_table[SND_DEV];
+ fn(attr);
+ } else if (strcmp(tag_name, "mic_info") == 0) {
+ if (section != INPUT_SND_DEVICE_TO_MIC_MAPPING) {
+ ALOGE("mic_info tag only supported with INPUT_SND_DEVICE_TO_MIC_MAPPING section");
+ return;
+ }
+ if (in_snd_device == SND_DEVICE_NONE) {
+ ALOGE("%s: Error in previous tags, do not process mic info", __func__);
+ return;
+ }
+ section_process_fn fn = section_table[MIC_INFO];
+ fn(attr);
+ }
} else {
ALOGE("%s: unknown caller!", __func__);
}
@@ -599,6 +1027,14 @@
section = ROOT;
} else if (strcmp(tag_name, "acdb_metainfo_key") == 0) {
section = ROOT;
+ } else if (strcmp(tag_name, "microphone_characteristics") == 0) {
+ section = ROOT;
+ } else if (strcmp(tag_name, "snd_devices") == 0) {
+ section = ROOT;
+ } else if (strcmp(tag_name, "input_snd_device") == 0) {
+ section = SND_DEVICES;
+ } else if (strcmp(tag_name, "input_snd_device_mic_mapping") == 0) {
+ section = INPUT_SND_DEVICE;
}
}