mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
Implement parsing of AudioPolicyManager config for finding
out supported format configurations of streams. This only applies
when running tests for HAL V6. Previously format configurations
mandated by CDD were used for testing, this does not work well
for non-primary modules.
Fix the following issues found while running the tests
for "r_submix" and "msd" modules:
- IStream::getSupportedFormats must return a status
to indicate that this capability is not supported by HAL;
- it is allowed for IStream::setDevices to return
NOT_SUPPORTED status.
Other changes:
- Factor out helper functions for generating format
configurations;
- Fix generation of the channel mask component in the names
of tests that use AudioConfig, add sampling rate to test
names.
Squashed with the following commit to avoid breaking compilation:
audio vts: Remove explicit dependency on the new types
Avoid using the new ChannelMaskSet and SampleRateSet types
directly to simplify upstreaming.
Bug: 141989952
Bug: 141847510
Test: atest VtsHalAudioV5_0TargetTest
atest VtsHalAudioV6_0TargetTest
also, run modified V5_0 test using generators for V6_0
Change-Id: If0d330881901908e546baab89f63d3333003e355
Merged-In: If0d330881901908e546baab89f63d3333003e355
341 lines
11 KiB
C++
341 lines
11 KiB
C++
/*
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "StreamHAL"
|
|
|
|
#include "core/default/Stream.h"
|
|
#include "common/all-versions/default/EffectMap.h"
|
|
#include "core/default/Conversions.h"
|
|
#include "core/default/Util.h"
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include <android/log.h>
|
|
#include <hardware/audio.h>
|
|
#include <hardware/audio_effect.h>
|
|
#include <media/TypeConverter.h>
|
|
#include <utils/SortedVector.h>
|
|
#include <utils/Vector.h>
|
|
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace audio {
|
|
namespace CPP_VERSION {
|
|
namespace implementation {
|
|
|
|
Stream::Stream(audio_stream_t* stream) : mStream(stream) {}
|
|
|
|
Stream::~Stream() {
|
|
mStream = nullptr;
|
|
}
|
|
|
|
// static
|
|
Result Stream::analyzeStatus(const char* funcName, int status) {
|
|
return util::analyzeStatus("stream", funcName, status);
|
|
}
|
|
|
|
// static
|
|
Result Stream::analyzeStatus(const char* funcName, int status,
|
|
const std::vector<int>& ignoreErrors) {
|
|
return util::analyzeStatus("stream", funcName, status, ignoreErrors);
|
|
}
|
|
|
|
char* Stream::halGetParameters(const char* keys) {
|
|
return mStream->get_parameters(mStream, keys);
|
|
}
|
|
|
|
int Stream::halSetParameters(const char* keysAndValues) {
|
|
return mStream->set_parameters(mStream, keysAndValues);
|
|
}
|
|
|
|
// Methods from ::android::hardware::audio::CPP_VERSION::IStream follow.
|
|
Return<uint64_t> Stream::getFrameSize() {
|
|
// Needs to be implemented by interface subclasses. But can't be declared as pure virtual,
|
|
// since interface subclasses implementation do not inherit from this class.
|
|
LOG_ALWAYS_FATAL("Stream::getFrameSize is pure abstract");
|
|
return uint64_t{};
|
|
}
|
|
|
|
Return<uint64_t> Stream::getFrameCount() {
|
|
int halFrameCount;
|
|
Result retval = getParam(AudioParameter::keyFrameCount, &halFrameCount);
|
|
return retval == Result::OK ? halFrameCount : 0;
|
|
}
|
|
|
|
Return<uint64_t> Stream::getBufferSize() {
|
|
return mStream->get_buffer_size(mStream);
|
|
}
|
|
|
|
Return<uint32_t> Stream::getSampleRate() {
|
|
return mStream->get_sample_rate(mStream);
|
|
}
|
|
|
|
#if MAJOR_VERSION == 2
|
|
Return<void> Stream::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
|
|
return getSupportedSampleRates(getFormat(), _hidl_cb);
|
|
}
|
|
Return<void> Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
|
|
return getSupportedChannelMasks(getFormat(), _hidl_cb);
|
|
}
|
|
#endif
|
|
|
|
Return<void> Stream::getSupportedSampleRates(AudioFormat format,
|
|
getSupportedSampleRates_cb _hidl_cb) {
|
|
AudioParameter context;
|
|
context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format));
|
|
String8 halListValue;
|
|
Result result =
|
|
getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue, context);
|
|
hidl_vec<uint32_t> sampleRates;
|
|
SortedVector<uint32_t> halSampleRates;
|
|
if (result == Result::OK) {
|
|
halSampleRates =
|
|
samplingRatesFromString(halListValue.string(), AudioParameter::valueListSeparator);
|
|
sampleRates.setToExternal(halSampleRates.editArray(), halSampleRates.size());
|
|
// Legacy get_parameter does not return a status_t, thus can not advertise of failure.
|
|
// Note that this method must succeed (non empty list) if the format is supported.
|
|
if (sampleRates.size() == 0) {
|
|
result = Result::NOT_SUPPORTED;
|
|
}
|
|
}
|
|
#if MAJOR_VERSION == 2
|
|
_hidl_cb(sampleRates);
|
|
#elif MAJOR_VERSION >= 4
|
|
_hidl_cb(result, sampleRates);
|
|
#endif
|
|
return Void();
|
|
}
|
|
|
|
Return<void> Stream::getSupportedChannelMasks(AudioFormat format,
|
|
getSupportedChannelMasks_cb _hidl_cb) {
|
|
AudioParameter context;
|
|
context.addInt(String8(AUDIO_PARAMETER_STREAM_FORMAT), int(format));
|
|
String8 halListValue;
|
|
Result result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue, context);
|
|
hidl_vec<AudioChannelBitfield> channelMasks;
|
|
SortedVector<audio_channel_mask_t> halChannelMasks;
|
|
if (result == Result::OK) {
|
|
halChannelMasks =
|
|
channelMasksFromString(halListValue.string(), AudioParameter::valueListSeparator);
|
|
channelMasks.resize(halChannelMasks.size());
|
|
for (size_t i = 0; i < halChannelMasks.size(); ++i) {
|
|
channelMasks[i] = AudioChannelBitfield(halChannelMasks[i]);
|
|
}
|
|
// Legacy get_parameter does not return a status_t, thus can not advertise of failure.
|
|
// Note that this method must succeed (non empty list) if the format is supported.
|
|
if (channelMasks.size() == 0) {
|
|
result = Result::NOT_SUPPORTED;
|
|
}
|
|
}
|
|
#if MAJOR_VERSION == 2
|
|
_hidl_cb(channelMasks);
|
|
#elif MAJOR_VERSION >= 4
|
|
_hidl_cb(result, channelMasks);
|
|
#endif
|
|
return Void();
|
|
}
|
|
|
|
Return<Result> Stream::setSampleRate(uint32_t sampleRateHz) {
|
|
return setParam(AudioParameter::keySamplingRate, static_cast<int>(sampleRateHz));
|
|
}
|
|
|
|
Return<AudioChannelBitfield> Stream::getChannelMask() {
|
|
return AudioChannelBitfield(mStream->get_channels(mStream));
|
|
}
|
|
|
|
Return<Result> Stream::setChannelMask(AudioChannelBitfield mask) {
|
|
return setParam(AudioParameter::keyChannels, static_cast<int>(mask));
|
|
}
|
|
|
|
Return<AudioFormat> Stream::getFormat() {
|
|
return AudioFormat(mStream->get_format(mStream));
|
|
}
|
|
|
|
Return<void> Stream::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
|
|
String8 halListValue;
|
|
Result result = getParam(AudioParameter::keyStreamSupportedFormats, &halListValue);
|
|
hidl_vec<AudioFormat> formats;
|
|
Vector<audio_format_t> halFormats;
|
|
if (result == Result::OK) {
|
|
halFormats = formatsFromString(halListValue.string(), AudioParameter::valueListSeparator);
|
|
formats.resize(halFormats.size());
|
|
for (size_t i = 0; i < halFormats.size(); ++i) {
|
|
formats[i] = AudioFormat(halFormats[i]);
|
|
}
|
|
// Legacy get_parameter does not return a status_t, thus can not advertise of failure.
|
|
// Note that the method must not return an empty list if this capability is supported.
|
|
if (formats.size() == 0) {
|
|
result = Result::NOT_SUPPORTED;
|
|
}
|
|
}
|
|
#if MAJOR_VERSION <= 5
|
|
_hidl_cb(formats);
|
|
#elif MAJOR_VERSION >= 6
|
|
_hidl_cb(result, formats);
|
|
#endif
|
|
return Void();
|
|
}
|
|
|
|
Return<Result> Stream::setFormat(AudioFormat format) {
|
|
return setParam(AudioParameter::keyFormat, static_cast<int>(format));
|
|
}
|
|
|
|
Return<void> Stream::getAudioProperties(getAudioProperties_cb _hidl_cb) {
|
|
uint32_t halSampleRate = mStream->get_sample_rate(mStream);
|
|
audio_channel_mask_t halMask = mStream->get_channels(mStream);
|
|
audio_format_t halFormat = mStream->get_format(mStream);
|
|
_hidl_cb(halSampleRate, AudioChannelBitfield(halMask), AudioFormat(halFormat));
|
|
return Void();
|
|
}
|
|
|
|
Return<Result> Stream::addEffect(uint64_t effectId) {
|
|
effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
|
|
if (halEffect != NULL) {
|
|
return analyzeStatus("add_audio_effect", mStream->add_audio_effect(mStream, halEffect));
|
|
} else {
|
|
ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
|
|
return Result::INVALID_ARGUMENTS;
|
|
}
|
|
}
|
|
|
|
Return<Result> Stream::removeEffect(uint64_t effectId) {
|
|
effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
|
|
if (halEffect != NULL) {
|
|
return analyzeStatus("remove_audio_effect",
|
|
mStream->remove_audio_effect(mStream, halEffect));
|
|
} else {
|
|
ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
|
|
return Result::INVALID_ARGUMENTS;
|
|
}
|
|
}
|
|
|
|
Return<Result> Stream::standby() {
|
|
return analyzeStatus("standby", mStream->standby(mStream));
|
|
}
|
|
|
|
Return<Result> Stream::setHwAvSync(uint32_t hwAvSync) {
|
|
return setParam(AudioParameter::keyStreamHwAvSync, static_cast<int>(hwAvSync));
|
|
}
|
|
|
|
#if MAJOR_VERSION == 2
|
|
Return<AudioDevice> Stream::getDevice() {
|
|
int device = 0;
|
|
Result retval = getParam(AudioParameter::keyRouting, &device);
|
|
return retval == Result::OK ? static_cast<AudioDevice>(device) : AudioDevice::NONE;
|
|
}
|
|
|
|
Return<Result> Stream::setDevice(const DeviceAddress& address) {
|
|
return setParam(AudioParameter::keyRouting, address);
|
|
}
|
|
|
|
Return<void> Stream::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
|
|
getParametersImpl({} /* context */, keys, _hidl_cb);
|
|
return Void();
|
|
}
|
|
|
|
Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& parameters) {
|
|
return setParametersImpl({} /* context */, parameters);
|
|
}
|
|
|
|
Return<Result> Stream::setConnectedState(const DeviceAddress& address, bool connected) {
|
|
return setParam(
|
|
connected ? AudioParameter::keyDeviceConnect : AudioParameter::keyDeviceDisconnect,
|
|
address);
|
|
}
|
|
#elif MAJOR_VERSION >= 4
|
|
Return<void> Stream::getDevices(getDevices_cb _hidl_cb) {
|
|
int device = 0;
|
|
Result retval = getParam(AudioParameter::keyRouting, &device);
|
|
hidl_vec<DeviceAddress> devices;
|
|
if (retval == Result::OK) {
|
|
devices.resize(1);
|
|
devices[0].device = static_cast<AudioDevice>(device);
|
|
}
|
|
_hidl_cb(retval, devices);
|
|
return Void();
|
|
}
|
|
|
|
Return<Result> Stream::setDevices(const hidl_vec<DeviceAddress>& devices) {
|
|
// FIXME: can the legacy API set multiple device with address ?
|
|
if (devices.size() > 1) {
|
|
return Result::NOT_SUPPORTED;
|
|
}
|
|
DeviceAddress address;
|
|
if (devices.size() == 1) {
|
|
address = devices[0];
|
|
} else {
|
|
address.device = AudioDevice::NONE;
|
|
}
|
|
return setParam(AudioParameter::keyRouting, address);
|
|
}
|
|
Return<void> Stream::getParameters(const hidl_vec<ParameterValue>& context,
|
|
const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
|
|
getParametersImpl(context, keys, _hidl_cb);
|
|
return Void();
|
|
}
|
|
|
|
Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& context,
|
|
const hidl_vec<ParameterValue>& parameters) {
|
|
return setParametersImpl(context, parameters);
|
|
}
|
|
#endif
|
|
|
|
Return<Result> Stream::start() {
|
|
return Result::NOT_SUPPORTED;
|
|
}
|
|
|
|
Return<Result> Stream::stop() {
|
|
return Result::NOT_SUPPORTED;
|
|
}
|
|
|
|
Return<void> Stream::createMmapBuffer(int32_t minSizeFrames __unused,
|
|
createMmapBuffer_cb _hidl_cb) {
|
|
Result retval(Result::NOT_SUPPORTED);
|
|
MmapBufferInfo info;
|
|
_hidl_cb(retval, info);
|
|
return Void();
|
|
}
|
|
|
|
Return<void> Stream::getMmapPosition(getMmapPosition_cb _hidl_cb) {
|
|
Result retval(Result::NOT_SUPPORTED);
|
|
MmapPosition position;
|
|
_hidl_cb(retval, position);
|
|
return Void();
|
|
}
|
|
|
|
Return<Result> Stream::close() {
|
|
return Result::NOT_SUPPORTED;
|
|
}
|
|
|
|
Return<void> Stream::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
|
|
if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
|
|
analyzeStatus("dump", mStream->dump(mStream, fd->data[0]));
|
|
}
|
|
return Void();
|
|
}
|
|
|
|
#if MAJOR_VERSION == 2
|
|
Return<void> Stream::debugDump(const hidl_handle& fd) {
|
|
return debug(fd, {} /* options */);
|
|
}
|
|
#endif
|
|
|
|
} // namespace implementation
|
|
} // namespace CPP_VERSION
|
|
} // namespace audio
|
|
} // namespace hardware
|
|
} // namespace android
|