Add support for getting all available microphones characteristics.

Add MicrophoneInfo class in native side and native logic for supporting
query all available microphones.

Bug: 64038649
Test: Run test and check the print log.
Change-Id: Ic0a9cce55a1265a66ba08fe81b56b56cb88ba42f
diff --git a/include/media/MicrophoneInfo.h b/include/media/MicrophoneInfo.h
new file mode 100644
index 0000000..b0199d4
--- /dev/null
+++ b/include/media/MicrophoneInfo.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_MICROPHONE_INFO_H
+#define ANDROID_MICROPHONE_INFO_H
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <system/audio.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+namespace android {
+namespace media {
+
+#define RETURN_IF_FAILED(calledOnce)                                     \
+    {                                                                    \
+        status_t returnStatus = calledOnce;                              \
+        if (returnStatus) {                                              \
+            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
+            return returnStatus;                                         \
+         }                                                               \
+    }
+
+class MicrophoneInfo : public Parcelable {
+public:
+    MicrophoneInfo() = default;
+    MicrophoneInfo(const MicrophoneInfo& microphoneInfo) = default;
+    MicrophoneInfo(audio_microphone_characteristic_t& characteristic) {
+        mDeviceId = String16(&characteristic.device_id[0]);
+        mPortId = characteristic.id;
+        mType = characteristic.type;
+        mAddress = String16(&characteristic.address[0]);
+        mDeviceLocation = characteristic.location;
+        mDeviceGroup = characteristic.group;
+        mIndexInTheGroup = characteristic.index_in_the_group;
+        mGeometricLocation.push_back(characteristic.geometric_location.x);
+        mGeometricLocation.push_back(characteristic.geometric_location.y);
+        mGeometricLocation.push_back(characteristic.geometric_location.z);
+        mOrientation.push_back(characteristic.orientation.x);
+        mOrientation.push_back(characteristic.orientation.y);
+        mOrientation.push_back(characteristic.orientation.z);
+        Vector<float> frequencies;
+        Vector<float> responses;
+        for (size_t i = 0; i < characteristic.num_frequency_responses; i++) {
+            frequencies.push_back(characteristic.frequency_responses[0][i]);
+            responses.push_back(characteristic.frequency_responses[1][i]);
+        }
+        mFrequencyResponses.push_back(frequencies);
+        mFrequencyResponses.push_back(responses);
+        for (size_t i = 0; i < AUDIO_CHANNEL_COUNT_MAX; i++) {
+            mChannelMapping.push_back(characteristic.channel_mapping[i]);
+        }
+        mSensitivity = characteristic.sensitivity;
+        mMaxSpl = characteristic.max_spl;
+        mMinSpl = characteristic.min_spl;
+        mDirectionality = characteristic.directionality;
+    }
+
+    virtual ~MicrophoneInfo() = default;
+
+    virtual status_t writeToParcel(Parcel* parcel) const {
+        RETURN_IF_FAILED(parcel->writeString16(mDeviceId));
+        RETURN_IF_FAILED(parcel->writeInt32(mPortId));
+        RETURN_IF_FAILED(parcel->writeUint32(mType));
+        RETURN_IF_FAILED(parcel->writeString16(mAddress));
+        RETURN_IF_FAILED(parcel->writeInt32(mDeviceLocation));
+        RETURN_IF_FAILED(parcel->writeInt32(mDeviceGroup));
+        RETURN_IF_FAILED(parcel->writeInt32(mIndexInTheGroup));
+        RETURN_IF_FAILED(writeFloatVector(parcel, mGeometricLocation));
+        RETURN_IF_FAILED(writeFloatVector(parcel, mOrientation));
+        if (mFrequencyResponses.size() != 2) {
+            return BAD_VALUE;
+        }
+        for (size_t i = 0; i < mFrequencyResponses.size(); i++) {
+            RETURN_IF_FAILED(parcel->writeInt32(mFrequencyResponses[i].size()));
+            RETURN_IF_FAILED(writeFloatVector(parcel, mFrequencyResponses[i]));
+        }
+        std::vector<int> channelMapping;
+        for (size_t i = 0; i < mChannelMapping.size(); ++i) {
+            channelMapping.push_back(mChannelMapping[i]);
+        }
+        RETURN_IF_FAILED(parcel->writeInt32Vector(channelMapping));
+        RETURN_IF_FAILED(parcel->writeFloat(mSensitivity));
+        RETURN_IF_FAILED(parcel->writeFloat(mMaxSpl));
+        RETURN_IF_FAILED(parcel->writeFloat(mMinSpl));
+        RETURN_IF_FAILED(parcel->writeInt32(mDirectionality));
+        return OK;
+    }
+
+    virtual status_t readFromParcel(const Parcel* parcel) {
+        RETURN_IF_FAILED(parcel->readString16(&mDeviceId));
+        RETURN_IF_FAILED(parcel->readInt32(&mPortId));
+        RETURN_IF_FAILED(parcel->readUint32(&mType));
+        RETURN_IF_FAILED(parcel->readString16(&mAddress));
+        RETURN_IF_FAILED(parcel->readInt32(&mDeviceLocation));
+        RETURN_IF_FAILED(parcel->readInt32(&mDeviceGroup));
+        RETURN_IF_FAILED(parcel->readInt32(&mIndexInTheGroup));
+        RETURN_IF_FAILED(readFloatVector(parcel, &mGeometricLocation, 3));
+        RETURN_IF_FAILED(readFloatVector(parcel, &mOrientation, 3));
+        int32_t frequenciesNum;
+        RETURN_IF_FAILED(parcel->readInt32(&frequenciesNum));
+        Vector<float> frequencies;
+        RETURN_IF_FAILED(readFloatVector(parcel, &frequencies, frequenciesNum));
+        int32_t responsesNum;
+        RETURN_IF_FAILED(parcel->readInt32(&responsesNum));
+        Vector<float> responses;
+        RETURN_IF_FAILED(readFloatVector(parcel, &responses, responsesNum));
+        if (frequencies.size() != responses.size()) {
+            return BAD_VALUE;
+        }
+        mFrequencyResponses.push_back(frequencies);
+        mFrequencyResponses.push_back(responses);
+        std::vector<int> channelMapping;
+        status_t result = parcel->readInt32Vector(&channelMapping);
+        if (result != OK) {
+            return result;
+        }
+        if (channelMapping.size() != AUDIO_CHANNEL_COUNT_MAX) {
+            return BAD_VALUE;
+        }
+        for (size_t i = 0; i < channelMapping.size(); i++) {
+            mChannelMapping.push_back(channelMapping[i]);
+        }
+        RETURN_IF_FAILED(parcel->readFloat(&mSensitivity));
+        RETURN_IF_FAILED(parcel->readFloat(&mMaxSpl));
+        RETURN_IF_FAILED(parcel->readFloat(&mMinSpl));
+        RETURN_IF_FAILED(parcel->readInt32(&mDirectionality));
+        return OK;
+    }
+
+    String16 getDeviceId() const {
+        return mDeviceId;
+    }
+
+    int getPortId() const {
+        return mPortId;
+    }
+
+    unsigned int getType() const {
+        return mType;
+    }
+
+    String16 getAddress() const {
+        return mAddress;
+    }
+
+    int getDeviceLocation() const {
+        return mDeviceLocation;
+    }
+
+    int getDeviceGroup() const {
+        return mDeviceGroup;
+    }
+
+    int getIndexInTheGroup() const {
+        return mIndexInTheGroup;
+    }
+
+    const Vector<float>& getGeometricLocation() const {
+        return mGeometricLocation;
+    }
+
+    const Vector<float>& getOrientation() const {
+        return mOrientation;
+    }
+
+    const Vector<Vector<float>>& getFrequencyResponses() const {
+        return mFrequencyResponses;
+    }
+
+    const Vector<int>& getChannelMapping() const {
+        return mChannelMapping;
+    }
+
+    float getSensitivity() const {
+        return mSensitivity;
+    }
+
+    float getMaxSpl() const {
+        return mMaxSpl;
+    }
+
+    float getMinSpl() const {
+        return mMinSpl;
+    }
+
+    int getDirectionality() const {
+        return mDirectionality;
+    }
+
+private:
+    status_t readFloatVector(
+            const Parcel* parcel, Vector<float> *vectorPtr, size_t defaultLength) {
+        std::unique_ptr<std::vector<float>> v;
+        status_t result = parcel->readFloatVector(&v);
+        if (result != OK) return result;
+        vectorPtr->clear();
+        if (v.get() != nullptr) {
+            for (const auto& iter : *v) {
+                vectorPtr->push_back(iter);
+            }
+        } else {
+            vectorPtr->resize(defaultLength);
+        }
+        return OK;
+    }
+    status_t writeFloatVector(Parcel* parcel, const Vector<float>& vector) const {
+        std::vector<float> v;
+        for (size_t i = 0; i < vector.size(); i++) {
+            v.push_back(vector[i]);
+        }
+        return parcel->writeFloatVector(v);
+    }
+
+    String16 mDeviceId;
+    int32_t mPortId;
+    uint32_t mType;
+    String16 mAddress;
+    int32_t mDeviceLocation;
+    int32_t mDeviceGroup;
+    int32_t mIndexInTheGroup;
+    Vector<float> mGeometricLocation;
+    Vector<float> mOrientation;
+    Vector<Vector<float>> mFrequencyResponses;
+    Vector<int> mChannelMapping;
+    float mSensitivity;
+    float mMaxSpl;
+    float mMinSpl;
+    int32_t mDirectionality;
+};
+
+} // namespace media
+} // namespace android
+
+#endif
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 7783ad3..1c4a80e 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1273,6 +1273,13 @@
     return aps->getStreamVolumeDB(stream, index, device);
 }
 
