1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_MICROPHONE_INFO_H
18#define ANDROID_MICROPHONE_INFO_H
19
20#include <binder/Parcel.h>
21#include <binder/Parcelable.h>
22#include <system/audio.h>
23#include <utils/String16.h>
24#include <utils/Vector.h>
25
26namespace android {
27namespace media {
28
29#define RETURN_IF_FAILED(calledOnce)                                     \
30    {                                                                    \
31        status_t returnStatus = calledOnce;                              \
32        if (returnStatus) {                                              \
33            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
34            return returnStatus;                                         \
35         }                                                               \
36    }
37
38class MicrophoneInfo : public Parcelable {
39public:
40    MicrophoneInfo() = default;
41    MicrophoneInfo(const MicrophoneInfo& microphoneInfo) = default;
42    MicrophoneInfo(audio_microphone_characteristic_t& characteristic) {
43        mDeviceId = String16(&characteristic.device_id[0]);
44        mPortId = characteristic.id;
45        mType = characteristic.device;
46        mAddress = String16(&characteristic.address[0]);
47        mDeviceLocation = characteristic.location;
48        mDeviceGroup = characteristic.group;
49        mIndexInTheGroup = characteristic.index_in_the_group;
50        mGeometricLocation.push_back(characteristic.geometric_location.x);
51        mGeometricLocation.push_back(characteristic.geometric_location.y);
52        mGeometricLocation.push_back(characteristic.geometric_location.z);
53        mOrientation.push_back(characteristic.orientation.x);
54        mOrientation.push_back(characteristic.orientation.y);
55        mOrientation.push_back(characteristic.orientation.z);
56        Vector<float> frequencies;
57        Vector<float> responses;
58        for (size_t i = 0; i < characteristic.num_frequency_responses; i++) {
59            frequencies.push_back(characteristic.frequency_responses[0][i]);
60            responses.push_back(characteristic.frequency_responses[1][i]);
61        }
62        mFrequencyResponses.push_back(frequencies);
63        mFrequencyResponses.push_back(responses);
64        for (size_t i = 0; i < AUDIO_CHANNEL_COUNT_MAX; i++) {
65            mChannelMapping.push_back(characteristic.channel_mapping[i]);
66        }
67        mSensitivity = characteristic.sensitivity;
68        mMaxSpl = characteristic.max_spl;
69        mMinSpl = characteristic.min_spl;
70        mDirectionality = characteristic.directionality;
71    }
72
73    virtual ~MicrophoneInfo() = default;
74
75    virtual status_t writeToParcel(Parcel* parcel) const {
76        RETURN_IF_FAILED(parcel->writeString16(mDeviceId));
77        RETURN_IF_FAILED(parcel->writeInt32(mPortId));
78        RETURN_IF_FAILED(parcel->writeUint32(mType));
79        RETURN_IF_FAILED(parcel->writeString16(mAddress));
80        RETURN_IF_FAILED(parcel->writeInt32(mDeviceLocation));
81        RETURN_IF_FAILED(parcel->writeInt32(mDeviceGroup));
82        RETURN_IF_FAILED(parcel->writeInt32(mIndexInTheGroup));
83        RETURN_IF_FAILED(writeFloatVector(parcel, mGeometricLocation));
84        RETURN_IF_FAILED(writeFloatVector(parcel, mOrientation));
85        if (mFrequencyResponses.size() != 2) {
86            return BAD_VALUE;
87        }
88        for (size_t i = 0; i < mFrequencyResponses.size(); i++) {
89            RETURN_IF_FAILED(parcel->writeInt32(mFrequencyResponses[i].size()));
90            RETURN_IF_FAILED(writeFloatVector(parcel, mFrequencyResponses[i]));
91        }
92        std::vector<int> channelMapping;
93        for (size_t i = 0; i < mChannelMapping.size(); ++i) {
94            channelMapping.push_back(mChannelMapping[i]);
95        }
96        RETURN_IF_FAILED(parcel->writeInt32Vector(channelMapping));
97        RETURN_IF_FAILED(parcel->writeFloat(mSensitivity));
98        RETURN_IF_FAILED(parcel->writeFloat(mMaxSpl));
99        RETURN_IF_FAILED(parcel->writeFloat(mMinSpl));
100        RETURN_IF_FAILED(parcel->writeInt32(mDirectionality));
101        return OK;
102    }
103
104    virtual status_t readFromParcel(const Parcel* parcel) {
105        RETURN_IF_FAILED(parcel->readString16(&mDeviceId));
106        RETURN_IF_FAILED(parcel->readInt32(&mPortId));
107        RETURN_IF_FAILED(parcel->readUint32(&mType));
108        RETURN_IF_FAILED(parcel->readString16(&mAddress));
109        RETURN_IF_FAILED(parcel->readInt32(&mDeviceLocation));
110        RETURN_IF_FAILED(parcel->readInt32(&mDeviceGroup));
111        RETURN_IF_FAILED(parcel->readInt32(&mIndexInTheGroup));
112        RETURN_IF_FAILED(readFloatVector(parcel, &mGeometricLocation, 3));
113        RETURN_IF_FAILED(readFloatVector(parcel, &mOrientation, 3));
114        int32_t frequenciesNum;
115        RETURN_IF_FAILED(parcel->readInt32(&frequenciesNum));
116        Vector<float> frequencies;
117        RETURN_IF_FAILED(readFloatVector(parcel, &frequencies, frequenciesNum));
118        int32_t responsesNum;
119        RETURN_IF_FAILED(parcel->readInt32(&responsesNum));
120        Vector<float> responses;
121        RETURN_IF_FAILED(readFloatVector(parcel, &responses, responsesNum));
122        if (frequencies.size() != responses.size()) {
123            return BAD_VALUE;
124        }
125        mFrequencyResponses.push_back(frequencies);
126        mFrequencyResponses.push_back(responses);
127        std::vector<int> channelMapping;
128        status_t result = parcel->readInt32Vector(&channelMapping);
129        if (result != OK) {
130            return result;
131        }
132        if (channelMapping.size() != AUDIO_CHANNEL_COUNT_MAX) {
133            return BAD_VALUE;
134        }
135        for (size_t i = 0; i < channelMapping.size(); i++) {
136            mChannelMapping.push_back(channelMapping[i]);
137        }
138        RETURN_IF_FAILED(parcel->readFloat(&mSensitivity));
139        RETURN_IF_FAILED(parcel->readFloat(&mMaxSpl));
140        RETURN_IF_FAILED(parcel->readFloat(&mMinSpl));
141        RETURN_IF_FAILED(parcel->readInt32(&mDirectionality));
142        return OK;
143    }
144
145    String16 getDeviceId() const {
146        return mDeviceId;
147    }
148
149    int getPortId() const {
150        return mPortId;
151    }
152
153    unsigned int getType() const {
154        return mType;
155    }
156
157    String16 getAddress() const {
158        return mAddress;
159    }
160
161    int getDeviceLocation() const {
162        return mDeviceLocation;
163    }
164
165    int getDeviceGroup() const {
166        return mDeviceGroup;
167    }
168
169    int getIndexInTheGroup() const {
170        return mIndexInTheGroup;
171    }
172
173    const Vector<float>& getGeometricLocation() const {
174        return mGeometricLocation;
175    }
176
177    const Vector<float>& getOrientation() const {
178        return mOrientation;
179    }
180
181    const Vector<Vector<float>>& getFrequencyResponses() const {
182        return mFrequencyResponses;
183    }
184
185    const Vector<int>& getChannelMapping() const {
186        return mChannelMapping;
187    }
188
189    float getSensitivity() const {
190        return mSensitivity;
191    }
192
193    float getMaxSpl() const {
194        return mMaxSpl;
195    }
196
197    float getMinSpl() const {
198        return mMinSpl;
199    }
200
201    int getDirectionality() const {
202        return mDirectionality;
203    }
204
205private:
206    status_t readFloatVector(
207            const Parcel* parcel, Vector<float> *vectorPtr, size_t defaultLength) {
208        std::unique_ptr<std::vector<float>> v;
209        status_t result = parcel->readFloatVector(&v);
210        if (result != OK) return result;
211        vectorPtr->clear();
212        if (v.get() != nullptr) {
213            for (const auto& iter : *v) {
214                vectorPtr->push_back(iter);
215            }
216        } else {
217            vectorPtr->resize(defaultLength);
218        }
219        return OK;
220    }
221    status_t writeFloatVector(Parcel* parcel, const Vector<float>& vector) const {
222        std::vector<float> v;
223        for (size_t i = 0; i < vector.size(); i++) {
224            v.push_back(vector[i]);
225        }
226        return parcel->writeFloatVector(v);
227    }
228
229    String16 mDeviceId;
230    int32_t mPortId;
231    uint32_t mType;
232    String16 mAddress;
233    int32_t mDeviceLocation;
234    int32_t mDeviceGroup;
235    int32_t mIndexInTheGroup;
236    Vector<float> mGeometricLocation;
237    Vector<float> mOrientation;
238    Vector<Vector<float>> mFrequencyResponses;
239    Vector<int> mChannelMapping;
240    float mSensitivity;
241    float mMaxSpl;
242    float mMinSpl;
243    int32_t mDirectionality;
244};
245
246} // namespace media
247} // namespace android
248
249#endif
250