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/HidlSupport.h"
21 #include "common/all-versions/default/EffectMap.h"
22 #include "core/default/Util.h"
23
24 #include <inttypes.h>
25
26 #include <HidlUtils.h>
27 #include <android/log.h>
28 #include <hardware/audio.h>
29 #include <hardware/audio_effect.h>
30 #include <media/AudioContainers.h>
31 #include <media/TypeConverter.h>
32 #include <util/CoreUtils.h>
33
34 namespace android {
35 namespace hardware {
36 namespace audio {
37 namespace CPP_VERSION {
38 namespace implementation {
39
40 using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
41 using ::android::hardware::audio::common::utils::splitString;
42
Stream(bool isInput,audio_stream_t * stream)43 Stream::Stream(bool isInput, audio_stream_t* stream) : mIsInput(isInput), mStream(stream) {
44 (void)mIsInput; // prevent 'unused field' warnings in pre-V7 versions.
45 }
46
~Stream()47 Stream::~Stream() {
48 mStream = nullptr;
49 }
50
51 // static
analyzeStatus(const char * funcName,int status)52 Result Stream::analyzeStatus(const char* funcName, int status) {
53 return util::analyzeStatus("stream", funcName, status);
54 }
55
56 // static
analyzeStatus(const char * funcName,int status,const std::vector<int> & ignoreErrors)57 Result Stream::analyzeStatus(const char* funcName, int status,
58 const std::vector<int>& ignoreErrors) {
59 return util::analyzeStatus("stream", funcName, status, ignoreErrors);
60 }
61
halGetParameters(const char * keys)62 char* Stream::halGetParameters(const char* keys) {
63 return mStream->get_parameters(mStream, keys);
64 }
65
halSetParameters(const char * keysAndValues)66 int Stream::halSetParameters(const char* keysAndValues) {
67 return mStream->set_parameters(mStream, keysAndValues);
68 }
69
70 // Methods from ::android::hardware::audio::CPP_VERSION::IStream follow.
getFrameSize()71 Return<uint64_t> Stream::getFrameSize() {
72 // Needs to be implemented by interface subclasses. But can't be declared as pure virtual,
73 // since interface subclasses implementation do not inherit from this class.
74 LOG_ALWAYS_FATAL("Stream::getFrameSize is pure abstract");
75 return uint64_t{};
76 }
77
getFrameCount()78 Return<uint64_t> Stream::getFrameCount() {
79 int halFrameCount;
80 Result retval = getParam(AudioParameter::keyFrameCount, &halFrameCount);
81 return retval == Result::OK ? halFrameCount : 0;
82 }
83
getBufferSize()84 Return<uint64_t> Stream::getBufferSize() {
85 return mStream->get_buffer_size(mStream);
86 }
87
88 #if MAJOR_VERSION <= 6
getSampleRate()89 Return<uint32_t> Stream::getSampleRate() {
90 return mStream->get_sample_rate(mStream);
91 }
92
93 #if MAJOR_VERSION == 2
getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)94 Return<void> Stream::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
95 return getSupportedSampleRates(getFormat(), _hidl_cb);
96 }
getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)97 Return<void> Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
98 return getSupportedChannelMasks(getFormat(), _hidl_cb);
99 }
100 #endif
101
getSupportedSampleRates(AudioFormat format,getSupportedSampleRates_cb _hidl_cb)102 Return<void> Stream::getSupportedSampleRates(AudioFormat format,
103 getSupportedSampleRates_cb _hidl_cb) {
104 AudioParameter context;
105 context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format));
106 String8 halListValue;
107 Result result =
108 getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue, context);
109 hidl_vec<uint32_t> sampleRates;
110 SampleRateSet halSampleRates;
111 if (result == Result::OK) {
112 halSampleRates =
113 samplingRatesFromString(halListValue.string(), AudioParameter::valueListSeparator);
114 sampleRates = hidl_vec<uint32_t>(halSampleRates.begin(), halSampleRates.end());
115 // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
116 // Note that this method must succeed (non empty list) if the format is supported.
117 if (sampleRates.size() == 0) {
118 result = Result::NOT_SUPPORTED;
119 }
120 }
121 #if MAJOR_VERSION == 2
122 _hidl_cb(sampleRates);
123 #elif MAJOR_VERSION >= 4
124 _hidl_cb(result, sampleRates);
125 #endif
126 return Void();
127 }
128
getSupportedChannelMasks(AudioFormat format,getSupportedChannelMasks_cb _hidl_cb)129 Return<void> Stream::getSupportedChannelMasks(AudioFormat format,
130 getSupportedChannelMasks_cb _hidl_cb) {
131 AudioParameter context;
132 context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format));
133 String8 halListValue;
134 Result result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue, context);
135 hidl_vec<AudioChannelBitfield> channelMasks;
136 ChannelMaskSet halChannelMasks;
137 if (result == Result::OK) {
138 halChannelMasks =
139 channelMasksFromString(halListValue.string(), AudioParameter::valueListSeparator);
140 channelMasks.resize(halChannelMasks.size());
141 size_t i = 0;
142 for (auto channelMask : halChannelMasks) {
143 channelMasks[i++] = AudioChannelBitfield(channelMask);
144 }
145 // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
146 // Note that this method must succeed (non empty list) if the format is supported.
147 if (channelMasks.size() == 0) {
148 result = Result::NOT_SUPPORTED;
149 }
150 }
151 #if MAJOR_VERSION == 2
152 _hidl_cb(channelMasks);
153 #elif MAJOR_VERSION >= 4
154 _hidl_cb(result, channelMasks);
155 #endif
156 return Void();
157 }
158
setSampleRate(uint32_t sampleRateHz)159 Return<Result> Stream::setSampleRate(uint32_t sampleRateHz) {
160 return setParam(AudioParameter::keySamplingRate, static_cast<int>(sampleRateHz));
161 }
162
getChannelMask()163 Return<AudioChannelBitfield> Stream::getChannelMask() {
164 return AudioChannelBitfield(mStream->get_channels(mStream));
165 }
166
setChannelMask(AudioChannelBitfield mask)167 Return<Result> Stream::setChannelMask(AudioChannelBitfield mask) {
168 return setParam(AudioParameter::keyChannels, static_cast<int>(mask));
169 }
170
getFormat()171 Return<AudioFormat> Stream::getFormat() {
172 return AudioFormat(mStream->get_format(mStream));
173 }
174
getSupportedFormats(getSupportedFormats_cb _hidl_cb)175 Return<void> Stream::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
176 String8 halListValue;
177 Result result = getParam(AudioParameter::keyStreamSupportedFormats, &halListValue);
178 hidl_vec<AudioFormat> formats;
179 FormatVector halFormats;
180 if (result == Result::OK) {
181 halFormats = formatsFromString(halListValue.string(), AudioParameter::valueListSeparator);
182 formats.resize(halFormats.size());
183 for (size_t i = 0; i < halFormats.size(); ++i) {
184 formats[i] = AudioFormat(halFormats[i]);
185 }
186 // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
187 // Note that the method must not return an empty list if this capability is supported.
188 if (formats.size() == 0) {
189 result = Result::NOT_SUPPORTED;
190 }
191 }
192 #if MAJOR_VERSION <= 5
193 _hidl_cb(formats);
194 #elif MAJOR_VERSION >= 6
195 _hidl_cb(result, formats);
196 #endif
197 return Void();
198 }
199
setFormat(AudioFormat format)200 Return<Result> Stream::setFormat(AudioFormat format) {
201 return setParam(AudioParameter::keyFormat, static_cast<int>(format));
202 }
203
getAudioProperties(getAudioProperties_cb _hidl_cb)204 Return<void> Stream::getAudioProperties(getAudioProperties_cb _hidl_cb) {
205 uint32_t halSampleRate = mStream->get_sample_rate(mStream);
206 audio_channel_mask_t halMask = mStream->get_channels(mStream);
207 audio_format_t halFormat = mStream->get_format(mStream);
208 _hidl_cb(halSampleRate, AudioChannelBitfield(halMask), AudioFormat(halFormat));
209 return Void();
210 }
211
212 #else // MAJOR_VERSION <= 6
213
getSupportedProfiles(getSupportedProfiles_cb _hidl_cb)214 Return<void> Stream::getSupportedProfiles(getSupportedProfiles_cb _hidl_cb) {
215 String8 halListValue;
216 Result result = getParam(AudioParameter::keyStreamSupportedFormats, &halListValue);
217 hidl_vec<AudioProfile> profiles;
218 if (result != Result::OK) {
219 _hidl_cb(result, profiles);
220 return Void();
221 }
222 // Ensure that the separator is one character, despite that it's defined as a C string.
223 static_assert(sizeof(AUDIO_PARAMETER_VALUE_LIST_SEPARATOR) == 2);
224 std::vector<std::string> halFormats =
225 splitString(halListValue.string(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
226 hidl_vec<AudioFormat> formats;
227 (void)HidlUtils::audioFormatsFromHal(halFormats, &formats);
228 std::vector<AudioProfile> tempProfiles;
229 for (const auto& format : formats) {
230 audio_format_t halFormat;
231 if (status_t status = HidlUtils::audioFormatToHal(format, &halFormat); status != NO_ERROR) {
232 continue;
233 }
234 AudioParameter context;
235 context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(halFormat));
236 // Query supported sample rates for the format.
237 result = getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue, context);
238 if (result != Result::OK) break;
239 std::vector<std::string> halSampleRates =
240 splitString(halListValue.string(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
241 hidl_vec<uint32_t> sampleRates;
242 sampleRates.resize(halSampleRates.size());
243 for (size_t i = 0; i < sampleRates.size(); ++i) {
244 sampleRates[i] = std::stoi(halSampleRates[i]);
245 }
246 // Query supported channel masks for the format.
247 result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue, context);
248 if (result != Result::OK) break;
249 std::vector<std::string> halChannelMasks =
250 splitString(halListValue.string(), AUDIO_PARAMETER_VALUE_LIST_SEPARATOR[0]);
251 hidl_vec<AudioChannelMask> channelMasks;
252 (void)HidlUtils::audioChannelMasksFromHal(halChannelMasks, &channelMasks);
253 // Create a profile.
254 if (channelMasks.size() != 0 && sampleRates.size() != 0) {
255 tempProfiles.push_back({.format = format,
256 .sampleRates = std::move(sampleRates),
257 .channelMasks = std::move(channelMasks)});
258 }
259 }
260 // Legacy get_parameter does not return a status_t, thus can not advertise of failure.
261 // Note that the method must not return an empty list if this capability is supported.
262 if (!tempProfiles.empty()) {
263 profiles = tempProfiles;
264 } else {
265 result = Result::NOT_SUPPORTED;
266 }
267 _hidl_cb(result, profiles);
268 return Void();
269 }
270
getAudioProperties(getAudioProperties_cb _hidl_cb)271 Return<void> Stream::getAudioProperties(getAudioProperties_cb _hidl_cb) {
272 audio_config_base_t halConfigBase = {mStream->get_sample_rate(mStream),
273 mStream->get_channels(mStream),
274 mStream->get_format(mStream)};
275 AudioConfigBase configBase = {};
276 status_t status = HidlUtils::audioConfigBaseFromHal(halConfigBase, mIsInput, &configBase);
277 _hidl_cb(Stream::analyzeStatus("get_audio_properties", status), configBase);
278 return Void();
279 }
280
setAudioProperties(const AudioConfigBaseOptional & config)281 Return<Result> Stream::setAudioProperties(const AudioConfigBaseOptional& config) {
282 audio_config_base_t halConfigBase = AUDIO_CONFIG_BASE_INITIALIZER;
283 bool formatSpecified, sRateSpecified, channelMaskSpecified;
284 status_t status = HidlUtils::audioConfigBaseOptionalToHal(
285 config, &halConfigBase, &formatSpecified, &sRateSpecified, &channelMaskSpecified);
286 if (status != NO_ERROR) {
287 return Stream::analyzeStatus("set_audio_properties", status);
288 }
289 if (sRateSpecified) {
290 if (Result result = setParam(AudioParameter::keySamplingRate,
291 static_cast<int>(halConfigBase.sample_rate));
292 result != Result::OK) {
293 return result;
294 }
295 }
296 if (channelMaskSpecified) {
297 if (Result result = setParam(AudioParameter::keyChannels,
298 static_cast<int>(halConfigBase.channel_mask));
299 result != Result::OK) {
300 return result;
301 }
302 }
303 if (formatSpecified) {
304 if (Result result =
305 setParam(AudioParameter::keyFormat, static_cast<int>(halConfigBase.format));
306 result != Result::OK) {
307 return result;
308 }
309 }
310 return Result::OK;
311 }
312
313 #endif // MAJOR_VERSION <= 6
314
addEffect(uint64_t effectId)315 Return<Result> Stream::addEffect(uint64_t effectId) {
316 effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
317 if (halEffect != NULL) {
318 return analyzeStatus("add_audio_effect", mStream->add_audio_effect(mStream, halEffect));
319 } else {
320 ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
321 return Result::INVALID_ARGUMENTS;
322 }
323 }
324
removeEffect(uint64_t effectId)325 Return<Result> Stream::removeEffect(uint64_t effectId) {
326 effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
327 if (halEffect != NULL) {
328 return analyzeStatus("remove_audio_effect",
329 mStream->remove_audio_effect(mStream, halEffect));
330 } else {
331 ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
332 return Result::INVALID_ARGUMENTS;
333 }
334 }
335
standby()336 Return<Result> Stream::standby() {
337 return analyzeStatus("standby", mStream->standby(mStream));
338 }
339
setHwAvSync(uint32_t hwAvSync)340 Return<Result> Stream::setHwAvSync(uint32_t hwAvSync) {
341 return setParam(AudioParameter::keyStreamHwAvSync, static_cast<int>(hwAvSync));
342 }
343
344 #if MAJOR_VERSION == 2
getDevice()345 Return<AudioDevice> Stream::getDevice() {
346 int device = 0;
347 Result retval = getParam(AudioParameter::keyRouting, &device);
348 return retval == Result::OK ? static_cast<AudioDevice>(device) : AudioDevice::NONE;
349 }
350
setDevice(const DeviceAddress & address)351 Return<Result> Stream::setDevice(const DeviceAddress& address) {
352 return setParam(AudioParameter::keyRouting, address);
353 }
354
getParameters(const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)355 Return<void> Stream::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
356 getParametersImpl({} /* context */, keys, _hidl_cb);
357 return Void();
358 }
359
setParameters(const hidl_vec<ParameterValue> & parameters)360 Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& parameters) {
361 return setParametersImpl({} /* context */, parameters);
362 }
363
setConnectedState(const DeviceAddress & address,bool connected)364 Return<Result> Stream::setConnectedState(const DeviceAddress& address, bool connected) {
365 return setParam(
366 connected ? AudioParameter::keyDeviceConnect : AudioParameter::keyDeviceDisconnect,
367 address);
368 }
369 #elif MAJOR_VERSION >= 4
getDevices(getDevices_cb _hidl_cb)370 Return<void> Stream::getDevices(getDevices_cb _hidl_cb) {
371 int halDevice = 0;
372 Result retval = getParam(AudioParameter::keyRouting, &halDevice);
373 hidl_vec<DeviceAddress> devices;
374 if (retval == Result::OK) {
375 devices.resize(1);
376 retval = Stream::analyzeStatus(
377 "get_devices",
378 CoreUtils::deviceAddressFromHal(static_cast<audio_devices_t>(halDevice), nullptr,
379 &devices[0]));
380 }
381 _hidl_cb(retval, devices);
382 return Void();
383 }
384
setDevices(const hidl_vec<DeviceAddress> & devices)385 Return<Result> Stream::setDevices(const hidl_vec<DeviceAddress>& devices) {
386 // FIXME: can the legacy API set multiple device with address ?
387 if (devices.size() > 1) {
388 return Result::NOT_SUPPORTED;
389 }
390 DeviceAddress address{};
391 if (devices.size() == 1) {
392 address = devices[0];
393 }
394 return setParam(AudioParameter::keyRouting, address);
395 }
396
getParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<hidl_string> & keys,getParameters_cb _hidl_cb)397 Return<void> Stream::getParameters(const hidl_vec<ParameterValue>& context,
398 const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
399 getParametersImpl(context, keys, _hidl_cb);
400 return Void();
401 }
402
setParameters(const hidl_vec<ParameterValue> & context,const hidl_vec<ParameterValue> & parameters)403 Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& context,
404 const hidl_vec<ParameterValue>& parameters) {
405 return setParametersImpl(context, parameters);
406 }
407 #endif
408
start()409 Return<Result> Stream::start() {
410 return Result::NOT_SUPPORTED;
411 }
412
stop()413 Return<Result> Stream::stop() {
414 return Result::NOT_SUPPORTED;
415 }
416
createMmapBuffer(int32_t minSizeFrames __unused,createMmapBuffer_cb _hidl_cb)417 Return<void> Stream::createMmapBuffer(int32_t minSizeFrames __unused,
418 createMmapBuffer_cb _hidl_cb) {
419 Result retval(Result::NOT_SUPPORTED);
420 MmapBufferInfo info;
421 _hidl_cb(retval, info);
422 return Void();
423 }
424
getMmapPosition(getMmapPosition_cb _hidl_cb)425 Return<void> Stream::getMmapPosition(getMmapPosition_cb _hidl_cb) {
426 Result retval(Result::NOT_SUPPORTED);
427 MmapPosition position;
428 _hidl_cb(retval, position);
429 return Void();
430 }
431
close()432 Return<Result> Stream::close() {
433 return Result::NOT_SUPPORTED;
434 }
435
debug(const hidl_handle & fd,const hidl_vec<hidl_string> &)436 Return<void> Stream::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
437 if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
438 analyzeStatus("dump", mStream->dump(mStream, fd->data[0]));
439 }
440 return Void();
441 }
442
443 #if MAJOR_VERSION == 2
debugDump(const hidl_handle & fd)444 Return<void> Stream::debugDump(const hidl_handle& fd) {
445 return debug(fd, {} /* options */);
446 }
447 #endif
448
449 } // namespace implementation
450 } // namespace CPP_VERSION
451 } // namespace audio
452 } // namespace hardware
453 } // namespace android
454