+status_t AudioSystem::getMicrophones(std::vector<media::MicrophoneInfo> *microphones)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->getMicrophones(microphones);
+}
+
 // ---------------------------------------------------------------------------
 
 int AudioSystem::AudioPolicyServiceClient::addAudioPortCallback(
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index ae9c96f..b6c98cc 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -85,6 +85,7 @@
     GET_AUDIO_HW_SYNC_FOR_SESSION,
     SYSTEM_READY,
     FRAME_COUNT_HAL,
+    LIST_MICROPHONES,
 };
 
 #define MAX_ITEMS_PER_LIST 1024
@@ -842,6 +843,18 @@
         }
         return reply.readInt64();
     }
+    virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        status_t status = remote()->transact(LIST_MICROPHONES, data, &reply);
+        if (status != NO_ERROR ||
+                (status = (status_t)reply.readInt32()) != NO_ERROR) {
+            return status;
+        }
+        status = reply.readParcelableVector(microphones);
+        return status;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -1407,6 +1420,16 @@
             reply->writeInt64( frameCountHAL((audio_io_handle_t) data.readInt32()) );
             return NO_ERROR;
         } break;
+        case LIST_MICROPHONES: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            std::vector<media::MicrophoneInfo> microphones;
+            status_t status = getMicrophones(&microphones);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->writeParcelableVector(microphones);
+            }
+            return NO_ERROR;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libaudioclient/aidl/android/media/MicrophoneInfo.aidl b/media/libaudioclient/aidl/android/media/MicrophoneInfo.aidl
new file mode 100644
index 0000000..d6e46cb
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/MicrophoneInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+parcelable MicrophoneInfo cpp_header "media/MicrophoneInfo.h";
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 52dcfaa..22b700d 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -23,11 +23,13 @@
 #include <media/AudioIoDescriptor.h>
 #include <media/IAudioFlingerClient.h>
 #include <media/IAudioPolicyServiceClient.h>
