Abstract away access to audio streams HAL in AudioFlinger
In this CL all direct access to audio_stream_t, audio_stream_out_t, and
audio_stream_in_t their functions is encapsulated within the new
hierarchy of Stream[In|Out]HalLocal classes. AudioFlinger uses
interface classes Stream[In|Out]HalInterface to access these functions.
Note that NBAIO still receives raw HAL stream handles and needs to be
converted separately.
Bug: 30222631
Test: manual with Loopback app
Change-Id: I6388cfa2006791c9c0aa7bb186719209726a2d48
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 068b917..c89b732 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -27,6 +27,7 @@
AudioHwDevice.cpp \
AudioStreamOut.cpp \
SpdifStreamOut.cpp \
+ StreamHalLocal.cpp \
DeviceHalLocal.cpp \
DevicesFactoryHalLocal.cpp \
EffectHalLocal.cpp \
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index b5ab782..81f59de 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -48,8 +48,6 @@
#include "DevicesFactoryHalInterface.h"
#include "EffectsFactoryHalInterface.h"
#include "ServiceUtilities.h"
-// FIXME: Remove after streams HAL is componentized
-#include "DeviceHalLocal.h"
#include <media/AudioResamplerPublic.h>
@@ -399,7 +397,7 @@
write(fd, result.string(), result.size());
}
- if (mEffectsFactoryHal.get() != NULL) {
+ if (mEffectsFactoryHal != 0) {
mEffectsFactoryHal->dumpEffects(fd);
} else {
String8 result(kNoEffectsFactory);
@@ -2013,7 +2011,6 @@
AudioStreamOut *out = thread->clearOutput();
ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
// from now on thread->mOutput is NULL
- static_cast<DeviceHalLocal*>(out->hwDev().get())->closeOutputStream(out->stream);
delete out;
}
@@ -2109,12 +2106,12 @@
audio_config_t halconfig = *config;
sp<DeviceHalInterface> inHwHal = inHwDev->hwDevice();
- audio_stream_in_t *inStream = NULL;
- status_t status = static_cast<DeviceHalLocal*>(inHwHal.get())->openInputStream(
+ sp<StreamInHalInterface> inStream;
+ status_t status = inHwHal->openInputStream(
*input, devices, &halconfig, flags, address.string(), source, &inStream);
ALOGV("openInput_l() openInputStream returned input %p, SamplingRate %d"
", Format %#x, Channels %x, flags %#x, status %d addr %s",
- inStream,
+ inStream.get(),
halconfig.sample_rate,
halconfig.format,
halconfig.channel_mask,
@@ -2131,13 +2128,13 @@
(audio_channel_count_from_in_mask(config->channel_mask) <= FCC_8)) {
// FIXME describe the change proposed by HAL (save old values so we can log them here)
ALOGV("openInput_l() reopening with proposed sampling rate and channel mask");
- inStream = NULL;
- status = static_cast<DeviceHalLocal*>(inHwHal.get())->openInputStream(
+ inStream.clear();
+ status = inHwHal->openInputStream(
*input, devices, &halconfig, flags, address.string(), source, &inStream);
// FIXME log this new status; HAL should not propose any further changes
}
- if (status == NO_ERROR && inStream != NULL) {
+ if (status == NO_ERROR && inStream != 0) {
#ifdef TEE_SINK
// Try to re-use most recently used Pipe to archive a copy of input for dumpsys,
@@ -2284,7 +2281,6 @@
AudioStreamIn *in = thread->clearInput();
ALOG_ASSERT(in != NULL, "in shouldn't be NULL");
// from now on thread->mInput is NULL
- static_cast<DeviceHalLocal*>(in->hwDev().get())->closeInputStream(in->stream);
delete in;
}
@@ -2649,7 +2645,7 @@
goto Exit;
}
- if (mEffectsFactoryHal.get() == NULL) {
+ if (mEffectsFactoryHal == 0) {
lStatus = NO_INIT;
goto Exit;
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 1890c94..bf8aaf7 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -58,6 +58,7 @@
#include "SpdifStreamOut.h"
#include "AudioHwDevice.h"
#include "LinearMap.h"
+#include "StreamHalInterface.h"
#include <powermanager/IPowerManager.h>
@@ -615,12 +616,12 @@
struct AudioStreamIn {
AudioHwDevice* const audioHwDev;
- audio_stream_in_t* const stream;
+ sp<StreamInHalInterface> stream;
audio_input_flags_t flags;
sp<DeviceHalInterface> hwDev() const { return audioHwDev->hwDevice(); }
- AudioStreamIn(AudioHwDevice *dev, audio_stream_in_t *in, audio_input_flags_t flags) :
+ AudioStreamIn(AudioHwDevice *dev, sp<StreamInHalInterface> in, audio_input_flags_t flags) :
audioHwDev(dev), stream(in), flags(flags) {}
};
diff --git a/services/audioflinger/AudioStreamOut.cpp b/services/audioflinger/AudioStreamOut.cpp
index 4839480..5a07b7f 100644
--- a/services/audioflinger/AudioStreamOut.cpp
+++ b/services/audioflinger/AudioStreamOut.cpp
@@ -24,9 +24,8 @@
#include "AudioHwDevice.h"
#include "AudioStreamOut.h"
#include "DeviceHalInterface.h"
+#include "StreamHalInterface.h"
-// FIXME: Remove after streams HAL is componentized
-#include "DeviceHalLocal.h"
namespace android {
@@ -44,6 +43,10 @@
{
}
+AudioStreamOut::~AudioStreamOut()
+{
+}
+
sp<DeviceHalInterface> AudioStreamOut::hwDev() const
{
return audioHwDev->hwDevice();
@@ -51,12 +54,12 @@
status_t AudioStreamOut::getRenderPosition(uint64_t *frames)
{
- if (stream == NULL) {
+ if (stream == 0) {
return NO_INIT;
}
uint32_t halPosition = 0;
- status_t status = stream->get_render_position(stream, &halPosition);
+ status_t status = stream->getRenderPosition(&halPosition);
if (status != NO_ERROR) {
return status;
}
@@ -88,12 +91,12 @@
status_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timespec *timestamp)
{
- if (stream == NULL) {
+ if (stream == 0) {
return NO_INIT;
}
uint64_t halPosition = 0;
- status_t status = stream->get_presentation_position(stream, &halPosition, timestamp);
+ status_t status = stream->getPresentationPosition(&halPosition, timestamp);
if (status != NO_ERROR) {
return status;
}
@@ -119,13 +122,13 @@
struct audio_config *config,
const char *address)
{
- audio_stream_out_t *outStream;
+ sp<StreamOutHalInterface> outStream;
audio_output_flags_t customFlags = (config->format == AUDIO_FORMAT_IEC61937)
? (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)
: flags;
- int status = static_cast<DeviceHalLocal*>(hwDev().get())->openOutputStream(
+ int status = hwDev()->openOutputStream(
handle,
devices,
customFlags,
@@ -135,7 +138,7 @@
ALOGV("AudioStreamOut::open(), HAL returned "
" stream %p, sampleRate %d, Format %#x, "
"channelMask %#x, status %d",
- outStream,
+ outStream.get(),
config->sample_rate,
config->format,
config->channel_mask,
@@ -147,7 +150,7 @@
struct audio_config customConfig = *config;
customConfig.format = AUDIO_FORMAT_PCM_16_BIT;
- status = static_cast<DeviceHalLocal*>(hwDev().get())->openOutputStream(
+ status = hwDev()->openOutputStream(
handle,
devices,
customFlags,
@@ -160,7 +163,7 @@
if (status == NO_ERROR) {
stream = outStream;
mHalFormatHasProportionalFrames = audio_has_proportional_frames(config->format);
- mHalFrameSize = audio_stream_out_frame_size(stream);
+ status = stream->getFrameSize(&mHalFrameSize);
}
return status;
@@ -168,47 +171,46 @@
audio_format_t AudioStreamOut::getFormat() const
{
- return stream->common.get_format(&stream->common);
+ audio_format_t result;
+ return stream->getFormat(&result) == OK ? result : AUDIO_FORMAT_INVALID;
}
uint32_t AudioStreamOut::getSampleRate() const
{
- return stream->common.get_sample_rate(&stream->common);
+ uint32_t result;
+ return stream->getSampleRate(&result) == OK ? result : 0;
}
audio_channel_mask_t AudioStreamOut::getChannelMask() const
{
- return stream->common.get_channels(&stream->common);
+ audio_channel_mask_t result;
+ return stream->getChannelMask(&result) == OK ? result : AUDIO_CHANNEL_INVALID;
}
int AudioStreamOut::flush()
{
- ALOG_ASSERT(stream != NULL);
mRenderPosition = 0;
mFramesWritten = 0;
mFramesWrittenAtStandby = 0;
- if (stream->flush != NULL) {
- return stream->flush(stream);
- }
- return NO_ERROR;
+ status_t result = stream->flush();
+ return result != INVALID_OPERATION ? result : NO_ERROR;
}
int AudioStreamOut::standby()
{
- ALOG_ASSERT(stream != NULL);
mRenderPosition = 0;
mFramesWrittenAtStandby = mFramesWritten;
- return stream->common.standby(&stream->common);
+ return stream->standby();
}
ssize_t AudioStreamOut::write(const void *buffer, size_t numBytes)
{
- ALOG_ASSERT(stream != NULL);
- ssize_t bytesWritten = stream->write(stream, buffer, numBytes);
- if (bytesWritten > 0 && mHalFrameSize > 0) {
+ size_t bytesWritten;
+ status_t result = stream->write(buffer, numBytes, &bytesWritten);
+ if (result == OK && bytesWritten > 0 && mHalFrameSize > 0) {
mFramesWritten += bytesWritten / mHalFrameSize;
}
- return bytesWritten;
+ return result == OK ? bytesWritten : result;
}
} // namespace android
diff --git a/services/audioflinger/AudioStreamOut.h b/services/audioflinger/AudioStreamOut.h
index d132f6f..b16b1af 100644
--- a/services/audioflinger/AudioStreamOut.h
+++ b/services/audioflinger/AudioStreamOut.h
@@ -27,6 +27,7 @@
class AudioHwDevice;
class DeviceHalInterface;
+class StreamOutHalInterface;
/**
* Managed access to a HAL output stream.
@@ -37,7 +38,7 @@
// For emphasis, we could also make all pointers to them be "const *",
// but that would clutter the code unnecessarily.
AudioHwDevice * const audioHwDev;
- audio_stream_out_t *stream;
+ sp<StreamOutHalInterface> stream;
const audio_output_flags_t flags;
sp<DeviceHalInterface> hwDev() const;
@@ -50,7 +51,7 @@
struct audio_config *config,
const char *address);
- virtual ~AudioStreamOut() { }
+ virtual ~AudioStreamOut();
// Get the bottom 32-bits of the 64-bit render position.
status_t getRenderPosition(uint32_t *frames);
diff --git a/services/audioflinger/BufferProviders.cpp b/services/audioflinger/BufferProviders.cpp
index c1ff1af..204fa17 100644
--- a/services/audioflinger/BufferProviders.cpp
+++ b/services/audioflinger/BufferProviders.cpp
@@ -151,7 +151,7 @@
return;
}
mEffectsFactory = EffectsFactoryHalInterface::create();
- if (mEffectsFactory.get() == NULL) {
+ if (mEffectsFactory == 0) {
ALOGE("DownmixerBufferProvider() error: could not obtain the effects factory");
return;
}
@@ -257,7 +257,7 @@
{
// find multichannel downmix effect if we have to play multichannel content
sp<EffectsFactoryHalInterface> effectsFactory = EffectsFactoryHalInterface::create();
- if (effectsFactory.get() == NULL) {
+ if (effectsFactory == 0) {
ALOGE("AudioMixer() error: could not obtain the effects factory");
return NO_INIT;
}
diff --git a/services/audioflinger/DeviceHalInterface.h b/services/audioflinger/DeviceHalInterface.h
index ea682f0..b5767ef 100644
--- a/services/audioflinger/DeviceHalInterface.h
+++ b/services/audioflinger/DeviceHalInterface.h
@@ -24,12 +24,12 @@
namespace android {
+class StreamInHalInterface;
+class StreamOutHalInterface;
+
class DeviceHalInterface : public RefBase
{
public:
- // The destructor automatically closes the device.
- virtual ~DeviceHalInterface() {}
-
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
virtual status_t getSupportedDevices(uint32_t *devices) = 0;
@@ -69,26 +69,24 @@
// Creates and opens the audio hardware output stream. The stream is closed
// by releasing all references to the returned object.
- // FIXME: Enable when StreamOutHalInterface is introduced.
- // virtual status_t openOutputStream(
- // audio_io_handle_t handle,
- // audio_devices_t devices,
- // audio_output_flags_t flags,
- // struct audio_config *config,
- // const char *address,
- // sp<StreamOutHalInterface> *outStream) = 0;
+ virtual status_t openOutputStream(
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ audio_output_flags_t flags,
+ struct audio_config *config,
+ const char *address,
+ sp<StreamOutHalInterface> *outStream) = 0;
// Creates and opens the audio hardware input stream. The stream is closed
// by releasing all references to the returned object.
- // FIXME: Enable when StreamInHalInterface is introduced.
- // virtual status_t openInputStream(
- // audio_io_handle_t handle,
- // audio_devices_t devices,
- // struct audio_config *config,
- // audio_input_flags_t flags,
- // const char *address,
- // audio_source_t source,
- // sp<StreamInHalInterface> *inStream) = 0;
+ virtual status_t openInputStream(
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ struct audio_config *config,
+ audio_input_flags_t flags,
+ const char *address,
+ audio_source_t source,
+ sp<StreamInHalInterface> *inStream) = 0;
// Creates an audio patch between several source and sink ports.
virtual status_t createAudioPatch(
@@ -112,6 +110,9 @@
protected:
// Subclasses can not be constructed directly by clients.
DeviceHalInterface() {}
+
+ // The destructor automatically closes the device.
+ virtual ~DeviceHalInterface() {}
};
} // namespace android
diff --git a/services/audioflinger/DeviceHalLocal.cpp b/services/audioflinger/DeviceHalLocal.cpp
index b602f16..160eb4a 100644
--- a/services/audioflinger/DeviceHalLocal.cpp
+++ b/services/audioflinger/DeviceHalLocal.cpp
@@ -20,6 +20,7 @@
#include <utils/Log.h>
#include "DeviceHalLocal.h"
+#include "StreamHalLocal.h"
namespace android {
@@ -89,10 +90,10 @@
}
status_t DeviceHalLocal::getParameters(const String8& keys, String8 *values) {
- char *c_values = mDev->get_parameters(mDev, keys.string());
- if (c_values != NULL) {
- values->setTo(c_values);
- free(c_values);
+ char *halValues = mDev->get_parameters(mDev, keys.string());
+ if (halValues != NULL) {
+ values->setTo(halValues);
+ free(halValues);
} else {
values->clear();
}
@@ -105,6 +106,39 @@
return OK;
}
+status_t DeviceHalLocal::openOutputStream(
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ audio_output_flags_t flags,
+ struct audio_config *config,
+ const char *address,
+ sp<StreamOutHalInterface> *outStream) {
+ audio_stream_out_t *halStream;
+ int openResut = mDev->open_output_stream(
+ mDev, handle, devices, flags, config, &halStream, address);
+ if (openResut == OK) {
+ *outStream = new StreamOutHalLocal(halStream, this);
+ }
+ return openResut;
+}
+
+status_t DeviceHalLocal::openInputStream(
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ struct audio_config *config,
+ audio_input_flags_t flags,
+ const char *address,
+ audio_source_t source,
+ sp<StreamInHalInterface> *inStream) {
+ audio_stream_in_t *halStream;
+ int openResult = mDev->open_input_stream(
+ mDev, handle, devices, config, &halStream, flags, address, source);
+ if (openResult == OK) {
+ *inStream = new StreamInHalLocal(halStream, this);
+ }
+ return openResult;
+}
+
status_t DeviceHalLocal::createAudioPatch(
unsigned int num_sources,
const struct audio_port_config *sources,
@@ -130,36 +164,12 @@
return mDev->dump(mDev, fd);
}
-status_t DeviceHalLocal::openOutputStream(
- audio_io_handle_t handle,
- audio_devices_t devices,
- audio_output_flags_t flags,
- struct audio_config *config,
- const char *address,
- struct audio_stream_out **stream_out) {
- return mDev->open_output_stream(mDev, handle, devices, flags, config, stream_out, address);
-}
-
-status_t DeviceHalLocal::closeOutputStream(struct audio_stream_out *stream_out) {
+void DeviceHalLocal::closeOutputStream(struct audio_stream_out *stream_out) {
mDev->close_output_stream(mDev, stream_out);
- return OK;
}
-status_t DeviceHalLocal::openInputStream(
- audio_io_handle_t handle,
- audio_devices_t devices,
- struct audio_config *config,
- audio_input_flags_t flags,
- const char *address,
- audio_source_t source,
- struct audio_stream_in **stream_in) {
- return mDev->open_input_stream(
- mDev, handle, devices, config, stream_in, flags, address, source);
-}
-
-status_t DeviceHalLocal::closeInputStream(struct audio_stream_in *stream_in) {
+void DeviceHalLocal::closeInputStream(struct audio_stream_in *stream_in) {
mDev->close_input_stream(mDev, stream_in);
- return OK;
}
} // namespace android
diff --git a/services/audioflinger/DeviceHalLocal.h b/services/audioflinger/DeviceHalLocal.h
index cc53e9c..1f808cf 100644
--- a/services/audioflinger/DeviceHalLocal.h
+++ b/services/audioflinger/DeviceHalLocal.h
@@ -24,9 +24,6 @@
class DeviceHalLocal : public DeviceHalInterface
{
public:
- // The destructor automatically closes the device.
- virtual ~DeviceHalLocal();
-
// Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
virtual status_t getSupportedDevices(uint32_t *devices);
@@ -66,26 +63,24 @@
// Creates and opens the audio hardware output stream. The stream is closed
// by releasing all references to the returned object.
- // FIXME: Enable when StreamOutHalInterface is introduced.
- // virtual status_t openOutputStream(
- // audio_io_handle_t handle,
- // audio_devices_t devices,
- // audio_output_flags_t flags,
- // struct audio_config *config,
- // const char *address,
- // sp<StreamOutHalInterface> *outStream);
+ virtual status_t openOutputStream(
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ audio_output_flags_t flags,
+ struct audio_config *config,
+ const char *address,
+ sp<StreamOutHalInterface> *outStream);
// Creates and opens the audio hardware input stream. The stream is closed
// by releasing all references to the returned object.
- // FIXME: Enable when StreamInHalInterface is introduced.
- // virtual status_t openInputStream(
- // audio_io_handle_t handle,
- // audio_devices_t devices,
- // struct audio_config *config,
- // audio_input_flags_t flags,
- // const char *address,
- // audio_source_t source,
- // sp<StreamInHalInterface> *inStream);
+ virtual status_t openInputStream(
+ audio_io_handle_t handle,
+ audio_devices_t devices,
+ struct audio_config *config,
+ audio_input_flags_t flags,
+ const char *address,
+ audio_source_t source,
+ sp<StreamInHalInterface> *inStream);
// Creates an audio patch between several source and sink ports.
virtual status_t createAudioPatch(
@@ -106,30 +101,8 @@
virtual status_t dump(int fd);
- // FIXME: Remove when StreamOutHalInterface is introduced.
- status_t openOutputStream(
- audio_io_handle_t handle,
- audio_devices_t devices,
- audio_output_flags_t flags,
- struct audio_config *config,
- const char *address,
- struct audio_stream_out **stream_out);
-
- // FIXME: Remove when StreamOutHalInterface is introduced.
- status_t closeOutputStream(struct audio_stream_out *stream_out);
-
- // FIXME: Remove when StreamInHalInterface is introduced.
- status_t openInputStream(
- audio_io_handle_t handle,
- audio_devices_t devices,
- struct audio_config *config,
- audio_input_flags_t flags,
- const char *address,
- audio_source_t source,
- struct audio_stream_in **stream_in);
-
- // FIXME: Remove when StreamInHalInterface is introduced.
- status_t closeInputStream(struct audio_stream_in *stream_in);
+ void closeOutputStream(struct audio_stream_out *stream_out);
+ void closeInputStream(struct audio_stream_in *stream_in);
private:
audio_hw_device_t *mDev;
@@ -138,6 +111,9 @@
// Can not be constructed directly by clients.
explicit DeviceHalLocal(audio_hw_device_t *dev);
+
+ // The destructor automatically closes the device.
+ virtual ~DeviceHalLocal();
};
} // namespace android
diff --git a/services/audioflinger/EffectHalInterface.h b/services/audioflinger/EffectHalInterface.h
index e774520..4bde112 100644
--- a/services/audioflinger/EffectHalInterface.h
+++ b/services/audioflinger/EffectHalInterface.h
@@ -26,9 +26,6 @@
class EffectHalInterface : public RefBase
{
public:
- // The destructor automatically releases the effect.
- virtual ~EffectHalInterface() {}
-
// Effect process function. Takes input samples as specified
// in input buffer descriptor and output processed samples as specified
// in output buffer descriptor.
@@ -48,6 +45,9 @@
protected:
// Subclasses can not be constructed directly by clients.
EffectHalInterface() {}
+
+ // The destructor automatically releases the effect.
+ virtual ~EffectHalInterface() {}
};
} // namespace android
diff --git a/services/audioflinger/EffectHalLocal.h b/services/audioflinger/EffectHalLocal.h
index 92b2153..73ba6d5 100644
--- a/services/audioflinger/EffectHalLocal.h
+++ b/services/audioflinger/EffectHalLocal.h
@@ -24,9 +24,6 @@
class EffectHalLocal : public EffectHalInterface
{
public:
- // The destructor automatically releases the effect.
- virtual ~EffectHalLocal();
-
// Effect process function. Takes input samples as specified
// in input buffer descriptor and output processed samples as specified
// in output buffer descriptor.
@@ -43,7 +40,6 @@
// Returns the effect descriptor.
virtual status_t getDescriptor(effect_descriptor_t *pDescriptor);
- // FIXME: Remove after converting the main audio HAL
effect_handle_t handle() const { return mHandle; }
private:
@@ -53,6 +49,9 @@
// Can not be constructed directly by clients.
explicit EffectHalLocal(effect_handle_t handle);
+
+ // The destructor automatically releases the effect.
+ virtual ~EffectHalLocal();
};
} // namespace android
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 25c1dbb..d4035d6 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -28,8 +28,6 @@
#include "AudioFlinger.h"
#include "EffectHalInterface.h"
-// FIXME: Remove after converting the main audio HAL
-#include "EffectHalLocal.h"
#include "EffectsFactoryHalInterface.h"
#include "ServiceUtilities.h"
@@ -80,9 +78,9 @@
// create effect engine from effect factory
mStatus = -ENODEV;
sp<AudioFlinger> audioFlinger = mAudioFlinger.promote();
- if (audioFlinger.get() != NULL) {
+ if (audioFlinger != 0) {
sp<EffectsFactoryHalInterface> effectsFactory = audioFlinger->getEffectsFactory();
- if (effectsFactory.get() != NULL) {
+ if (effectsFactory != 0) {
mStatus = effectsFactory->createEffect(
&desc->uuid, sessionId, thread->id(), &mEffectInterface);
}
@@ -107,7 +105,7 @@
AudioFlinger::EffectModule::~EffectModule()
{
ALOGV("Destructor %p", this);
- if (mEffectInterface.get() != NULL) {
+ if (mEffectInterface != 0) {
remove_effect_from_hal_l();
// release effect engine
mEffectInterface.clear();
@@ -276,7 +274,7 @@
{
Mutex::Autolock _l(mLock);
- if (mState == DESTROYED || mEffectInterface.get() == NULL ||
+ if (mState == DESTROYED || mEffectInterface == 0 ||
mConfig.inputCfg.buffer.raw == NULL ||
mConfig.outputCfg.buffer.raw == NULL) {
return;
@@ -338,7 +336,7 @@
void AudioFlinger::EffectModule::reset_l()
{
- if (mStatus != NO_ERROR || mEffectInterface.get() == NULL) {
+ if (mStatus != NO_ERROR || mEffectInterface == 0) {
return;
}
mEffectInterface->command(EFFECT_CMD_RESET, 0, NULL, 0, NULL);
@@ -351,7 +349,7 @@
uint32_t size;
audio_channel_mask_t channelMask;
- if (mEffectInterface.get() == NULL) {
+ if (mEffectInterface == 0) {
status = NO_INIT;
goto exit;
}
@@ -458,7 +456,7 @@
status_t AudioFlinger::EffectModule::init()
{
Mutex::Autolock _l(mLock);
- if (mEffectInterface.get() == NULL) {
+ if (mEffectInterface == 0) {
return NO_INIT;
}
status_t cmdStatus;
@@ -480,10 +478,10 @@
(mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
- audio_stream_t *stream = thread->stream();
- if (stream != NULL) {
- stream->add_audio_effect(stream,
- static_cast<EffectHalLocal*>(mEffectInterface.get())->handle());
+ sp<StreamHalInterface> stream = thread->stream();
+ if (stream != 0) {
+ status_t result = stream->addEffect(mEffectInterface);
+ ALOGE_IF(result != OK, "Error when adding effect: %d", result);
}
}
}
@@ -509,7 +507,7 @@
status_t AudioFlinger::EffectModule::start_l()
{
- if (mEffectInterface.get() == NULL) {
+ if (mEffectInterface == 0) {
return NO_INIT;
}
if (mStatus != NO_ERROR) {
@@ -539,7 +537,7 @@
status_t AudioFlinger::EffectModule::stop_l()
{
- if (mEffectInterface.get() == NULL) {
+ if (mEffectInterface == 0) {
return NO_INIT;
}
if (mStatus != NO_ERROR) {
@@ -567,10 +565,10 @@
(mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
- audio_stream_t *stream = thread->stream();
- if (stream != NULL) {
- stream->remove_audio_effect(stream,
- static_cast<EffectHalLocal*>(mEffectInterface.get())->handle());
+ sp<StreamHalInterface> stream = thread->stream();
+ if (stream != 0) {
+ status_t result = stream->removeEffect(mEffectInterface);
+ ALOGE_IF(result != OK, "Error when removing effect: %d", result);
}
}
}
@@ -593,7 +591,7 @@
Mutex::Autolock _l(mLock);
ALOGVV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface.get());
- if (mState == DESTROYED || mEffectInterface.get() == NULL) {
+ if (mState == DESTROYED || mEffectInterface == 0) {
return NO_INIT;
}
if (mStatus != NO_ERROR) {
diff --git a/services/audioflinger/EffectsFactoryHalInterface.h b/services/audioflinger/EffectsFactoryHalInterface.h
index a865dd1..9a08f68 100644
--- a/services/audioflinger/EffectsFactoryHalInterface.h
+++ b/services/audioflinger/EffectsFactoryHalInterface.h
@@ -28,8 +28,6 @@
class EffectsFactoryHalInterface : public RefBase
{
public:
- virtual ~EffectsFactoryHalInterface() {}
-
// Returns the number of different effects in all loaded libraries.
virtual status_t queryNumberEffects(uint32_t *pNumEffects) = 0;
@@ -57,6 +55,8 @@
protected:
// Subclasses can not be constructed directly by clients.
EffectsFactoryHalInterface() {}
+
+ virtual ~EffectsFactoryHalInterface() {}
};
} // namespace android
diff --git a/services/audioflinger/EffectsFactoryHalLocal.h b/services/audioflinger/EffectsFactoryHalLocal.h
index 244176a..9f6b5ce 100644
--- a/services/audioflinger/EffectsFactoryHalLocal.h
+++ b/services/audioflinger/EffectsFactoryHalLocal.h
@@ -24,8 +24,6 @@
class EffectsFactoryHalLocal : public EffectsFactoryHalInterface
{
public:
- virtual ~EffectsFactoryHalLocal() {}
-
// Returns the number of different effects in all loaded libraries.
virtual status_t queryNumberEffects(uint32_t *pNumEffects);
@@ -50,6 +48,8 @@
// Can not be constructed directly by clients.
EffectsFactoryHalLocal() {}
+
+ virtual ~EffectsFactoryHalLocal() {}
};
} // namespace android
diff --git a/services/audioflinger/SpdifStreamOut.cpp b/services/audioflinger/SpdifStreamOut.cpp
index 004a068..b9260f8 100644
--- a/services/audioflinger/SpdifStreamOut.cpp
+++ b/services/audioflinger/SpdifStreamOut.cpp
@@ -23,7 +23,6 @@
#include <audio_utils/spdif/SPDIFEncoder.h>
#include "AudioHwDevice.h"
-#include "AudioStreamOut.h"
#include "SpdifStreamOut.h"
namespace android {
diff --git a/services/audioflinger/SpdifStreamOut.h b/services/audioflinger/SpdifStreamOut.h
index 801c1f0..fc9bb6e 100644
--- a/services/audioflinger/SpdifStreamOut.h
+++ b/services/audioflinger/SpdifStreamOut.h
@@ -23,7 +23,6 @@
#include <system/audio.h>
-#include "AudioHwDevice.h"
#include "AudioStreamOut.h"
#include <audio_utils/spdif/SPDIFEncoder.h>
diff --git a/services/audioflinger/StreamHalInterface.h b/services/audioflinger/StreamHalInterface.h
new file mode 100644
index 0000000..0339069
--- /dev/null
+++ b/services/audioflinger/StreamHalInterface.h
@@ -0,0 +1,154 @@
+/*
+ * 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_STREAM_HAL_INTERFACE_H
+#define ANDROID_HARDWARE_STREAM_HAL_INTERFACE_H
+
+#include <hardware/audio_effect.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+#include "EffectHalInterface.h"
+
+namespace android {
+
+class StreamHalInterface : public virtual RefBase
+{
+ public:
+ // Return the sampling rate in Hz - eg. 44100.
+ virtual status_t getSampleRate(uint32_t *rate) = 0;
+
+ // Return size of input/output buffer in bytes for this stream - eg. 4800.
+ virtual status_t getBufferSize(size_t *size) = 0;
+
+ // Return the channel mask.
+ virtual status_t getChannelMask(audio_channel_mask_t *mask) = 0;
+
+ // Return the audio format - e.g. AUDIO_FORMAT_PCM_16_BIT.
+ virtual status_t getFormat(audio_format_t *format) = 0;
+
+ // Convenience method.
+ virtual status_t getAudioProperties(
+ uint32_t *sampleRate, audio_channel_mask_t *mask, audio_format_t *format) = 0;
+
+ // Set audio stream parameters.
+ virtual status_t setParameters(const String8& kvPairs) = 0;
+
+ // Get audio stream parameters.
+ virtual status_t getParameters(const String8& keys, String8 *values) = 0;
+
+ // Return the frame size (number of bytes per sample) of a stream.
+ virtual status_t getFrameSize(size_t *size) = 0;
+
+ // Add or remove the effect on the stream.
+ virtual status_t addEffect(sp<EffectHalInterface> effect) = 0;
+ virtual status_t removeEffect(sp<EffectHalInterface> effect) = 0;
+
+ // Put the audio hardware input/output into standby mode.
+ virtual status_t standby() = 0;
+
+ virtual status_t dump(int fd) = 0;
+
+ protected:
+ // Subclasses can not be constructed directly by clients.
+ StreamHalInterface() {}
+
+ // The destructor automatically closes the stream.
+ virtual ~StreamHalInterface() {}
+};
+
+class StreamOutHalInterfaceCallback : public virtual RefBase {
+ public:
+ virtual void onWriteReady() {}
+ virtual void onDrainReady() {}
+ virtual void onError() {}
+
+ protected:
+ StreamOutHalInterfaceCallback() {}
+ virtual ~StreamOutHalInterfaceCallback() {}
+};
+
+class StreamOutHalInterface : public virtual StreamHalInterface {
+ public:
+ // Return the audio hardware driver estimated latency in milliseconds.
+ virtual status_t getLatency(uint32_t *latency) = 0;
+
+ // Use this method in situations where audio mixing is done in the hardware.
+ virtual status_t setVolume(float left, float right) = 0;
+
+ // Write audio buffer to driver.
+ virtual status_t write(const void *buffer, size_t bytes, size_t *written) = 0;
+
+ // Return the number of audio frames written by the audio dsp to DAC since
+ // the output has exited standby.
+ virtual status_t getRenderPosition(uint32_t *dspFrames) = 0;
+
+ // Get the local time at which the next write to the audio driver will be presented.
+ virtual status_t getNextWriteTimestamp(int64_t *timestamp) = 0;
+
+ // Set the callback for notifying completion of non-blocking write and drain.
+ // The callback must be owned by someone else. The output stream does not own it
+ // to avoid strong pointer loops.
+ virtual status_t setCallback(sp<StreamOutHalInterfaceCallback> callback) = 0;
+
+ // Returns whether pause and resume operations are supported.
+ virtual status_t supportsPauseAndResume(bool *supportsPause, bool *supportsResume) = 0;
+
+ // Notifies to the audio driver to resume playback following a pause.
+ virtual status_t pause() = 0;
+
+ // Notifies to the audio driver to resume playback following a pause.
+ virtual status_t resume() = 0;
+
+ // Returns whether drain operation is supported.
+ virtual status_t supportsDrain(bool *supportsDrain) = 0;
+
+ // Requests notification when data buffered by the driver/hardware has been played.
+ virtual status_t drain(audio_drain_type_t type) = 0;
+
+ // Notifies to the audio driver to flush the queued data.
+ virtual status_t flush() = 0;
+
+ // Return a recent count of the number of audio frames presented to an external observer.
+ virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) = 0;
+
+ protected:
+ virtual ~StreamOutHalInterface() {}
+};
+
+class StreamInHalInterface : public virtual StreamHalInterface {
+ public:
+ // Set the input gain for the audio driver.
+ virtual status_t setGain(float gain) = 0;
+
+ // Read audio buffer in from driver.
+ virtual status_t read(void *buffer, size_t bytes, size_t *read) = 0;
+
+ // Return the amount of input frames lost in the audio driver.
+ virtual status_t getInputFramesLost(uint32_t *framesLost) = 0;
+
+ // Return a recent count of the number of audio frames received and
+ // the clock time associated with that frame count.
+ virtual status_t getCapturePosition(int64_t *frames, int64_t *time) = 0;
+
+ protected:
+ virtual ~StreamInHalInterface() {}
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_STREAM_HAL_INTERFACE_H
diff --git a/services/audioflinger/StreamHalLocal.cpp b/services/audioflinger/StreamHalLocal.cpp
new file mode 100644
index 0000000..cdd714b
--- /dev/null
+++ b/services/audioflinger/StreamHalLocal.cpp
@@ -0,0 +1,257 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "AudioFlinger::StreamHalLocal"
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+
+#include "DeviceHalLocal.h"
+#include "EffectHalLocal.h"
+#include "StreamHalLocal.h"
+
+namespace android {
+
+StreamHalLocal::StreamHalLocal(audio_stream_t *stream, sp<DeviceHalLocal> device)
+ : mDevice(device), mStream(stream) {
+}
+
+StreamHalLocal::~StreamHalLocal() {
+ mStream = 0;
+ mDevice.clear();
+}
+
+status_t StreamHalLocal::getSampleRate(uint32_t *rate) {
+ *rate = mStream->get_sample_rate(mStream);
+ return OK;
+}
+
+status_t StreamHalLocal::getBufferSize(size_t *size) {
+ *size = mStream->get_buffer_size(mStream);
+ return OK;
+}
+
+status_t StreamHalLocal::getChannelMask(audio_channel_mask_t *mask) {
+ *mask = mStream->get_channels(mStream);
+ return OK;
+}
+
+status_t StreamHalLocal::getFormat(audio_format_t *format) {
+ *format = mStream->get_format(mStream);
+ return OK;
+}
+
+status_t StreamHalLocal::getAudioProperties(
+ uint32_t *sampleRate, audio_channel_mask_t *mask, audio_format_t *format) {
+ *sampleRate = mStream->get_sample_rate(mStream);
+ *mask = mStream->get_channels(mStream);
+ *format = mStream->get_format(mStream);
+ return OK;
+}
+
+status_t StreamHalLocal::setParameters(const String8& kvPairs) {
+ return mStream->set_parameters(mStream, kvPairs.string());
+}
+
+status_t StreamHalLocal::getParameters(const String8& keys, String8 *values) {
+ char *halValues = mStream->get_parameters(mStream, keys.string());
+ if (halValues != NULL) {
+ values->setTo(halValues);
+ free(halValues);
+ } else {
+ values->clear();
+ }
+ return OK;
+}
+
+status_t StreamHalLocal::addEffect(sp<EffectHalInterface> effect) {
+ return mStream->add_audio_effect(mStream,
+ static_cast<EffectHalLocal*>(effect.get())->handle());
+}
+
+status_t StreamHalLocal::removeEffect(sp<EffectHalInterface> effect) {
+ return mStream->remove_audio_effect(mStream,
+ static_cast<EffectHalLocal*>(effect.get())->handle());
+}
+
+status_t StreamHalLocal::standby() {
+ return mStream->standby(mStream);
+}
+
+status_t StreamHalLocal::dump(int fd) {
+ return mStream->dump(mStream, fd);
+}
+
+StreamOutHalLocal::StreamOutHalLocal(audio_stream_out_t *stream, sp<DeviceHalLocal> device)
+ : StreamHalLocal(&stream->common, device), mStream(stream) {
+}
+
+StreamOutHalLocal::~StreamOutHalLocal() {
+ mCallback.clear();
+ mDevice->closeOutputStream(mStream);
+ mStream = 0;
+}
+
+status_t StreamOutHalLocal::getFrameSize(size_t *size) {
+ *size = audio_stream_out_frame_size(mStream);
+ return OK;
+}
+
+status_t StreamOutHalLocal::getLatency(uint32_t *latency) {
+ *latency = mStream->get_latency(mStream);
+ return OK;
+}
+
+status_t StreamOutHalLocal::setVolume(float left, float right) {
+ if (mStream->set_volume == NULL) return INVALID_OPERATION;
+ return mStream->set_volume(mStream, left, right);
+}
+
+status_t StreamOutHalLocal::write(const void *buffer, size_t bytes, size_t *written) {
+ ssize_t writeResult = mStream->write(mStream, buffer, bytes);
+ if (writeResult > 0) {
+ *written = writeResult;
+ return OK;
+ } else {
+ *written = 0;
+ return writeResult;
+ }
+}
+
+status_t StreamOutHalLocal::getRenderPosition(uint32_t *dspFrames) {
+ return mStream->get_render_position(mStream, dspFrames);
+}
+
+status_t StreamOutHalLocal::getNextWriteTimestamp(int64_t *timestamp) {
+ if (mStream->get_next_write_timestamp == NULL) return INVALID_OPERATION;
+ return mStream->get_next_write_timestamp(mStream, timestamp);
+}
+
+status_t StreamOutHalLocal::setCallback(sp<StreamOutHalInterfaceCallback> callback) {
+ if (mStream->set_callback == NULL) return INVALID_OPERATION;
+ status_t result = mStream->set_callback(mStream, StreamOutHalLocal::asyncCallback, this);
+ if (result == OK) {
+ mCallback = callback;
+ }
+ return result;
+}
+
+// static
+int StreamOutHalLocal::asyncCallback(stream_callback_event_t event, void*, void *cookie) {
+ // We act as if we gave a wp<StreamOutHalLocal> to HAL. This way we should handle
+ // correctly the case when the callback is invoked while StreamOutHalLocal's destructor is
+ // already running, because the destructor is invoked after the refcount has been atomically
+ // decremented.
+ wp<StreamOutHalLocal> weakSelf(reinterpret_cast<StreamOutHalLocal*>(cookie));
+ sp<StreamOutHalLocal> self = weakSelf.promote();
+ if (self == 0) return 0;
+ sp<StreamOutHalInterfaceCallback> callback = self->mCallback.promote();
+ if (callback == 0) return 0;
+ ALOGV("asyncCallback() event %d", event);
+ switch (event) {
+ case STREAM_CBK_EVENT_WRITE_READY:
+ callback->onWriteReady();
+ break;
+ case STREAM_CBK_EVENT_DRAIN_READY:
+ callback->onDrainReady();
+ break;
+ case STREAM_CBK_EVENT_ERROR:
+ callback->onError();
+ break;
+ default:
+ ALOGW("asyncCallback() unknown event %d", event);
+ break;
+ }
+ return 0;
+}
+
+status_t StreamOutHalLocal::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
+ *supportsPause = mStream->pause != NULL;
+ *supportsResume = mStream->resume != NULL;
+ return OK;
+}
+
+status_t StreamOutHalLocal::pause() {
+ if (mStream->pause == NULL) return INVALID_OPERATION;
+ return mStream->pause(mStream);
+}
+
+status_t StreamOutHalLocal::resume() {
+ if (mStream->resume == NULL) return INVALID_OPERATION;
+ return mStream->resume(mStream);
+}
+
+status_t StreamOutHalLocal::supportsDrain(bool *supportsDrain) {
+ *supportsDrain = mStream->drain != NULL;
+ return OK;
+}
+
+status_t StreamOutHalLocal::drain(audio_drain_type_t type) {
+ if (mStream->drain == NULL) return INVALID_OPERATION;
+ return mStream->drain(mStream, type);
+}
+
+status_t StreamOutHalLocal::flush() {
+ if (mStream->flush == NULL) return INVALID_OPERATION;
+ return mStream->flush(mStream);
+}
+
+status_t StreamOutHalLocal::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
+ if (mStream->get_presentation_position == NULL) return INVALID_OPERATION;
+ return mStream->get_presentation_position(mStream, frames, timestamp);
+}
+
+
+StreamInHalLocal::StreamInHalLocal(audio_stream_in_t *stream, sp<DeviceHalLocal> device)
+ : StreamHalLocal(&stream->common, device), mStream(stream) {
+}
+
+StreamInHalLocal::~StreamInHalLocal() {
+ mDevice->closeInputStream(mStream);
+ mStream = 0;
+}
+
+status_t StreamInHalLocal::getFrameSize(size_t *size) {
+ *size = audio_stream_in_frame_size(mStream);
+ return OK;
+}
+
+status_t StreamInHalLocal::setGain(float gain) {
+ return mStream->set_gain(mStream, gain);
+}
+
+status_t StreamInHalLocal::read(void *buffer, size_t bytes, size_t *read) {
+ ssize_t readResult = mStream->read(mStream, buffer, bytes);
+ if (readResult > 0) {
+ *read = readResult;
+ return OK;
+ } else {
+ *read = 0;
+ return readResult;
+ }
+}
+
+status_t StreamInHalLocal::getInputFramesLost(uint32_t *framesLost) {
+ *framesLost = mStream->get_input_frames_lost(mStream);
+ return OK;
+}
+
+status_t StreamInHalLocal::getCapturePosition(int64_t *frames, int64_t *time) {
+ if (mStream->get_capture_position == NULL) return INVALID_OPERATION;
+ return mStream->get_capture_position(mStream, frames, time);
+}
+
+} // namespace android
diff --git a/services/audioflinger/StreamHalLocal.h b/services/audioflinger/StreamHalLocal.h
new file mode 100644
index 0000000..d8c30d3
--- /dev/null
+++ b/services/audioflinger/StreamHalLocal.h
@@ -0,0 +1,169 @@
+/*
+ * 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_STREAM_HAL_LOCAL_H
+#define ANDROID_HARDWARE_STREAM_HAL_LOCAL_H
+
+#include "StreamHalInterface.h"
+
+namespace android {
+
+class DeviceHalLocal;
+
+class StreamHalLocal : public virtual StreamHalInterface
+{
+ public:
+ // Return the sampling rate in Hz - eg. 44100.
+ virtual status_t getSampleRate(uint32_t *rate);
+
+ // Return size of input/output buffer in bytes for this stream - eg. 4800.
+ virtual status_t getBufferSize(size_t *size);
+
+ // Return the channel mask.
+ virtual status_t getChannelMask(audio_channel_mask_t *mask);
+
+ // Return the audio format - e.g. AUDIO_FORMAT_PCM_16_BIT.
+ virtual status_t getFormat(audio_format_t *format);
+
+ // Convenience method.
+ virtual status_t getAudioProperties(
+ uint32_t *sampleRate, audio_channel_mask_t *mask, audio_format_t *format);
+
+ // Set audio stream parameters.
+ virtual status_t setParameters(const String8& kvPairs);
+
+ // Get audio stream parameters.
+ virtual status_t getParameters(const String8& keys, String8 *values);
+
+ // Add or remove the effect on the stream.
+ virtual status_t addEffect(sp<EffectHalInterface> effect);
+ virtual status_t removeEffect(sp<EffectHalInterface> effect);
+
+ // Put the audio hardware input/output into standby mode.
+ virtual status_t standby();
+
+ virtual status_t dump(int fd);
+
+ protected:
+ // Subclasses can not be constructed directly by clients.
+ StreamHalLocal(audio_stream_t *stream, sp<DeviceHalLocal> device);
+
+ // The destructor automatically closes the stream.
+ virtual ~StreamHalLocal();
+
+ sp<DeviceHalLocal> mDevice;
+
+ private:
+ audio_stream_t *mStream;
+};
+
+class StreamOutHalLocal : public StreamOutHalInterface, public StreamHalLocal {
+ public:
+ // Return the frame size (number of bytes per sample) of a stream.
+ virtual status_t getFrameSize(size_t *size);
+
+ // Return the audio hardware driver estimated latency in milliseconds.
+ virtual status_t getLatency(uint32_t *latency);
+
+ // Use this method in situations where audio mixing is done in the hardware.
+ virtual status_t setVolume(float left, float right);
+
+ // Write audio buffer to driver.
+ virtual status_t write(const void *buffer, size_t bytes, size_t *written);
+
+ // Return the number of audio frames written by the audio dsp to DAC since
+ // the output has exited standby.
+ virtual status_t getRenderPosition(uint32_t *dspFrames);
+
+ // Get the local time at which the next write to the audio driver will be presented.
+ virtual status_t getNextWriteTimestamp(int64_t *timestamp);
+
+ // Set the callback for notifying completion of non-blocking write and drain.
+ virtual status_t setCallback(sp<StreamOutHalInterfaceCallback> callback);
+
+ // Returns whether pause and resume operations are supported.
+ virtual status_t supportsPauseAndResume(bool *supportsPause, bool *supportsResume);
+
+ // Notifies to the audio driver to resume playback following a pause.
+ virtual status_t pause();
+
+ // Notifies to the audio driver to resume playback following a pause.
+ virtual status_t resume();
+
+ // Returns whether drain operation is supported.
+ virtual status_t supportsDrain(bool *supportsDrain);
+
+ // Requests notification when data buffered by the driver/hardware has been played.
+ virtual status_t drain(audio_drain_type_t type);
+
+ // Notifies to the audio driver to flush the queued data.
+ virtual status_t flush();
+
+ // Return a recent count of the number of audio frames presented to an external observer.
+ virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp);
+
+ // FIXME: Remove after NBAIO is converted.
+ audio_stream_out_t *getStream() const { return mStream; }
+
+ private:
+ audio_stream_out_t *mStream;
+ wp<StreamOutHalInterfaceCallback> mCallback;
+
+ friend class DeviceHalLocal;
+
+ // Can not be constructed directly by clients.
+ StreamOutHalLocal(audio_stream_out_t *stream, sp<DeviceHalLocal> device);
+
+ virtual ~StreamOutHalLocal();
+
+ static int asyncCallback(stream_callback_event_t event, void *param, void *cookie);
+};
+
+class StreamInHalLocal : public StreamInHalInterface, public StreamHalLocal {
+ public:
+ // Return the frame size (number of bytes per sample) of a stream.
+ virtual status_t getFrameSize(size_t *size);
+
+ // Set the input gain for the audio driver.
+ virtual status_t setGain(float gain);
+
+ // Read audio buffer in from driver.
+ virtual status_t read(void *buffer, size_t bytes, size_t *read);
+
+ // Return the amount of input frames lost in the audio driver.
+ virtual status_t getInputFramesLost(uint32_t *framesLost);
+
+ // Return a recent count of the number of audio frames received and
+ // the clock time associated with that frame count.
+ virtual status_t getCapturePosition(int64_t *frames, int64_t *time);
+
+ // FIXME: Remove after NBAIO is converted.
+ audio_stream_in_t *getStream() const { return mStream; }
+
+ private:
+ audio_stream_in_t *mStream;
+
+ friend class DeviceHalLocal;
+
+ // Can not be constructed directly by clients.
+ StreamInHalLocal(audio_stream_in_t *stream, sp<DeviceHalLocal> device);
+
+ virtual ~StreamInHalLocal();
+};
+
+} // namespace android
+
+#endif // ANDROID_HARDWARE_STREAM_HAL_LOCAL_H
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 923fcf6..b07c914 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -73,6 +73,9 @@
#include "AutoPark.h"
+// FIXME: Remove after NBAIO is converted
+#include "StreamHalLocal.h"
+
// ----------------------------------------------------------------------------
// Note: the following macro is used for extremely verbose logging message. In
@@ -1847,7 +1850,8 @@
ALOGV(" preExit()");
// FIXME this is using hard-coded strings but in the future, this functionality will be
// converted to use audio HAL extensions required to support tunneling
- mOutput->stream->common.set_parameters(&mOutput->stream->common, "exiting=1");
+ status_t result = mOutput->stream->setParameters(String8("exiting=1"));
+ ALOGE_IF(result != OK, "Error when setting parameters on exit: %d", result);
}
// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
@@ -1969,7 +1973,12 @@
&& audio_has_proportional_frames(format) && sharedBuffer == 0) {
// this must match AudioTrack.cpp calculateMinFrameCount().
// TODO: Move to a common library
- uint32_t latencyMs = mOutput->stream->get_latency(mOutput->stream);
+ uint32_t latencyMs = 0;
+ lStatus = mOutput->stream->getLatency(&latencyMs);
+ if (lStatus != OK) {
+ ALOGE("Error when retrieving output stream latency: %d", lStatus);
+ goto Exit;
+ }
uint32_t minBufCount = latencyMs / ((1000 * mNormalFrameCount) / mSampleRate);
if (minBufCount < 2) {
minBufCount = 2;
@@ -2100,11 +2109,11 @@
}
uint32_t AudioFlinger::PlaybackThread::latency_l() const
{
- if (initCheck() == NO_ERROR) {
- return correctLatency_l(mOutput->stream->get_latency(mOutput->stream));
- } else {
- return 0;
+ uint32_t latency;
+ if (initCheck() == NO_ERROR && mOutput->stream->getLatency(&latency) == OK) {
+ return correctLatency_l(latency);
}
+ return 0;
}
void AudioFlinger::PlaybackThread::setMasterVolume(float value)
@@ -2269,14 +2278,11 @@
String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
{
Mutex::Autolock _l(mLock);
- if (initCheck() != NO_ERROR) {
- return String8();
+ String8 out_s8;
+ if (initCheck() == NO_ERROR && mOutput->stream->getParameters(keys, &out_s8) == OK) {
+ return out_s8;
}
-
- char *s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string());
- const String8 out_s8(s);
- free(s);
- return out_s8;
+ return String8();
}
void AudioFlinger::PlaybackThread::ioConfigChanged(audio_io_config_event event, pid_t pid) {
@@ -2305,21 +2311,18 @@
mAudioFlinger->ioConfigChanged(event, desc, pid);
}
-void AudioFlinger::PlaybackThread::writeCallback()
+void AudioFlinger::PlaybackThread::onWriteReady()
{
- ALOG_ASSERT(mCallbackThread != 0);
mCallbackThread->resetWriteBlocked();
}
-void AudioFlinger::PlaybackThread::drainCallback()
+void AudioFlinger::PlaybackThread::onDrainReady()
{
- ALOG_ASSERT(mCallbackThread != 0);
mCallbackThread->resetDraining();
}
-void AudioFlinger::PlaybackThread::errorCallback()
+void AudioFlinger::PlaybackThread::onError()
{
- ALOG_ASSERT(mCallbackThread != 0);
mCallbackThread->setAsyncError();
}
@@ -2343,30 +2346,6 @@
}
}
-// static
-int AudioFlinger::PlaybackThread::asyncCallback(stream_callback_event_t event,
- void *param __unused,
- void *cookie)
-{
- AudioFlinger::PlaybackThread *me = (AudioFlinger::PlaybackThread *)cookie;
- ALOGV("asyncCallback() event %d", event);
- switch (event) {
- case STREAM_CBK_EVENT_WRITE_READY:
- me->writeCallback();
- break;
- case STREAM_CBK_EVENT_DRAIN_READY:
- me->drainCallback();
- break;
- case STREAM_CBK_EVENT_ERROR:
- me->errorCallback();
- break;
- default:
- ALOGW("asyncCallback() unknown event %d", event);
- break;
- }
- return 0;
-}
-
void AudioFlinger::PlaybackThread::readOutputParameters_l()
{
// unfortunately we have no way of recovering from errors here, hence the LOG_ALWAYS_FATAL
@@ -2383,7 +2362,8 @@
mChannelCount = audio_channel_count_from_out_mask(mChannelMask);
// Get actual HAL format.
- mHALFormat = mOutput->stream->common.get_format(&mOutput->stream->common);
+ status_t result = mOutput->stream->getFormat(&mHALFormat);
+ LOG_ALWAYS_FATAL_IF(result != OK, "Error when retrieving output stream format: %d", result);
// Get format from the shim, which will be different than the HAL format
// if playing compressed audio over HDMI passthrough.
mFormat = mOutput->getFormat();
@@ -2396,17 +2376,17 @@
mFormat);
}
mFrameSize = mOutput->getFrameSize();
- mBufferSize = mOutput->stream->common.get_buffer_size(&mOutput->stream->common);
+ result = mOutput->stream->getBufferSize(&mBufferSize);
+ LOG_ALWAYS_FATAL_IF(result != OK,
+ "Error when retrieving output stream buffer size: %d", result);
mFrameCount = mBufferSize / mFrameSize;
if (mFrameCount & 15) {
ALOGW("HAL output buffer size is %zu frames but AudioMixer requires multiples of 16 frames",
mFrameCount);
}
- if ((mOutput->flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING) &&
- (mOutput->stream->set_callback != NULL)) {
- if (mOutput->stream->set_callback(mOutput->stream,
- AudioFlinger::PlaybackThread::asyncCallback, this) == 0) {
+ if (mOutput->flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING) {
+ if (mOutput->stream->setCallback(this) == OK) {
mUseAsyncWrite = true;
mCallbackThread = new AudioFlinger::AsyncCallbackThread(this);
}
@@ -2414,14 +2394,15 @@
mHwSupportsPause = false;
if (mOutput->flags & AUDIO_OUTPUT_FLAG_DIRECT) {
- if (mOutput->stream->pause != NULL) {
- if (mOutput->stream->resume != NULL) {
+ bool supportsPause = false, supportsResume = false;
+ if (mOutput->stream->supportsPauseAndResume(&supportsPause, &supportsResume) == OK) {
+ if (supportsPause && supportsResume) {
mHwSupportsPause = true;
- } else {
+ } else if (supportsPause) {
ALOGW("direct output implements pause but not resume");
+ } else if (supportsResume) {
+ ALOGW("direct output implements resume but not pause");
}
- } else if (mOutput->stream->resume != NULL) {
- ALOGW("direct output implements resume but not pause");
}
}
if (!mHwSupportsPause && mOutput->flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) {
@@ -2611,12 +2592,12 @@
}
// this method must always be called either with ThreadBase mLock held or inside the thread loop
-audio_stream_t* AudioFlinger::PlaybackThread::stream() const
+sp<StreamHalInterface> AudioFlinger::PlaybackThread::stream() const
{
if (mOutput == NULL) {
return NULL;
}
- return &mOutput->stream->common;
+ return mOutput->stream;
}
uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs() const
@@ -2754,7 +2735,8 @@
void AudioFlinger::PlaybackThread::threadLoop_drain()
{
- if (mOutput->stream->drain) {
+ bool supportsDrain = false;
+ if (mOutput->stream->supportsDrain(&supportsDrain) == OK && supportsDrain) {
ALOGV("draining %s", (mMixerStatus == MIXER_DRAIN_TRACK) ? "early" : "full");
if (mUseAsyncWrite) {
ALOGW_IF(mDrainSequence & 1, "threadLoop_drain(): out of sequence drain request");
@@ -2762,9 +2744,10 @@
ALOG_ASSERT(mCallbackThread != 0);
mCallbackThread->setDraining(mDrainSequence);
}
- mOutput->stream->drain(mOutput->stream,
+ status_t result = mOutput->stream->drain(
(mMixerStatus == MIXER_DRAIN_TRACK) ? AUDIO_DRAIN_EARLY_NOTIFY
: AUDIO_DRAIN_ALL);
+ ALOGE_IF(result != OK, "Error when draining stream: %d", result);
}
}
@@ -3449,11 +3432,9 @@
}
return status;
}
- if ((mType == OFFLOAD || mType == DIRECT)
- && mOutput != NULL && mOutput->stream->get_presentation_position) {
+ if ((mType == OFFLOAD || mType == DIRECT) && mOutput != NULL) {
uint64_t position64;
- int ret = mOutput->getPresentationPosition(&position64, ×tamp.mTime);
- if (ret == 0) {
+ if (mOutput->getPresentationPosition(&position64, ×tamp.mTime) == OK) {
timestamp.mPosition = (uint32_t)position64;
return NO_ERROR;
}
@@ -3540,8 +3521,7 @@
AudioParameter param = AudioParameter(String8(address));
free(address);
param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)type);
- status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
- param.toString().string());
+ status = mOutput->stream->setParameters(param.toString());
*handle = AUDIO_PATCH_HANDLE_NONE;
}
if (configChanged) {
@@ -3577,8 +3557,7 @@
} else {
AudioParameter param;
param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0);
- status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
- param.toString().string());
+ status = mOutput->stream->setParameters(param.toString());
}
return status;
}
@@ -3630,7 +3609,8 @@
return;
}
// create an NBAIO sink for the HAL output stream, and negotiate
- mOutputSink = new AudioStreamOutSink(output->stream);
+ mOutputSink = new AudioStreamOutSink(
+ static_cast<StreamOutHalLocal*>(output->stream.get())->getStream());
size_t numCounterOffers = 0;
const NBAIO_Format offers[1] = {Format_from_SR_C(mSampleRate, mChannelCount, mFormat)};
#if !LOG_NDEBUG
@@ -4144,8 +4124,11 @@
// We have consumed all the buffers of this track.
// This would be incomplete if we auto-paused on underrun
{
- size_t audioHALFrames =
- (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
+ uint32_t latency = 0;
+ status_t result = mOutput->stream->getLatency(&latency);
+ ALOGE_IF(result != OK,
+ "Error when retrieving output stream latency: %d", result);
+ size_t audioHALFrames = (latency * mSampleRate) / 1000;
int64_t framesWritten = mBytesWritten / mFrameSize;
if (!(mStandby || track->presentationComplete(framesWritten, audioHALFrames))) {
// track stays in active list until presentation is complete
@@ -4686,14 +4669,12 @@
}
if (status == NO_ERROR) {
- status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
- keyValuePair.string());
+ status = mOutput->stream->setParameters(keyValuePair);
if (!mStandby && status == INVALID_OPERATION) {
mOutput->standby();
mStandby = true;
mBytesWritten = 0;
- status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
- keyValuePair.string());
+ status = mOutput->stream->setParameters(keyValuePair);
}
if (status == NO_ERROR && reconfig) {
readOutputParameters_l();
@@ -4834,9 +4815,8 @@
left = (float)vl / (1 << 24);
right = (float)vr / (1 << 24);
}
- if (mOutput->stream->set_volume) {
- mOutput->stream->set_volume(mOutput->stream, left, right);
- }
+ status_t result = mOutput->stream->setVolume(left, right);
+ ALOGE_IF(result != OK, "Error when setting output stream volume: %d", result);
}
}
}
@@ -5046,13 +5026,15 @@
// if resume is received before pause is executed.
if (mHwSupportsPause && !mStandby &&
(doHwPause || (mFlushPending && !mHwPaused && (count != 0)))) {
- mOutput->stream->pause(mOutput->stream);
+ status_t result = mOutput->stream->pause();
+ ALOGE_IF(result != OK, "Error when pausing output stream: %d", result);
}
if (mFlushPending) {
flushHw_l();
}
if (mHwSupportsPause && !mStandby && doHwResume) {
- mOutput->stream->resume(mOutput->stream);
+ status_t result = mOutput->stream->resume();
+ ALOGE_IF(result != OK, "Error when resuming output stream: %d", result);
}
// remove all the tracks that need to be...
removeTracks_l(*tracksToRemove);
@@ -5190,14 +5172,12 @@
}
}
if (status == NO_ERROR) {
- status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
- keyValuePair.string());
+ status = mOutput->stream->setParameters(keyValuePair);
if (!mStandby && status == INVALID_OPERATION) {
mOutput->standby();
mStandby = true;
mBytesWritten = 0;
- status = mOutput->stream->common.set_parameters(&mOutput->stream->common,
- keyValuePair.string());
+ status = mOutput->stream->setParameters(keyValuePair);
}
if (status == NO_ERROR && reconfig) {
readOutputParameters_l();
@@ -5584,8 +5564,11 @@
// Drain has completed or we are in standby, signal presentation complete
if (!(mDrainSequence & 1) || !last || mStandby) {
track->mState = TrackBase::STOPPED;
- size_t audioHALFrames =
- (mOutput->stream->get_latency(mOutput->stream)*mSampleRate) / 1000;
+ uint32_t latency = 0;
+ status_t result = mOutput->stream->getLatency(&latency);
+ ALOGE_IF(result != OK,
+ "Error when retrieving output stream latency: %d", result);
+ size_t audioHALFrames = (latency * mSampleRate) / 1000;
int64_t framesWritten =
mBytesWritten / mOutput->getFrameSize();
track->presentationComplete(framesWritten, audioHALFrames);
@@ -5597,16 +5580,15 @@
// fill a buffer, then remove it from active list.
if (--(track->mRetryCount) <= 0) {
bool running = false;
- if (mOutput->stream->get_presentation_position != nullptr) {
- uint64_t position = 0;
- struct timespec unused;
- // The running check restarts the retry counter at least once.
- int ret = mOutput->stream->get_presentation_position(
- mOutput->stream, &position, &unused);
- if (ret == NO_ERROR && position != mOffloadUnderrunPosition) {
- running = true;
- mOffloadUnderrunPosition = position;
- }
+ uint64_t position = 0;
+ struct timespec unused;
+ // The running check restarts the retry counter at least once.
+ status_t ret = mOutput->stream->getPresentationPosition(&position, &unused);
+ if (ret == NO_ERROR && position != mOffloadUnderrunPosition) {
+ running = true;
+ mOffloadUnderrunPosition = position;
+ }
+ if (ret == NO_ERROR) {
ALOGVV("underrun counter, running(%d): %lld vs %lld", running,
(long long)position, (long long)mOffloadUnderrunPosition);
}
@@ -5634,13 +5616,15 @@
// before flush and then resume HW. This can happen in case of pause/flush/resume
// if resume is received before pause is executed.
if (!mStandby && (doHwPause || (mFlushPending && !mHwPaused && (count != 0)))) {
- mOutput->stream->pause(mOutput->stream);
+ status_t result = mOutput->stream->pause();
+ ALOGE_IF(result != OK, "Error when pausing output stream: %d", result);
}
if (mFlushPending) {
flushHw_l();
}
if (!mStandby && doHwResume) {
- mOutput->stream->resume(mOutput->stream);
+ status_t result = mOutput->stream->resume();
+ ALOGE_IF(result != OK, "Error when resuming output stream: %d", result);
}
// remove all the tracks that need to be...
@@ -5915,7 +5899,8 @@
readInputParameters_l();
// create an NBAIO source for the HAL input stream, and negotiate
- mInputSource = new AudioStreamInSource(input->stream);
+ mInputSource = new AudioStreamInSource(
+ static_cast<StreamInHalLocal*>(input->stream.get())->getStream());
size_t numCounterOffers = 0;
const NBAIO_Format offers[1] = {Format_from_SR_C(mSampleRate, mChannelCount, mFormat)};
#if !LOG_NDEBUG
@@ -6304,11 +6289,12 @@
// otherwise use the HAL / AudioStreamIn directly
} else {
ATRACE_BEGIN("read");
- ssize_t bytesRead = mInput->stream->read(mInput->stream,
- (uint8_t*)mRsmpInBuffer + rear * mFrameSize, mBufferSize);
+ size_t bytesRead;
+ status_t result = mInput->stream->read(
+ (uint8_t*)mRsmpInBuffer + rear * mFrameSize, mBufferSize, &bytesRead);
ATRACE_END();
- if (bytesRead < 0) {
- framesRead = bytesRead;
+ if (result < 0) {
+ framesRead = result;
} else {
framesRead = bytesRead / mFrameSize;
}
@@ -6320,10 +6306,9 @@
mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = systemTime();
// Update server timestamp with kernel stats
- if (mInput->stream->get_capture_position != nullptr
- && mPipeSource.get() == nullptr /* don't obtain for FastCapture, could block */) {
+ if (mPipeSource.get() == nullptr /* don't obtain for FastCapture, could block */) {
int64_t position, time;
- int ret = mInput->stream->get_capture_position(mInput->stream, &position, &time);
+ int ret = mInput->stream->getCapturePosition(&position, &time);
if (ret == NO_ERROR) {
mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = position;
mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] = time;
@@ -6532,7 +6517,8 @@
sq->end(false /*didModify*/);
}
}
- mInput->stream->common.standby(&mInput->stream->common);
+ status_t result = mInput->stream->standby();
+ ALOGE_IF(result != OK, "Error when putting input stream into standby: %d", result);
// If going into standby, flush the pipe source.
if (mPipeSource.get() != nullptr) {
@@ -7386,22 +7372,22 @@
}
if (status == NO_ERROR) {
- status = mInput->stream->common.set_parameters(&mInput->stream->common,
- keyValuePair.string());
+ status = mInput->stream->setParameters(keyValuePair);
if (status == INVALID_OPERATION) {
inputStandBy();
- status = mInput->stream->common.set_parameters(&mInput->stream->common,
- keyValuePair.string());
+ status = mInput->stream->setParameters(keyValuePair);
}
if (reconfig) {
- if (status == BAD_VALUE &&
- audio_is_linear_pcm(mInput->stream->common.get_format(&mInput->stream->common)) &&
- audio_is_linear_pcm(reqFormat) &&
- (mInput->stream->common.get_sample_rate(&mInput->stream->common)
- <= (AUDIO_RESAMPLER_DOWN_RATIO_MAX * samplingRate)) &&
- audio_channel_count_from_in_mask(
- mInput->stream->common.get_channels(&mInput->stream->common)) <= FCC_8) {
- status = NO_ERROR;
+ if (status == BAD_VALUE) {
+ uint32_t sRate;
+ audio_channel_mask_t channelMask;
+ audio_format_t format;
+ if (mInput->stream->getAudioProperties(&sRate, &channelMask, &format) == OK &&
+ audio_is_linear_pcm(format) && audio_is_linear_pcm(reqFormat) &&
+ sRate <= (AUDIO_RESAMPLER_DOWN_RATIO_MAX * samplingRate) &&
+ audio_channel_count_from_in_mask(channelMask) <= FCC_8) {
+ status = NO_ERROR;
+ }
}
if (status == NO_ERROR) {
readInputParameters_l();
@@ -7416,14 +7402,13 @@
String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
{
Mutex::Autolock _l(mLock);
- if (initCheck() != NO_ERROR) {
- return String8();
+ if (initCheck() == NO_ERROR) {
+ String8 out_s8;
+ if (mInput->stream->getParameters(keys, &out_s8) == OK) {
+ return out_s8;
+ }
}
-
- char *s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string());
- const String8 out_s8(s);
- free(s);
- return out_s8;
+ return String8();
}
void AudioFlinger::RecordThread::ioConfigChanged(audio_io_config_event event, pid_t pid) {
@@ -7452,19 +7437,16 @@
void AudioFlinger::RecordThread::readInputParameters_l()
{
- mSampleRate = mInput->stream->common.get_sample_rate(&mInput->stream->common);
- mChannelMask = mInput->stream->common.get_channels(&mInput->stream->common);
+ status_t result = mInput->stream->getAudioProperties(&mSampleRate, &mChannelMask, &mHALFormat);
+ LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving audio properties from HAL: %d", result);
mChannelCount = audio_channel_count_from_in_mask(mChannelMask);
- if (mChannelCount > FCC_8) {
- ALOGE("HAL channel count %d > %d", mChannelCount, FCC_8);
- }
- mHALFormat = mInput->stream->common.get_format(&mInput->stream->common);
+ LOG_ALWAYS_FATAL_IF(mChannelCount > FCC_8, "HAL channel count %d > %d", mChannelCount, FCC_8);
mFormat = mHALFormat;
- if (!audio_is_linear_pcm(mFormat)) {
- ALOGE("HAL format %#x is not linear pcm", mFormat);
- }
- mFrameSize = audio_stream_in_frame_size(mInput->stream);
- mBufferSize = mInput->stream->common.get_buffer_size(&mInput->stream->common);
+ LOG_ALWAYS_FATAL_IF(!audio_is_linear_pcm(mFormat), "HAL format %#x is not linear pcm", mFormat);
+ result = mInput->stream->getFrameSize(&mFrameSize);
+ LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving frame size from HAL: %d", result);
+ result = mInput->stream->getBufferSize(&mBufferSize);
+ LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving buffer size from HAL: %d", result);
mFrameCount = mBufferSize / mFrameSize;
// This is the formula for calculating the temporary buffer size.
// With 7 HAL buffers, we can guarantee ability to down-sample the input by ratio of 6:1 to
@@ -7498,11 +7480,11 @@
uint32_t AudioFlinger::RecordThread::getInputFramesLost()
{
Mutex::Autolock _l(mLock);
- if (initCheck() != NO_ERROR) {
- return 0;
+ uint32_t result;
+ if (initCheck() == NO_ERROR && mInput->stream->getInputFramesLost(&result) == OK) {
+ return result;
}
-
- return mInput->stream->get_input_frames_lost(mInput->stream);
+ return 0;
}
// hasAudioSession_l() must be called with ThreadBase::mLock held
@@ -7549,12 +7531,12 @@
}
// this method must always be called either with ThreadBase mLock held or inside the thread loop
-audio_stream_t* AudioFlinger::RecordThread::stream() const
+sp<StreamHalInterface> AudioFlinger::RecordThread::stream() const
{
if (mInput == NULL) {
return NULL;
}
- return &mInput->stream->common;
+ return mInput->stream;
}
status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
@@ -7646,8 +7628,7 @@
(int)patch->sources[0].ext.device.type);
param.addInt(String8(AUDIO_PARAMETER_STREAM_INPUT_SOURCE),
(int)patch->sinks[0].ext.mix.usecase.source);
- status = mInput->stream->common.set_parameters(&mInput->stream->common,
- param.toString().string());
+ status = mInput->stream->setParameters(param.toString());
*handle = AUDIO_PATCH_HANDLE_NONE;
}
@@ -7671,8 +7652,7 @@
} else {
AudioParameter param;
param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0);
- status = mInput->stream->common.set_parameters(&mInput->stream->common,
- param.toString().string());
+ status = mInput->stream->setParameters(param.toString());
}
return status;
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 15536f1..255fa8f 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -286,7 +286,7 @@
audio_devices_t outDevice() const { return mOutDevice; }
audio_devices_t inDevice() const { return mInDevice; }
- virtual audio_stream_t* stream() const = 0;
+ virtual sp<StreamHalInterface> stream() const = 0;
sp<EffectHandle> createEffect_l(
const sp<AudioFlinger::Client>& client,
@@ -484,7 +484,7 @@
};
// --- PlaybackThread ---
-class PlaybackThread : public ThreadBase {
+class PlaybackThread : public ThreadBase, public StreamOutHalInterfaceCallback {
public:
#include "PlaybackTracks.h"
@@ -539,13 +539,13 @@
virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove) = 0;
void removeTracks_l(const Vector< sp<Track> >& tracksToRemove);
- void writeCallback();
- void resetWriteBlocked(uint32_t sequence);
- void drainCallback();
- void resetDraining(uint32_t sequence);
- void errorCallback();
+ // StreamOutHalInterfaceCallback implementation
+ virtual void onWriteReady();
+ virtual void onDrainReady();
+ virtual void onError();
- static int asyncCallback(stream_callback_event_t event, void *param, void *cookie);
+ void resetWriteBlocked(uint32_t sequence);
+ void resetDraining(uint32_t sequence);
virtual bool waitingAsyncCallback();
virtual bool waitingAsyncCallback_l();
@@ -591,7 +591,7 @@
AudioStreamOut* getOutput() const;
AudioStreamOut* clearOutput();
- virtual audio_stream_t* stream() const;
+ virtual sp<StreamHalInterface> stream() const;
// a very large number of suspend() will eventually wraparound, but unlikely
void suspend() { (void) android_atomic_inc(&mSuspended); }
@@ -1297,7 +1297,7 @@
void dump(int fd, const Vector<String16>& args);
AudioStreamIn* clearInput();
- virtual audio_stream_t* stream() const;
+ virtual sp<StreamHalInterface> stream() const;
virtual bool checkForNewParameter_l(const String8& keyValuePair,