diff options
Diffstat (limited to 'services')
30 files changed, 570 insertions, 55 deletions
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk index 9b4ba79..474fb46 100644 --- a/services/audioflinger/Android.mk +++ b/services/audioflinger/Android.mk @@ -60,6 +60,14 @@ LOCAL_STATIC_LIBRARIES := \ libcpustats \ libmedia_helper +#QTI Resampler +ifeq ($(call is-vendor-board-platform,QCOM), true) +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)), true) +LOCAL_CFLAGS += -DQTI_RESAMPLER +endif +endif +#QTI Resampler + LOCAL_MODULE:= libaudioflinger LOCAL_32_BIT_ONLY := true @@ -123,7 +131,19 @@ LOCAL_C_INCLUDES := \ LOCAL_SHARED_LIBRARIES := \ libcutils \ libdl \ - liblog + liblog \ + libaudioutils + +#QTI Resampler +ifeq ($(call is-vendor-board-platform,QCOM), true) +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)), true) +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 +endif +endif +#QTI Resampler LOCAL_MODULE := libaudioresampler diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 9ec5802..d7af22c 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -131,6 +131,14 @@ const char *formatToString(audio_format_t format) { case AUDIO_FORMAT_OPUS: return "opus"; case AUDIO_FORMAT_AC3: return "ac-3"; case AUDIO_FORMAT_E_AC3: return "e-ac-3"; + case AUDIO_FORMAT_PCM_OFFLOAD: + switch (format) { + case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD: return "pcm-16bit-offload"; + case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD: return "pcm-24bit-offload"; + default: + break; + } + break; default: break; } @@ -1053,9 +1061,24 @@ status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& } mHardwareStatus = AUDIO_HW_IDLE; } - // disable AEC and NS if the device is a BT SCO headset supporting those pre processings + AudioParameter param = AudioParameter(keyValuePairs); - String8 value; + String8 value, key; + key = String8("SND_CARD_STATUS"); + if (param.get(key, value) == NO_ERROR) { + ALOGV("Set keySoundCardStatus:%s", value.string()); + if ((value.find("OFFLINE", 0) != -1) ) { + ALOGV("OFFLINE detected - call InvalidateTracks()"); + for (size_t i = 0; i < mPlaybackThreads.size(); i++) { + PlaybackThread *thread = mPlaybackThreads.valueAt(i).get(); + if( thread->getOutput()->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ){ + thread->invalidateTracks(AUDIO_STREAM_MUSIC); + } + } + } + } + + // disable AEC and NS if the device is a BT SCO headset supporting those pre processings if (param.get(String8(AUDIO_PARAMETER_KEY_BT_NREC), value) == NO_ERROR) { bool btNrecIsOff = (value == AUDIO_PARAMETER_VALUE_OFF); if (mBtNrecIsOff != btNrecIsOff) { @@ -1353,11 +1376,10 @@ AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid) : RefBase(), mAudioFlinger(audioFlinger), // FIXME should be a "k" constant not hard-coded, in .h or ro. property, see 4 lines below - mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")), + mMemoryDealer(new MemoryDealer(4100*1024, "AudioFlinger::Client")), //4MB + 1 more 4k page mPid(pid), mTimedTrackCount(0) { - // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer } // Client destructor must be called with AudioFlinger::mClientLock held @@ -1818,7 +1840,11 @@ sp<AudioFlinger::PlaybackThread> AudioFlinger::openOutput_l(audio_module_handle_ || !isValidPcmSinkFormat(config->format) || !isValidPcmSinkChannelMask(config->channel_mask)) { thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady); - ALOGV("openOutput_l() created direct output: ID %d thread %p", *output, thread); + ALOGV("openOutput_l() created direct output: ID %d thread %p ", *output, thread); + //Check if this is DirectPCM, if so + if (flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) { + thread->mIsDirectPcm = true; + } } else { thread = new MixerThread(this, outputStream, *output, devices, mSystemReady); ALOGV("openOutput_l() created mixer output: ID %d thread %p", *output, thread); @@ -2960,6 +2986,7 @@ void AudioFlinger::dumpTee(int fd, const sp<NBAIO_Source>& source, audio_io_hand bool firstRead = true; #define TEE_SINK_READ 1024 // frames per I/O operation void *buffer = malloc(TEE_SINK_READ * frameSize); + CHECK (buffer != NULL); for (;;) { size_t count = TEE_SINK_READ; ssize_t actual = teeSource->read(buffer, count, diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp index 8a9a837..27a2f65 100644 --- a/services/audioflinger/AudioMixer.cpp +++ b/services/audioflinger/AudioMixer.cpp @@ -85,6 +85,9 @@ static const bool kUseFloat = true; // Set to default copy buffer size in frames for input processing. static const size_t kCopyBufferFrameCount = 256; +#ifdef QTI_RESAMPLER +#define QTI_RESAMPLER_MAX_SAMPLERATE 192000 +#endif namespace android { // ---------------------------------------------------------------------------- @@ -779,6 +782,13 @@ bool AudioMixer::track_t::setResampler(uint32_t trackSampleRate, uint32_t devSam // but if none exists, it is the channel count (1 for mono). const int resamplerChannelCount = downmixerBufferProvider != NULL ? mMixerChannelCount : channelCount; +#ifdef QTI_RESAMPLER + if ((trackSampleRate <= QTI_RESAMPLER_MAX_SAMPLERATE) && + (trackSampleRate > devSampleRate * 2) && + ((devSampleRate == 48000)||(devSampleRate == 44100))) { + quality = AudioResampler::QTI_QUALITY; + } +#endif ALOGVV("Creating resampler:" " format(%#x) channels(%d) devSampleRate(%u) quality(%d)\n", mMixerInFormat, resamplerChannelCount, devSampleRate, quality); @@ -1644,6 +1654,9 @@ void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state, // Note: In case of later int16_t sink output, // conversion and clamping is done by memcpy_to_i16_from_float(). } while (--outFrames); + //assign fout to out, when no more frames are available, so that 0s + //can be filled at the right place + out = (int32_t *)fout; break; case AUDIO_FORMAT_PCM_16_BIT: if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN_INT || uint32_t(vr) > UNITY_GAIN_INT)) { diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h index 7165c6c..f0ae4ec 100644 --- a/services/audioflinger/AudioMixer.h +++ b/services/audioflinger/AudioMixer.h @@ -137,6 +137,7 @@ public: case AUDIO_FORMAT_PCM_8_BIT: case AUDIO_FORMAT_PCM_16_BIT: case AUDIO_FORMAT_PCM_24_BIT_PACKED: + case AUDIO_FORMAT_PCM_8_24_BIT: case AUDIO_FORMAT_PCM_32_BIT: case AUDIO_FORMAT_PCM_FLOAT: return true; diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp index e49b7b1..ab3294a 100644 --- a/services/audioflinger/AudioResampler.cpp +++ b/services/audioflinger/AudioResampler.cpp @@ -28,6 +28,10 @@ #include "AudioResamplerCubic.h" #include "AudioResamplerDyn.h" +#ifdef QTI_RESAMPLER +#include "AudioResamplerQTI.h" +#endif + #ifdef __arm__ #define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1 #endif @@ -90,6 +94,9 @@ bool AudioResampler::qualityIsSupported(src_quality quality) case DYN_LOW_QUALITY: case DYN_MED_QUALITY: case DYN_HIGH_QUALITY: +#ifdef QTI_RESAMPLER + case QTI_QUALITY: +#endif return true; default: return false; @@ -110,7 +117,11 @@ void AudioResampler::init_routine() if (*endptr == '\0') { defaultQuality = (src_quality) l; ALOGD("forcing AudioResampler quality to %d", defaultQuality); +#ifdef QTI_RESAMPLER + if (defaultQuality < DEFAULT_QUALITY || defaultQuality > QTI_QUALITY) { +#else if (defaultQuality < DEFAULT_QUALITY || defaultQuality > DYN_HIGH_QUALITY) { +#endif defaultQuality = DEFAULT_QUALITY; } } @@ -129,6 +140,9 @@ uint32_t AudioResampler::qualityMHz(src_quality quality) case HIGH_QUALITY: return 20; case VERY_HIGH_QUALITY: +#ifdef QTI_RESAMPLER + case QTI_QUALITY: //for QTI_QUALITY, currently assuming same as VHQ +#endif return 34; case DYN_LOW_QUALITY: return 4; @@ -204,6 +218,11 @@ AudioResampler* AudioResampler::create(audio_format_t format, int inChannelCount case DYN_HIGH_QUALITY: quality = DYN_MED_QUALITY; break; +#ifdef QTI_RESAMPLER + case QTI_QUALITY: + quality = DYN_HIGH_QUALITY; + break; +#endif } } pthread_mutex_unlock(&mutex); @@ -250,6 +269,12 @@ AudioResampler* AudioResampler::create(audio_format_t format, int inChannelCount } } break; +#ifdef QTI_RESAMPLER + case QTI_QUALITY: + ALOGV("Create QTI_QUALITY Resampler = %d",quality); + resampler = new AudioResamplerQTI(format, inChannelCount, sampleRate); + break; +#endif } // initialize resampler diff --git a/services/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h index a8e3e6f..6669a85 100644 --- a/services/audioflinger/AudioResampler.h +++ b/services/audioflinger/AudioResampler.h @@ -47,6 +47,9 @@ public: DYN_LOW_QUALITY=5, DYN_MED_QUALITY=6, DYN_HIGH_QUALITY=7, +#ifdef QTI_RESAMPLER + QTI_QUALITY=8, +#endif }; static const CONSTEXPR float UNITY_GAIN_FLOAT = 1.0f; diff --git a/services/audioflinger/AudioResamplerQTI.cpp b/services/audioflinger/AudioResamplerQTI.cpp new file mode 100644 index 0000000..44b741e --- /dev/null +++ b/services/audioflinger/AudioResamplerQTI.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2014, The Linux Foundation. All rights reserved. + * Not a Contribution. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AudioResamplerQTI.h" +#include "QCT_Resampler.h" +#include <sys/time.h> +#include <audio_utils/primitives.h> + +namespace android { +AudioResamplerQTI::AudioResamplerQTI(int format, + int inChannelCount, int32_t sampleRate) + :AudioResampler(inChannelCount, sampleRate, QTI_QUALITY), + mOutFrameCount(0), mTmpBuf(0), mResamplerOutBuf(0), mFrameIndex(0) +{ + stateSize = QCT_Resampler::MemAlloc(format, inChannelCount, sampleRate, sampleRate); + mState = new int16_t[stateSize]; + mVolume[0] = mVolume[1] = 0; + mBuffer.frameCount = 0; +} + +AudioResamplerQTI::~AudioResamplerQTI() +{ + if (mState) { + delete [] mState; + } + if (mTmpBuf) { + delete [] mTmpBuf; + } + if(mResamplerOutBuf) { + delete [] mResamplerOutBuf; + } +} + +size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount, + AudioBufferProvider* provider) +{ + int16_t vl = mVolume[0]; + int16_t vr = mVolume[1]; + int16_t *pBuf; + + size_t inFrameRequest; + size_t inFrameCount = getNumInSample(outFrameCount); + size_t index = 0; + size_t frameIndex = mFrameIndex; + size_t out_count = outFrameCount * 2; + float *fout = reinterpret_cast<float *>(out); + + if (mChannelCount == 1) { + inFrameRequest = inFrameCount; + } else { + inFrameRequest = inFrameCount * 2; + } + + if (mOutFrameCount < outFrameCount) { + mOutFrameCount = outFrameCount; + if (mTmpBuf) { + delete [] mTmpBuf; + } + if(mResamplerOutBuf) { + delete [] mResamplerOutBuf; + } + mTmpBuf = new int16_t[inFrameRequest + 16]; + mResamplerOutBuf = new int32_t[out_count]; + } + + if (mChannelCount == 1) { + // buffer is empty, fetch a new one + while (index < inFrameCount) { + if (!mBuffer.frameCount) { + mBuffer.frameCount = inFrameCount; + provider->getNextBuffer(&mBuffer); + frameIndex = 0; + } + + if (mBuffer.raw == NULL) { + while (index < inFrameCount) { + mTmpBuf[index++] = 0; + } + QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount); + goto resample_exit; + } + + mTmpBuf[index++] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++)); + + if (frameIndex >= mBuffer.frameCount) { + provider->releaseBuffer(&mBuffer); + } + } + + QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount); + } else { + pBuf = &mTmpBuf[inFrameCount]; + // buffer is empty, fetch a new one + while (index < inFrameCount) { + if (!mBuffer.frameCount) { + mBuffer.frameCount = inFrameCount; + provider->getNextBuffer(&mBuffer); + frameIndex = 0; + } + if (mBuffer.raw == NULL) { + while (index < inFrameCount) { + mTmpBuf[index] = 0; + pBuf[index++] = 0; + } + QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount); + goto resample_exit; + } + + mTmpBuf[index] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++)); + pBuf[index++] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++)); + if (frameIndex >= mBuffer.frameCount * 2) { + provider->releaseBuffer(&mBuffer); + } + } + + QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, 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); + } + + mFrameIndex = frameIndex; + return index; +} + +void AudioResamplerQTI::setSampleRate(int32_t inSampleRate) +{ + if (mInSampleRate != inSampleRate) { + mInSampleRate = inSampleRate; + init(); + } +} + +void AudioResamplerQTI::init() +{ + QCT_Resampler::Init(mState, mChannelCount, mInSampleRate, mSampleRate); +} + +size_t AudioResamplerQTI::getNumInSample(size_t outFrameCount) +{ + size_t size = (size_t)QCT_Resampler::GetNumInSamp(mState, outFrameCount); + return size; +} + +void AudioResamplerQTI::reset() +{ + AudioResampler::reset(); +} + +}; // namespace android diff --git a/services/audioflinger/AudioResamplerQTI.h b/services/audioflinger/AudioResamplerQTI.h new file mode 100644 index 0000000..0b30a9f --- /dev/null +++ b/services/audioflinger/AudioResamplerQTI.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2014, The Linux Foundation. All rights reserved. + * Not a Contribution. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdint.h> +#include <sys/types.h> +#include <cutils/log.h> + +#include "AudioResampler.h" + +namespace android { +// ---------------------------------------------------------------------------- + +class AudioResamplerQTI : public AudioResampler { +public: + AudioResamplerQTI(int format, int inChannelCount, int32_t sampleRate); + ~AudioResamplerQTI(); + size_t resample(int32_t* out, size_t outFrameCount, + AudioBufferProvider* provider); + void setSampleRate(int32_t inSampleRate); + size_t getNumInSample(size_t outFrameCount); + + int16_t *mState; + int16_t *mTmpBuf; + int32_t *mResamplerOutBuf; + size_t mFrameIndex; + size_t stateSize; + size_t mOutFrameCount; + + static const int kNumTmpBufSize = 1024; + + void init(); + void reset(); +}; + +// ---------------------------------------------------------------------------- +}; // namespace android + diff --git a/services/audioflinger/BufferProviders.cpp b/services/audioflinger/BufferProviders.cpp index a8be206..434a514 100644 --- a/services/audioflinger/BufferProviders.cpp +++ b/services/audioflinger/BufferProviders.cpp @@ -24,6 +24,7 @@ #include <media/EffectsFactoryApi.h> #include <utils/Log.h> +#include <media/stagefright/foundation/ADebug.h> #include "Configuration.h" #include "BufferProviders.h" @@ -205,6 +206,7 @@ DownmixerBufferProvider::DownmixerBufferProvider( const int downmixParamSize = sizeof(effect_param_t) + psizePadded + sizeof(downmix_type_t); effect_param_t * const param = (effect_param_t *) malloc(downmixParamSize); + CHECK(param != NULL); param->psize = sizeof(downmix_params_t); const downmix_params_t downmixParam = DOWNMIX_PARAM_TYPE; memcpy(param->data, &downmixParam, param->psize); diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp index 949c91d..54ca6c3 100644 --- a/services/audioflinger/Effects.cpp +++ b/services/audioflinger/Effects.cpp @@ -318,6 +318,7 @@ void AudioFlinger::EffectModule::reset_l() status_t AudioFlinger::EffectModule::configure() { status_t status; + status_t cmdStatus = 0; sp<ThreadBase> thread; uint32_t size; audio_channel_mask_t channelMask; @@ -383,7 +384,6 @@ status_t AudioFlinger::EffectModule::configure() ALOGV("configure() %p thread %p buffer %p framecount %d", this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount); - status_t cmdStatus; size = sizeof(int); status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_SET_CONFIG, @@ -434,7 +434,7 @@ status_t AudioFlinger::EffectModule::init() if (mEffectInterface == NULL) { return NO_INIT; } - status_t cmdStatus; + status_t cmdStatus = 0; uint32_t size = sizeof(status_t); status_t status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_INIT, @@ -476,7 +476,7 @@ status_t AudioFlinger::EffectModule::start_l() if (mStatus != NO_ERROR) { return mStatus; } - status_t cmdStatus; + status_t cmdStatus = 0; uint32_t size = sizeof(status_t); status_t status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_ENABLE, @@ -677,7 +677,7 @@ status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, if (isProcessEnabled() && ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL || (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) { - status_t cmdStatus; + status_t cmdStatus = 0; uint32_t volume[2]; uint32_t *pVolume = NULL; uint32_t size = sizeof(volume); @@ -712,7 +712,7 @@ status_t AudioFlinger::EffectModule::setDevice(audio_devices_t device) } status_t status = NO_ERROR; if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) { - status_t cmdStatus; + status_t cmdStatus = 0; uint32_t size = sizeof(status_t); uint32_t cmd = audio_is_output_devices(device) ? EFFECT_CMD_SET_DEVICE : EFFECT_CMD_SET_INPUT_DEVICE; @@ -734,7 +734,7 @@ status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode) } status_t status = NO_ERROR; if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) { - status_t cmdStatus; + status_t cmdStatus = 0; uint32_t size = sizeof(status_t); status = (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_SET_AUDIO_MODE, @@ -1113,7 +1113,8 @@ status_t AudioFlinger::EffectHandle::enable() mEnabled = false; } else { if (thread != 0) { - if (thread->type() == ThreadBase::OFFLOAD) { + if ((thread->type() == ThreadBase::OFFLOAD) || + (thread->type() == ThreadBase::DIRECT && thread->mIsDirectPcm)) { PlaybackThread *t = (PlaybackThread *)thread.get(); Mutex::Autolock _l(t->mLock); t->broadcast_l(); diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index f586291..cdf8b1e 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -544,6 +544,7 @@ AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio mSystemReady(systemReady) { memset(&mPatch, 0, sizeof(struct audio_patch)); + mIsDirectPcm = false; } AudioFlinger::ThreadBase::~ThreadBase() @@ -1154,7 +1155,8 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l( // Reject any effect on Direct output threads for now, since the format of // mSinkBuffer is not guaranteed to be compatible with effect processing (PCM 16 stereo). - if (mType == DIRECT) { + // Exception: allow effects for Direct PCM + if (mType == DIRECT && !mIsDirectPcm) { ALOGW("createEffect_l() Cannot add effect %s on Direct output type thread %s", desc->name, mThreadName); lStatus = BAD_VALUE; @@ -1171,12 +1173,17 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l( } // Allow global effects only on offloaded and mixer threads + // Exception: allow effects for Direct PCM if (sessionId == AUDIO_SESSION_OUTPUT_MIX) { switch (mType) { case MIXER: case OFFLOAD: break; case DIRECT: + if (mIsDirectPcm) { + // Allow effects when direct PCM enabled on Direct output + break; + } case DUPLICATING: case RECORD: default: @@ -1229,7 +1236,13 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l( if (lStatus != NO_ERROR) { goto Exit; } - effect->setOffloaded(mType == OFFLOAD, mId); + + bool setVal = false; + if (mType == OFFLOAD || (mType == DIRECT && mIsDirectPcm)) { + setVal = true; + } + + effect->setOffloaded(setVal, mId); lStatus = chain->addEffect_l(effect); if (lStatus != NO_ERROR) { @@ -1313,7 +1326,13 @@ status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect) return BAD_VALUE; } - effect->setOffloaded(mType == OFFLOAD, mId); + bool setval = false; + + if ((mType == OFFLOAD) || (mType == DIRECT && mIsDirectPcm)) { + setval = true; + } + + effect->setOffloaded(setval, mId); status_t status = chain->addEffect_l(effect); if (status != NO_ERROR) { @@ -5295,6 +5314,8 @@ void AudioFlinger::DuplicatingThread::threadLoop_mix() } else { if (mMixerBufferValid) { memset(mMixerBuffer, 0, mMixerBufferSize); + } else if (mEffectBufferValid) { + memset(mEffectBuffer, 0, mEffectBufferSize); } else { memset(mSinkBuffer, 0, mSinkBufferSize); } @@ -5316,7 +5337,11 @@ void AudioFlinger::DuplicatingThread::threadLoop_sleepTime() } else if (mBytesWritten != 0) { if (mMixerStatus == MIXER_TRACKS_ENABLED) { writeFrames = mNormalFrameCount; - memset(mSinkBuffer, 0, mSinkBufferSize); + if (mMixerBufferValid) { + memset(mMixerBuffer, 0, mMixerBufferSize); + } else { + memset(mSinkBuffer, 0, mSinkBufferSize); + } } else { // flush remaining overflow buffers in output tracks writeFrames = 0; diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h index 46ac300..9e32ea1 100644 --- a/services/audioflinger/Threads.h +++ b/services/audioflinger/Threads.h @@ -457,6 +457,7 @@ protected: static const size_t kLogSize = 4 * 1024; sp<NBLog::Writer> mNBLogWriter; bool mSystemReady; + bool mIsDirectPcm; // flag to indicate unique Direct thread }; // --- PlaybackThread --- diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index b3fac0b..98eb87f 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -24,6 +24,7 @@ #include <math.h> #include <sys/syscall.h> #include <utils/Log.h> +#include <media/stagefright/foundation/ADebug.h> #include <private/media/AudioTrackShared.h> @@ -1774,6 +1775,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frame if (mBufferQueue.size() < kMaxOverFlowBuffers) { pInBuffer = new Buffer; pInBuffer->mBuffer = malloc(inBuffer.frameCount * mFrameSize); + CHECK(pInBuffer->mBuffer != NULL); pInBuffer->frameCount = inBuffer.frameCount; pInBuffer->raw = pInBuffer->mBuffer; memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize); diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk index 8728ff3..8c6a53c 100644 --- a/services/audiopolicy/common/managerdefinitions/Android.mk +++ b/services/audiopolicy/common/managerdefinitions/Android.mk @@ -31,6 +31,27 @@ LOCAL_C_INCLUDES += \ LOCAL_EXPORT_C_INCLUDE_DIRS := \ $(LOCAL_PATH)/include +ifeq ($(call is-vendor-board-platform,QCOM),true) +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_FLAC_OFFLOAD)),true) +LOCAL_CFLAGS += -DFLAC_OFFLOAD_ENABLED +endif +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_PROXY_DEVICE)),true) +LOCAL_CFLAGS += -DAUDIO_EXTN_AFE_PROXY_ENABLED +endif +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_WMA_OFFLOAD)),true) +LOCAL_CFLAGS += -DWMA_OFFLOAD_ENABLED +endif +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_ALAC_OFFLOAD)),true) +LOCAL_CFLAGS += -DALAC_OFFLOAD_ENABLED +endif +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_APE_OFFLOAD)),true) +LOCAL_CFLAGS += -DAPE_OFFLOAD_ENABLED +endif +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_AAC_ADTS_OFFLOAD)),true) +LOCAL_CFLAGS += -DAAC_ADTS_OFFLOAD_ENABLED +endif +endif + LOCAL_MODULE := libaudiopolicycomponents include $(BUILD_STATIC_LIBRARY) diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h index 50f622d..e1c2999 100644 --- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h +++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h @@ -72,6 +72,7 @@ public: sp<AudioPort> mPort; audio_devices_t mDevice; // current device this output is routed to audio_patch_handle_t mPatchHandle; + audio_io_handle_t mIoHandle; // output handle uint32_t mRefCount[AUDIO_STREAM_CNT]; // number of streams of each type using this output nsecs_t mStopTime[AUDIO_STREAM_CNT]; float mCurVolume[AUDIO_STREAM_CNT]; // current stream volume in dB @@ -116,7 +117,6 @@ public: virtual void toAudioPort(struct audio_port *port) const; const sp<IOProfile> mProfile; // I/O profile this output derives from - audio_io_handle_t mIoHandle; // output handle uint32_t mLatency; // audio_output_flags_t mFlags; // AudioMix *mPolicyMix; // non NULL when used by a dynamic policy diff --git a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h index 78d2cdf..4a394bb 100644 --- a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h +++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h @@ -74,6 +74,9 @@ const StringToEnum sDeviceTypeToEnumTable[] = { STRING_TO_ENUM(AUDIO_DEVICE_OUT_FM), STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_LINE), STRING_TO_ENUM(AUDIO_DEVICE_OUT_IP), +#ifdef AUDIO_EXTN_AFE_PROXY_ENABLED + STRING_TO_ENUM(AUDIO_DEVICE_OUT_PROXY), +#endif STRING_TO_ENUM(AUDIO_DEVICE_IN_AMBIENT), STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC), STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET), @@ -153,6 +156,7 @@ const StringToEnum sDeviceNameToEnumTable[] = { const StringToEnum sOutputFlagNameToEnumTable[] = { STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT), + STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT_PCM), STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY), STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST), STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER), @@ -198,6 +202,33 @@ const StringToEnum sFormatNameToEnumTable[] = { STRING_TO_ENUM(AUDIO_FORMAT_E_AC3), STRING_TO_ENUM(AUDIO_FORMAT_DTS), STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD), +#ifdef FLAC_OFFLOAD_ENABLED + STRING_TO_ENUM(AUDIO_FORMAT_FLAC), +#endif +#ifdef WMA_OFFLOAD_ENABLED + STRING_TO_ENUM(AUDIO_FORMAT_WMA), + STRING_TO_ENUM(AUDIO_FORMAT_WMA_PRO), +#endif + STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT_OFFLOAD), + STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_OFFLOAD), +#ifdef ALAC_OFFLOAD_ENABLED + STRING_TO_ENUM(AUDIO_FORMAT_ALAC), +#endif +#ifdef APE_OFFLOAD_ENABLED + STRING_TO_ENUM(AUDIO_FORMAT_APE), +#endif +#ifdef AAC_ADTS_OFFLOAD_ENABLED + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_MAIN), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_LC), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_SSR), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_LTP), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V1), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_SCALABLE), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_ERLC), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_LD), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V2), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_ELD), +#endif }; const StringToEnum sOutChannelsNameToEnumTable[] = { @@ -206,12 +237,17 @@ const StringToEnum sOutChannelsNameToEnumTable[] = { STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD), STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1), STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1), + STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1), + STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND), + STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA), + STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1), }; const StringToEnum sInChannelsNameToEnumTable[] = { STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO), STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO), STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK), + STRING_TO_ENUM(AUDIO_CHANNEL_IN_5POINT1), }; const StringToEnum sIndexChannelsNameToEnumTable[] = { diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp index a278375..5ddeaed 100644 --- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp +++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp @@ -33,7 +33,7 @@ namespace android { AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port, AudioPolicyClientInterface *clientInterface) - : mPort(port), mDevice(AUDIO_DEVICE_NONE), + : mPort(port), mDevice(AUDIO_DEVICE_NONE), mIoHandle(0), mPatchHandle(0), mClientInterface(clientInterface), mId(0) { // clear usage count for all stream types @@ -223,7 +223,7 @@ void AudioOutputDescriptor::log(const char* indent) SwAudioOutputDescriptor::SwAudioOutputDescriptor( const sp<IOProfile>& profile, AudioPolicyClientInterface *clientInterface) : AudioOutputDescriptor(profile, clientInterface), - mProfile(profile), mIoHandle(0), mLatency(0), + mProfile(profile), mLatency(0), mFlags((audio_output_flags_t)0), mPolicyMix(NULL), mOutput1(0), mOutput2(0), mDirectOpenCount(0), mGlobalRefCount(0) { diff --git a/services/audiopolicy/enginedefault/Android.mk b/services/audiopolicy/enginedefault/Android.mk index 8d43b89..de84e96 100755 --- a/services/audiopolicy/enginedefault/Android.mk +++ b/services/audiopolicy/enginedefault/Android.mk @@ -31,6 +31,11 @@ LOCAL_C_INCLUDES := \ $(call include-path-for, bionic) \ $(TOPDIR)frameworks/av/services/audiopolicy/common/include +ifeq ($(call is-vendor-board-platform,QCOM),true) +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_PROXY_DEVICE)),true) +LOCAL_CFLAGS += -DAUDIO_EXTN_AFE_PROXY_ENABLED +endif +endif LOCAL_MODULE := libaudiopolicyenginedefault LOCAL_MODULE_TAGS := optional diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp index 0686414..8b4a085 100755 --- a/services/audiopolicy/enginedefault/src/Engine.cpp +++ b/services/audiopolicy/enginedefault/src/Engine.cpp @@ -408,9 +408,10 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const if (device) break; device = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL; if (device) break; - device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; - if (device) break; } + // Allow voice call on USB ANLG DOCK headset + device = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; + if (device) break; device = availableOutputDevicesType & AUDIO_DEVICE_OUT_EARPIECE; if (device) break; device = mApmObserver->getDefaultOutputDevice()->type(); @@ -450,6 +451,13 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const } break; } + + if (isInCall() && (device == AUDIO_DEVICE_NONE)) { + // when in call, get the device for Phone strategy + device = getDeviceForStrategy(STRATEGY_PHONE); + break; + } + break; case STRATEGY_SONIFICATION: @@ -498,6 +506,13 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const case STRATEGY_REROUTING: case STRATEGY_MEDIA: { uint32_t device2 = AUDIO_DEVICE_NONE; + + if (isInCall() && (device == AUDIO_DEVICE_NONE)) { + // when in call, get the device for Phone strategy + device = getDeviceForStrategy(STRATEGY_PHONE); + break; + } + if (strategy != STRATEGY_SONIFICATION) { // no sonification on remote submix (e.g. WFD) if (availableOutputDevices.getDevice(AUDIO_DEVICE_OUT_REMOTE_SUBMIX, String8("0")) != 0) { @@ -541,14 +556,23 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; } - if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) { + if ((strategy != STRATEGY_SONIFICATION) && (device == AUDIO_DEVICE_NONE) + && (device2 == AUDIO_DEVICE_NONE)) { // no sonification on aux digital (e.g. HDMI) device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL; } if ((device2 == AUDIO_DEVICE_NONE) && - (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) { + (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK) + && (strategy != STRATEGY_SONIFICATION)) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; } +#ifdef AUDIO_EXTN_AFE_PROXY_ENABLED + if ((strategy != STRATEGY_SONIFICATION) && (device == AUDIO_DEVICE_NONE) + && (device2 == AUDIO_DEVICE_NONE)) { + // no sonification on WFD sink + device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_PROXY; + } +#endif if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; } @@ -671,6 +695,8 @@ audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) cons device = AUDIO_DEVICE_IN_WIRED_HEADSET; } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) { device = AUDIO_DEVICE_IN_USB_DEVICE; + } else if (availableDeviceTypes & AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET) { + device = AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET; } else if (availableDeviceTypes & AUDIO_DEVICE_IN_BUILTIN_MIC) { device = AUDIO_DEVICE_IN_BUILTIN_MIC; } diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index 8419ed5..acdd23d 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -351,6 +351,14 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs AUDIO_OUTPUT_FLAG_NONE, AUDIO_FORMAT_INVALID); if (output != AUDIO_IO_HANDLE_NONE) { + // close active input (if any) before opening new input + audio_io_handle_t activeInput = mInputs.getActiveInput(); + if (activeInput != 0) { + ALOGV("updateCallRouting() close active input before opening new input"); + sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput); + stopInput(activeInput, activeDesc->mSessions.itemAt(0)); + releaseInput(activeInput, activeDesc->mSessions.itemAt(0)); + } sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); ALOG_ASSERT(!outputDesc->isDuplicated(), "updateCallRouting() RX device output is duplicated"); @@ -1336,6 +1344,12 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, ALOGW("getInputForAttr() could not find device for source %d", inputSource); return BAD_VALUE; } + // block request to open input on USB during voice call + if((AUDIO_MODE_IN_CALL == mEngine->getPhoneState()) && + (device == AUDIO_DEVICE_IN_USB_DEVICE)) { + ALOGV("getInputForAttr(): blocking the request to open input on USB device"); + return BAD_VALUE; + } if (policyMix != NULL) { address = policyMix->mRegistrationId; if (policyMix->mMixType == MIX_TYPE_RECORDERS) { @@ -1356,20 +1370,6 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr, } else { *inputType = API_INPUT_LEGACY; } - // adapt channel selection to input source - switch (inputSource) { - case AUDIO_SOURCE_VOICE_UPLINK: - channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK; - break; - case AUDIO_SOURCE_VOICE_DOWNLINK: - channelMask = AUDIO_CHANNEL_IN_VOICE_DNLINK; - break; - case AUDIO_SOURCE_VOICE_CALL: - channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK; - break; - default: - break; - } if (inputSource == AUDIO_SOURCE_HOTWORD) { ssize_t index = mSoundTriggerSessions.indexOfKey(session); if (index >= 0) { @@ -1773,6 +1773,7 @@ audio_io_handle_t AudioPolicyManager::selectOutputForEffects( audio_io_handle_t outputOffloaded = 0; audio_io_handle_t outputDeepBuffer = 0; + audio_io_handle_t outputDirectPcm = 0; for (size_t i = 0; i < outputs.size(); i++) { sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(outputs[i]); @@ -1780,6 +1781,9 @@ audio_io_handle_t AudioPolicyManager::selectOutputForEffects( if ((desc->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { outputOffloaded = outputs[i]; } + if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) != 0) { + outputDirectPcm = outputs[i]; + } if ((desc->mFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) { outputDeepBuffer = outputs[i]; } @@ -1790,6 +1794,9 @@ audio_io_handle_t AudioPolicyManager::selectOutputForEffects( if (outputOffloaded != 0) { return outputOffloaded; } + if (outputDirectPcm != 0) { + return outputDirectPcm; + } if (outputDeepBuffer != 0) { return outputDeepBuffer; } @@ -3781,7 +3788,7 @@ void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy) { audio_devices_t oldDevice = getDeviceForStrategy(strategy, true /*fromCache*/); audio_devices_t newDevice = getDeviceForStrategy(strategy, false /*fromCache*/); - SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevice(oldDevice, mPreviousOutputs); + SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevice(oldDevice, mOutputs); SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(newDevice, mOutputs); // also take into account external policy-related changes: add all outputs which are diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h index bbdf396..c40a435 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.h +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h @@ -350,7 +350,7 @@ protected: // handle special cases for sonification strategy while in call: mute streams or replace by // a special tone in the device used for communication - void handleIncallSonification(audio_stream_type_t stream, bool starting, bool stateChange); + virtual void handleIncallSonification(audio_stream_type_t stream, bool starting, bool stateChange); audio_mode_t getPhoneState(); @@ -397,7 +397,7 @@ protected: // must be called every time a condition that affects the device choice for a given output is // changed: connected device, phone state, force use, output start, output stop.. // see getDeviceForStrategy() for the use of fromCache parameter - audio_devices_t getNewOutputDevice(const sp<AudioOutputDescriptor>& outputDesc, + virtual audio_devices_t getNewOutputDevice(const sp<AudioOutputDescriptor>& outputDesc, bool fromCache); // updates cache of device used by all strategies (mDeviceForStrategy[]) @@ -484,11 +484,11 @@ protected: // if argument "device" is different from AUDIO_DEVICE_NONE, startSource() will force // the re-evaluation of the output device. - status_t startSource(sp<AudioOutputDescriptor> outputDesc, + virtual status_t startSource(sp<AudioOutputDescriptor> outputDesc, audio_stream_type_t stream, audio_devices_t device, uint32_t *delayMs); - status_t stopSource(sp<AudioOutputDescriptor> outputDesc, + virtual status_t stopSource(sp<AudioOutputDescriptor> outputDesc, audio_stream_type_t stream, bool forceDeviceUpdate); @@ -571,7 +571,7 @@ protected: // Audio Policy Engine Interface. AudioPolicyManagerInterface *mEngine; -private: +protected: // updates device caching and output for streams that can influence the // routing of notifications void handleNotificationRoutingForStream(audio_stream_type_t stream); @@ -586,7 +586,7 @@ private: SortedVector<audio_io_handle_t>& outputs /*out*/); uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; } // internal method to return the output handle for the given device and format - audio_io_handle_t getOutputForDevice( + virtual audio_io_handle_t getOutputForDevice( audio_devices_t device, audio_session_t session, audio_stream_type_t stream, @@ -610,7 +610,7 @@ private: AudioMix **policyMix = NULL); // Called by setDeviceConnectionState(). - status_t setDeviceConnectionStateInt(audio_devices_t device, + virtual status_t setDeviceConnectionStateInt(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address, const char *device_name); diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp index 282ddeb..e71d7a5 100644 --- a/services/audiopolicy/service/AudioPolicyEffects.cpp +++ b/services/audiopolicy/service/AudioPolicyEffects.cpp @@ -442,6 +442,7 @@ effect_param_t *AudioPolicyEffects::loadEffectParameter(cnode *root) size_t curSize = sizeof(effect_param_t); size_t totSize = sizeof(effect_param_t) + 2 * sizeof(int); effect_param_t *fx_param = (effect_param_t *)malloc(totSize); + CHECK(fx_param != NULL); param = config_find(root, PARAM_TAG); value = config_find(root, VALUE_TAG); diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h index 3dec437..3845050 100644 --- a/services/audiopolicy/service/AudioPolicyEffects.h +++ b/services/audiopolicy/service/AudioPolicyEffects.h @@ -27,6 +27,8 @@ #include <utils/Vector.h> #include <utils/SortedVector.h> +#include <media/stagefright/foundation/ADebug.h> + namespace android { // ---------------------------------------------------------------------------- @@ -102,6 +104,7 @@ private: ((origParam->psize + 3) & ~3) + ((origParam->vsize + 3) & ~3); effect_param_t *dupParam = (effect_param_t *) malloc(origSize); + CHECK(dupParam != NULL); memcpy(dupParam, origParam, origSize); // This works because the param buffer allocation is also done by // multiples of 4 bytes originally. In theory we should memcpy only diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp index c77cc45..41dd40c 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -899,10 +899,12 @@ void AudioPolicyService::AudioCommandThread::insertCommand_l(sp<AudioCommand>& c } else { data2->mKeyValuePairs = param2.toString(); } - command->mTime = command2->mTime; - // force delayMs to non 0 so that code below does not request to wait for - // command status as the command is now delayed - delayMs = 1; + if (!data2->mKeyValuePairs.compare(data->mKeyValuePairs)) { + command->mTime = command2->mTime; + // force delayMs to non 0 so that code below does not request to wait for + // command status as the command is now delayed + delayMs = 1; + } } break; case SET_VOLUME: { diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk index 45900c4..ab09cb3 100644 --- a/services/camera/libcameraservice/Android.mk +++ b/services/camera/libcameraservice/Android.mk @@ -79,6 +79,14 @@ LOCAL_C_INCLUDES += \ LOCAL_CFLAGS += -Wall -Wextra +ifeq ($(BOARD_NEEDS_MEMORYHEAPION),true) + LOCAL_CFLAGS += -DUSE_MEMORY_HEAP_ION +endif + +ifneq ($(BOARD_NUMBER_OF_CAMERAS),) + LOCAL_CFLAGS += -DMAX_CAMERAS=$(BOARD_NUMBER_OF_CAMERAS) +endif + LOCAL_MODULE:= libcameraservice include $(BUILD_SHARED_LIBRARY) diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 2aaefe9..db6272b 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -2082,7 +2082,11 @@ sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user) void CameraService::Client::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode, const CaptureResultExtras& resultExtras) { - mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0); + if (mRemoteCallback != NULL) { + mRemoteCallback->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0); + } else { + ALOGE("mRemoteCallback is NULL!!"); + } } // NOTE: function is idempotent diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index cd97b08..b3903d4 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -49,6 +49,10 @@ #include <memory> #include <utility> +#ifndef MAX_CAMERAS +#define MAX_CAMERAS 2 +#endif + namespace android { extern volatile int32_t gLogLevel; diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp index 38e35cd..1bb2910 100644 --- a/services/camera/libcameraservice/api1/CameraClient.cpp +++ b/services/camera/libcameraservice/api1/CameraClient.cpp @@ -56,6 +56,9 @@ CameraClient::CameraClient(const sp<CameraService>& cameraService, mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT); mLegacyMode = legacyMode; mPlayShutterSound = true; + + mLongshotEnabled = false; + mBurstCnt = 0; LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId); } @@ -360,12 +363,14 @@ status_t CameraClient::setPreviewCallbackTarget( // start preview mode status_t CameraClient::startPreview() { + Mutex::Autolock lock(mLock); LOG1("startPreview (pid %d)", getCallingPid()); return startCameraMode(CAMERA_PREVIEW_MODE); } // start recording mode status_t CameraClient::startRecording() { + Mutex::Autolock lock(mLock); LOG1("startRecording (pid %d)", getCallingPid()); return startCameraMode(CAMERA_RECORDING_MODE); } @@ -373,7 +378,6 @@ status_t CameraClient::startRecording() { // start preview or recording status_t CameraClient::startCameraMode(camera_mode mode) { LOG1("startCameraMode(%d)", mode); - Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; @@ -553,6 +557,10 @@ status_t CameraClient::takePicture(int msgType) { CAMERA_MSG_COMPRESSED_IMAGE); enableMsgType(picMsgType); + mBurstCnt = mHardware->getParameters().getInt("num-snaps-per-shutter"); + if(mBurstCnt <= 0) + mBurstCnt = 1; + LOG1("mBurstCnt = %d", mBurstCnt); return mHardware->takePicture(); } @@ -655,6 +663,20 @@ status_t CameraClient::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) { } else if (cmd == CAMERA_CMD_PING) { // If mHardware is 0, checkPidAndHardware will return error. return OK; + } else if (cmd == CAMERA_CMD_HISTOGRAM_ON) { + enableMsgType(CAMERA_MSG_STATS_DATA); + } else if (cmd == CAMERA_CMD_HISTOGRAM_OFF) { + disableMsgType(CAMERA_MSG_STATS_DATA); + } else if (cmd == CAMERA_CMD_METADATA_ON) { + enableMsgType(CAMERA_MSG_META_DATA); + } else if (cmd == CAMERA_CMD_METADATA_OFF) { + disableMsgType(CAMERA_MSG_META_DATA); + } else if ( cmd == CAMERA_CMD_LONGSHOT_ON ) { + mLongshotEnabled = true; + } else if ( cmd == CAMERA_CMD_LONGSHOT_OFF ) { + mLongshotEnabled = false; + disableMsgType(CAMERA_MSG_SHUTTER); + disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); } return mHardware->sendCommand(cmd, arg1, arg2); @@ -797,7 +819,9 @@ void CameraClient::handleShutter(void) { c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0); if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return; } - disableMsgType(CAMERA_MSG_SHUTTER); + if ( !mLongshotEnabled ) { + disableMsgType(CAMERA_MSG_SHUTTER); + } // Shutters only happen in response to takePicture, so mark device as // idle now, until preview is restarted @@ -882,7 +906,13 @@ void CameraClient::handleRawPicture(const sp<IMemory>& mem) { // picture callback - compressed picture ready void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) { - disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); + if (mBurstCnt) + mBurstCnt--; + + if (!mBurstCnt && !mLongshotEnabled) { + LOG1("handleCompressedPicture mBurstCnt = %d", mBurstCnt); + disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE); + } sp<ICameraClient> c = mRemoteCallback; mLock.unlock(); diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h index 95616b2..9d2d02f 100644 --- a/services/camera/libcameraservice/api1/CameraClient.h +++ b/services/camera/libcameraservice/api1/CameraClient.h @@ -162,6 +162,9 @@ private: // This function keeps trying to grab mLock, or give up if the message // is found to be disabled. It returns true if mLock is grabbed. bool lockIfMessageWanted(int32_t msgType); + + bool mLongshotEnabled; + int mBurstCnt; }; } diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h index 7f14cd4..35947a9 100644 --- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h +++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h @@ -25,7 +25,10 @@ #include <camera/Camera.h> #include <camera/CameraParameters.h> #include <system/window.h> -#include <hardware/camera.h> +#include "hardware/camera.h" +#ifdef USE_MEMORY_HEAP_ION +#include <binder/MemoryHeapIon.h> +#endif namespace android { @@ -322,6 +325,10 @@ public: void releaseRecordingFrame(const sp<IMemory>& mem) { ALOGV("%s(%s)", __FUNCTION__, mName.string()); + if (mem == NULL) { + ALOGE("%s: NULL memory reference", __FUNCTION__); + return; + } if (mDevice->ops->release_recording_frame) { ssize_t offset; size_t size; @@ -501,7 +508,11 @@ private: mBufSize(buf_size), mNumBufs(num_buffers) { +#ifdef USE_MEMORY_HEAP_ION + mHeap = new MemoryHeapIon(fd, buf_size * num_buffers); +#else mHeap = new MemoryHeapBase(fd, buf_size * num_buffers); +#endif commonInitialization(); } @@ -509,7 +520,11 @@ private: mBufSize(buf_size), mNumBufs(num_buffers) { +#ifdef USE_MEMORY_HEAP_ION + mHeap = new MemoryHeapIon(buf_size * num_buffers); +#else mHeap = new MemoryHeapBase(buf_size * num_buffers); +#endif commonInitialization(); } @@ -541,14 +556,24 @@ private: camera_memory_t handle; }; +#ifdef USE_MEMORY_HEAP_ION + static camera_memory_t* __get_memory(int fd, size_t buf_size, uint_t num_bufs, + void *ion_fd) + { +#else static camera_memory_t* __get_memory(int fd, size_t buf_size, uint_t num_bufs, void *user __attribute__((unused))) { +#endif CameraHeapMemory *mem; if (fd < 0) mem = new CameraHeapMemory(buf_size, num_bufs); else mem = new CameraHeapMemory(fd, buf_size, num_bufs); +#ifdef USE_MEMORY_HEAP_ION + if (ion_fd) + *((int *) ion_fd) = mem->mHeap->getHeapID(); +#endif mem->incStrong(mem); return &mem->handle; } |