From 08dd93847f31a7d9efc3290f518af6dcedd37d66 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Thu, 25 Jun 2015 11:48:20 -0700 Subject: audio policy: fix several device descriptor issues. - checkOutputsForDevice() should only clear device descriptor attributes if the device is digital. - checkInputsForDevice() did not clear device descriptor attributes at all. - AudioPort::clearCapabilities() and importAudioPort() should not manage gains as these are device specific. - importAudioPort() should load a default port config. Bug: 21990937. Change-Id: Ida762ed8f9baaabae392cb4291eff1a8d3009751 --- .../common/managerdefinitions/include/AudioPort.h | 2 +- .../common/managerdefinitions/include/DeviceDescriptor.h | 1 + .../common/managerdefinitions/src/AudioPort.cpp | 16 ---------------- .../common/managerdefinitions/src/DeviceDescriptor.cpp | 7 +++++++ .../audiopolicy/managerdefault/AudioPolicyManager.cpp | 14 +++++++++++--- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h index 82e2c43..4fdf5b4 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h @@ -42,7 +42,7 @@ public: virtual void toAudioPort(struct audio_port *port) const; - void importAudioPort(const sp port); + virtual void importAudioPort(const sp port); void clearCapabilities(); void loadSamplingRates(char *name); diff --git a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h index d1a2f4f..c42ece6 100644 --- a/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/DeviceDescriptor.h @@ -44,6 +44,7 @@ public: virtual void attach(const sp& module); virtual void loadGains(cnode *root); virtual void toAudioPort(struct audio_port *port) const; + virtual void importAudioPort(const sp port); audio_port_handle_t getId() const; audio_devices_t type() const { return mDeviceType; } diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp index afcd073..4e24f19 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp @@ -151,28 +151,12 @@ void AudioPort::importAudioPort(const sp port) { } } } - for (size_t k = 0 ; k < port->mGains.size() ; k++) { - sp gain = port->mGains.itemAt(k); - if (gain != 0) { - bool hasGain = false; - for (size_t l = 0 ; l < mGains.size() ; l++) { - if (gain == mGains.itemAt(l)) { - hasGain = true; - break; - } - } - if (!hasGain) { // never import a gain twice - mGains.add(gain); - } - } - } } void AudioPort::clearCapabilities() { mChannelMasks.clear(); mFormats.clear(); mSamplingRates.clear(); - mGains.clear(); } void AudioPort::loadSamplingRates(char *name) diff --git a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp index 797077a..1f1fca3 100644 --- a/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/DeviceDescriptor.cpp @@ -301,6 +301,13 @@ void DeviceDescriptor::toAudioPort(struct audio_port *port) const strncpy(port->ext.device.address, mAddress.string(), AUDIO_DEVICE_MAX_ADDRESS_LEN); } +void DeviceDescriptor::importAudioPort(const sp port) { + AudioPort::importAudioPort(port); + mSamplingRate = port->pickSamplingRate(); + mFormat = port->pickFormat(); + mChannelMask = port->pickChannelMask(); +} + status_t DeviceDescriptor::dump(int fd, int spaces, int index) const { const size_t SIZE = 256; diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index a0de34d..ee25b71 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -3140,8 +3140,11 @@ status_t AudioPolicyManager::checkOutputsForDevice(const sp de { audio_devices_t device = devDesc->type(); sp desc; - // erase all current sample rates, formats and channel masks - devDesc->clearCapabilities(); + + if (audio_device_is_digital(device)) { + // erase all current sample rates, formats and channel masks + devDesc->clearCapabilities(); + } if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { // first list already open outputs that can be routed to this device @@ -3433,8 +3436,13 @@ status_t AudioPolicyManager::checkInputsForDevice(const sp dev const String8 address) { audio_devices_t device = devDesc->type(); - sp desc; + + if (audio_device_is_digital(device)) { + // erase all current sample rates, formats and channel masks + devDesc->clearCapabilities(); + } + if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) { // first list already open inputs that can be routed to this device for (size_t input_index = 0; input_index < mInputs.size(); input_index++) { -- cgit v1.1 From 16538d342e49e426a5825ecbcf92b9adb17ed25e Mon Sep 17 00:00:00 2001 From: Phil Burk Date: Mon, 6 Jul 2015 16:24:14 -0700 Subject: AudioFlinger: reset frame position on standby The HAL does not reset the frame position on standby(). But applications expect the frame position to be reset. So we subtract the position at standby from the current position. Bug: 21724210 Bug: 21930805 Change-Id: I0c4520ba1c6c06a580f45f6bafc8cf1d56969f07 Signed-off-by: Phil Burk --- services/audioflinger/AudioStreamOut.cpp | 85 ++++++++++++++++++++++++++++---- services/audioflinger/AudioStreamOut.h | 13 ++++- services/audioflinger/SpdifStreamOut.cpp | 47 ------------------ services/audioflinger/SpdifStreamOut.h | 9 ---- 4 files changed, 87 insertions(+), 67 deletions(-) diff --git a/services/audioflinger/AudioStreamOut.cpp b/services/audioflinger/AudioStreamOut.cpp index e6d8f09..f953cc8 100644 --- a/services/audioflinger/AudioStreamOut.cpp +++ b/services/audioflinger/AudioStreamOut.cpp @@ -27,25 +27,59 @@ namespace android { // ---------------------------------------------------------------------------- - AudioStreamOut::AudioStreamOut(AudioHwDevice *dev, audio_output_flags_t flags) : audioHwDev(dev) , stream(NULL) , flags(flags) + , mFramesWritten(0) + , mFramesWrittenAtStandby(0) + , mRenderPosition(0) + , mRateMultiplier(1) + , mHalFormatIsLinearPcm(false) + , mHalFrameSize(0) { } -audio_hw_device_t* AudioStreamOut::hwDev() const +audio_hw_device_t *AudioStreamOut::hwDev() const { return audioHwDev->hwDevice(); } -status_t AudioStreamOut::getRenderPosition(uint32_t *frames) +status_t AudioStreamOut::getRenderPosition(uint64_t *frames) { if (stream == NULL) { return NO_INIT; } - return stream->get_render_position(stream, frames); + + uint32_t halPosition = 0; + status_t status = stream->get_render_position(stream, &halPosition); + if (status != NO_ERROR) { + return status; + } + + // Maintain a 64-bit render position using the 32-bit result from the HAL. + // This delta calculation relies on the arithmetic overflow behavior + // of integers. For example (100 - 0xFFFFFFF0) = 116. + uint32_t truncatedPosition = (uint32_t)mRenderPosition; + int32_t deltaHalPosition = (int32_t)(halPosition - truncatedPosition); + if (deltaHalPosition > 0) { + mRenderPosition += deltaHalPosition; + } + // Scale from HAL sample rate to application rate. + *frames = mRenderPosition / mRateMultiplier; + + return status; +} + +// return bottom 32-bits of the render position +status_t AudioStreamOut::getRenderPosition(uint32_t *frames) +{ + uint64_t position64 = 0; + status_t status = getRenderPosition(&position64); + if (status == NO_ERROR) { + *frames = (uint32_t)position64; + } + return status; } status_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) @@ -53,7 +87,26 @@ status_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timesp if (stream == NULL) { return NO_INIT; } - return stream->get_presentation_position(stream, frames, timestamp); + + uint64_t halPosition = 0; + status_t status = stream->get_presentation_position(stream, &halPosition, timestamp); + if (status != NO_ERROR) { + return status; + } + + // Adjust for standby using HAL rate frames. + // Only apply this correction if the HAL is getting PCM frames. + if (mHalFormatIsLinearPcm) { + uint64_t adjustedPosition = (halPosition <= mFramesWrittenAtStandby) ? + 0 : (halPosition - mFramesWrittenAtStandby); + // Scale from HAL sample rate to application rate. + *frames = adjustedPosition / mRateMultiplier; + } else { + // For offloaded MP3 and other compressed formats. + *frames = halPosition; + } + + return status; } status_t AudioStreamOut::open( @@ -62,7 +115,7 @@ status_t AudioStreamOut::open( struct audio_config *config, const char *address) { - audio_stream_out_t* outStream; + audio_stream_out_t *outStream; int status = hwDev()->open_output_stream( hwDev(), handle, @@ -82,6 +135,9 @@ status_t AudioStreamOut::open( if (status == NO_ERROR) { stream = outStream; + mHalFormatIsLinearPcm = audio_is_linear_pcm(config->format); + ALOGI("AudioStreamOut::open(), mHalFormatIsLinearPcm = %d", (int)mHalFormatIsLinearPcm); + mHalFrameSize = audio_stream_out_frame_size(stream); } return status; @@ -89,13 +145,15 @@ status_t AudioStreamOut::open( size_t AudioStreamOut::getFrameSize() { - ALOG_ASSERT(stream != NULL); - return audio_stream_out_frame_size(stream); + return mHalFrameSize; } int AudioStreamOut::flush() { ALOG_ASSERT(stream != NULL); + mRenderPosition = 0; + mFramesWritten = 0; + mFramesWrittenAtStandby = 0; if (stream->flush != NULL) { return stream->flush(stream); } @@ -105,13 +163,20 @@ int AudioStreamOut::flush() int AudioStreamOut::standby() { ALOG_ASSERT(stream != NULL); + mRenderPosition = 0; + mFramesWrittenAtStandby = mFramesWritten; + ALOGI("AudioStreamOut::standby(), mFramesWrittenAtStandby = %llu", mFramesWrittenAtStandby); return stream->common.standby(&stream->common); } -ssize_t AudioStreamOut::write(const void* buffer, size_t bytes) +ssize_t AudioStreamOut::write(const void *buffer, size_t numBytes) { ALOG_ASSERT(stream != NULL); - return stream->write(stream, buffer, bytes); + ssize_t bytesWritten = stream->write(stream, buffer, numBytes); + if (bytesWritten > 0 && mHalFrameSize > 0) { + mFramesWritten += bytesWritten / mHalFrameSize; + } + return bytesWritten; } } // namespace android diff --git a/services/audioflinger/AudioStreamOut.h b/services/audioflinger/AudioStreamOut.h index e91ca9c..761e771 100644 --- a/services/audioflinger/AudioStreamOut.h +++ b/services/audioflinger/AudioStreamOut.h @@ -53,7 +53,10 @@ public: virtual ~AudioStreamOut() { } - virtual status_t getRenderPosition(uint32_t *frames); + // Get the bottom 32-bits of the 64-bit render position. + status_t getRenderPosition(uint32_t *frames); + + virtual status_t getRenderPosition(uint64_t *frames); virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp); @@ -76,6 +79,14 @@ public: virtual status_t flush(); virtual status_t standby(); + +protected: + uint64_t mFramesWritten; // reset by flush + uint64_t mFramesWrittenAtStandby; + uint64_t mRenderPosition; // reset by flush or standby + int mRateMultiplier; + bool mHalFormatIsLinearPcm; + size_t mHalFrameSize; }; } // namespace android diff --git a/services/audioflinger/SpdifStreamOut.cpp b/services/audioflinger/SpdifStreamOut.cpp index ac637ef..6af7bce 100644 --- a/services/audioflinger/SpdifStreamOut.cpp +++ b/services/audioflinger/SpdifStreamOut.cpp @@ -36,10 +36,7 @@ SpdifStreamOut::SpdifStreamOut(AudioHwDevice *dev, audio_output_flags_t flags, audio_format_t format) : AudioStreamOut(dev,flags) - , mRateMultiplier(1) , mSpdifEncoder(this, format) - , mRenderPositionHal(0) - , mPreviousHalPosition32(0) { } @@ -97,62 +94,18 @@ status_t SpdifStreamOut::open( return status; } -// Account for possibly higher sample rate. -status_t SpdifStreamOut::getRenderPosition(uint32_t *frames) -{ - uint32_t halPosition = 0; - status_t status = AudioStreamOut::getRenderPosition(&halPosition); - if (status != NO_ERROR) { - return status; - } - - // Accumulate a 64-bit position so that we wrap at the right place. - if (mRateMultiplier != 1) { - // Maintain a 64-bit render position. - int32_t deltaHalPosition = (int32_t)(halPosition - mPreviousHalPosition32); - mPreviousHalPosition32 = halPosition; - mRenderPositionHal += deltaHalPosition; - - // Scale from device sample rate to application rate. - uint64_t renderPositionApp = mRenderPositionHal / mRateMultiplier; - ALOGV("SpdifStreamOut::getRenderPosition() " - "renderPositionAppRate = %llu = %llu / %u\n", - renderPositionApp, mRenderPositionHal, mRateMultiplier); - - *frames = (uint32_t)renderPositionApp; - } else { - *frames = halPosition; - } - return status; -} - int SpdifStreamOut::flush() { mSpdifEncoder.reset(); - mRenderPositionHal = 0; - mPreviousHalPosition32 = 0; return AudioStreamOut::flush(); } int SpdifStreamOut::standby() { mSpdifEncoder.reset(); - mRenderPositionHal = 0; - mPreviousHalPosition32 = 0; return AudioStreamOut::standby(); } -// Account for possibly higher sample rate. -// This is much easier when all the values are 64-bit. -status_t SpdifStreamOut::getPresentationPosition(uint64_t *frames, - struct timespec *timestamp) -{ - uint64_t halFrames = 0; - status_t status = AudioStreamOut::getPresentationPosition(&halFrames, timestamp); - *frames = halFrames / mRateMultiplier; - return status; -} - size_t SpdifStreamOut::getFrameSize() { return sizeof(int8_t); diff --git a/services/audioflinger/SpdifStreamOut.h b/services/audioflinger/SpdifStreamOut.h index d81c064..a61a7bd 100644 --- a/services/audioflinger/SpdifStreamOut.h +++ b/services/audioflinger/SpdifStreamOut.h @@ -49,10 +49,6 @@ public: struct audio_config *config, const char *address); - virtual status_t getRenderPosition(uint32_t *frames); - - virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp); - /** * Write audio buffer to driver. Returns number of bytes written, or a * negative status_t. If at least one frame was written successfully prior to the error, @@ -92,13 +88,8 @@ private: SpdifStreamOut * const mSpdifStreamOut; }; - int mRateMultiplier; MySPDIFEncoder mSpdifEncoder; - // Used to implement getRenderPosition() - int64_t mRenderPositionHal; - uint32_t mPreviousHalPosition32; - ssize_t writeDataBurst(const void* data, size_t bytes); ssize_t writeInternal(const void* buffer, size_t bytes); -- cgit v1.1