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
diff --git a/audio/2.0/IDevice.hal b/audio/2.0/IDevice.hal
index 38bfe21..630a32c 100644
--- a/audio/2.0/IDevice.hal
+++ b/audio/2.0/IDevice.hal
@@ -102,6 +102,8 @@
/*
* 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 @@
* @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 @@
* @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
diff --git a/audio/2.0/IStreamOut.hal b/audio/2.0/IStreamOut.hal
index 55a852d..4ba3b2f 100644
--- a/audio/2.0/IStreamOut.hal
+++ b/audio/2.0/IStreamOut.hal
@@ -90,11 +90,25 @@
* 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.
*
* @return supportsPause true if pausing is supported.
diff --git a/audio/2.0/default/Conversions.cpp b/audio/2.0/default/Conversions.cpp
index 1ba16e1..e669185 100644
--- a/audio/2.0/default/Conversions.cpp
+++ b/audio/2.0/default/Conversions.cpp
@@ -29,27 +29,31 @@
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());
}
diff --git a/audio/2.0/default/Device.cpp b/audio/2.0/default/Device.cpp
index 339f371..9c227f6 100644
--- a/audio/2.0/default/Device.cpp
+++ b/audio/2.0/default/Device.cpp
@@ -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 @@
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::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 @@
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 @@
&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 @@
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 @@
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 @@
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<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<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));
}
diff --git a/audio/2.0/default/Device.h b/audio/2.0/default/Device.h
index 3fd67e3..a7d95a0 100644
--- a/audio/2.0/default/Device.h
+++ b/audio/2.0/default/Device.h
@@ -36,22 +36,13 @@
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 @@
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 @@
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.
diff --git a/audio/2.0/default/PrimaryDevice.cpp b/audio/2.0/default/PrimaryDevice.cpp
index a8aa5ec..905203b 100644
--- a/audio/2.0/default/PrimaryDevice.cpp
+++ b/audio/2.0/default/PrimaryDevice.cpp
@@ -83,6 +83,10 @@
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,
diff --git a/audio/2.0/default/PrimaryDevice.h b/audio/2.0/default/PrimaryDevice.h
index 968c208..db01fb3 100644
--- a/audio/2.0/default/PrimaryDevice.h
+++ b/audio/2.0/default/PrimaryDevice.h
@@ -76,6 +76,7 @@
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,
diff --git a/audio/2.0/default/StreamOut.cpp b/audio/2.0/default/StreamOut.cpp
index 2106256..4ee4961 100644
--- a/audio/2.0/default/StreamOut.cpp
+++ b/audio/2.0/default/StreamOut.cpp
@@ -191,23 +191,27 @@
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);
diff --git a/audio/2.0/default/StreamOut.h b/audio/2.0/default/StreamOut.h
index ca33b2d..b76214a 100644
--- a/audio/2.0/default/StreamOut.h
+++ b/audio/2.0/default/StreamOut.h
@@ -83,6 +83,7 @@
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 @@
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();