1 // Copyright (C) 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "AudioProxyStreamOut.h"
16
17 #include "HidlTypeUtil.h"
18
19 #define CHECK_OPT_API(func) \
20 do { \
21 if (!mStream->func) return Result::NOT_SUPPORTED; \
22 } while (0)
23
24 namespace audio_proxy {
25 namespace CPP_VERSION {
26 namespace {
27
28 template <typename T>
getArraySize(const T * const arr,T terminator)29 size_t getArraySize(const T* const arr, T terminator) {
30 if (!arr) {
31 return 0;
32 }
33
34 const T* ptr = arr;
35 while (*ptr != terminator) {
36 ptr++;
37 }
38
39 return ptr - arr;
40 }
41
42 template <typename T, typename H>
convertToHidlVec(const T * const arr,T terminator)43 hidl_vec<H> convertToHidlVec(const T* const arr, T terminator) {
44 const size_t size = getArraySize(arr, terminator);
45 hidl_vec<H> vec(size);
46
47 for (size_t i = 0; i < size; i++) {
48 vec[i] = H(arr[i]);
49 }
50
51 return vec;
52 }
53
buildKeyValVec(const hidl_vec<ParameterValue> & parameters)54 std::vector<audio_proxy_key_val_t> buildKeyValVec(
55 const hidl_vec<ParameterValue>& parameters) {
56 std::vector<audio_proxy_key_val_t> kvVec(parameters.size() + 1);
57
58 for (size_t i = 0; i < parameters.size(); i++) {
59 kvVec[i] = {parameters[i].key.c_str(), parameters[i].value.c_str()};
60 }
61
62 // Terminator.
63 kvVec.back() = {};
64 return kvVec;
65 }
66
buildKeyVec(const hidl_vec<hidl_string> & keys)67 std::vector<const char*> buildKeyVec(const hidl_vec<hidl_string>& keys) {
68 std::vector<const char*> keyVec(keys.size() + 1);
69 for (size_t i = 0; i < keys.size(); i++) {
70 keyVec[i] = keys[i].c_str();
71 }
72
73 // Terminator.
74 keyVec.back() = nullptr;
75 return keyVec;
76 }
77
onParametersAvailable(void * obj,const audio_proxy_key_val_t * params)78 void onParametersAvailable(void* obj, const audio_proxy_key_val_t* params) {
79 std::vector<ParameterValue>* results =
80 static_cast<std::vector<ParameterValue>*>(obj);
81 while (params->key != nullptr) {
82 ParameterValue result;
83 result.key = params->key;
84 result.value = params->val;
85 results->push_back(result);
86 params++;
87 }
88 }
89 } // namespace
90
AudioProxyStreamOut(audio_proxy_stream_out_t * stream,audio_proxy_device_t * device)91 AudioProxyStreamOut::AudioProxyStreamOut(audio_proxy_stream_out_t* stream,
92 audio_proxy_device_t* device)
93 : mStream(stream), mDevice(device) {}
94
~AudioProxyStreamOut()95 AudioProxyStreamOut::~AudioProxyStreamOut() {
96 mDevice->close_output_stream(mDevice, mStream);
97 }
98
getFrameCount() const99 uint64_t AudioProxyStreamOut::getFrameCount() const {
100 return mStream->get_frame_count(mStream);
101 }
102
getSampleRate() const103 uint32_t AudioProxyStreamOut::getSampleRate() const {
104 return mStream->get_sample_rate(mStream);
105 }
106
setSampleRate(uint32_t rate)107 Result AudioProxyStreamOut::setSampleRate(uint32_t rate) {
108 CHECK_OPT_API(set_sample_rate);
109 return toResult(mStream->set_sample_rate(mStream, rate));
110 }
111
getSupportedSampleRates(AudioFormat format) const112 hidl_vec<uint32_t> AudioProxyStreamOut::getSupportedSampleRates(
113 AudioFormat format) const {
114 return convertToHidlVec<uint32_t, uint32_t>(
115 mStream->get_supported_sample_rates(
116 mStream, static_cast<audio_proxy_format_t>(format)),
117 0);
118 }
119
getBufferSize() const120 size_t AudioProxyStreamOut::getBufferSize() const {
121 return mStream->get_buffer_size(mStream);
122 }
123
getChannelMask() const124 hidl_bitfield<AudioChannelMask> AudioProxyStreamOut::getChannelMask() const {
125 return hidl_bitfield<AudioChannelMask>(mStream->get_channel_mask(mStream));
126 }
127
setChannelMask(hidl_bitfield<AudioChannelMask> mask)128 Result AudioProxyStreamOut::setChannelMask(
129 hidl_bitfield<AudioChannelMask> mask) {
130 CHECK_OPT_API(set_channel_mask);
131 return toResult(mStream->set_channel_mask(
132 mStream, static_cast<audio_proxy_channel_mask_t>(mask)));
133 }
134
135 hidl_vec<hidl_bitfield<AudioChannelMask>>
getSupportedChannelMasks(AudioFormat format) const136 AudioProxyStreamOut::getSupportedChannelMasks(AudioFormat format) const {
137 const audio_proxy_channel_mask_t* channelMasks =
138 mStream->get_supported_channel_masks(
139 mStream, static_cast<audio_proxy_format_t>(format));
140
141 return convertToHidlVec<audio_proxy_channel_mask_t,
142 hidl_bitfield<AudioChannelMask>>(
143 channelMasks, AUDIO_PROXY_CHANNEL_INVALID);
144 }
145
getFormat() const146 AudioFormat AudioProxyStreamOut::getFormat() const {
147 return AudioFormat(mStream->get_format(mStream));
148 }
149
getSupportedFormats() const150 hidl_vec<AudioFormat> AudioProxyStreamOut::getSupportedFormats() const {
151 return convertToHidlVec<audio_proxy_format_t, AudioFormat>(
152 mStream->get_supported_formats(mStream), AUDIO_PROXY_FORMAT_INVALID);
153 }
154
setFormat(AudioFormat format)155 Result AudioProxyStreamOut::setFormat(AudioFormat format) {
156 CHECK_OPT_API(set_format);
157 return toResult(
158 mStream->set_format(mStream, static_cast<audio_proxy_format_t>(format)));
159 }
160
standby()161 Result AudioProxyStreamOut::standby() {
162 return toResult(mStream->standby(mStream));
163 }
164
setParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<ParameterValue> & parameters)165 Result AudioProxyStreamOut::setParameters(
166 const hidl_vec<ParameterValue>& context,
167 const hidl_vec<ParameterValue>& parameters) {
168 std::vector<audio_proxy_key_val_t> contextKvVec = buildKeyValVec(context);
169 std::vector<audio_proxy_key_val_t> parameterKvVec =
170 buildKeyValVec(parameters);
171 return toResult(mStream->set_parameters(mStream, contextKvVec.data(),
172 parameterKvVec.data()));
173 }
174
getParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<hidl_string> & keys) const175 hidl_vec<ParameterValue> AudioProxyStreamOut::getParameters(
176 const hidl_vec<ParameterValue>& context,
177 const hidl_vec<hidl_string>& keys) const {
178 std::vector<audio_proxy_key_val_t> contextKvVec = buildKeyValVec(context);
179 std::vector<const char*> keyVec = buildKeyVec(keys);
180
181 std::vector<ParameterValue> results;
182 results.reserve(keys.size());
183
184 mStream->get_parameters(mStream, contextKvVec.data(), keyVec.data(),
185 onParametersAvailable, &results);
186
187 return hidl_vec<ParameterValue>(results);
188 }
189
write(const void * buffer,size_t bytes)190 ssize_t AudioProxyStreamOut::write(const void* buffer, size_t bytes) {
191 return mStream->write(mStream, buffer, bytes);
192 }
193
getLatency() const194 uint32_t AudioProxyStreamOut::getLatency() const {
195 return mStream->get_latency(mStream);
196 }
197
getRenderPosition(uint32_t * dsp_frames) const198 Result AudioProxyStreamOut::getRenderPosition(uint32_t* dsp_frames) const {
199 CHECK_OPT_API(get_render_position);
200 return toResult(mStream->get_render_position(mStream, dsp_frames));
201 }
202
getNextWriteTimestamp(int64_t * timestamp) const203 Result AudioProxyStreamOut::getNextWriteTimestamp(int64_t* timestamp) const {
204 CHECK_OPT_API(get_next_write_timestamp);
205 return toResult(mStream->get_next_write_timestamp(mStream, timestamp));
206 }
207
getPresentationPosition(uint64_t * frames,TimeSpec * timestamp) const208 Result AudioProxyStreamOut::getPresentationPosition(uint64_t* frames,
209 TimeSpec* timestamp) const {
210 struct timespec ts;
211 int ret = mStream->get_presentation_position(mStream, frames, &ts);
212 if (ret != 0) {
213 return toResult(ret);
214 }
215
216 timestamp->tvSec = ts.tv_sec;
217 timestamp->tvNSec = ts.tv_nsec;
218 return Result::OK;
219 }
220
pause()221 Result AudioProxyStreamOut::pause() {
222 return toResult(mStream->pause(mStream));
223 }
224
resume()225 Result AudioProxyStreamOut::resume() {
226 return toResult(mStream->resume(mStream));
227 }
228
supportsDrain() const229 bool AudioProxyStreamOut::supportsDrain() const {
230 return mStream->drain != nullptr;
231 }
232
drain(AudioDrain type)233 Result AudioProxyStreamOut::drain(AudioDrain type) {
234 return toResult(
235 mStream->drain(mStream, static_cast<audio_proxy_drain_type_t>(type)));
236 }
237
flush()238 Result AudioProxyStreamOut::flush() {
239 return toResult(mStream->flush(mStream));
240 }
241
setVolume(float left,float right)242 Result AudioProxyStreamOut::setVolume(float left, float right) {
243 CHECK_OPT_API(set_volume);
244 return toResult(mStream->set_volume(mStream, left, right));
245 }
246
247 } // namespace CPP_VERSION
248 } // namespace audio_proxy
249