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
gugelfrei
jiabin 7 years ago
parent 6e075b43b0
commit 46a76fa5ff

@ -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

@ -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<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(

@ -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<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 @@ 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<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);
}

@ -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";

@ -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 @@ public:
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

@ -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 @@ 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<media::MicrophoneInfo> *microphones) = 0;
};

@ -1972,6 +1972,43 @@ status_t AudioFlinger::systemReady()
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)
{

@ -250,6 +250,8 @@ public:
/* 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,

Loading…
Cancel
Save