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