Support query microphones information.

Add conversions between hal and framework.

Bug: 64038649
Bug: 75041465
Test: Manual Testing and Cts test
Change-Id: I88a292f0509e09467750affbe84350ed82cdd500
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Conversions.h b/audio/core/all-versions/default/include/core/all-versions/default/Conversions.h
index fa05350..b38eca3 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Conversions.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Conversions.h
@@ -30,6 +30,11 @@
 
 std::string deviceAddressToHal(const DeviceAddress& address);
 
+#ifdef AUDIO_HAL_VERSION_4_0
+bool halToMicrophoneCharacteristics(MicrophoneInfo* pDst,
+                                    const struct audio_microphone_characteristic_t& src);
+#endif
+
 }  // namespace implementation
 }  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Conversions.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/Conversions.impl.h
index 3f3f936..004a99e 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Conversions.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Conversions.impl.h
@@ -24,6 +24,8 @@
 namespace AUDIO_HAL_VERSION {
 namespace implementation {
 
+using ::android::hardware::audio::common::AUDIO_HAL_VERSION::AudioDevice;
+
 std::string deviceAddressToHal(const DeviceAddress& address) {
     // HAL assumes that the address is NUL-terminated.
     char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
@@ -54,6 +56,132 @@
     return halAddress;
 }
 
+#ifdef AUDIO_HAL_VERSION_4_0
+status_t deviceAddressFromHal(audio_devices_t device, const char* halAddress,
+                              DeviceAddress* address) {
+    if (address == nullptr) {
+        return BAD_VALUE;
+    }
+    address->device = AudioDevice(device);
+    if (halAddress == nullptr || strnlen(halAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
+        return OK;
+    }
+
+    const bool isInput = (device & AUDIO_DEVICE_BIT_IN) != 0;
+    if (isInput) device &= ~AUDIO_DEVICE_BIT_IN;
+    if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_A2DP) != 0) ||
+        (isInput && (device & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
+        int status =
+            sscanf(halAddress, "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX", &address->address.mac[0],
+                   &address->address.mac[1], &address->address.mac[2], &address->address.mac[3],
+                   &address->address.mac[4], &address->address.mac[5]);
+        return status == 6 ? OK : BAD_VALUE;
+    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_IP) != 0) ||
+               (isInput && (device & AUDIO_DEVICE_IN_IP) != 0)) {
+        int status =
+            sscanf(halAddress, "%hhu.%hhu.%hhu.%hhu", &address->address.ipv4[0],
+                   &address->address.ipv4[1], &address->address.ipv4[2], &address->address.ipv4[3]);
+        return status == 4 ? OK : BAD_VALUE;
+    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_ALL_USB)) != 0 ||
+               (isInput && (device & AUDIO_DEVICE_IN_ALL_USB)) != 0) {
+        int status = sscanf(halAddress, "card=%d;device=%d", &address->address.alsa.card,
+                            &address->address.alsa.device);
+        return status == 2 ? OK : BAD_VALUE;
+    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_BUS) != 0) ||
+               (isInput && (device & AUDIO_DEVICE_IN_BUS) != 0)) {
+        address->busAddress = halAddress;
+        return OK;
+    } else if ((!isInput && (device & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0 ||
+               (isInput && (device & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
+        address->rSubmixAddress = halAddress;
+        return OK;
+    }
+    address->busAddress = halAddress;
+    return OK;
+}
+
+AudioMicrophoneChannelMapping halToChannelMapping(audio_microphone_channel_mapping_t mapping) {
+    switch (mapping) {
+        case AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED:
+            return AudioMicrophoneChannelMapping::UNUSED;
+        case AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT:
+            return AudioMicrophoneChannelMapping::DIRECT;
+        case AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED:
+            return AudioMicrophoneChannelMapping::PROCESSED;
+    }
+}
+
+AudioMicrophoneLocation halToLocation(audio_microphone_location_t location) {
+    switch (location) {
+        default:
+        case AUDIO_MICROPHONE_LOCATION_UNKNOWN:
+            return AudioMicrophoneLocation::UNKNOWN;
+        case AUDIO_MICROPHONE_LOCATION_MAINBODY:
+            return AudioMicrophoneLocation::MAINBODY;
+        case AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE:
+            return AudioMicrophoneLocation::MAINBODY_MOVABLE;
+        case AUDIO_MICROPHONE_LOCATION_PERIPHERAL:
+            return AudioMicrophoneLocation::PERIPHERAL;
+    }
+}
+
+AudioMicrophoneDirectionality halToDirectionality(audio_microphone_directionality_t dir) {
+    switch (dir) {
+        default:
+        case AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN:
+            return AudioMicrophoneDirectionality::UNKNOWN;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_OMNI:
+            return AudioMicrophoneDirectionality::OMNI;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL:
+            return AudioMicrophoneDirectionality::BI_DIRECTIONAL;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID:
+            return AudioMicrophoneDirectionality::CARDIOID;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID:
+            return AudioMicrophoneDirectionality::HYPER_CARDIOID;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID:
+            return AudioMicrophoneDirectionality::SUPER_CARDIOID;
+    }
+}
+
+bool halToMicrophoneCharacteristics(MicrophoneInfo* pDst,
+                                    const struct audio_microphone_characteristic_t& src) {
+    bool status = false;
+    if (pDst != NULL) {
+        pDst->deviceId = src.device_id;
+
+        if (deviceAddressFromHal(src.device, src.address, &pDst->deviceAddress) != OK) {
+            return false;
+        }
+        pDst->channelMapping.resize(AUDIO_CHANNEL_COUNT_MAX);
+        for (size_t ch = 0; ch < pDst->channelMapping.size(); ch++) {
+            pDst->channelMapping[ch] = halToChannelMapping(src.channel_mapping[ch]);
+        }
+        pDst->location = halToLocation(src.location);
+        pDst->group = (AudioMicrophoneGroup)src.group;
+        pDst->indexInTheGroup = (uint32_t)src.index_in_the_group;
+        pDst->sensitivity = src.sensitivity;
+        pDst->maxSpl = src.max_spl;
+        pDst->minSpl = src.min_spl;
+        pDst->directionality = halToDirectionality(src.directionality);
+        pDst->frequencyResponse.resize(src.num_frequency_responses);
+        for (size_t k = 0; k < src.num_frequency_responses; k++) {
+            pDst->frequencyResponse[k].frequency = src.frequency_responses[0][k];
+            pDst->frequencyResponse[k].level = src.frequency_responses[1][k];
+        }
+        pDst->position.x = src.geometric_location.x;
+        pDst->position.y = src.geometric_location.y;
+        pDst->position.z = src.geometric_location.z;
+
+        pDst->orientation.x = src.orientation.x;
+        pDst->orientation.y = src.orientation.y;
+        pDst->orientation.z = src.orientation.z;
+
+        status = true;
+    }
+    return status;
+}
+#endif
+
 }  // namespace implementation
 }  // namespace AUDIO_HAL_VERSION
 }  // namespace audio
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
index fb4b686..581e1dc 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
@@ -332,8 +332,20 @@
 
 #ifdef AUDIO_HAL_VERSION_4_0
 Return<void> Device::getMicrophones(getMicrophones_cb _hidl_cb) {
-    // TODO return device microphones
-    _hidl_cb(Result::NOT_SUPPORTED, {});
+    Result retval = Result::NOT_SUPPORTED;
+    size_t actual_mics = AUDIO_MICROPHONE_MAX_COUNT;
+    audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
+
+    hidl_vec<MicrophoneInfo> microphones;
+    if (mDevice->get_microphones != NULL &&
+        mDevice->get_microphones(mDevice, &mic_array[0], &actual_mics) == 0) {
+        microphones.resize(actual_mics);
+        for (size_t i = 0; i < actual_mics; ++i) {
+            halToMicrophoneCharacteristics(&microphones[i], mic_array[i]);
+        }
+        retval = Result::OK;
+    }
+    _hidl_cb(retval, microphones);
     return Void();
 }
 
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h
index dcd3df1..c03b055 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/StreamIn.impl.h
@@ -26,6 +26,8 @@
 
 using ::android::hardware::audio::AUDIO_HAL_VERSION::MessageQueueFlagBits;
 using ::android::hardware::audio::all_versions::implementation::isGainNormalized;
+#include "Conversions.h"
+#include "Util.h"
 
 namespace android {
 namespace hardware {
@@ -454,7 +456,21 @@
 }
 
 Return<void> StreamIn::getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) {
-    _hidl_cb(Result::NOT_SUPPORTED, {});  // TODO: retrieve from legacy
+    Result retval = Result::NOT_SUPPORTED;
+    size_t actual_mics = AUDIO_MICROPHONE_MAX_COUNT;
+    audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
+
+    hidl_vec<MicrophoneInfo> microphones;
+    if (mStream->get_active_microphones != NULL &&
+        mStream->get_active_microphones(mStream, &mic_array[0], &actual_mics) == 0) {
+        microphones.resize(actual_mics);
+        for (size_t i = 0; i < actual_mics; ++i) {
+            halToMicrophoneCharacteristics(&microphones[i], mic_array[i]);
+        }
+        retval = Result::OK;
+    }
+
+    _hidl_cb(retval, microphones);
     return Void();
 }
 #endif