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 #define LOG_TAG "StreamHAL"
18
19 #include "core/default/Stream.h"
20 #include "common/all-versions/default/EffectMap.h"
21 #include "core/default/Conversions.h"
22 #include "core/default/Util.h"
23
24 #include <inttypes.h>
25
26 #include <android/log.h>
27 #include <hardware/audio.h>
28 #include <hardware/audio_effect.h>
29 #include <media/AudioContainers.h>
30 #include <media/TypeConverter.h>
31
32 namespace android {
33 namespace hardware {
34 namespace audio {
35 namespace CPP_VERSION {
36 namespace implementation {
37
Stream(audio_stream_t * stream)38 Stream::Stream(audio_stream_t* stream) : mStream(stream) {}
39
~Stream()40 Stream::~Stream() {
41 mStream = nullptr;
42 }
43
44 // static
analyzeStatus(const char * funcName,int status)45 Result Stream::analyzeStatus(const char* funcName, int status) {
46 return util::analyzeStatus("stream", funcName, status);
47 }
48
49 // static
analyzeStatus(const char * funcName,int status,const std::vector<int> & ignoreErrors)50 Result Stream::analyzeStatus(const char* funcName, int status,
51 const std::vector<int>& ignoreErrors) {
52 return util::analyzeStatus("stream", funcName, status, ignoreErrors);
53 }
54
halGetParameters(const char * keys)55 char* Stream::halGetParameters(const char* keys) {
56 return mStream->get_parameters(mStream, keys);
57 }
58
halSetParameters(const char * keysAndValues)59 int Stream::halSetParameters(const char* keysAndValues) {
60 return mStream->set_parameters(mStream, keysAndValues);
61 }
62
63 // Methods from ::android::hardware::audio::CPP_VERSION::IStream follow.
getFrameSize()64 Return<uint64_t> Stream::getFrameSize() {
65 // Needs to be implemented by interface subclasses. But can't be declared as pure virtual,
66 // since interface subclasses implementation do not inherit from this class.
67 LOG_ALWAYS_FATAL("Stream::getFrameSize is pure abstract");
68 return uint64_t{};
69 }
70
getFrameCount()71 Return<uint64_t> Stream::getFrameCount() {
72 int halFrameCount;
73 Result retval = getParam(AudioParameter::keyFrameCount, &halFrameCount);
74 return retval == Result::OK ? halFrameCount : 0;
75 }
76
getBufferSize()77 Return<uint64_t> Stream::getBufferSize() {
78 return mStream->get_buffer_size(mStream);
79 }
80
getSampleRate()81 Return<uint32_t> Stream::getSampleRate() {
82 return mStream->get_sample_rate(mStream);
83 }
84
85 #if MAJOR_VERSION == 2
getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)86 Return<void> Stream::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
87 return getSupportedSampleRates(getFormat(), _hidl_cb);
88 }
getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)89 Return<void> Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
90 return getSupportedChannelMasks(getFormat(), _hidl_cb);
91 }
92 #endif
93
getSupportedSampleRates(AudioFormat format,getSupportedSampleRates_cb _hidl_cb)94 Return<void> Stream::getSupportedSampleRates(AudioFormat format,
95 getSupportedSampleRates_cb _hidl_cb) {
96 AudioParameter context;
97 context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format));
98 String8 halListValue;
99 Result result =
100 getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue, context);
101 hidl_vec<uint32_t> sampleRates;
102 SampleRateSet halSampleRates;
103 if (result == Result::OK) {
104 halSampleRates =
105 samplingRatesFromString(halListValue.string(), AudioParameter::valueListSeparator);
106 sampleRates = hidl_vec<uint32_t>(halSampleRates.begin(), halSampleRates.end());
107 // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
108 // Note that this method must succeed (non empty list) if the format is supported.
109 if (sampleRates.size() == 0) {
110 result = Result::NOT_SUPPORTED;
111 }
112 }
113 #if MAJOR_VERSION == 2
114 _hidl_cb(sampleRates);
115 #elif MAJOR_VERSION >= 4
116 _hidl_cb(result, sampleRates);
117 #endif
118 return Void();
119 }
120
getSupportedChannelMasks(AudioFormat format,getSupportedChannelMasks_cb _hidl_cb)121 Return<void> Stream::getSupportedChannelMasks(AudioFormat format,
122 getSupportedChannelMasks_cb _hidl_cb) {
123 AudioParameter context;
124 context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format));
125 String8 halListValue;
126 Result result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue, context);
127 hidl_vec<AudioChannelBitfield> channelMasks;
128 ChannelMaskSet halChannelMasks;
129 if (result == Result::OK) {
130 halChannelMasks =
131 channelMasksFromString(halListValue.string(), AudioParameter::valueListSeparator);
132 channelMasks.resize(halChannelMasks.size());
133 size_t i = 0;
134 for (auto channelMask : halChannelMasks) {
135 channelMasks[i++] = AudioChannelBitfield(channelMask);
136 }
137 // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
138 // Note that this method must succeed (non empty list) if the format is supported.
139 if (channelMasks.size() == 0) {
140 result = Result::NOT_SUPPORTED;
141 }
142 }
143 #if MAJOR_VERSION == 2
144 _hidl_cb(channelMasks);
145 #elif MAJOR_VERSION >= 4
146 _hidl_cb(result, channelMasks);
147 #endif
148 return Void();
149 }
150
setSampleRate(uint32_t sampleRateHz)151 Return<Result> Stream::setSampleRate(uint32_t sampleRateHz) {
152 return setParam(AudioParameter::keySamplingRate, static_cast<int>(sampleRateHz));
153 }
154
getChannelMask()155 Return<AudioChannelBitfield> Stream::getChannelMask() {
156 return AudioChannelBitfield(mStream->get_channels(mStream));
157 }
158
setChannelMask(AudioChannelBitfield mask)159 Return<Result> Stream::setChannelMask(AudioChannelBitfield mask) {
160 return setParam(AudioParameter::keyChannels, static_cast<int>(mask));
161 }
162
getFormat()163 Return<AudioFormat> Stream::getFormat() {
164 return AudioFormat(mStream->get_format(mStream));
165 }
166
getSupportedFormats(getSupportedFormats_cb _hidl_cb)167 Return<void> Stream::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
168 String8 halListValue;
169 Result result = getParam(AudioParameter::keyStreamSupportedFormats, &halListValue);
170 hidl_vec<AudioFormat> formats;
171 FormatVector halFormats;
172 if (result == Result::OK) {
173 halFormats = formatsFromString(halListValue.string(), AudioParameter::valueListSeparator);
174 formats.resize(halFormats.size());
175 for (size_t i = 0; i < halFormats.size(); ++i) {
176 formats[i] = AudioFormat(halFormats[i]);
177 }
178 // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
179 // Note that the method must not return an empty list if this capability is supported.
180 if (formats.size() == 0) {
181 result = Result::NOT_SUPPORTED;
182 }
183 }
184 #if MAJOR_VERSION <= 5
185 _hidl_cb(formats);
186 #elif MAJOR_VERSION >= 6
187 _hidl_cb(result, formats);
188 #endif
189 return Void();
190 }
191
setFormat(AudioFormat format)192 Return<Result> Stream::setFormat(AudioFormat format) {
193 return setParam(AudioParameter::keyFormat, static_cast<int>(format));
194 }
195
getAudioProperties(getAudioProperties_cb _hidl_cb)196 Return<void> Stream::getAudioProperties(getAudioProperties_cb _hidl_cb) {
197 uint32_t halSampleRate = mStream->get_sample_rate(mStream);
198 audio_channel_mask_t halMask = mStream->get_channels(mStream);
199 audio_format_t halFormat = mStream->get_format(mStream);
200 _hidl_cb(halSampleRate, AudioChannelBitfield(halMask), AudioFormat(halFormat));
201 return Void();
202 }
203
addEffect(uint64_t effectId)204 Return<Result> Stream::addEffect(uint64_t effectId) {
205 effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
206 if (halEffect != NULL) {
207 return analyzeStatus("add_audio_effect", mStream->add_audio_effect(mStream, halEffect));
208 } else {
209 ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
210 return Result::INVALID_ARGUMENTS;
211 }
212 }
213
removeEffect(uint64_t effectId)214 Return<Result> Stream::removeEffect(uint64_t effectId) {
215 effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
216 if (halEffect != NULL) {
217 return analyzeStatus("remove_audio_effect",
218 mStream->remove_audio_effect(mStream, halEffect));
219 } else {
220 ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
221 return Result::INVALID_ARGUMENTS;
222 }
223 }
224
standby()225 Return<Result> Stream::standby() {
226 return analyzeStatus("standby", mStream->standby(mStream));
227 }
228
setHwAvSync(uint32_t hwAvSync)229 Return<Result> Stream::setHwAvSync(uint32_t hwAvSync) {
230 return setParam(AudioParameter::keyStreamHwAvSync, static_cast<int>(hwAvSync));
231 }
232
233 #if MAJOR_VERSION == 2
getDevice()234 Return<AudioDevice> Stream::getDevice() {
235 int device = 0;
236 Result retval = getParam(AudioParameter::keyRouting, &device);
237 return retval == Result::OK ? static_cast<AudioDevice>(device) : AudioDevice::NONE;
238 }
239
setDevice(const DeviceAddress & address)240 Return<Result> Stream::setDevice(const DeviceAddress& address) {
241 return setParam(AudioParameter::keyRouting, address);
242 }
243
getParameters(const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)244 Return<void> Stream::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
245 getParametersImpl({} /* context */, keys, _hidl_cb);
246 return Void();
247 }
248
setParameters(const hidl_vec<ParameterValue> & parameters)249 Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& parameters) {
250 return setParametersImpl({} /* context */, parameters);
251 }
252
setConnectedState(const DeviceAddress & address,bool connected)253 Return<Result> Stream::setConnectedState(const DeviceAddress& address, bool connected) {
254 return setParam(
255 connected ? AudioParameter::keyDeviceConnect : AudioParameter::keyDeviceDisconnect,
256 address);
257 }
258 #elif MAJOR_VERSION >= 4
getDevices(getDevices_cb _hidl_cb)259 Return<void> Stream::getDevices(getDevices_cb _hidl_cb) {
260 int device = 0;
261 Result retval = getParam(AudioParameter::keyRouting, &device);
262 hidl_vec<DeviceAddress> devices;
263 if (retval == Result::OK) {
264 devices.resize(1);
265 devices[0].device = static_cast<AudioDevice>(device);
266 }
267 _hidl_cb(retval, devices);
268 return Void();
269 }
270
setDevices(const hidl_vec<DeviceAddress> & devices)271 Return<Result> Stream::setDevices(const hidl_vec<DeviceAddress>& devices) {
272 // FIXME: can the legacy API set multiple device with address ?
273 if (devices.size() > 1) {
274 return Result::NOT_SUPPORTED;
275 }
276 DeviceAddress address;
277 if (devices.size() == 1) {
278 address = devices[0];
279 } else {
280 address.device = AudioDevice::NONE;
281 }
282 return setParam(AudioParameter::keyRouting, address);
283 }
getParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)284 Return<void> Stream::getParameters(const hidl_vec<ParameterValue>& context,
285 const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
286 getParametersImpl(context, keys, _hidl_cb);
287 return Void();
288 }
289
setParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<ParameterValue> & parameters)290 Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& context,
291 const hidl_vec<ParameterValue>& parameters) {
292 return setParametersImpl(context, parameters);
293 }
294 #endif
295
start()296 Return<Result> Stream::start() {
297 return Result::NOT_SUPPORTED;
298 }
299
stop()300 Return<Result> Stream::stop() {
301 return Result::NOT_SUPPORTED;
302 }
303
createMmapBuffer(int32_t minSizeFrames __unused,createMmapBuffer_cb _hidl_cb)304 Return<void> Stream::createMmapBuffer(int32_t minSizeFrames __unused,
305 createMmapBuffer_cb _hidl_cb) {
306 Result retval(Result::NOT_SUPPORTED);
307 MmapBufferInfo info;
308 _hidl_cb(retval, info);
309 return Void();
310 }
311
getMmapPosition(getMmapPosition_cb _hidl_cb)312 Return<void> Stream::getMmapPosition(getMmapPosition_cb _hidl_cb) {
313 Result retval(Result::NOT_SUPPORTED);
314 MmapPosition position;
315 _hidl_cb(retval, position);
316 return Void();
317 }
318
close()319 Return<Result> Stream::close() {
320 return Result::NOT_SUPPORTED;
321 }
322
debug(const hidl_handle & fd,const hidl_vec<hidl_string> &)323 Return<void> Stream::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
324 if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
325 analyzeStatus("dump", mStream->dump(mStream, fd->data[0]));
326 }
327 return Void();
328 }
329
330 #if MAJOR_VERSION == 2
debugDump(const hidl_handle & fd)331 Return<void> Stream::debugDump(const hidl_handle& fd) {
332 return debug(fd, {} /* options */);
333 }
334 #endif
335
336 } // namespace implementation
337 } // namespace CPP_VERSION
338 } // namespace audio
339 } // namespace hardware
340 } // namespace android
341