mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:23:37 +00:00
Audio HAL: fixes for issues discovered after client conversion
Several issues addressed:
-- added IDevice.supportsAudioPatches to query whether
create/removeAudioPatch is actually supported by HAL;
-- IStreamOutCallback proxy needs to be owned by IStreamOut
implementation. In order for the client to reset the reference,
added method IStreamOut.clearCallback;
-- IDevice.open{Input|Output}Stream need to return a "suggested" audio
config from HAL;
-- code for converting between system/audio.h and HIDL
data structures has been moved to
android.hardware.audio.common@2.0-util library for reuse;
-- added a workaround for the issue with QC effects HAL trying to write
into the input parameters buffer, which is r/o by Binder design.
Bug: 30222631
Change-Id: I64af24d79c12d6ac3b0f87d085a821913e29237b
Test: tried using with WIP HIDL client on N5X
This commit is contained in:
@@ -102,6 +102,8 @@ interface IDevice {
|
||||
|
||||
/*
|
||||
* This method creates and opens the audio hardware output stream.
|
||||
* If the stream can not be opened with the proposed audio config,
|
||||
* HAL must provide suggested values for the audio config.
|
||||
*
|
||||
* @param ioHandle handle assigned by AudioFlinger.
|
||||
* @param device device type and (if needed) address.
|
||||
@@ -109,15 +111,21 @@ interface IDevice {
|
||||
* @param flags additional flags.
|
||||
* @return retval operation completion status.
|
||||
* @return outStream created output stream.
|
||||
* @return suggestedConfig in case of invalid parameters, suggested config.
|
||||
*/
|
||||
openOutputStream(
|
||||
AudioIoHandle ioHandle,
|
||||
DeviceAddress device,
|
||||
AudioConfig config,
|
||||
AudioOutputFlag flags) generates (Result retval, IStreamOut outStream);
|
||||
AudioOutputFlag flags) generates (
|
||||
Result retval,
|
||||
IStreamOut outStream,
|
||||
AudioConfig suggestedConfig);
|
||||
|
||||
/*
|
||||
* This method creates and opens the audio hardware input stream.
|
||||
* If the stream can not be opened with the proposed audio config,
|
||||
* HAL must provide suggested values for the audio config.
|
||||
*
|
||||
* @param ioHandle handle assigned by AudioFlinger.
|
||||
* @param device device type and (if needed) address.
|
||||
@@ -125,14 +133,25 @@ interface IDevice {
|
||||
* @param flags additional flags.
|
||||
* @param source source specification.
|
||||
* @return retval operation completion status.
|
||||
* @return inStream created input stream.
|
||||
* @return inStream in case of success, created input stream.
|
||||
* @return suggestedConfig in case of invalid parameters, suggested config.
|
||||
*/
|
||||
openInputStream(
|
||||
AudioIoHandle ioHandle,
|
||||
DeviceAddress device,
|
||||
AudioConfig config,
|
||||
AudioInputFlag flags,
|
||||
AudioSource source) generates (Result retval, IStreamIn inStream);
|
||||
AudioSource source) generates (
|
||||
Result retval,
|
||||
IStreamIn inStream,
|
||||
AudioConfig suggestedConfig);
|
||||
|
||||
/*
|
||||
* Returns whether HAL supports audio patches.
|
||||
*
|
||||
* @return supports true if audio patches are supported.
|
||||
*/
|
||||
supportsAudioPatches() generates (bool supports);
|
||||
|
||||
/*
|
||||
* Creates an audio patch between several source and sink ports. The handle
|
||||
|
||||
@@ -90,10 +90,24 @@ interface IStreamOut extends IStream {
|
||||
* Calling this function implies that all future 'write' and 'drain'
|
||||
* must be non-blocking and use the callback to signal completion.
|
||||
*
|
||||
* 'clearCallback' method needs to be called in order to release the local
|
||||
* callback proxy on the server side and thus dereference the callback
|
||||
* implementation on the client side.
|
||||
*
|
||||
* @return retval operation completion status.
|
||||
*/
|
||||
setCallback(IStreamOutCallback callback) generates (Result retval);
|
||||
|
||||
/*
|
||||
* Clears the callback previously set via 'setCallback' method.
|
||||
*
|
||||
* Warning: failure to call this method results in callback implementation
|
||||
* on the client side being held until the HAL server termination.
|
||||
*
|
||||
* @return retval operation completion status: OK or NOT_SUPPORTED.
|
||||
*/
|
||||
clearCallback() generates (Result retval);
|
||||
|
||||
/*
|
||||
* Returns whether HAL supports pausing and resuming of streams.
|
||||
*
|
||||
|
||||
@@ -29,27 +29,31 @@ std::string deviceAddressToHal(const DeviceAddress& address) {
|
||||
char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
|
||||
memset(halAddress, 0, sizeof(halAddress));
|
||||
uint32_t halDevice = static_cast<uint32_t>(address.device);
|
||||
if ((halDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0
|
||||
|| (halDevice & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0) {
|
||||
const bool isInput = (halDevice & AUDIO_DEVICE_BIT_IN) != 0;
|
||||
if (isInput) halDevice &= ~AUDIO_DEVICE_BIT_IN;
|
||||
if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0)
|
||||
|| (isInput && (halDevice & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
|
||||
snprintf(halAddress, sizeof(halAddress),
|
||||
"%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
address.address.mac[0], address.address.mac[1], address.address.mac[2],
|
||||
address.address.mac[3], address.address.mac[4], address.address.mac[5]);
|
||||
} else if ((halDevice & AUDIO_DEVICE_OUT_IP) != 0 || (halDevice & AUDIO_DEVICE_IN_IP) != 0) {
|
||||
} else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_IP) != 0)
|
||||
|| (isInput && (halDevice & AUDIO_DEVICE_IN_IP) != 0)) {
|
||||
snprintf(halAddress, sizeof(halAddress),
|
||||
"%d.%d.%d.%d",
|
||||
address.address.ipv4[0], address.address.ipv4[1],
|
||||
address.address.ipv4[2], address.address.ipv4[3]);
|
||||
} else if ((halDevice & AUDIO_DEVICE_OUT_ALL_USB) != 0
|
||||
|| (halDevice & AUDIO_DEVICE_IN_ALL_USB) != 0) {
|
||||
} else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_USB) != 0)
|
||||
|| (isInput && (halDevice & AUDIO_DEVICE_IN_ALL_USB) != 0)) {
|
||||
snprintf(halAddress, sizeof(halAddress),
|
||||
"card=%d;device=%d",
|
||||
address.address.alsa.card, address.address.alsa.device);
|
||||
} else if ((halDevice & AUDIO_DEVICE_OUT_BUS) != 0 || (halDevice & AUDIO_DEVICE_IN_BUS) != 0) {
|
||||
} else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_BUS) != 0)
|
||||
|| (isInput && (halDevice & AUDIO_DEVICE_IN_BUS) != 0)) {
|
||||
snprintf(halAddress, sizeof(halAddress),
|
||||
"%s", address.busAddress.c_str());
|
||||
} else if ((halDevice & AUDIO_DEVICE_OUT_REMOTE_SUBMIX) != 0
|
||||
|| (halDevice & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0) {
|
||||
} else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0
|
||||
|| (isInput && (halDevice & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
|
||||
snprintf(halAddress, sizeof(halAddress),
|
||||
"%s", address.rSubmixAddress.c_str());
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#define LOG_TAG "DeviceHAL"
|
||||
//#define LOG_NDEBUG 0
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory.h>
|
||||
@@ -24,6 +25,7 @@
|
||||
|
||||
#include "Conversions.h"
|
||||
#include "Device.h"
|
||||
#include "HidlUtils.h"
|
||||
#include "StreamIn.h"
|
||||
#include "StreamOut.h"
|
||||
|
||||
@@ -43,267 +45,6 @@ Device::~Device() {
|
||||
mDevice = nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
void Device::audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig) {
|
||||
memset(halConfig, 0, sizeof(audio_config_t));
|
||||
halConfig->sample_rate = config.sampleRateHz;
|
||||
halConfig->channel_mask = static_cast<audio_channel_mask_t>(config.channelMask);
|
||||
halConfig->format = static_cast<audio_format_t>(config.format);
|
||||
audioOffloadInfoToHal(config.offloadInfo, &halConfig->offload_info);
|
||||
halConfig->frame_count = config.frameCount;
|
||||
}
|
||||
|
||||
// static
|
||||
void Device::audioGainConfigFromHal(
|
||||
const struct audio_gain_config& halConfig, AudioGainConfig* config) {
|
||||
config->index = halConfig.index;
|
||||
config->mode = AudioGainMode(halConfig.mode);
|
||||
config->channelMask = AudioChannelMask(halConfig.channel_mask);
|
||||
for (size_t i = 0; i < sizeof(audio_channel_mask_t) * 8; ++i) {
|
||||
config->values[i] = halConfig.values[i];
|
||||
}
|
||||
config->rampDurationMs = halConfig.ramp_duration_ms;
|
||||
}
|
||||
|
||||
// static
|
||||
void Device::audioGainConfigToHal(
|
||||
const AudioGainConfig& config, struct audio_gain_config* halConfig) {
|
||||
halConfig->index = config.index;
|
||||
halConfig->mode = static_cast<audio_gain_mode_t>(config.mode);
|
||||
halConfig->channel_mask = static_cast<audio_channel_mask_t>(config.channelMask);
|
||||
memset(halConfig->values, 0, sizeof(halConfig->values));
|
||||
for (size_t i = 0; i < sizeof(audio_channel_mask_t) * 8; ++i) {
|
||||
halConfig->values[i] = config.values[i];
|
||||
}
|
||||
halConfig->ramp_duration_ms = config.rampDurationMs;
|
||||
}
|
||||
|
||||
// static
|
||||
void Device::audioGainFromHal(const struct audio_gain& halGain, AudioGain* gain) {
|
||||
gain->mode = AudioGainMode(halGain.mode);
|
||||
gain->channelMask = AudioChannelMask(halGain.channel_mask);
|
||||
gain->minValue = halGain.min_value;
|
||||
gain->maxValue = halGain.max_value;
|
||||
gain->defaultValue = halGain.default_value;
|
||||
gain->stepValue = halGain.step_value;
|
||||
gain->minRampMs = halGain.min_ramp_ms;
|
||||
gain->maxRampMs = halGain.max_ramp_ms;
|
||||
}
|
||||
|
||||
// static
|
||||
void Device::audioGainToHal(const AudioGain& gain, struct audio_gain* halGain) {
|
||||
halGain->mode = static_cast<audio_gain_mode_t>(gain.mode);
|
||||
halGain->channel_mask = static_cast<audio_channel_mask_t>(gain.channelMask);
|
||||
halGain->min_value = gain.minValue;
|
||||
halGain->max_value = gain.maxValue;
|
||||
halGain->default_value = gain.defaultValue;
|
||||
halGain->step_value = gain.stepValue;
|
||||
halGain->min_ramp_ms = gain.minRampMs;
|
||||
halGain->max_ramp_ms = gain.maxRampMs;
|
||||
}
|
||||
|
||||
// static
|
||||
void Device::audioOffloadInfoToHal(
|
||||
const AudioOffloadInfo& offload, audio_offload_info_t* halOffload) {
|
||||
*halOffload = AUDIO_INFO_INITIALIZER;
|
||||
halOffload->sample_rate = offload.sampleRateHz;
|
||||
halOffload->channel_mask = static_cast<audio_channel_mask_t>(offload.channelMask);
|
||||
halOffload->stream_type = static_cast<audio_stream_type_t>(offload.streamType);
|
||||
halOffload->bit_rate = offload.bitRatePerSecond;
|
||||
halOffload->duration_us = offload.durationMicroseconds;
|
||||
halOffload->has_video = offload.hasVideo;
|
||||
halOffload->is_streaming = offload.isStreaming;
|
||||
}
|
||||
|
||||
// static
|
||||
void Device::audioPortConfigFromHal(
|
||||
const struct audio_port_config& halConfig, AudioPortConfig* config) {
|
||||
config->id = halConfig.id;
|
||||
config->role = AudioPortRole(halConfig.role);
|
||||
config->type = AudioPortType(halConfig.type);
|
||||
config->configMask = AudioPortConfigMask(halConfig.config_mask);
|
||||
config->sampleRateHz = halConfig.sample_rate;
|
||||
config->channelMask = AudioChannelMask(halConfig.channel_mask);
|
||||
config->format = AudioFormat(halConfig.format);
|
||||
audioGainConfigFromHal(halConfig.gain, &config->gain);
|
||||
switch (halConfig.type) {
|
||||
case AUDIO_PORT_TYPE_NONE: break;
|
||||
case AUDIO_PORT_TYPE_DEVICE: {
|
||||
config->ext.device.hwModule = halConfig.ext.device.hw_module;
|
||||
config->ext.device.type = AudioDevice(halConfig.ext.device.type);
|
||||
memcpy(config->ext.device.address.data(),
|
||||
halConfig.ext.device.address,
|
||||
AUDIO_DEVICE_MAX_ADDRESS_LEN);
|
||||
break;
|
||||
}
|
||||
case AUDIO_PORT_TYPE_MIX: {
|
||||
config->ext.mix.hwModule = halConfig.ext.mix.hw_module;
|
||||
config->ext.mix.ioHandle = halConfig.ext.mix.handle;
|
||||
if (halConfig.role == AUDIO_PORT_ROLE_SOURCE) {
|
||||
config->ext.mix.useCase.source = AudioSource(halConfig.ext.mix.usecase.source);
|
||||
} else if (halConfig.role == AUDIO_PORT_ROLE_SINK) {
|
||||
config->ext.mix.useCase.stream = AudioStreamType(halConfig.ext.mix.usecase.stream);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AUDIO_PORT_TYPE_SESSION: {
|
||||
config->ext.session.session = halConfig.ext.session.session;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void Device::audioPortConfigToHal(
|
||||
const AudioPortConfig& config, struct audio_port_config* halConfig) {
|
||||
memset(halConfig, 0, sizeof(audio_port_config));
|
||||
halConfig->id = config.id;
|
||||
halConfig->role = static_cast<audio_port_role_t>(config.role);
|
||||
halConfig->type = static_cast<audio_port_type_t>(config.type);
|
||||
halConfig->config_mask = static_cast<unsigned int>(config.configMask);
|
||||
halConfig->sample_rate = config.sampleRateHz;
|
||||
halConfig->channel_mask = static_cast<audio_channel_mask_t>(config.channelMask);
|
||||
halConfig->format = static_cast<audio_format_t>(config.format);
|
||||
audioGainConfigToHal(config.gain, &halConfig->gain);
|
||||
switch (config.type) {
|
||||
case AudioPortType::NONE: break;
|
||||
case AudioPortType::DEVICE: {
|
||||
halConfig->ext.device.hw_module = config.ext.device.hwModule;
|
||||
halConfig->ext.device.type = static_cast<audio_devices_t>(config.ext.device.type);
|
||||
memcpy(halConfig->ext.device.address,
|
||||
config.ext.device.address.data(),
|
||||
AUDIO_DEVICE_MAX_ADDRESS_LEN);
|
||||
break;
|
||||
}
|
||||
case AudioPortType::MIX: {
|
||||
halConfig->ext.mix.hw_module = config.ext.mix.hwModule;
|
||||
halConfig->ext.mix.handle = config.ext.mix.ioHandle;
|
||||
if (config.role == AudioPortRole::SOURCE) {
|
||||
halConfig->ext.mix.usecase.source =
|
||||
static_cast<audio_source_t>(config.ext.mix.useCase.source);
|
||||
} else if (config.role == AudioPortRole::SINK) {
|
||||
halConfig->ext.mix.usecase.stream =
|
||||
static_cast<audio_stream_type_t>(config.ext.mix.useCase.stream);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AudioPortType::SESSION: {
|
||||
halConfig->ext.session.session =
|
||||
static_cast<audio_session_t>(config.ext.session.session);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<audio_port_config[]> Device::audioPortConfigsToHal(
|
||||
const hidl_vec<AudioPortConfig>& configs) {
|
||||
std::unique_ptr<audio_port_config[]> halConfigs(new audio_port_config[configs.size()]);
|
||||
for (size_t i = 0; i < configs.size(); ++i) {
|
||||
audioPortConfigToHal(configs[i], &halConfigs[i]);
|
||||
}
|
||||
return halConfigs;
|
||||
}
|
||||
|
||||
// static
|
||||
void Device::audioPortFromHal(const struct audio_port& halPort, AudioPort* port) {
|
||||
port->id = halPort.id;
|
||||
port->role = AudioPortRole(halPort.role);
|
||||
port->type = AudioPortType(halPort.type);
|
||||
port->name.setToExternal(halPort.name, strlen(halPort.name));
|
||||
port->sampleRates.resize(halPort.num_sample_rates);
|
||||
for (size_t i = 0; i < halPort.num_sample_rates; ++i) {
|
||||
port->sampleRates[i] = halPort.sample_rates[i];
|
||||
}
|
||||
port->channelMasks.resize(halPort.num_channel_masks);
|
||||
for (size_t i = 0; i < halPort.num_channel_masks; ++i) {
|
||||
port->channelMasks[i] = AudioChannelMask(halPort.channel_masks[i]);
|
||||
}
|
||||
port->formats.resize(halPort.num_formats);
|
||||
for (size_t i = 0; i < halPort.num_formats; ++i) {
|
||||
port->formats[i] = AudioFormat(halPort.formats[i]);
|
||||
}
|
||||
port->gains.resize(halPort.num_gains);
|
||||
for (size_t i = 0; i < halPort.num_gains; ++i) {
|
||||
audioGainFromHal(halPort.gains[i], &port->gains[i]);
|
||||
}
|
||||
audioPortConfigFromHal(halPort.active_config, &port->activeConfig);
|
||||
switch (halPort.type) {
|
||||
case AUDIO_PORT_TYPE_NONE: break;
|
||||
case AUDIO_PORT_TYPE_DEVICE: {
|
||||
port->ext.device.hwModule = halPort.ext.device.hw_module;
|
||||
port->ext.device.type = AudioDevice(halPort.ext.device.type);
|
||||
memcpy(port->ext.device.address.data(),
|
||||
halPort.ext.device.address,
|
||||
AUDIO_DEVICE_MAX_ADDRESS_LEN);
|
||||
break;
|
||||
}
|
||||
case AUDIO_PORT_TYPE_MIX: {
|
||||
port->ext.mix.hwModule = halPort.ext.mix.hw_module;
|
||||
port->ext.mix.ioHandle = halPort.ext.mix.handle;
|
||||
port->ext.mix.latencyClass = AudioMixLatencyClass(halPort.ext.mix.latency_class);
|
||||
break;
|
||||
}
|
||||
case AUDIO_PORT_TYPE_SESSION: {
|
||||
port->ext.session.session = halPort.ext.session.session;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void Device::audioPortToHal(const AudioPort& port, struct audio_port* halPort) {
|
||||
memset(halPort, 0, sizeof(audio_port));
|
||||
halPort->id = port.id;
|
||||
halPort->role = static_cast<audio_port_role_t>(port.role);
|
||||
halPort->type = static_cast<audio_port_type_t>(port.type);
|
||||
memcpy(halPort->name,
|
||||
port.name.c_str(),
|
||||
std::min(port.name.size(), static_cast<size_t>(AUDIO_PORT_MAX_NAME_LEN)));
|
||||
halPort->num_sample_rates =
|
||||
std::min(port.sampleRates.size(), static_cast<size_t>(AUDIO_PORT_MAX_SAMPLING_RATES));
|
||||
for (size_t i = 0; i < halPort->num_sample_rates; ++i) {
|
||||
halPort->sample_rates[i] = port.sampleRates[i];
|
||||
}
|
||||
halPort->num_channel_masks =
|
||||
std::min(port.channelMasks.size(), static_cast<size_t>(AUDIO_PORT_MAX_CHANNEL_MASKS));
|
||||
for (size_t i = 0; i < halPort->num_channel_masks; ++i) {
|
||||
halPort->channel_masks[i] = static_cast<audio_channel_mask_t>(port.channelMasks[i]);
|
||||
}
|
||||
halPort->num_formats =
|
||||
std::min(port.formats.size(), static_cast<size_t>(AUDIO_PORT_MAX_FORMATS));
|
||||
for (size_t i = 0; i < halPort->num_formats; ++i) {
|
||||
halPort->formats[i] = static_cast<audio_format_t>(port.formats[i]);
|
||||
}
|
||||
halPort->num_gains = std::min(port.gains.size(), static_cast<size_t>(AUDIO_PORT_MAX_GAINS));
|
||||
for (size_t i = 0; i < halPort->num_gains; ++i) {
|
||||
audioGainToHal(port.gains[i], &halPort->gains[i]);
|
||||
}
|
||||
audioPortConfigToHal(port.activeConfig, &halPort->active_config);
|
||||
switch (port.type) {
|
||||
case AudioPortType::NONE: break;
|
||||
case AudioPortType::DEVICE: {
|
||||
halPort->ext.device.hw_module = port.ext.device.hwModule;
|
||||
halPort->ext.device.type = static_cast<audio_devices_t>(port.ext.device.type);
|
||||
memcpy(halPort->ext.device.address,
|
||||
port.ext.device.address.data(),
|
||||
AUDIO_DEVICE_MAX_ADDRESS_LEN);
|
||||
break;
|
||||
}
|
||||
case AudioPortType::MIX: {
|
||||
halPort->ext.mix.hw_module = port.ext.mix.hwModule;
|
||||
halPort->ext.mix.handle = port.ext.mix.ioHandle;
|
||||
halPort->ext.mix.latency_class =
|
||||
static_cast<audio_mix_latency_class_t>(port.ext.mix.latencyClass);
|
||||
break;
|
||||
}
|
||||
case AudioPortType::SESSION: {
|
||||
halPort->ext.session.session = static_cast<audio_session_t>(port.ext.session.session);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Result Device::analyzeStatus(const char* funcName, int status) {
|
||||
if (status != 0) {
|
||||
ALOGW("Device %p %s: %s", mDevice, funcName, strerror(-status));
|
||||
@@ -381,7 +122,7 @@ Return<void> Device::getMasterMute(getMasterMute_cb _hidl_cb) {
|
||||
Return<void> Device::getInputBufferSize(
|
||||
const AudioConfig& config, getInputBufferSize_cb _hidl_cb) {
|
||||
audio_config_t halConfig;
|
||||
audioConfigToHal(config, &halConfig);
|
||||
HidlUtils::audioConfigToHal(config, &halConfig);
|
||||
size_t halBufferSize = mDevice->get_input_buffer_size(mDevice, &halConfig);
|
||||
Result retval(Result::INVALID_ARGUMENTS);
|
||||
uint64_t bufferSize = 0;
|
||||
@@ -400,8 +141,14 @@ Return<void> Device::openOutputStream(
|
||||
AudioOutputFlag flags,
|
||||
openOutputStream_cb _hidl_cb) {
|
||||
audio_config_t halConfig;
|
||||
audioConfigToHal(config, &halConfig);
|
||||
HidlUtils::audioConfigToHal(config, &halConfig);
|
||||
audio_stream_out_t *halStream;
|
||||
ALOGV("open_output_stream handle: %d devices: %x flags: %#x "
|
||||
"srate: %d format %#x channels %x address %s",
|
||||
ioHandle,
|
||||
static_cast<audio_devices_t>(device.device), static_cast<audio_output_flags_t>(flags),
|
||||
halConfig.sample_rate, halConfig.format, halConfig.channel_mask,
|
||||
deviceAddressToHal(device).c_str());
|
||||
int status = mDevice->open_output_stream(
|
||||
mDevice,
|
||||
ioHandle,
|
||||
@@ -410,11 +157,14 @@ Return<void> Device::openOutputStream(
|
||||
&halConfig,
|
||||
&halStream,
|
||||
deviceAddressToHal(device).c_str());
|
||||
ALOGV("open_output_stream status %d stream %p", status, halStream);
|
||||
sp<IStreamOut> streamOut;
|
||||
if (status == OK) {
|
||||
streamOut = new StreamOut(mDevice, halStream);
|
||||
}
|
||||
_hidl_cb(analyzeStatus("open_output_stream", status), streamOut);
|
||||
AudioConfig suggestedConfig;
|
||||
HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
|
||||
_hidl_cb(analyzeStatus("open_output_stream", status), streamOut, suggestedConfig);
|
||||
return Void();
|
||||
}
|
||||
|
||||
@@ -426,8 +176,14 @@ Return<void> Device::openInputStream(
|
||||
AudioSource source,
|
||||
openInputStream_cb _hidl_cb) {
|
||||
audio_config_t halConfig;
|
||||
audioConfigToHal(config, &halConfig);
|
||||
HidlUtils::audioConfigToHal(config, &halConfig);
|
||||
audio_stream_in_t *halStream;
|
||||
ALOGV("open_input_stream handle: %d devices: %x flags: %#x "
|
||||
"srate: %d format %#x channels %x address %s source %d",
|
||||
ioHandle,
|
||||
static_cast<audio_devices_t>(device.device), static_cast<audio_input_flags_t>(flags),
|
||||
halConfig.sample_rate, halConfig.format, halConfig.channel_mask,
|
||||
deviceAddressToHal(device).c_str(), static_cast<audio_source_t>(source));
|
||||
int status = mDevice->open_input_stream(
|
||||
mDevice,
|
||||
ioHandle,
|
||||
@@ -437,14 +193,21 @@ Return<void> Device::openInputStream(
|
||||
static_cast<audio_input_flags_t>(flags),
|
||||
deviceAddressToHal(device).c_str(),
|
||||
static_cast<audio_source_t>(source));
|
||||
ALOGV("open_input_stream status %d stream %p", status, halStream);
|
||||
sp<IStreamIn> streamIn;
|
||||
if (status == OK) {
|
||||
streamIn = new StreamIn(mDevice, halStream);
|
||||
}
|
||||
_hidl_cb(analyzeStatus("open_input_stream", status), streamIn);
|
||||
AudioConfig suggestedConfig;
|
||||
HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
|
||||
_hidl_cb(analyzeStatus("open_input_stream", status), streamIn, suggestedConfig);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<bool> Device::supportsAudioPatches() {
|
||||
return version() >= AUDIO_DEVICE_API_VERSION_3_0;
|
||||
}
|
||||
|
||||
Return<void> Device::createAudioPatch(
|
||||
const hidl_vec<AudioPortConfig>& sources,
|
||||
const hidl_vec<AudioPortConfig>& sinks,
|
||||
@@ -452,8 +215,8 @@ Return<void> Device::createAudioPatch(
|
||||
Result retval(Result::NOT_SUPPORTED);
|
||||
AudioPatchHandle patch = 0;
|
||||
if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
|
||||
std::unique_ptr<audio_port_config[]> halSources(audioPortConfigsToHal(sources));
|
||||
std::unique_ptr<audio_port_config[]> halSinks(audioPortConfigsToHal(sinks));
|
||||
std::unique_ptr<audio_port_config[]> halSources(HidlUtils::audioPortConfigsToHal(sources));
|
||||
std::unique_ptr<audio_port_config[]> halSinks(HidlUtils::audioPortConfigsToHal(sinks));
|
||||
audio_patch_handle_t halPatch;
|
||||
retval = analyzeStatus(
|
||||
"create_audio_patch",
|
||||
@@ -481,11 +244,11 @@ Return<Result> Device::releaseAudioPatch(int32_t patch) {
|
||||
|
||||
Return<void> Device::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb) {
|
||||
audio_port halPort;
|
||||
audioPortToHal(port, &halPort);
|
||||
HidlUtils::audioPortToHal(port, &halPort);
|
||||
Result retval = analyzeStatus("get_audio_port", mDevice->get_audio_port(mDevice, &halPort));
|
||||
AudioPort resultPort = port;
|
||||
if (retval == Result::OK) {
|
||||
audioPortFromHal(halPort, &resultPort);
|
||||
HidlUtils::audioPortFromHal(halPort, &resultPort);
|
||||
}
|
||||
_hidl_cb(retval, resultPort);
|
||||
return Void();
|
||||
@@ -494,7 +257,7 @@ Return<void> Device::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_c
|
||||
Return<Result> Device::setAudioPortConfig(const AudioPortConfig& config) {
|
||||
if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
|
||||
struct audio_port_config halPortConfig;
|
||||
audioPortConfigToHal(config, &halPortConfig);
|
||||
HidlUtils::audioPortConfigToHal(config, &halPortConfig);
|
||||
return analyzeStatus(
|
||||
"set_audio_port_config", mDevice->set_audio_port_config(mDevice, &halPortConfig));
|
||||
}
|
||||
|
||||
@@ -36,22 +36,13 @@ namespace V2_0 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::hardware::audio::common::V2_0::AudioConfig;
|
||||
using ::android::hardware::audio::common::V2_0::AudioGain;
|
||||
using ::android::hardware::audio::common::V2_0::AudioGainConfig;
|
||||
using ::android::hardware::audio::common::V2_0::AudioGainMode;
|
||||
using ::android::hardware::audio::common::V2_0::AudioHwSync;
|
||||
using ::android::hardware::audio::common::V2_0::AudioInputFlag;
|
||||
using ::android::hardware::audio::common::V2_0::AudioMixLatencyClass;
|
||||
using ::android::hardware::audio::common::V2_0::AudioOffloadInfo;
|
||||
using ::android::hardware::audio::common::V2_0::AudioOutputFlag;
|
||||
using ::android::hardware::audio::common::V2_0::AudioPatchHandle;
|
||||
using ::android::hardware::audio::common::V2_0::AudioPort;
|
||||
using ::android::hardware::audio::common::V2_0::AudioPortConfig;
|
||||
using ::android::hardware::audio::common::V2_0::AudioPortConfigMask;
|
||||
using ::android::hardware::audio::common::V2_0::AudioPortRole;
|
||||
using ::android::hardware::audio::common::V2_0::AudioPortType;
|
||||
using ::android::hardware::audio::common::V2_0::AudioSource;
|
||||
using ::android::hardware::audio::common::V2_0::AudioStreamType;
|
||||
using ::android::hardware::audio::V2_0::DeviceAddress;
|
||||
using ::android::hardware::audio::V2_0::IDevice;
|
||||
using ::android::hardware::audio::V2_0::IStreamIn;
|
||||
@@ -90,6 +81,7 @@ struct Device : public IDevice, public ParametersUtil {
|
||||
AudioInputFlag flags,
|
||||
AudioSource source,
|
||||
openInputStream_cb _hidl_cb) override;
|
||||
Return<bool> supportsAudioPatches() override;
|
||||
Return<void> createAudioPatch(
|
||||
const hidl_vec<AudioPortConfig>& sources,
|
||||
const hidl_vec<AudioPortConfig>& sinks,
|
||||
@@ -111,24 +103,6 @@ struct Device : public IDevice, public ParametersUtil {
|
||||
private:
|
||||
audio_hw_device_t *mDevice;
|
||||
|
||||
static void audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig);
|
||||
static void audioGainConfigFromHal(
|
||||
const struct audio_gain_config& halConfig, AudioGainConfig* config);
|
||||
static void audioGainConfigToHal(
|
||||
const AudioGainConfig& config, struct audio_gain_config* halConfig);
|
||||
static void audioGainFromHal(const struct audio_gain& halGain, AudioGain* gain);
|
||||
static void audioGainToHal(const AudioGain& gain, struct audio_gain* halGain);
|
||||
static void audioOffloadInfoToHal(
|
||||
const AudioOffloadInfo& offload, audio_offload_info_t* halOffload);
|
||||
static void audioPortConfigFromHal(
|
||||
const struct audio_port_config& halConfig, AudioPortConfig* config);
|
||||
static void audioPortConfigToHal(
|
||||
const AudioPortConfig& config, struct audio_port_config* halConfig);
|
||||
static std::unique_ptr<audio_port_config[]> audioPortConfigsToHal(
|
||||
const hidl_vec<AudioPortConfig>& configs);
|
||||
static void audioPortFromHal(const struct audio_port& halPort, AudioPort* port);
|
||||
static void audioPortToHal(const AudioPort& port, struct audio_port* halPort);
|
||||
|
||||
virtual ~Device();
|
||||
|
||||
// Methods from ParametersUtil.
|
||||
|
||||
@@ -83,6 +83,10 @@ Return<void> PrimaryDevice::openInputStream(
|
||||
return mDevice->openInputStream(ioHandle, device, config, flags, source, _hidl_cb);
|
||||
}
|
||||
|
||||
Return<bool> PrimaryDevice::supportsAudioPatches() {
|
||||
return mDevice->supportsAudioPatches();
|
||||
}
|
||||
|
||||
Return<void> PrimaryDevice::createAudioPatch(
|
||||
const hidl_vec<AudioPortConfig>& sources,
|
||||
const hidl_vec<AudioPortConfig>& sinks,
|
||||
|
||||
@@ -76,6 +76,7 @@ struct PrimaryDevice : public IPrimaryDevice {
|
||||
AudioInputFlag flags,
|
||||
AudioSource source,
|
||||
openInputStream_cb _hidl_cb) override;
|
||||
Return<bool> supportsAudioPatches() override;
|
||||
Return<void> createAudioPatch(
|
||||
const hidl_vec<AudioPortConfig>& sources,
|
||||
const hidl_vec<AudioPortConfig>& sinks,
|
||||
|
||||
@@ -191,23 +191,27 @@ Return<Result> StreamOut::setCallback(const sp<IStreamOutCallback>& callback) {
|
||||
return mStreamCommon->analyzeStatus("set_callback", result);
|
||||
}
|
||||
|
||||
Return<Result> StreamOut::clearCallback() {
|
||||
if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED;
|
||||
mCallback.clear();
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
// static
|
||||
int StreamOut::asyncCallback(stream_callback_event_t event, void*, void *cookie) {
|
||||
wp<StreamOut> weakSelf(reinterpret_cast<StreamOut*>(cookie));
|
||||
sp<StreamOut> self = weakSelf.promote();
|
||||
if (self == 0) return 0;
|
||||
sp<IStreamOutCallback> callback = self->mCallback.promote();
|
||||
if (callback == 0) return 0;
|
||||
if (self == nullptr || self->mCallback == nullptr) return 0;
|
||||
ALOGV("asyncCallback() event %d", event);
|
||||
switch (event) {
|
||||
case STREAM_CBK_EVENT_WRITE_READY:
|
||||
callback->onWriteReady();
|
||||
self->mCallback->onWriteReady();
|
||||
break;
|
||||
case STREAM_CBK_EVENT_DRAIN_READY:
|
||||
callback->onDrainReady();
|
||||
self->mCallback->onDrainReady();
|
||||
break;
|
||||
case STREAM_CBK_EVENT_ERROR:
|
||||
callback->onError();
|
||||
self->mCallback->onError();
|
||||
break;
|
||||
default:
|
||||
ALOGW("asyncCallback() unknown event %d", event);
|
||||
|
||||
@@ -83,6 +83,7 @@ struct StreamOut : public IStreamOut {
|
||||
Return<void> getRenderPosition(getRenderPosition_cb _hidl_cb) override;
|
||||
Return<void> getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb) override;
|
||||
Return<Result> setCallback(const sp<IStreamOutCallback>& callback) override;
|
||||
Return<Result> clearCallback() override;
|
||||
Return<void> supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb) override;
|
||||
Return<Result> pause() override;
|
||||
Return<Result> resume() override;
|
||||
@@ -95,9 +96,7 @@ struct StreamOut : public IStreamOut {
|
||||
audio_hw_device_t *mDevice;
|
||||
audio_stream_out_t *mStream;
|
||||
sp<Stream> mStreamCommon;
|
||||
// Do not store sp<> to avoid creating a reference loop if the entity that holds
|
||||
// onto the output stream owns or implements the callback.
|
||||
wp<IStreamOutCallback> mCallback;
|
||||
sp<IStreamOutCallback> mCallback;
|
||||
|
||||
virtual ~StreamOut();
|
||||
|
||||
|
||||
@@ -20,10 +20,13 @@ include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := android.hardware.audio.common@2.0-util
|
||||
LOCAL_SRC_FILES := \
|
||||
EffectMap.cpp \
|
||||
HidlUtils.cpp \
|
||||
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libutils \
|
||||
libhidlbase \
|
||||
android.hardware.audio.common@2.0 \
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
328
audio/common/2.0/default/HidlUtils.cpp
Normal file
328
audio/common/2.0/default/HidlUtils.cpp
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "HidlUtils.h"
|
||||
|
||||
using ::android::hardware::audio::common::V2_0::AudioChannelMask;
|
||||
using ::android::hardware::audio::common::V2_0::AudioDevice;
|
||||
using ::android::hardware::audio::common::V2_0::AudioFormat;
|
||||
using ::android::hardware::audio::common::V2_0::AudioGainMode;
|
||||
using ::android::hardware::audio::common::V2_0::AudioMixLatencyClass;
|
||||
using ::android::hardware::audio::common::V2_0::AudioPortConfigMask;
|
||||
using ::android::hardware::audio::common::V2_0::AudioPortRole;
|
||||
using ::android::hardware::audio::common::V2_0::AudioPortType;
|
||||
using ::android::hardware::audio::common::V2_0::AudioSource;
|
||||
using ::android::hardware::audio::common::V2_0::AudioStreamType;
|
||||
|
||||
namespace android {
|
||||
|
||||
void HidlUtils::audioConfigFromHal(const audio_config_t& halConfig, AudioConfig* config) {
|
||||
config->sampleRateHz = halConfig.sample_rate;
|
||||
config->channelMask = AudioChannelMask(halConfig.channel_mask);
|
||||
config->format = AudioFormat(halConfig.format);
|
||||
audioOffloadInfoFromHal(halConfig.offload_info, &config->offloadInfo);
|
||||
config->frameCount = halConfig.frame_count;
|
||||
}
|
||||
|
||||
void HidlUtils::audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig) {
|
||||
memset(halConfig, 0, sizeof(audio_config_t));
|
||||
halConfig->sample_rate = config.sampleRateHz;
|
||||
halConfig->channel_mask = static_cast<audio_channel_mask_t>(config.channelMask);
|
||||
halConfig->format = static_cast<audio_format_t>(config.format);
|
||||
audioOffloadInfoToHal(config.offloadInfo, &halConfig->offload_info);
|
||||
halConfig->frame_count = config.frameCount;
|
||||
}
|
||||
|
||||
void HidlUtils::audioGainConfigFromHal(
|
||||
const struct audio_gain_config& halConfig, AudioGainConfig* config) {
|
||||
config->index = halConfig.index;
|
||||
config->mode = AudioGainMode(halConfig.mode);
|
||||
config->channelMask = AudioChannelMask(halConfig.channel_mask);
|
||||
for (size_t i = 0; i < sizeof(audio_channel_mask_t) * 8; ++i) {
|
||||
config->values[i] = halConfig.values[i];
|
||||
}
|
||||
config->rampDurationMs = halConfig.ramp_duration_ms;
|
||||
}
|
||||
|
||||
void HidlUtils::audioGainConfigToHal(
|
||||
const AudioGainConfig& config, struct audio_gain_config* halConfig) {
|
||||
halConfig->index = config.index;
|
||||
halConfig->mode = static_cast<audio_gain_mode_t>(config.mode);
|
||||
halConfig->channel_mask = static_cast<audio_channel_mask_t>(config.channelMask);
|
||||
memset(halConfig->values, 0, sizeof(halConfig->values));
|
||||
for (size_t i = 0; i < sizeof(audio_channel_mask_t) * 8; ++i) {
|
||||
halConfig->values[i] = config.values[i];
|
||||
}
|
||||
halConfig->ramp_duration_ms = config.rampDurationMs;
|
||||
}
|
||||
|
||||
void HidlUtils::audioGainFromHal(const struct audio_gain& halGain, AudioGain* gain) {
|
||||
gain->mode = AudioGainMode(halGain.mode);
|
||||
gain->channelMask = AudioChannelMask(halGain.channel_mask);
|
||||
gain->minValue = halGain.min_value;
|
||||
gain->maxValue = halGain.max_value;
|
||||
gain->defaultValue = halGain.default_value;
|
||||
gain->stepValue = halGain.step_value;
|
||||
gain->minRampMs = halGain.min_ramp_ms;
|
||||
gain->maxRampMs = halGain.max_ramp_ms;
|
||||
}
|
||||
|
||||
void HidlUtils::audioGainToHal(const AudioGain& gain, struct audio_gain* halGain) {
|
||||
halGain->mode = static_cast<audio_gain_mode_t>(gain.mode);
|
||||
halGain->channel_mask = static_cast<audio_channel_mask_t>(gain.channelMask);
|
||||
halGain->min_value = gain.minValue;
|
||||
halGain->max_value = gain.maxValue;
|
||||
halGain->default_value = gain.defaultValue;
|
||||
halGain->step_value = gain.stepValue;
|
||||
halGain->min_ramp_ms = gain.minRampMs;
|
||||
halGain->max_ramp_ms = gain.maxRampMs;
|
||||
}
|
||||
|
||||
void HidlUtils::audioOffloadInfoFromHal(
|
||||
const audio_offload_info_t& halOffload, AudioOffloadInfo* offload) {
|
||||
offload->sampleRateHz = halOffload.sample_rate;
|
||||
offload->channelMask = AudioChannelMask(halOffload.channel_mask);
|
||||
offload->streamType = AudioStreamType(halOffload.stream_type);
|
||||
offload->bitRatePerSecond = halOffload.bit_rate;
|
||||
offload->durationMicroseconds = halOffload.duration_us;
|
||||
offload->hasVideo = halOffload.has_video;
|
||||
offload->isStreaming = halOffload.is_streaming;
|
||||
}
|
||||
|
||||
void HidlUtils::audioOffloadInfoToHal(
|
||||
const AudioOffloadInfo& offload, audio_offload_info_t* halOffload) {
|
||||
*halOffload = AUDIO_INFO_INITIALIZER;
|
||||
halOffload->sample_rate = offload.sampleRateHz;
|
||||
halOffload->channel_mask = static_cast<audio_channel_mask_t>(offload.channelMask);
|
||||
halOffload->stream_type = static_cast<audio_stream_type_t>(offload.streamType);
|
||||
halOffload->bit_rate = offload.bitRatePerSecond;
|
||||
halOffload->duration_us = offload.durationMicroseconds;
|
||||
halOffload->has_video = offload.hasVideo;
|
||||
halOffload->is_streaming = offload.isStreaming;
|
||||
}
|
||||
|
||||
void HidlUtils::audioPortConfigFromHal(
|
||||
const struct audio_port_config& halConfig, AudioPortConfig* config) {
|
||||
config->id = halConfig.id;
|
||||
config->role = AudioPortRole(halConfig.role);
|
||||
config->type = AudioPortType(halConfig.type);
|
||||
config->configMask = AudioPortConfigMask(halConfig.config_mask);
|
||||
config->sampleRateHz = halConfig.sample_rate;
|
||||
config->channelMask = AudioChannelMask(halConfig.channel_mask);
|
||||
config->format = AudioFormat(halConfig.format);
|
||||
audioGainConfigFromHal(halConfig.gain, &config->gain);
|
||||
switch (halConfig.type) {
|
||||
case AUDIO_PORT_TYPE_NONE: break;
|
||||
case AUDIO_PORT_TYPE_DEVICE: {
|
||||
config->ext.device.hwModule = halConfig.ext.device.hw_module;
|
||||
config->ext.device.type = AudioDevice(halConfig.ext.device.type);
|
||||
memcpy(config->ext.device.address.data(),
|
||||
halConfig.ext.device.address,
|
||||
AUDIO_DEVICE_MAX_ADDRESS_LEN);
|
||||
break;
|
||||
}
|
||||
case AUDIO_PORT_TYPE_MIX: {
|
||||
config->ext.mix.hwModule = halConfig.ext.mix.hw_module;
|
||||
config->ext.mix.ioHandle = halConfig.ext.mix.handle;
|
||||
if (halConfig.role == AUDIO_PORT_ROLE_SOURCE) {
|
||||
config->ext.mix.useCase.source = AudioSource(halConfig.ext.mix.usecase.source);
|
||||
} else if (halConfig.role == AUDIO_PORT_ROLE_SINK) {
|
||||
config->ext.mix.useCase.stream = AudioStreamType(halConfig.ext.mix.usecase.stream);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AUDIO_PORT_TYPE_SESSION: {
|
||||
config->ext.session.session = halConfig.ext.session.session;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HidlUtils::audioPortConfigToHal(
|
||||
const AudioPortConfig& config, struct audio_port_config* halConfig) {
|
||||
memset(halConfig, 0, sizeof(audio_port_config));
|
||||
halConfig->id = config.id;
|
||||
halConfig->role = static_cast<audio_port_role_t>(config.role);
|
||||
halConfig->type = static_cast<audio_port_type_t>(config.type);
|
||||
halConfig->config_mask = static_cast<unsigned int>(config.configMask);
|
||||
halConfig->sample_rate = config.sampleRateHz;
|
||||
halConfig->channel_mask = static_cast<audio_channel_mask_t>(config.channelMask);
|
||||
halConfig->format = static_cast<audio_format_t>(config.format);
|
||||
audioGainConfigToHal(config.gain, &halConfig->gain);
|
||||
switch (config.type) {
|
||||
case AudioPortType::NONE: break;
|
||||
case AudioPortType::DEVICE: {
|
||||
halConfig->ext.device.hw_module = config.ext.device.hwModule;
|
||||
halConfig->ext.device.type = static_cast<audio_devices_t>(config.ext.device.type);
|
||||
memcpy(halConfig->ext.device.address,
|
||||
config.ext.device.address.data(),
|
||||
AUDIO_DEVICE_MAX_ADDRESS_LEN);
|
||||
break;
|
||||
}
|
||||
case AudioPortType::MIX: {
|
||||
halConfig->ext.mix.hw_module = config.ext.mix.hwModule;
|
||||
halConfig->ext.mix.handle = config.ext.mix.ioHandle;
|
||||
if (config.role == AudioPortRole::SOURCE) {
|
||||
halConfig->ext.mix.usecase.source =
|
||||
static_cast<audio_source_t>(config.ext.mix.useCase.source);
|
||||
} else if (config.role == AudioPortRole::SINK) {
|
||||
halConfig->ext.mix.usecase.stream =
|
||||
static_cast<audio_stream_type_t>(config.ext.mix.useCase.stream);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AudioPortType::SESSION: {
|
||||
halConfig->ext.session.session =
|
||||
static_cast<audio_session_t>(config.ext.session.session);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HidlUtils::audioPortConfigsFromHal(
|
||||
unsigned int numHalConfigs, const struct audio_port_config *halConfigs,
|
||||
hidl_vec<AudioPortConfig> *configs) {
|
||||
configs->resize(numHalConfigs);
|
||||
for (unsigned int i = 0; i < numHalConfigs; ++i) {
|
||||
audioPortConfigFromHal(halConfigs[i], &(*configs)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<audio_port_config[]> HidlUtils::audioPortConfigsToHal(
|
||||
const hidl_vec<AudioPortConfig>& configs) {
|
||||
std::unique_ptr<audio_port_config[]> halConfigs(new audio_port_config[configs.size()]);
|
||||
for (size_t i = 0; i < configs.size(); ++i) {
|
||||
audioPortConfigToHal(configs[i], &halConfigs[i]);
|
||||
}
|
||||
return halConfigs;
|
||||
}
|
||||
|
||||
void HidlUtils::audioPortFromHal(const struct audio_port& halPort, AudioPort* port) {
|
||||
port->id = halPort.id;
|
||||
port->role = AudioPortRole(halPort.role);
|
||||
port->type = AudioPortType(halPort.type);
|
||||
port->name.setToExternal(halPort.name, strlen(halPort.name));
|
||||
port->sampleRates.resize(halPort.num_sample_rates);
|
||||
for (size_t i = 0; i < halPort.num_sample_rates; ++i) {
|
||||
port->sampleRates[i] = halPort.sample_rates[i];
|
||||
}
|
||||
port->channelMasks.resize(halPort.num_channel_masks);
|
||||
for (size_t i = 0; i < halPort.num_channel_masks; ++i) {
|
||||
port->channelMasks[i] = AudioChannelMask(halPort.channel_masks[i]);
|
||||
}
|
||||
port->formats.resize(halPort.num_formats);
|
||||
for (size_t i = 0; i < halPort.num_formats; ++i) {
|
||||
port->formats[i] = AudioFormat(halPort.formats[i]);
|
||||
}
|
||||
port->gains.resize(halPort.num_gains);
|
||||
for (size_t i = 0; i < halPort.num_gains; ++i) {
|
||||
audioGainFromHal(halPort.gains[i], &port->gains[i]);
|
||||
}
|
||||
audioPortConfigFromHal(halPort.active_config, &port->activeConfig);
|
||||
switch (halPort.type) {
|
||||
case AUDIO_PORT_TYPE_NONE: break;
|
||||
case AUDIO_PORT_TYPE_DEVICE: {
|
||||
port->ext.device.hwModule = halPort.ext.device.hw_module;
|
||||
port->ext.device.type = AudioDevice(halPort.ext.device.type);
|
||||
memcpy(port->ext.device.address.data(),
|
||||
halPort.ext.device.address,
|
||||
AUDIO_DEVICE_MAX_ADDRESS_LEN);
|
||||
break;
|
||||
}
|
||||
case AUDIO_PORT_TYPE_MIX: {
|
||||
port->ext.mix.hwModule = halPort.ext.mix.hw_module;
|
||||
port->ext.mix.ioHandle = halPort.ext.mix.handle;
|
||||
port->ext.mix.latencyClass = AudioMixLatencyClass(halPort.ext.mix.latency_class);
|
||||
break;
|
||||
}
|
||||
case AUDIO_PORT_TYPE_SESSION: {
|
||||
port->ext.session.session = halPort.ext.session.session;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HidlUtils::audioPortToHal(const AudioPort& port, struct audio_port* halPort) {
|
||||
memset(halPort, 0, sizeof(audio_port));
|
||||
halPort->id = port.id;
|
||||
halPort->role = static_cast<audio_port_role_t>(port.role);
|
||||
halPort->type = static_cast<audio_port_type_t>(port.type);
|
||||
memcpy(halPort->name,
|
||||
port.name.c_str(),
|
||||
std::min(port.name.size(), static_cast<size_t>(AUDIO_PORT_MAX_NAME_LEN)));
|
||||
halPort->num_sample_rates =
|
||||
std::min(port.sampleRates.size(), static_cast<size_t>(AUDIO_PORT_MAX_SAMPLING_RATES));
|
||||
for (size_t i = 0; i < halPort->num_sample_rates; ++i) {
|
||||
halPort->sample_rates[i] = port.sampleRates[i];
|
||||
}
|
||||
halPort->num_channel_masks =
|
||||
std::min(port.channelMasks.size(), static_cast<size_t>(AUDIO_PORT_MAX_CHANNEL_MASKS));
|
||||
for (size_t i = 0; i < halPort->num_channel_masks; ++i) {
|
||||
halPort->channel_masks[i] = static_cast<audio_channel_mask_t>(port.channelMasks[i]);
|
||||
}
|
||||
halPort->num_formats =
|
||||
std::min(port.formats.size(), static_cast<size_t>(AUDIO_PORT_MAX_FORMATS));
|
||||
for (size_t i = 0; i < halPort->num_formats; ++i) {
|
||||
halPort->formats[i] = static_cast<audio_format_t>(port.formats[i]);
|
||||
}
|
||||
halPort->num_gains = std::min(port.gains.size(), static_cast<size_t>(AUDIO_PORT_MAX_GAINS));
|
||||
for (size_t i = 0; i < halPort->num_gains; ++i) {
|
||||
audioGainToHal(port.gains[i], &halPort->gains[i]);
|
||||
}
|
||||
audioPortConfigToHal(port.activeConfig, &halPort->active_config);
|
||||
switch (port.type) {
|
||||
case AudioPortType::NONE: break;
|
||||
case AudioPortType::DEVICE: {
|
||||
halPort->ext.device.hw_module = port.ext.device.hwModule;
|
||||
halPort->ext.device.type = static_cast<audio_devices_t>(port.ext.device.type);
|
||||
memcpy(halPort->ext.device.address,
|
||||
port.ext.device.address.data(),
|
||||
AUDIO_DEVICE_MAX_ADDRESS_LEN);
|
||||
break;
|
||||
}
|
||||
case AudioPortType::MIX: {
|
||||
halPort->ext.mix.hw_module = port.ext.mix.hwModule;
|
||||
halPort->ext.mix.handle = port.ext.mix.ioHandle;
|
||||
halPort->ext.mix.latency_class =
|
||||
static_cast<audio_mix_latency_class_t>(port.ext.mix.latencyClass);
|
||||
break;
|
||||
}
|
||||
case AudioPortType::SESSION: {
|
||||
halPort->ext.session.session = static_cast<audio_session_t>(port.ext.session.session);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HidlUtils::uuidFromHal(const audio_uuid_t& halUuid, Uuid* uuid) {
|
||||
uuid->timeLow = halUuid.timeLow;
|
||||
uuid->timeMid = halUuid.timeMid;
|
||||
uuid->versionAndTimeHigh = halUuid.timeHiAndVersion;
|
||||
uuid->variantAndClockSeqHigh = halUuid.clockSeq;
|
||||
memcpy(uuid->node.data(), halUuid.node, uuid->node.size());
|
||||
}
|
||||
|
||||
void HidlUtils::uuidToHal(const Uuid& uuid, audio_uuid_t* halUuid) {
|
||||
halUuid->timeLow = uuid.timeLow;
|
||||
halUuid->timeMid = uuid.timeMid;
|
||||
halUuid->timeHiAndVersion = uuid.versionAndTimeHigh;
|
||||
halUuid->clockSeq = uuid.variantAndClockSeqHigh;
|
||||
memcpy(halUuid->node, uuid.node.data(), uuid.node.size());
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
67
audio/common/2.0/default/HidlUtils.h
Normal file
67
audio/common/2.0/default/HidlUtils.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef android_hardware_audio_V2_0_Hidl_Utils_H_
|
||||
#define android_hardware_audio_V2_0_Hidl_Utils_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <android/hardware/audio/common/2.0/types.h>
|
||||
#include <system/audio.h>
|
||||
|
||||
using ::android::hardware::audio::common::V2_0::AudioConfig;
|
||||
using ::android::hardware::audio::common::V2_0::AudioGain;
|
||||
using ::android::hardware::audio::common::V2_0::AudioGainConfig;
|
||||
using ::android::hardware::audio::common::V2_0::AudioOffloadInfo;
|
||||
using ::android::hardware::audio::common::V2_0::AudioPort;
|
||||
using ::android::hardware::audio::common::V2_0::AudioPortConfig;
|
||||
using ::android::hardware::audio::common::V2_0::Uuid;
|
||||
using ::android::hardware::hidl_vec;
|
||||
|
||||
namespace android {
|
||||
|
||||
class HidlUtils {
|
||||
public:
|
||||
static void audioConfigFromHal(const audio_config_t& halConfig, AudioConfig* config);
|
||||
static void audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig);
|
||||
static void audioGainConfigFromHal(
|
||||
const struct audio_gain_config& halConfig, AudioGainConfig* config);
|
||||
static void audioGainConfigToHal(
|
||||
const AudioGainConfig& config, struct audio_gain_config* halConfig);
|
||||
static void audioGainFromHal(const struct audio_gain& halGain, AudioGain* gain);
|
||||
static void audioGainToHal(const AudioGain& gain, struct audio_gain* halGain);
|
||||
static void audioOffloadInfoFromHal(
|
||||
const audio_offload_info_t& halOffload, AudioOffloadInfo* offload);
|
||||
static void audioOffloadInfoToHal(
|
||||
const AudioOffloadInfo& offload, audio_offload_info_t* halOffload);
|
||||
static void audioPortConfigFromHal(
|
||||
const struct audio_port_config& halConfig, AudioPortConfig* config);
|
||||
static void audioPortConfigToHal(
|
||||
const AudioPortConfig& config, struct audio_port_config* halConfig);
|
||||
static void audioPortConfigsFromHal(
|
||||
unsigned int numHalConfigs, const struct audio_port_config *halConfigs,
|
||||
hidl_vec<AudioPortConfig> *configs);
|
||||
static std::unique_ptr<audio_port_config[]> audioPortConfigsToHal(
|
||||
const hidl_vec<AudioPortConfig>& configs);
|
||||
static void audioPortFromHal(const struct audio_port& halPort, AudioPort* port);
|
||||
static void audioPortToHal(const AudioPort& port, struct audio_port* halPort);
|
||||
static void uuidFromHal(const audio_uuid_t& halUuid, Uuid* uuid);
|
||||
static void uuidToHal(const Uuid& uuid, audio_uuid_t* halUuid);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif // android_hardware_audio_V2_0_Hidl_Utils_H_
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Conversions.h"
|
||||
#include "HidlUtils.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -28,8 +29,8 @@ namespace implementation {
|
||||
|
||||
void effectDescriptorFromHal(
|
||||
const effect_descriptor_t& halDescriptor, EffectDescriptor* descriptor) {
|
||||
uuidFromHal(halDescriptor.type, &descriptor->type);
|
||||
uuidFromHal(halDescriptor.uuid, &descriptor->uuid);
|
||||
HidlUtils::uuidFromHal(halDescriptor.type, &descriptor->type);
|
||||
HidlUtils::uuidFromHal(halDescriptor.uuid, &descriptor->uuid);
|
||||
descriptor->flags = EffectFlags(halDescriptor.flags);
|
||||
descriptor->cpuLoad = halDescriptor.cpuLoad;
|
||||
descriptor->memoryUsage = halDescriptor.memoryUsage;
|
||||
@@ -38,22 +39,6 @@ void effectDescriptorFromHal(
|
||||
halDescriptor.implementor, descriptor->implementor.size());
|
||||
}
|
||||
|
||||
void uuidFromHal(const effect_uuid_t& halUuid, Uuid* uuid) {
|
||||
uuid->timeLow = halUuid.timeLow;
|
||||
uuid->timeMid = halUuid.timeMid;
|
||||
uuid->versionAndTimeHigh = halUuid.timeHiAndVersion;
|
||||
uuid->variantAndClockSeqHigh = halUuid.clockSeq;
|
||||
memcpy(uuid->node.data(), halUuid.node, uuid->node.size());
|
||||
}
|
||||
|
||||
void uuidToHal(const Uuid& uuid, effect_uuid_t* halUuid) {
|
||||
halUuid->timeLow = uuid.timeLow;
|
||||
halUuid->timeMid = uuid.timeMid;
|
||||
halUuid->timeHiAndVersion = uuid.versionAndTimeHigh;
|
||||
halUuid->clockSeq = uuid.variantAndClockSeqHigh;
|
||||
memcpy(halUuid->node, uuid.node.data(), uuid.node.size());
|
||||
}
|
||||
|
||||
std::string uuidToString(const effect_uuid_t& halUuid) {
|
||||
char str[64];
|
||||
snprintf(str, sizeof(str), "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
|
||||
|
||||
@@ -29,13 +29,10 @@ namespace effect {
|
||||
namespace V2_0 {
|
||||
namespace implementation {
|
||||
|
||||
using ::android::hardware::audio::common::V2_0::Uuid;
|
||||
using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
|
||||
|
||||
void effectDescriptorFromHal(
|
||||
const effect_descriptor_t& halDescriptor, EffectDescriptor* descriptor);
|
||||
void uuidFromHal(const effect_uuid_t& halUuid, Uuid* uuid);
|
||||
void uuidToHal(const Uuid& uuid, effect_uuid_t* halUuid);
|
||||
std::string uuidToString(const effect_uuid_t& halUuid);
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <memory.h>
|
||||
|
||||
#define LOG_TAG "EffectHAL"
|
||||
@@ -56,10 +55,15 @@ template<typename T> size_t Effect::alignedSizeIn(size_t s) {
|
||||
}
|
||||
|
||||
// static
|
||||
template<typename T> void Effect::hidlVecToHal(
|
||||
const hidl_vec<T>& vec, uint32_t* halDataSize, void** halData) {
|
||||
*halDataSize = static_cast<T>(vec.size() * sizeof(T));
|
||||
*halData = static_cast<void*>(const_cast<T*>(&vec[0]));
|
||||
template<typename T> std::unique_ptr<uint8_t[]> Effect::hidlVecToHal(
|
||||
const hidl_vec<T>& vec, uint32_t* halDataSize) {
|
||||
// Due to bugs in HAL, they may attempt to write into the provided
|
||||
// input buffer. The original binder buffer is r/o, thus it is needed
|
||||
// to create a r/w version.
|
||||
*halDataSize = vec.size() * sizeof(T);
|
||||
std::unique_ptr<uint8_t[]> halData(new uint8_t[*halDataSize]);
|
||||
memcpy(&halData[0], &vec[0], *halDataSize);
|
||||
return halData;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -393,12 +397,13 @@ Return<Result> Effect::setDevice(AudioDevice device) {
|
||||
Return<void> Effect::setAndGetVolume(
|
||||
const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
|
||||
uint32_t halDataSize;
|
||||
void *halData;
|
||||
hidlVecToHal(volumes, &halDataSize, &halData);
|
||||
std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize);
|
||||
uint32_t halResultSize = halDataSize;
|
||||
uint32_t halResult[volumes.size()];
|
||||
Result retval = sendCommandReturningData(
|
||||
EFFECT_CMD_SET_VOLUME, "SET_VOLUME", halDataSize, halData, &halResultSize, halResult);
|
||||
EFFECT_CMD_SET_VOLUME, "SET_VOLUME",
|
||||
halDataSize, &halData[0],
|
||||
&halResultSize, halResult);
|
||||
hidl_vec<uint32_t> result;
|
||||
if (retval == Result::OK) {
|
||||
result.setToExternal(&halResult[0], halResultSize);
|
||||
@@ -528,13 +533,12 @@ Return<void> Effect::command(
|
||||
uint32_t resultMaxSize,
|
||||
command_cb _hidl_cb) {
|
||||
uint32_t halDataSize;
|
||||
void *halData;
|
||||
hidlVecToHal(data, &halDataSize, &halData);
|
||||
std::unique_ptr<uint8_t[]> halData = hidlVecToHal(data, &halDataSize);
|
||||
uint32_t halResultSize = resultMaxSize;
|
||||
std::unique_ptr<uint8_t[]> halResult(new uint8_t[halResultSize]);
|
||||
memset(&halResult[0], 0, halResultSize);
|
||||
status_t status = (*mHandle)->command(
|
||||
mHandle, commandId, halDataSize, halData, &halResultSize, &halResult[0]);
|
||||
mHandle, commandId, halDataSize, &halData[0], &halResultSize, &halResult[0]);
|
||||
hidl_vec<uint8_t> result;
|
||||
if (status == OK) {
|
||||
result.setToExternal(&halResult[0], halResultSize);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#ifndef HIDL_GENERATED_android_hardware_audio_effect_V2_0_Effect_H_
|
||||
#define HIDL_GENERATED_android_hardware_audio_effect_V2_0_Effect_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <android/hardware/audio/effect/2.0/IEffect.h>
|
||||
@@ -180,8 +181,8 @@ struct Effect : public IEffect {
|
||||
virtual ~Effect();
|
||||
|
||||
template<typename T> static size_t alignedSizeIn(size_t s);
|
||||
template<typename T> static void hidlVecToHal(
|
||||
const hidl_vec<T>& vec, uint32_t* halDataSize, void** halData);
|
||||
template<typename T> std::unique_ptr<uint8_t[]> hidlVecToHal(
|
||||
const hidl_vec<T>& vec, uint32_t* halDataSize);
|
||||
static void effectAuxChannelsConfigFromHal(
|
||||
const channel_config_t& halConfig, EffectAuxChannelsConfig* config);
|
||||
static void effectAuxChannelsConfigToHal(
|
||||
|
||||
@@ -33,8 +33,9 @@
|
||||
#include "AutomaticGainControlEffect.h"
|
||||
#include "BassBoostEffect.h"
|
||||
#include "Conversions.h"
|
||||
#include "EffectsFactory.h"
|
||||
#include "DownmixEffect.h"
|
||||
#include "EffectsFactory.h"
|
||||
#include "HidlUtils.h"
|
||||
#include "Effect.h"
|
||||
#include "EffectMap.h"
|
||||
#include "EnvironmentalReverbEffect.h"
|
||||
@@ -131,7 +132,7 @@ exit:
|
||||
|
||||
Return<void> EffectsFactory::getDescriptor(const Uuid& uid, getDescriptor_cb _hidl_cb) {
|
||||
effect_uuid_t halUuid;
|
||||
uuidToHal(uid, &halUuid);
|
||||
HidlUtils::uuidToHal(uid, &halUuid);
|
||||
effect_descriptor_t halDescriptor;
|
||||
status_t status = EffectGetDescriptor(&halUuid, &halDescriptor);
|
||||
EffectDescriptor descriptor;
|
||||
@@ -153,7 +154,7 @@ Return<void> EffectsFactory::getDescriptor(const Uuid& uid, getDescriptor_cb _hi
|
||||
Return<void> EffectsFactory::createEffect(
|
||||
const Uuid& uid, int32_t session, int32_t ioHandle, createEffect_cb _hidl_cb) {
|
||||
effect_uuid_t halUuid;
|
||||
uuidToHal(uid, &halUuid);
|
||||
HidlUtils::uuidToHal(uid, &halUuid);
|
||||
effect_handle_t handle;
|
||||
Result retval(Result::OK);
|
||||
status_t status = EffectCreate(&halUuid, session, ioHandle, &handle);
|
||||
|
||||
Reference in New Issue
Block a user