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