From 46a76fa5ffb88dbde2c67335dbc5cf20b75b10b6 Mon Sep 17 00:00:00 2001 From: jiabin Date: Fri, 5 Jan 2018 10:18:21 -0800 Subject: [PATCH] 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 --- include/media/MicrophoneInfo.h | 249 ++++++++++++++++++ media/libaudioclient/AudioSystem.cpp | 7 + media/libaudioclient/IAudioFlinger.cpp | 23 ++ .../aidl/android/media/MicrophoneInfo.aidl | 19 ++ .../include/media/AudioSystem.h | 4 + .../include/media/IAudioFlinger.h | 5 + services/audioflinger/AudioFlinger.cpp | 37 +++ services/audioflinger/AudioFlinger.h | 2 + 8 files changed, 346 insertions(+) create mode 100644 include/media/MicrophoneInfo.h create mode 100644 media/libaudioclient/aidl/android/media/MicrophoneInfo.aidl diff --git a/include/media/MicrophoneInfo.h b/include/media/MicrophoneInfo.h new file mode 100644 index 0000000000..b0199d496e --- /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 +#include +#include +#include +#include + +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 frequencies; + Vector 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 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 frequencies; + RETURN_IF_FAILED(readFloatVector(parcel, &frequencies, frequenciesNum)); + int32_t responsesNum; + RETURN_IF_FAILED(parcel->readInt32(&responsesNum)); + Vector 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 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& getGeometricLocation() const { + return mGeometricLocation; + } + + const Vector& getOrientation() const { + return mOrientation; + } + + const Vector>& getFrequencyResponses() const { + return mFrequencyResponses; + } + + const Vector& 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 *vectorPtr, size_t defaultLength) { + std::unique_ptr> 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& vector) const { + std::vector 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 mGeometricLocation; + Vector mOrientation; + Vector> mFrequencyResponses; + Vector 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 7783ad364a..1c4a80e82a 100644 --- a/media/libaudioclient/AudioSystem.cpp +++ b/media/libaudioclient/AudioSystem.cpp @@ -1273,6 +1273,13 @@ float AudioSystem::getStreamVolumeDB(audio_stream_type_t stream, int index, audi return aps->getStreamVolumeDB(stream, index, device); } +status_t AudioSystem::getMicrophones(std::vector *microphones) +{ + const sp& 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 ae9c96fe72..b6c98cca48 100644 --- a/media/libaudioclient/IAudioFlinger.cpp +++ b/media/libaudioclient/IAudioFlinger.cpp @@ -85,6 +85,7 @@ enum { GET_AUDIO_HW_SYNC_FOR_SESSION, SYSTEM_READY, FRAME_COUNT_HAL, + LIST_MICROPHONES, }; #define MAX_ITEMS_PER_LIST 1024 @@ -842,6 +843,18 @@ public: } return reply.readInt64(); } + virtual status_t getMicrophones(std::vector *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 @@ status_t BnAudioFlinger::onTransact( reply->writeInt64( frameCountHAL((audio_io_handle_t) data.readInt32()) ); return NO_ERROR; } break; + case LIST_MICROPHONES: { + CHECK_INTERFACE(IAudioFlinger, data, reply); + std::vector microphones; + status_t status = getMicrophones(µphones); + 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 0000000000..d6e46cb9aa --- /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 52dcfaad88..22b700d6b7 100644 --- a/media/libaudioclient/include/media/AudioSystem.h +++ b/media/libaudioclient/include/media/AudioSystem.h @@ -23,11 +23,13 @@ #include #include #include +#include #include #include #include #include #include +#include namespace android { @@ -336,6 +338,8 @@ public: static float getStreamVolumeDB( audio_stream_type_t stream, int index, audio_devices_t device); + static status_t getMicrophones(std::vector *microphones); + // ---------------------------------------------------------------------------- class AudioPortCallback : public RefBase diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h index e8d405b42d..e6bf72f547 100644 --- a/media/libaudioclient/include/media/IAudioFlinger.h +++ b/media/libaudioclient/include/media/IAudioFlinger.h @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include "android/media/IAudioRecord.h" @@ -486,6 +488,9 @@ public: // 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 *microphones) = 0; }; diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 113744f4fb..b8017522cc 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1972,6 +1972,43 @@ status_t AudioFlinger::systemReady() return NO_ERROR; } +status_t AudioFlinger::getMicrophones(std::vector *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 296f0924f9..83caca7408 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -250,6 +250,8 @@ public: /* Indicate JAVA services are ready (scheduling, power management ...) */ virtual status_t systemReady(); + virtual status_t getMicrophones(std::vector *microphones); + virtual status_t onTransact( uint32_t code, const Parcel& data,