summaryrefslogtreecommitdiffstats
path: root/services/audioflinger
diff options
context:
space:
mode:
Diffstat (limited to 'services/audioflinger')
-rw-r--r--services/audioflinger/Android.mk11
-rw-r--r--services/audioflinger/AudioMixer.cpp3
-rw-r--r--services/audioflinger/AudioResamplerQTI.cpp21
-rw-r--r--services/audioflinger/AudioResamplerQTI.h2
-rw-r--r--services/audioflinger/Effects.cpp29
-rw-r--r--services/audioflinger/FastCapture.cpp1
-rw-r--r--services/audioflinger/FastCaptureDumpState.cpp2
-rw-r--r--services/audioflinger/FastMixer.cpp18
-rw-r--r--services/audioflinger/ServiceUtilities.cpp8
-rw-r--r--services/audioflinger/ServiceUtilities.h1
-rw-r--r--services/audioflinger/Threads.cpp52
-rw-r--r--services/audioflinger/Threads.h4
12 files changed, 119 insertions, 33 deletions
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 0dd2af6..8ea26d3 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -160,12 +160,19 @@ LOCAL_SHARED_LIBRARIES := \
libaudioutils
#QTI Resampler
-ifeq ($(call is-vendor-board-platform,QCOM), true)
-ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)), true)
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)),true)
+ifdef TARGET_2ND_ARCH
LOCAL_SRC_FILES_$(TARGET_2ND_ARCH) += AudioResamplerQTI.cpp.arm
LOCAL_C_INCLUDES_$(TARGET_2ND_ARCH) += $(TARGET_OUT_HEADERS)/mm-audio/audio-src
LOCAL_SHARED_LIBRARIES_$(TARGET_2ND_ARCH) += libqct_resampler
LOCAL_CFLAGS_$(TARGET_2ND_ARCH) += -DQTI_RESAMPLER
+else
+LOCAL_SRC_FILES += AudioResamplerQTI.cpp.arm
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audio-src
+LOCAL_SHARED_LIBRARIES += libqct_resampler
+LOCAL_CFLAGS += -DQTI_RESAMPLER
+endif
endif
endif
#QTI Resampler
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 806eaf1..bb9d4e5 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -781,7 +781,8 @@ bool AudioMixer::track_t::setResampler(uint32_t trackSampleRate, uint32_t devSam
#ifdef QTI_RESAMPLER
if ((trackSampleRate <= QTI_RESAMPLER_MAX_SAMPLERATE) &&
(trackSampleRate > devSampleRate * 2) &&
- ((devSampleRate == 48000)||(devSampleRate == 44100))) {
+ ((devSampleRate == 48000)||(devSampleRate == 44100)) &&
+ (resamplerChannelCount <= 2)) {
quality = AudioResampler::QTI_QUALITY;
}
#endif
diff --git a/services/audioflinger/AudioResamplerQTI.cpp b/services/audioflinger/AudioResamplerQTI.cpp
index 44b741e..0d57e09 100644
--- a/services/audioflinger/AudioResamplerQTI.cpp
+++ b/services/audioflinger/AudioResamplerQTI.cpp
@@ -51,8 +51,9 @@ size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount,
{
int16_t vl = mVolume[0];
int16_t vr = mVolume[1];
- int16_t *pBuf;
+ int32_t *pBuf;
+ int64_t tempL, tempR;
size_t inFrameRequest;
size_t inFrameCount = getNumInSample(outFrameCount);
size_t index = 0;
@@ -74,7 +75,7 @@ size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount,
if(mResamplerOutBuf) {
delete [] mResamplerOutBuf;
}
- mTmpBuf = new int16_t[inFrameRequest + 16];
+ mTmpBuf = new int32_t[inFrameRequest + 16];
mResamplerOutBuf = new int32_t[out_count];
}
@@ -95,7 +96,7 @@ size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount,
goto resample_exit;
}
- mTmpBuf[index++] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++));
+ mTmpBuf[index++] = clampq4_27_from_float(*((float *)mBuffer.raw + frameIndex++));
if (frameIndex >= mBuffer.frameCount) {
provider->releaseBuffer(&mBuffer);
@@ -121,8 +122,8 @@ size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount,
goto resample_exit;
}
- mTmpBuf[index] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++));
- pBuf[index++] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++));
+ mTmpBuf[index] = clampq4_27_from_float(*((float *)mBuffer.raw + frameIndex++));
+ pBuf[index++] = clampq4_27_from_float(*((float *)mBuffer.raw + frameIndex++));
if (frameIndex >= mBuffer.frameCount * 2) {
provider->releaseBuffer(&mBuffer);
}
@@ -133,8 +134,12 @@ size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount,
resample_exit:
for (int i = 0; i < out_count; i += 2) {
- fout[i] += float_from_q4_27(mResamplerOutBuf[i] * vl);
- fout[i+1] += float_from_q4_27(mResamplerOutBuf[i+1] * vr);
+ // Multiplying q4.27 data with u4.12 gain could result in 39 fractional bit data(27+12)
+ // To get back the 27 fractional bit format output data, do right shift by 12
+ tempL = (int64_t)mResamplerOutBuf[i] * vl;
+ tempR = (int64_t)mResamplerOutBuf[i+1] * vr;
+ fout[i] += float_from_q4_27((int32_t)(tempL>>12));
+ fout[i+1] += float_from_q4_27((int32_t)(tempR>>12));
}
mFrameIndex = frameIndex;
@@ -151,7 +156,7 @@ void AudioResamplerQTI::setSampleRate(int32_t inSampleRate)
void AudioResamplerQTI::init()
{
- QCT_Resampler::Init(mState, mChannelCount, mInSampleRate, mSampleRate);
+ QCT_Resampler::Init(mState, mChannelCount, mInSampleRate, mSampleRate, 1/*32bit in*/);
}
size_t AudioResamplerQTI::getNumInSample(size_t outFrameCount)
diff --git a/services/audioflinger/AudioResamplerQTI.h b/services/audioflinger/AudioResamplerQTI.h
index 0b30a9f..1cf93fc 100644
--- a/services/audioflinger/AudioResamplerQTI.h
+++ b/services/audioflinger/AudioResamplerQTI.h
@@ -35,7 +35,7 @@ public:
size_t getNumInSample(size_t outFrameCount);
int16_t *mState;
- int16_t *mTmpBuf;
+ int32_t *mTmpBuf;
int32_t *mResamplerOutBuf;
size_t mFrameIndex;
size_t stateSize;
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 879b6c9..5505d2e 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -543,6 +543,13 @@ status_t AudioFlinger::EffectModule::remove_effect_from_hal_l()
return NO_ERROR;
}
+// round up delta valid if value and divisor are positive.
+template <typename T>
+static T roundUpDelta(const T &value, const T &divisor) {
+ T remainder = value % divisor;
+ return remainder == 0 ? 0 : divisor - remainder;
+}
+
status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
uint32_t cmdSize,
void *pCmdData,
@@ -558,6 +565,28 @@ status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
if (mStatus != NO_ERROR) {
return mStatus;
}
+ if (cmdCode == EFFECT_CMD_GET_PARAM &&
+ (*replySize < sizeof(effect_param_t) ||
+ ((effect_param_t *)pCmdData)->psize > *replySize - sizeof(effect_param_t))) {
+ android_errorWriteLog(0x534e4554, "29251553");
+ return -EINVAL;
+ }
+ if ((cmdCode == EFFECT_CMD_SET_PARAM
+ || cmdCode == EFFECT_CMD_SET_PARAM_DEFERRED) && // DEFERRED not generally used
+ (sizeof(effect_param_t) > cmdSize
+ || ((effect_param_t *)pCmdData)->psize > cmdSize
+ - sizeof(effect_param_t)
+ || ((effect_param_t *)pCmdData)->vsize > cmdSize
+ - sizeof(effect_param_t)
+ - ((effect_param_t *)pCmdData)->psize
+ || roundUpDelta(((effect_param_t *)pCmdData)->psize, (uint32_t)sizeof(int)) >
+ cmdSize
+ - sizeof(effect_param_t)
+ - ((effect_param_t *)pCmdData)->psize
+ - ((effect_param_t *)pCmdData)->vsize)) {
+ android_errorWriteLog(0x534e4554, "30204301");
+ return -EINVAL;
+ }
status_t status = (*mEffectInterface)->command(mEffectInterface,
cmdCode,
cmdSize,
diff --git a/services/audioflinger/FastCapture.cpp b/services/audioflinger/FastCapture.cpp
index 2493fb7..7c8a25f 100644
--- a/services/audioflinger/FastCapture.cpp
+++ b/services/audioflinger/FastCapture.cpp
@@ -25,6 +25,7 @@
#include <media/AudioBufferProvider.h>
#include <utils/Log.h>
#include <utils/Trace.h>
+#include "AudioFlinger.h"
#include "FastCapture.h"
namespace android {
diff --git a/services/audioflinger/FastCaptureDumpState.cpp b/services/audioflinger/FastCaptureDumpState.cpp
index 53eeba5..de4a6db 100644
--- a/services/audioflinger/FastCaptureDumpState.cpp
+++ b/services/audioflinger/FastCaptureDumpState.cpp
@@ -15,7 +15,7 @@
*/
#define LOG_TAG "FastCaptureDumpState"
-//define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#include "Configuration.h"
#include <utils/Log.h>
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 45c68b5..2bc8066 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -334,6 +334,11 @@ void FastMixer::onWork()
if ((command & FastMixerState::MIX) && (mMixer != NULL) && mIsWarm) {
ALOG_ASSERT(mMixerBuffer != NULL);
+
+ // AudioMixer::mState.enabledTracks is undefined if mState.hook == process__validate,
+ // so we keep a side copy of enabledTracks
+ bool anyEnabledTracks = false;
+
// for each track, update volume and check for underrun
unsigned currentTrackMask = current->mTrackMask;
while (currentTrackMask != 0) {
@@ -392,11 +397,13 @@ void FastMixer::onWork()
underruns.mBitFields.mPartial++;
underruns.mBitFields.mMostRecent = UNDERRUN_PARTIAL;
mMixer->enable(name);
+ anyEnabledTracks = true;
}
} else {
underruns.mBitFields.mFull++;
underruns.mBitFields.mMostRecent = UNDERRUN_FULL;
mMixer->enable(name);
+ anyEnabledTracks = true;
}
ftDump->mUnderruns = underruns;
ftDump->mFramesReady = framesReady;
@@ -407,9 +414,14 @@ void FastMixer::onWork()
pts = AudioBufferProvider::kInvalidPTS;
}
- // process() is CPU-bound
- mMixer->process(pts);
- mMixerBufferState = MIXED;
+ if (anyEnabledTracks) {
+ // process() is CPU-bound
+ mMixer->process(pts);
+ mMixerBufferState = MIXED;
+ } else if (mMixerBufferState != ZEROED) {
+ mMixerBufferState = UNDEFINED;
+ }
+
} else if (mMixerBufferState == MIXED) {
mMixerBufferState = UNDEFINED;
}
diff --git a/services/audioflinger/ServiceUtilities.cpp b/services/audioflinger/ServiceUtilities.cpp
index 2e68dad..031ff05 100644
--- a/services/audioflinger/ServiceUtilities.cpp
+++ b/services/audioflinger/ServiceUtilities.cpp
@@ -106,6 +106,14 @@ bool captureAudioOutputAllowed() {
return ok;
}
+bool accessFmRadioAllowed() {
+ static const String16 sAccessFmRadio("android.permission.ACCESS_FM_RADIO");
+ // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
+ bool ok = PermissionCache::checkCallingPermission(sAccessFmRadio);
+ if (!ok) ALOGE("Request requires android.permission.ACCESS_FM_RADIO");
+ return ok;
+}
+
bool captureHotwordAllowed() {
static const String16 sCaptureHotwordAllowed("android.permission.CAPTURE_AUDIO_HOTWORD");
// IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
diff --git a/services/audioflinger/ServiceUtilities.h b/services/audioflinger/ServiceUtilities.h
index fba6dce..dffb114 100644
--- a/services/audioflinger/ServiceUtilities.h
+++ b/services/audioflinger/ServiceUtilities.h
@@ -21,6 +21,7 @@ namespace android {
extern pid_t getpid_cached;
bool recordingAllowed(const String16& opPackageName);
+bool accessFmRadioAllowed();
bool captureAudioOutputAllowed();
bool captureHotwordAllowed();
bool settingsAllowed();
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index c3ee6c2..e5e8bdb 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2574,11 +2574,10 @@ void AudioFlinger::PlaybackThread::cacheParameters_l()
}
}
-void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamType)
+void AudioFlinger::PlaybackThread::invalidateTracks_l(audio_stream_type_t streamType)
{
ALOGV("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
this, streamType, mTracks.size());
- Mutex::Autolock _l(mLock);
size_t size = mTracks.size();
for (size_t i = 0; i < size; i++) {
@@ -2589,6 +2588,12 @@ void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamTy
}
}
+void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamType)
+{
+ Mutex::Autolock _l(mLock);
+ invalidateTracks_l(streamType);
+}
+
status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
{
int session = chain->sessionId();
@@ -4470,8 +4475,12 @@ void AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& ar
dprintf(fd, " AudioMixer tracks: 0x%08x\n", mAudioMixer->trackNames());
// Make a non-atomic copy of fast mixer dump state so it won't change underneath us
- const FastMixerDumpState copy(mFastMixerDumpState);
- copy.dump(fd);
+ // while we are dumping it. It may be inconsistent, but it won't mutate!
+ // This is a large object so we place it on the heap.
+ // FIXME 25972958: Need an intelligent copy constructor that does not touch unused pages.
+ const FastMixerDumpState *copy = new FastMixerDumpState(mFastMixerDumpState);
+ copy->dump(fd);
+ delete copy;
#ifdef STATE_QUEUE_DUMP
// Similar for state queue
@@ -4863,6 +4872,10 @@ bool AudioFlinger::DirectOutputThread::shouldStandby_l()
bool trackPaused = false;
bool trackStopped = false;
+ if ((mType == DIRECT) && audio_is_linear_pcm(mFormat) && !usesHwAvSync()) {
+ return !mStandby;
+ }
+
// do not put the HAL in standby when paused. AwesomePlayer clear the offloaded AudioTrack
// after a timeout and we will enter standby then.
if (mTracks.size() > 0) {
@@ -4983,6 +4996,8 @@ void AudioFlinger::DirectOutputThread::cacheParameters_l()
mStandbyDelayNs = 0;
} else if ((mType == OFFLOAD) && !audio_is_linear_pcm(mFormat)) {
mStandbyDelayNs = kOffloadStandbyDelayNs;
+ } else if (mType == DIRECT && mIsDirectPcm) {
+ mStandbyDelayNs = kOffloadStandbyDelayNs;
} else {
mStandbyDelayNs = microseconds(mActiveSleepTimeUs*2);
}
@@ -5154,15 +5169,9 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
if (track->isInvalid()) {
ALOGW("An invalidated track shouldn't be in active list");
tracksToRemove->add(track);
- continue;
- }
-
- if (track->mState == TrackBase::IDLE) {
+ } else if (track->mState == TrackBase::IDLE) {
ALOGW("An idle track shouldn't be in active list");
- continue;
- }
-
- if (track->isPausing()) {
+ } else if (track->isPausing()) {
track->setPaused();
if (last) {
if (mHwSupportsPause && !mHwPaused) {
@@ -5185,7 +5194,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr
if (last) {
mFlushPending = true;
}
- } else if (track->isResumePending()){
+ } else if (track->isResumePending()) {
track->resumeAck();
if (last) {
if (mPausedBytesRemaining) {
@@ -5361,6 +5370,13 @@ void AudioFlinger::OffloadThread::flushHw_l()
}
}
+void AudioFlinger::OffloadThread::invalidateTracks(audio_stream_type_t streamType)
+{
+ Mutex::Autolock _l(mLock);
+ mFlushPending = true;
+ PlaybackThread::invalidateTracks_l(streamType);
+}
+
// ----------------------------------------------------------------------------
AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
@@ -6454,9 +6470,13 @@ void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& a
dprintf(fd, " Fast capture thread: %s\n", hasFastCapture() ? "yes" : "no");
dprintf(fd, " Fast track available: %s\n", mFastTrackAvail ? "yes" : "no");
- // Make a non-atomic copy of fast capture dump state so it won't change underneath us
- const FastCaptureDumpState copy(mFastCaptureDumpState);
- copy.dump(fd);
+ // Make a non-atomic copy of fast capture dump state so it won't change underneath us
+ // while we are dumping it. It may be inconsistent, but it won't mutate!
+ // This is a large object so we place it on the heap.
+ // FIXME 25972958: Need an intelligent copy constructor that does not touch unused pages.
+ const FastCaptureDumpState *copy = new FastCaptureDumpState(mFastCaptureDumpState);
+ copy->dump(fd);
+ delete copy;
}
void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args __unused)
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 48ff77d..8fab1e4 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -617,7 +617,8 @@ public:
virtual bool isValidSyncEvent(const sp<SyncEvent>& event) const;
// called with AudioFlinger lock held
- void invalidateTracks(audio_stream_type_t streamType);
+ void invalidateTracks_l(audio_stream_type_t streamType);
+ virtual void invalidateTracks(audio_stream_type_t streamType);
virtual size_t frameCount() const { return mNormalFrameCount; }
@@ -1000,6 +1001,7 @@ protected:
virtual bool waitingAsyncCallback();
virtual bool waitingAsyncCallback_l();
+ virtual void invalidateTracks(audio_stream_type_t streamType);
private:
size_t mPausedWriteLength; // length in bytes of write interrupted by pause