/* * 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.device; 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