+#include <media/MicrophoneInfo.h>
 #include <system/audio.h>
 #include <system/audio_effect.h>
 #include <system/audio_policy.h>
 #include <utils/Errors.h>
 #include <utils/Mutex.h>
+#include <vector>
 
 namespace android {
 
@@ -336,6 +338,8 @@
     static float    getStreamVolumeDB(
             audio_stream_type_t stream, int index, audio_devices_t device);
 
+    static status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+
     // ----------------------------------------------------------------------------
 
     class AudioPortCallback : public RefBase
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index e8d405b..e6bf72f 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -35,6 +35,8 @@
 #include <media/IEffect.h>
 #include <media/IEffectClient.h>
 #include <utils/String8.h>
+#include <media/MicrophoneInfo.h>
+#include <vector>
 
 #include "android/media/IAudioRecord.h"
 
@@ -486,6 +488,9 @@
 
     // Returns the number of frames per audio HAL buffer.
     virtual size_t frameCountHAL(audio_io_handle_t ioHandle) const = 0;
+
+    /* List available microphones and their characteristics */
+    virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
 };
 
 
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 113744f..b801752 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1972,6 +1972,43 @@
     return NO_ERROR;
 }
 
+status_t AudioFlinger::getMicrophones(std::vector<media::MicrophoneInfo> *microphones)
+{
+    // Fake data
+    size_t fakeNum = 2;
+    audio_devices_t fakeTypes[] = { AUDIO_DEVICE_IN_BUILTIN_MIC, AUDIO_DEVICE_IN_BACK_MIC };
+    for (size_t i = 0; i < fakeNum; i++) {
+        struct audio_microphone_characteristic_t characteristics;
+        sprintf(characteristics.device_id, "microphone:%zu", i);
+        characteristics.type = fakeTypes[i];
+        sprintf(characteristics.address, "");
+        characteristics.location = AUDIO_MICROPHONE_LOCATION_MAINBODY;
+        characteristics.group = 0;
+        characteristics.index_in_the_group = i;
+        characteristics.sensitivity = 1.0f;
+        characteristics.max_spl = 100.0f;
+        characteristics.min_spl = 0.0f;
+        characteristics.directionality = AUDIO_MICROPHONE_DIRECTIONALITY_OMNI;
+        characteristics.num_frequency_responses = 5 - i;
+        for (size_t j = 0; j < characteristics.num_frequency_responses; j++) {
+            characteristics.frequency_responses[0][j] = 100.0f - j;
+            characteristics.frequency_responses[1][j] = 100.0f + j;
+        }
+        for (size_t j = 0; j < AUDIO_CHANNEL_COUNT_MAX; j++) {
+            characteristics.channel_mapping[j] = AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
+        }
+        characteristics.geometric_location.x = 0.1f;
+        characteristics.geometric_location.y = 0.2f;
+        characteristics.geometric_location.z = 0.3f;
+        characteristics.orientation.x = 0.0f;
+        characteristics.orientation.y = 1.0f;
+        characteristics.orientation.z = 0.0f;
+        media::MicrophoneInfo microphoneInfo = media::MicrophoneInfo(characteristics);
+        microphones->push_back(microphoneInfo);
+    }
+    return NO_ERROR;
+}
+
 // setAudioHwSyncForSession_l() must be called with AudioFlinger::mLock held
 void AudioFlinger::setAudioHwSyncForSession_l(PlaybackThread *thread, audio_session_t sessionId)
 {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 296f092..83caca7 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -250,6 +250,8 @@
     /* Indicate JAVA services are ready (scheduling, power management ...) */
     virtual status_t systemReady();
 
+    virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+
     virtual     status_t    onTransact(
                                 uint32_t code,
                                 const Parcel& data,