summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/audioflinger/Android.mk47
-rw-r--r--services/audioflinger/AudioFlinger.cpp72
-rw-r--r--services/audioflinger/AudioMixer.cpp27
-rw-r--r--services/audioflinger/AudioMixer.h1
-rw-r--r--services/audioflinger/AudioResampler.cpp25
-rw-r--r--services/audioflinger/AudioResampler.h3
-rw-r--r--services/audioflinger/AudioResamplerQTI.cpp168
-rw-r--r--services/audioflinger/AudioResamplerQTI.h52
-rw-r--r--services/audioflinger/BufferProviders.cpp2
-rw-r--r--services/audioflinger/Effects.cpp25
-rw-r--r--services/audioflinger/FastCapture.cpp2
-rw-r--r--services/audioflinger/Threads.cpp188
-rw-r--r--services/audioflinger/Threads.h26
-rw-r--r--services/audioflinger/Tracks.cpp14
-rw-r--r--services/audiopolicy/Android.mk4
-rw-r--r--services/audiopolicy/AudioPolicyInterface.h3
-rw-r--r--services/audiopolicy/common/managerdefinitions/Android.mk19
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h2
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h45
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h3
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp8
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp5
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp5
-rwxr-xr-xservices/audiopolicy/engineconfigurable/src/Stream.cpp10
-rwxr-xr-xservices/audiopolicy/enginedefault/Android.mk5
-rwxr-xr-xservices/audiopolicy/enginedefault/src/Engine.cpp46
-rw-r--r--services/audiopolicy/managerdefault/AudioPolicyManager.cpp72
-rw-r--r--services/audiopolicy/managerdefault/AudioPolicyManager.h14
-rw-r--r--services/audiopolicy/service/AudioPolicyClientImpl.cpp6
-rw-r--r--services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp5
-rw-r--r--services/audiopolicy/service/AudioPolicyEffects.cpp47
-rw-r--r--services/audiopolicy/service/AudioPolicyEffects.h15
-rw-r--r--services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp15
-rw-r--r--services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp25
-rw-r--r--services/audiopolicy/service/AudioPolicyService.cpp160
-rw-r--r--services/audiopolicy/service/AudioPolicyService.h57
-rw-r--r--services/camera/libcameraservice/Android.mk8
-rw-r--r--services/camera/libcameraservice/CameraService.h4
-rw-r--r--services/camera/libcameraservice/api1/Camera2Client.cpp2
-rw-r--r--services/camera/libcameraservice/api1/CameraClient.cpp36
-rw-r--r--services/camera/libcameraservice/api1/CameraClient.h3
-rw-r--r--services/camera/libcameraservice/device1/CameraHardwareInterface.h27
42 files changed, 1205 insertions, 98 deletions
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 9b4ba79..0dd2af6 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -1,3 +1,23 @@
+#
+# This file was modified by DTS, Inc. The portions of the
+# code that are surrounded by "DTS..." are copyrighted and
+# licensed separately, as follows:
+#
+# (C) 2015 DTS, Inc.
+#
+# 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.
+#
+
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -60,6 +80,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
@@ -78,6 +106,11 @@ LOCAL_SRC_FILES += \
LOCAL_CFLAGS += -DSTATE_QUEUE_INSTANTIATIONS='"StateQueueInstantiations.cpp"'
LOCAL_CFLAGS += -fvisibility=hidden
+ifeq ($(strip $(BOARD_USES_SRS_TRUEMEDIA)),true)
+LOCAL_SHARED_LIBRARIES += libsrsprocessing
+LOCAL_CFLAGS += -DSRS_PROCESSING
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audio-effects
+endif
include $(BUILD_SHARED_LIBRARY)
@@ -123,7 +156,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 fab1ef5..23215dd 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -13,6 +13,25 @@
** 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.
+**
+** This file was modified by DTS, Inc. The portions of the
+** code that are surrounded by "DTS..." are copyrighted and
+** licensed separately, as follows:
+**
+** (C) 2015 DTS, Inc.
+**
+** 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.
+**
*/
@@ -64,6 +83,9 @@
#include <media/nbaio/PipeReader.h>
#include <media/AudioParameter.h>
#include <private/android_filesystem_config.h>
+#ifdef SRS_PROCESSING
+#include "postpro_patch.h"
+#endif
// ----------------------------------------------------------------------------
@@ -131,6 +153,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;
}
@@ -1043,6 +1073,13 @@ status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8&
if (ioHandle == AUDIO_IO_HANDLE_NONE) {
Mutex::Autolock _l(mLock);
status_t final_result = NO_ERROR;
+#ifdef SRS_PROCESSING
+ POSTPRO_PATCH_PARAMS_SET(keyValuePairs);
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+ PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+ thread->setPostPro();
+ }
+#endif
{
AutoMutex lock(mHardwareLock);
mHardwareStatus = AUDIO_HW_SET_PARAMETER;
@@ -1053,9 +1090,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) {
@@ -1122,6 +1174,9 @@ String8 AudioFlinger::getParameters(audio_io_handle_t ioHandle, const String8& k
if (ioHandle == AUDIO_IO_HANDLE_NONE) {
String8 out_s8;
+#ifdef SRS_PROCESSING
+ POSTPRO_PATCH_PARAMS_GET(keys, out_s8);
+#endif
for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
char *s;
@@ -1347,6 +1402,12 @@ sp<AudioFlinger::PlaybackThread> AudioFlinger::getEffectThread_l(int sessionId,
+void AudioFlinger::PlaybackThread::setPostPro()
+{
+ Mutex::Autolock _l(mLock);
+ if (mType == OFFLOAD)
+ broadcast_l();
+}
// ----------------------------------------------------------------------------
AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
@@ -1822,7 +1883,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);
@@ -2964,6 +3029,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);
+ ALOG_ASSERT(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..806eaf1 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 {
// ----------------------------------------------------------------------------
@@ -305,6 +308,11 @@ bool AudioMixer::setChannelMasks(int name,
void AudioMixer::track_t::unprepareForDownmix() {
ALOGV("AudioMixer::unprepareForDownmix(%p)", this);
+ if (mPostDownmixReformatBufferProvider != NULL) {
+ delete mPostDownmixReformatBufferProvider;
+ mPostDownmixReformatBufferProvider = NULL;
+ reconfigureBufferProviders();
+ }
mDownmixRequiresFormat = AUDIO_FORMAT_INVALID;
if (downmixerBufferProvider != NULL) {
// this track had previously been configured with a downmixer, delete it
@@ -360,18 +368,9 @@ status_t AudioMixer::track_t::prepareForDownmix()
void AudioMixer::track_t::unprepareForReformat() {
ALOGV("AudioMixer::unprepareForReformat(%p)", this);
- bool requiresReconfigure = false;
if (mReformatBufferProvider != NULL) {
delete mReformatBufferProvider;
mReformatBufferProvider = NULL;
- requiresReconfigure = true;
- }
- if (mPostDownmixReformatBufferProvider != NULL) {
- delete mPostDownmixReformatBufferProvider;
- mPostDownmixReformatBufferProvider = NULL;
- requiresReconfigure = true;
- }
- if (requiresReconfigure) {
reconfigureBufferProviders();
}
}
@@ -779,6 +778,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 +1650,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..879b6c9 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,13 +1113,15 @@ 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();
}
if (!mEffect->isOffloadable()) {
- if (thread->type() == ThreadBase::OFFLOAD) {
+ if (thread->type() == ThreadBase::OFFLOAD ||
+ (thread->type() == ThreadBase::DIRECT && thread->mIsDirectPcm)) {
PlaybackThread *t = (PlaybackThread *)thread.get();
t->invalidateTracks(AUDIO_STREAM_MUSIC);
}
@@ -1156,7 +1158,8 @@ status_t AudioFlinger::EffectHandle::disable()
sp<ThreadBase> thread = mEffect->thread().promote();
if (thread != 0) {
thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
- 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();
@@ -1439,8 +1442,10 @@ void AudioFlinger::EffectChain::process_l()
(mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
// never process effects when:
// - on an OFFLOAD thread
+ // - on DIRECT thread with directPcm flag enabled
// - no more tracks are on the session and the effect tail has been rendered
- bool doProcess = (thread->type() != ThreadBase::OFFLOAD);
+ bool doProcess = ((thread->type() != ThreadBase::OFFLOAD) &&
+ (!(thread->type() == ThreadBase::DIRECT && thread->mIsDirectPcm)));
if (!isGlobalSession) {
bool tracksOnSession = (trackCnt() != 0);
diff --git a/services/audioflinger/FastCapture.cpp b/services/audioflinger/FastCapture.cpp
index 1bba5f6..2493fb7 100644
--- a/services/audioflinger/FastCapture.cpp
+++ b/services/audioflinger/FastCapture.cpp
@@ -105,7 +105,7 @@ void FastCapture::onStateChange()
mFormat = mInputSource->format();
mSampleRate = Format_sampleRate(mFormat);
unsigned channelCount = Format_channelCount(mFormat);
- ALOG_ASSERT(channelCount >= 1 && channelCount <= FCC_8);
+ ALOG_ASSERT(channelCount >= 1 && channelCount <= 8);
}
dumpState->mSampleRate = mSampleRate;
eitherChanged = true;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 7d2d550..c3ee6c2 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -13,6 +13,25 @@
** 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.
+**
+** This file was modified by DTS, Inc. The portions of the
+** code that are surrounded by "DTS..." are copyrighted and
+** licensed separately, as follows:
+**
+** (C) 2015 DTS, Inc.
+**
+** 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.
+**
*/
@@ -72,6 +91,9 @@
#include <cpustats/ThreadCpuUsage.h>
#endif
+#ifdef SRS_PROCESSING
+#include "postpro_patch.h"
+#endif
// ----------------------------------------------------------------------------
// Note: the following macro is used for extremely verbose logging message. In
@@ -544,6 +566,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 +1177,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;
@@ -1163,7 +1187,7 @@ sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
// Reject any effect on mixer or duplicating multichannel sinks.
// TODO: fix both format and multichannel issues with effects.
- if ((mType == MIXER || mType == DUPLICATING) && mChannelCount != FCC_2) {
+ if ((mType == MIXER || mType == DUPLICATING) && mChannelCount > FCC_2) {
ALOGW("createEffect_l() Cannot add effect %s for multichannel(%d) %s threads",
desc->name, mChannelCount, mType == MIXER ? "MIXER" : "DUPLICATING");
lStatus = BAD_VALUE;
@@ -1171,12 +1195,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 +1258,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 +1348,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) {
@@ -2167,6 +2208,7 @@ void AudioFlinger::PlaybackThread::readOutputParameters_l()
kUseFastMixer == FastMixer_Dynamic)) {
size_t minNormalFrameCount = (kMinNormalSinkBufferSizeMs * mSampleRate) / 1000;
size_t maxNormalFrameCount = (kMaxNormalSinkBufferSizeMs * mSampleRate) / 1000;
+
// round up minimum and round down maximum to nearest 16 frames to satisfy AudioMixer
minNormalFrameCount = (minNormalFrameCount + 15) & ~15;
maxNormalFrameCount = maxNormalFrameCount & ~15;
@@ -2182,19 +2224,6 @@ void AudioFlinger::PlaybackThread::readOutputParameters_l()
} else {
multiplier = (double) maxNormalFrameCount / (double) mFrameCount;
}
- } else {
- // prefer an even multiplier, for compatibility with doubling of fast tracks due to HAL
- // SRC (it would be unusual for the normal sink buffer size to not be a multiple of fast
- // track, but we sometimes have to do this to satisfy the maximum frame count
- // constraint)
- // FIXME this rounding up should not be done if no HAL SRC
- uint32_t truncMult = (uint32_t) multiplier;
- if ((truncMult & 1)) {
- if ((truncMult + 1) * mFrameCount <= maxNormalFrameCount) {
- ++truncMult;
- }
- }
- multiplier = (double) truncMult;
}
}
mNormalFrameCount = multiplier * mFrameCount;
@@ -2731,6 +2760,19 @@ bool AudioFlinger::PlaybackThread::threadLoop()
const String8 myName(String8::format("thread %p type %d TID %d", this, mType, gettid()));
acquireWakeLock();
+#ifdef SRS_PROCESSING
+ String8 bt_param = String8("bluetooth_enabled=0");
+ POSTPRO_PATCH_PARAMS_SET(bt_param);
+ if (mType == MIXER) {
+ POSTPRO_PATCH_OUTPROC_PLAY_INIT(this, myName);
+ } else if (mType == OFFLOAD) {
+ POSTPRO_PATCH_OUTPROC_DIRECT_INIT(this, myName);
+ POSTPRO_PATCH_OUTPROC_PLAY_ROUTE_BY_VALUE(this, mOutDevice);
+ } else if (mType == DIRECT) {
+ POSTPRO_PATCH_OUTPROC_DIRECT_INIT(this, myName);
+ POSTPRO_PATCH_OUTPROC_PLAY_ROUTE_BY_VALUE(this, mOutDevice);
+ }
+#endif
// mNBLogWriter->log can only be called while thread mutex mLock is held.
// So if you need to log when mutex is unlocked, set logString to a non-NULL string,
@@ -2906,7 +2948,8 @@ bool AudioFlinger::PlaybackThread::threadLoop()
}
// only process effects if we're going to write
- if (mSleepTimeUs == 0 && mType != OFFLOAD) {
+ if (mSleepTimeUs == 0 && mType != OFFLOAD &&
+ !(mType == DIRECT && mIsDirectPcm)) {
for (size_t i = 0; i < effectChains.size(); i ++) {
effectChains[i]->process_l();
}
@@ -2916,12 +2959,18 @@ bool AudioFlinger::PlaybackThread::threadLoop()
// was read from audio track: process only updates effect state
// and thus does have to be synchronized with audio writes but may have
// to be called while waiting for async write callback
- if (mType == OFFLOAD) {
+ if ((mType == OFFLOAD) || (mType == DIRECT && mIsDirectPcm)) {
for (size_t i = 0; i < effectChains.size(); i ++) {
effectChains[i]->process_l();
}
}
-
+#ifdef SRS_PROCESSING
+ // Offload thread
+ if (mType == OFFLOAD) {
+ char buffer[2];
+ POSTPRO_PATCH_OUTPROC_DIRECT_SAMPLES(this, AUDIO_FORMAT_PCM_16_BIT, (int16_t *) buffer, 2, 48000, 2);
+ }
+#endif
// Only if the Effects buffer is enabled and there is data in the
// Effects buffer (buffer valid), we need to
// copy into the sink buffer.
@@ -2939,6 +2988,11 @@ bool AudioFlinger::PlaybackThread::threadLoop()
// mSleepTimeUs == 0 means we must write to audio hardware
if (mSleepTimeUs == 0) {
ssize_t ret = 0;
+#ifdef SRS_PROCESSING
+ if (mType == MIXER && mMixerStatus == MIXER_TRACKS_READY) {
+ POSTPRO_PATCH_OUTPROC_PLAY_SAMPLES(this, mFormat, mSinkBuffer, mSinkBufferSize, mSampleRate, mChannelCount);
+ }
+#endif
if (mBytesRemaining) {
ret = threadLoop_write();
if (ret < 0) {
@@ -2982,8 +3036,9 @@ bool AudioFlinger::PlaybackThread::threadLoop()
// the app won't fill fast enough to handle the sudden draw).
const int32_t deltaMs = delta / 1000000;
- const int32_t throttleMs = mHalfBufferMs - deltaMs;
- if ((signed)mHalfBufferMs >= throttleMs && throttleMs > 0) {
+ const int32_t halfBufferMs = mHalfBufferMs / (mEffectBufferValid ? 4 : 1);
+ const int32_t throttleMs = halfBufferMs - deltaMs;
+ if ((signed)halfBufferMs >= throttleMs && throttleMs > 0) {
usleep(throttleMs * 1000);
// notify of throttle start on verbose log
ALOGV_IF(mThreadThrottleEndMs == mThreadThrottleTimeMs,
@@ -3034,7 +3089,15 @@ bool AudioFlinger::PlaybackThread::threadLoop()
threadLoop_standby();
mStandby = true;
}
-
+#ifdef SRS_PROCESSING
+ if (mType == MIXER) {
+ POSTPRO_PATCH_OUTPROC_PLAY_EXIT(this, myName);
+ } else if (mType == OFFLOAD) {
+ POSTPRO_PATCH_OUTPROC_DIRECT_EXIT(this, myName);
+ } else if (mType == DIRECT) {
+ POSTPRO_PATCH_OUTPROC_DIRECT_EXIT(this, myName);
+ }
+#endif
releaseWakeLock();
mWakeLockUids.clear();
mActiveTracksGeneration++;
@@ -3128,6 +3191,10 @@ status_t AudioFlinger::PlaybackThread::createAudioPatch_l(const struct audio_pat
type |= patch->sinks[i].ext.device.type;
}
+#ifdef SRS_PROCESSING
+ POSTPRO_PATCH_OUTPROC_PLAY_ROUTE_BY_VALUE(this, type);
+#endif
+
#ifdef ADD_BATTERY_DATA
// when changing the audio output device, call addBatteryData to notify
// the change
@@ -3311,11 +3378,15 @@ AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, Aud
}
if (initFastMixer) {
audio_format_t fastMixerFormat;
+#ifdef LEGACY_ALSA_AUDIO
+ fastMixerFormat = AUDIO_FORMAT_PCM_16_BIT;
+#else
if (mMixerBufferEnabled && mEffectBufferEnabled) {
fastMixerFormat = AUDIO_FORMAT_PCM_FLOAT;
} else {
fastMixerFormat = AUDIO_FORMAT_PCM_16_BIT;
}
+#endif
if (mFormat != fastMixerFormat) {
// change our Sink format to accept our intermediate precision
mFormat = fastMixerFormat;
@@ -4280,6 +4351,9 @@ bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePa
AudioParameter param = AudioParameter(keyValuePair);
int value;
+#ifdef SRS_PROCESSING
+ POSTPRO_PATCH_OUTPROC_PLAY_ROUTE(this, param, value);
+#endif
if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
reconfig = true;
}
@@ -4823,6 +4897,7 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameter_l(const String8& key
AudioParameter param = AudioParameter(keyValuePair);
int value;
+
if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
// forward device change to effects that have requested to be
// aware of attached audio device.
@@ -5312,6 +5387,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);
}
@@ -5333,7 +5410,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;
@@ -6573,7 +6654,11 @@ size_t AudioFlinger::RecordThread::RecordBufferConverter::convert(void *dst,
break;
}
// format convert to destination buffer
+#ifdef LEGACY_ALSA_AUDIO
+ convert(dst, buffer.raw, buffer.frameCount);
+#else
convertNoResampler(dst, buffer.raw, buffer.frameCount);
+#endif
dst = (int8_t*)dst + buffer.frameCount * mDstFrameSize;
i -= buffer.frameCount;
@@ -6593,7 +6678,11 @@ size_t AudioFlinger::RecordThread::RecordBufferConverter::convert(void *dst,
memset(mBuf, 0, frames * mBufFrameSize);
frames = mResampler->resample((int32_t*)mBuf, frames, provider);
// format convert to destination buffer
+#ifdef LEGACY_ALSA_AUDIO
+ convert(dst, mBuf, frames);
+#else
convertResampler(dst, mBuf, frames);
+#endif
}
return frames;
}
@@ -6694,6 +6783,56 @@ status_t AudioFlinger::RecordThread::RecordBufferConverter::updateParameters(
return NO_ERROR;
}
+#ifdef LEGACY_ALSA_AUDIO
+void AudioFlinger::RecordThread::RecordBufferConverter::convert(
+ void *dst, /*const*/ void *src, size_t frames)
+{
+ // check if a memcpy will do
+ if (mResampler == NULL
+ && mSrcChannelCount == mDstChannelCount
+ && mSrcFormat == mDstFormat) {
+ memcpy(dst, src,
+ frames * mDstChannelCount * audio_bytes_per_sample(mDstFormat));
+ return;
+ }
+ // reallocate buffer if needed
+ if (mBufFrameSize != 0 && mBufFrames < frames) {
+ free(mBuf);
+ mBufFrames = frames;
+ (void)posix_memalign(&mBuf, 32, mBufFrames * mBufFrameSize);
+ }
+ // do processing
+ if (mResampler != NULL) {
+ // src channel count is always >= 2.
+ void *dstBuf = mBuf != NULL ? mBuf : dst;
+ // ditherAndClamp() works as long as all buffers returned by
+ // activeTrack->getNextBuffer() are 32 bit aligned which should be always true.
+ if (mDstChannelCount == 1) {
+ // the resampler always outputs stereo samples.
+ // FIXME: this rewrites back into src
+ ditherAndClamp((int32_t *)src, (const int32_t *)src, frames);
+ downmix_to_mono_i16_from_stereo_i16((int16_t *)dstBuf,
+ (const int16_t *)src, frames);
+ } else {
+ ditherAndClamp((int32_t *)dstBuf, (const int32_t *)src, frames);
+ }
+ } else if (mSrcChannelCount != mDstChannelCount) {
+ void *dstBuf = mBuf != NULL ? mBuf : dst;
+ if (mSrcChannelCount == 1) {
+ upmix_to_stereo_i16_from_mono_i16((int16_t *)dstBuf, (const int16_t *)src,
+ frames);
+ } else {
+ downmix_to_mono_i16_from_stereo_i16((int16_t *)dstBuf,
+ (const int16_t *)src, frames);
+ }
+ }
+ if (mSrcFormat != mDstFormat) {
+ void *srcBuf = mBuf != NULL ? mBuf : src;
+ memcpy_by_audio_format(dst, mDstFormat, srcBuf, mSrcFormat,
+ frames * mDstChannelCount);
+ }
+}
+#else
void AudioFlinger::RecordThread::RecordBufferConverter::convertNoResampler(
void *dst, const void *src, size_t frames)
{
@@ -6767,6 +6906,7 @@ void AudioFlinger::RecordThread::RecordBufferConverter::convertResampler(
memcpy_by_audio_format(dst, mDstFormat, src, AUDIO_FORMAT_PCM_FLOAT,
frames * mDstChannelCount);
}
+#endif
bool AudioFlinger::RecordThread::checkForNewParameter_l(const String8& keyValuePair,
status_t& status)
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 46ac300..48ff77d 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -13,6 +13,24 @@
** 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.
+**
+** This file was modified by DTS, Inc. The portions of the
+** code that are surrounded by "DTS..." are copyrighted and
+** licensed separately, as follows:
+**
+** (C) 2015 DTS, Inc.
+**
+** 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 INCLUDING_FROM_AUDIOFLINGER_H
@@ -457,6 +475,7 @@ protected:
static const size_t kLogSize = 4 * 1024;
sp<NBLog::Writer> mNBLogWriter;
bool mSystemReady;
+ bool mIsDirectPcm; // flag to indicate unique Direct thread
};
// --- PlaybackThread ---
@@ -536,7 +555,7 @@ public:
void setMasterVolume(float value);
void setMasterMute(bool muted);
-
+ void setPostPro();
void setStreamVolume(audio_stream_type_t stream, float value);
void setStreamMute(audio_stream_type_t stream, bool muted);
@@ -1159,11 +1178,16 @@ public:
}
private:
+#ifdef LEGACY_ALSA_AUDIO
+ // internal convert function for format and channel mask.
+ void convert(void *dst, /*const*/ void *src, size_t frames);
+#else
// format conversion when not using resampler
void convertNoResampler(void *dst, const void *src, size_t frames);
// format conversion when using resampler; modifies src in-place
void convertResampler(void *dst, /*not-a-const*/ void *src, size_t frames);
+#endif
// user provided information
audio_channel_mask_t mSrcChannelMask;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 0e24b52..f3b5375 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>
@@ -706,10 +707,11 @@ status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t ev
mState = state;
}
}
- // track was already in the active list, not a problem
- if (status == ALREADY_EXISTS) {
- status = NO_ERROR;
- } else {
+ // If track was already in the active list, not a problem unless
+ // track is fast and sharedBuffer is used and frameReady has already become 0.
+ // In such case we need to call obtainbuffer() to refresh the framesReady value.
+ if ((status != ALREADY_EXISTS) ||
+ (isFastTrack() && (mSharedBuffer != 0) && (framesReady() == 0))) {
// Acknowledge any pending flush(), so that subsequent new data isn't discarded.
// It is usually unsafe to access the server proxy from a binder thread.
// But in this case we know the mixer thread (whether normal mixer or fast mixer)
@@ -720,6 +722,9 @@ status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t ev
buffer.mFrameCount = 1;
(void) mAudioTrackServerProxy->obtainBuffer(&buffer, true /*ackFlush*/);
}
+
+ if (status == ALREADY_EXISTS)
+ status = NO_ERROR;
} else {
status = BAD_VALUE;
}
@@ -1775,6 +1780,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/Android.mk b/services/audiopolicy/Android.mk
index 5b38e1c..69fc0e8 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -40,6 +40,10 @@ LOCAL_SHARED_LIBRARIES += \
libaudiopolicymanager
endif
+ifeq ($(BOARD_HAVE_PRE_KITKAT_AUDIO_POLICY_BLOB),true)
+ LOCAL_CFLAGS += -DHAVE_PRE_KITKAT_AUDIO_POLICY_BLOB
+endif
+
LOCAL_STATIC_LIBRARIES := \
libmedia_helper \
libaudiopolicycomponents
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index c1e7bc0..a5edc14 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -331,6 +331,9 @@ public:
virtual audio_unique_id_t newAudioUniqueId() = 0;
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0;
+
+ virtual void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
+ audio_unique_id_t sessionId, bool added) = 0;
};
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface);
diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk
index 8728ff3..5ef9b38 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.mk
+++ b/services/audiopolicy/common/managerdefinitions/Android.mk
@@ -31,6 +31,25 @@ LOCAL_C_INCLUDES += \
LOCAL_EXPORT_C_INCLUDE_DIRS := \
$(LOCAL_PATH)/include
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_FLAC_OFFLOAD)),true)
+LOCAL_CFLAGS += -DFLAC_OFFLOAD_ENABLED
+endif
+ifneq ($(strip $(AUDIO_FEATURE_ENABLED_PROXY_DEVICE)),false)
+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
+
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..6f80435 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),
@@ -96,6 +99,9 @@ const StringToEnum sDeviceTypeToEnumTable[] = {
STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
STRING_TO_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
STRING_TO_ENUM(AUDIO_DEVICE_IN_IP),
+#ifdef LEGACY_ALSA_AUDIO
+ STRING_TO_ENUM(AUDIO_DEVICE_IN_COMMUNICATION),
+#endif
};
const StringToEnum sDeviceNameToEnumTable[] = {
@@ -153,6 +159,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),
@@ -162,6 +169,7 @@ const StringToEnum sOutputFlagNameToEnumTable[] = {
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_TTS),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_RAW),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_SYNC),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
};
const StringToEnum sInputFlagNameToEnumTable[] = {
@@ -198,6 +206,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 +241,22 @@ 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),
+#ifdef LEGACY_ALSA_AUDIO
+ STRING_TO_ENUM(AUDIO_CHANNEL_IN_VOICE_CALL_MONO),
+ STRING_TO_ENUM(AUDIO_CHANNEL_IN_VOICE_DNLINK_MONO),
+ STRING_TO_ENUM(AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO),
+#endif
};
const StringToEnum sIndexChannelsNameToEnumTable[] = {
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
index c9783a1..396541b 100644
--- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -21,6 +21,7 @@
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include <utils/Errors.h>
+#include <utils/Thread.h>
namespace android {
@@ -66,6 +67,8 @@ private:
* Maximum memory allocated to audio effects in KB
*/
static const uint32_t MAX_EFFECTS_MEMORY = 512;
+
+ Mutex mLock;
};
}; // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index a278375..cefbe79 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)
{
@@ -428,7 +428,11 @@ audio_io_handle_t SwAudioOutputCollection::getA2dpOutput() const
return this->keyAt(i);
}
}
+#ifdef LEGACY_ALSA_AUDIO
+ return 1;
+#else
return 0;
+#endif
}
sp<SwAudioOutputDescriptor> SwAudioOutputCollection::getPrimaryOutput() const
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
index 33d838d..6a0d079 100644
--- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -56,6 +56,7 @@ status_t EffectDescriptorCollection::registerEffect(const effect_descriptor_t *d
int session,
int id)
{
+ Mutex::Autolock _l(mLock);
if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
desc->name, desc->memoryUsage);
@@ -80,6 +81,7 @@ status_t EffectDescriptorCollection::registerEffect(const effect_descriptor_t *d
status_t EffectDescriptorCollection::unregisterEffect(int id)
{
+ Mutex::Autolock _l(mLock);
ssize_t index = indexOfKey(id);
if (index < 0) {
ALOGW("unregisterEffect() unknown effect ID %d", id);
@@ -106,6 +108,7 @@ status_t EffectDescriptorCollection::unregisterEffect(int id)
status_t EffectDescriptorCollection::setEffectEnabled(int id, bool enabled)
{
+ Mutex::Autolock _l(mLock);
ssize_t index = indexOfKey(id);
if (index < 0) {
ALOGW("unregisterEffect() unknown effect ID %d", id);
@@ -148,6 +151,7 @@ status_t EffectDescriptorCollection::setEffectEnabled(const sp<EffectDescriptor>
bool EffectDescriptorCollection::isNonOffloadableEffectEnabled()
{
+ Mutex::Autolock _l(mLock);
for (size_t i = 0; i < size(); i++) {
sp<EffectDescriptor> effectDesc = valueAt(i);
if (effectDesc->mEnabled && (effectDesc->mStrategy == STRATEGY_MEDIA) &&
@@ -172,6 +176,7 @@ uint32_t EffectDescriptorCollection::getMaxEffectsMemory() const
status_t EffectDescriptorCollection::dump(int fd)
{
+ Mutex::Autolock _l(mLock);
const size_t SIZE = 256;
char buffer[SIZE];
diff --git a/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
index b682e2c..4ca27c2 100644
--- a/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp
@@ -35,7 +35,10 @@ namespace android {
StreamDescriptor::StreamDescriptor()
: mIndexMin(0), mIndexMax(1), mCanBeMuted(true)
{
- mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, 0);
+ // Initialize the current stream's index to mIndexMax so volume isn't 0 in
+ // cases where the Java layer doesn't call into the audio policy service to
+ // set the default volume.
+ mIndexCur.add(AUDIO_DEVICE_OUT_DEFAULT, mIndexMax);
}
int StreamDescriptor::getVolumeIndex(audio_devices_t device) const
diff --git a/services/audiopolicy/engineconfigurable/src/Stream.cpp b/services/audiopolicy/engineconfigurable/src/Stream.cpp
index bea2c19..a929435 100755
--- a/services/audiopolicy/engineconfigurable/src/Stream.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Stream.cpp
@@ -98,13 +98,13 @@ float Element<audio_stream_type_t>::volIndexToDb(Volume::device_category deviceC
if (it == mVolumeProfiles.end()) {
ALOGE("%s: device category %d not found for stream %s", __FUNCTION__, deviceCategory,
getName().c_str());
- return 1.0f;
+ return 0.0f;
}
const VolumeCurvePoints curve = mVolumeProfiles[deviceCategory];
if (curve.size() != Volume::VOLCNT) {
ALOGE("%s: invalid profile for category %d and for stream %s", __FUNCTION__, deviceCategory,
getName().c_str());
- return 1.0f;
+ return 0.0f;
}
// the volume index in the UI is relative to the min and max volume indices for this stream type
@@ -113,7 +113,7 @@ float Element<audio_stream_type_t>::volIndexToDb(Volume::device_category deviceC
if (mIndexMax - mIndexMin == 0) {
ALOGE("%s: Invalid volume indexes Min=Max=%d", __FUNCTION__, mIndexMin);
- return 1.0f;
+ return 0.0f;
}
int volIdx = (nbSteps * (indexInUi - mIndexMin)) /
(mIndexMax - mIndexMin);
@@ -121,7 +121,7 @@ float Element<audio_stream_type_t>::volIndexToDb(Volume::device_category deviceC
// find what part of the curve this index volume belongs to, or if it's out of bounds
int segment = 0;
if (volIdx < curve[Volume::VOLMIN].mIndex) { // out of bounds
- return 0.0f;
+ return VOLUME_MIN_DB;
} else if (volIdx < curve[Volume::VOLKNEE1].mIndex) {
segment = 0;
} else if (volIdx < curve[Volume::VOLKNEE2].mIndex) {
@@ -129,7 +129,7 @@ float Element<audio_stream_type_t>::volIndexToDb(Volume::device_category deviceC
} else if (volIdx <= curve[Volume::VOLMAX].mIndex) {
segment = 2;
} else { // out of bounds
- return 1.0f;
+ return 0.0f;
}
// linear interpolation in the attenuation table in dB
diff --git a/services/audiopolicy/enginedefault/Android.mk b/services/audiopolicy/enginedefault/Android.mk
index 8d43b89..f6ffa2a 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)
+ifneq ($(strip $(AUDIO_FEATURE_ENABLED_PROXY_DEVICE)),false)
+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..627e1d3 100755
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -355,7 +355,11 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
// - cannot route from voice call RX OR
// - audio HAL version is < 3.0 and TX device is on the primary HW module
if (getPhoneState() == AUDIO_MODE_IN_CALL) {
+#ifdef LEGACY_ALSA_AUDIO
+ audio_devices_t txDevice = getDeviceForInputSource(AUDIO_SOURCE_VOICE_CALL);
+#else
audio_devices_t txDevice = getDeviceForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
+#endif
sp<AudioOutputDescriptor> primaryOutput = outputs.getPrimaryOutput();
audio_devices_t availPrimaryInputDevices =
availableInputDevices.getDevicesFromHwModule(primaryOutput->getModuleHandle());
@@ -408,9 +412,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 +455,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 +510,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 +560,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;
}
@@ -591,9 +619,11 @@ audio_devices_t Engine::getDeviceForStrategy(routing_strategy strategy) const
audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) const
{
- const DeviceVector &availableOutputDevices = mApmObserver->getAvailableOutputDevices();
const DeviceVector &availableInputDevices = mApmObserver->getAvailableInputDevices();
+#ifndef LEGACY_ALSA_AUDIO
+ const DeviceVector &availableOutputDevices = mApmObserver->getAvailableOutputDevices();
const SwAudioOutputCollection &outputs = mApmObserver->getOutputs();
+#endif
audio_devices_t availableDeviceTypes = availableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
uint32_t device = AUDIO_DEVICE_NONE;
@@ -623,6 +653,9 @@ audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) cons
break;
case AUDIO_SOURCE_VOICE_COMMUNICATION:
+#ifdef LEGACY_ALSA_AUDIO
+ device = AUDIO_DEVICE_IN_COMMUNICATION;
+#else
// Allow only use of devices on primary input if in call and HAL does not support routing
// to voice call path.
if ((getPhoneState() == AUDIO_MODE_IN_CALL) &&
@@ -660,6 +693,7 @@ audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) cons
}
break;
}
+#endif
break;
case AUDIO_SOURCE_VOICE_RECOGNITION:
@@ -671,6 +705,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 5ff1c0b..50b5087 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -88,6 +88,20 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
}
ALOGV("setDeviceConnectionState() connecting device %x", device);
+#ifdef LEGACY_ALSA_AUDIO
+ if (device & AUDIO_DEVICE_OUT_ALL_A2DP) {
+ AudioParameter param;
+ param.add(String8("a2dp_connected"), String8("true"));
+ mpClientInterface->setParameters(0, param.toString());
+ }
+
+ if (device & AUDIO_DEVICE_OUT_USB_ACCESSORY) {
+ AudioParameter param;
+ param.add(String8("usb_connected"), String8("true"));
+ mpClientInterface->setParameters(0, param.toString());
+ }
+#endif
+
// register new device as available
index = mAvailableOutputDevices.add(devDesc);
if (index >= 0) {
@@ -139,6 +153,20 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
// remove device from available output devices
mAvailableOutputDevices.remove(devDesc);
+#ifdef LEGACY_ALSA_AUDIO
+ if (device & AUDIO_DEVICE_OUT_ALL_A2DP) {
+ AudioParameter param;
+ param.add(String8("a2dp_connected"), String8("false"));
+ mpClientInterface->setParameters(0, param.toString());
+ }
+
+ if (device & AUDIO_DEVICE_OUT_USB_ACCESSORY) {
+ AudioParameter param;
+ param.add(String8("usb_connected"), String8("true"));
+ mpClientInterface->setParameters(0, param.toString());
+ }
+#endif
+
checkOutputsForDevice(devDesc, state, outputs, devDesc->mAddress);
// Propagate device availability to Engine
@@ -305,7 +333,11 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs
if(!hasPrimaryOutput()) {
return;
}
+#ifdef LEGACY_ALSA_AUDIO
+ audio_devices_t txDevice = getDeviceAndMixForInputSource(AUDIO_SOURCE_VOICE_CALL);
+#else
audio_devices_t txDevice = getDeviceAndMixForInputSource(AUDIO_SOURCE_VOICE_COMMUNICATION);
+#endif
ALOGV("updateCallRouting device rxDevice %08x txDevice %08x", rxDevice, txDevice);
// release existing RX patch if any
@@ -351,6 +383,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");
@@ -608,7 +648,8 @@ sp<IOProfile> AudioPolicyManager::getProfileForDirectOutput(
// only retain flags that will drive the direct output profile selection
// if explicitly requested
static const uint32_t kRelevantFlags =
- (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
+ (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD |
+ AUDIO_OUTPUT_FLAG_VOIP_RX);
flags =
(audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT);
@@ -1356,6 +1397,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) {
@@ -1376,20 +1423,22 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
} else {
*inputType = API_INPUT_LEGACY;
}
+#ifdef LEGACY_ALSA_AUDIO
// adapt channel selection to input source
switch (inputSource) {
case AUDIO_SOURCE_VOICE_UPLINK:
- channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK;
+ channelMask |= AUDIO_CHANNEL_IN_VOICE_UPLINK;
break;
case AUDIO_SOURCE_VOICE_DOWNLINK:
- channelMask = AUDIO_CHANNEL_IN_VOICE_DNLINK;
+ channelMask |= AUDIO_CHANNEL_IN_VOICE_DNLINK;
break;
case AUDIO_SOURCE_VOICE_CALL:
- channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK;
+ channelMask |= AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK;
break;
default:
break;
}
+#endif
if (inputSource == AUDIO_SOURCE_HOTWORD) {
ssize_t index = mSoundTriggerSessions.indexOfKey(session);
if (index >= 0) {
@@ -1802,6 +1851,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]);
@@ -1809,6 +1859,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];
}
@@ -1819,6 +1872,9 @@ audio_io_handle_t AudioPolicyManager::selectOutputForEffects(
if (outputOffloaded != 0) {
return outputOffloaded;
}
+ if (outputDirectPcm != 0) {
+ return outputDirectPcm;
+ }
if (outputDeepBuffer != 0) {
return outputDeepBuffer;
}
@@ -3810,7 +3866,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
@@ -3891,11 +3947,13 @@ void AudioPolicyManager::checkOutputForAllStrategies()
void AudioPolicyManager::checkA2dpSuspend()
{
+#ifndef LEGACY_ALSA_AUDIO
audio_io_handle_t a2dpOutput = mOutputs.getA2dpOutput();
if (a2dpOutput == 0) {
mA2dpSuspended = false;
return;
}
+#endif
bool isScoConnected =
((mAvailableInputDevices.types() & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET &
@@ -3920,7 +3978,9 @@ void AudioPolicyManager::checkA2dpSuspend()
((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) &&
(mEngine->getPhoneState() != AUDIO_MODE_RINGTONE))) {
+#ifndef LEGACY_ALSA_AUDIO
mpClientInterface->restoreOutput(a2dpOutput);
+#endif
mA2dpSuspended = false;
}
} else {
@@ -3930,7 +3990,9 @@ void AudioPolicyManager::checkA2dpSuspend()
((mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) ||
(mEngine->getPhoneState() == AUDIO_MODE_RINGTONE))) {
+#ifndef LEGACY_ALSA_AUDIO
mpClientInterface->suspendOutput(a2dpOutput);
+#endif
mA2dpSuspended = true;
}
}
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/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 489a9be..d71daa4 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -219,6 +219,12 @@ void AudioPolicyService::AudioPolicyClient::onDynamicPolicyMixStateUpdate(
mAudioPolicyService->onDynamicPolicyMixStateUpdate(regId, state);
}
+void AudioPolicyService::AudioPolicyClient::onOutputSessionEffectsUpdate(
+ audio_stream_type_t stream, audio_unique_id_t sessionId, bool added)
+{
+ mAudioPolicyService->onOutputSessionEffectsUpdate(stream, sessionId, added);
+}
+
audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId()
{
return AudioSystem::newAudioUniqueId();
diff --git a/services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp b/services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp
index a79f8ae..36c85f1 100644
--- a/services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImplLegacy.cpp
@@ -125,8 +125,13 @@ audio_io_handle_t aps_open_output_on_module(void *service __unused,
audio_output_flags_t flags,
const audio_offload_info_t *offloadInfo)
{
+#ifdef HAVE_PRE_KITKAT_AUDIO_POLICY_BLOB
+ return open_output(module, pDevices, pSamplingRate, pFormat, pChannelMask,
+ pLatencyMs, flags, NULL);
+#else
return open_output(module, pDevices, pSamplingRate, pFormat, pChannelMask,
pLatencyMs, flags, offloadInfo);
+#endif
}
audio_io_handle_t aps_open_dup_output(void *service __unused,
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 282ddeb..f2d7f6f 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -28,6 +28,7 @@
#include <utils/Vector.h>
#include <utils/SortedVector.h>
#include <cutils/config_utils.h>
+#include "AudioPolicyService.h"
#include "AudioPolicyEffects.h"
#include "ServiceUtilities.h"
@@ -37,10 +38,13 @@ namespace android {
// AudioPolicyEffects Implementation
// ----------------------------------------------------------------------------
-AudioPolicyEffects::AudioPolicyEffects()
+AudioPolicyEffects::AudioPolicyEffects(AudioPolicyService *audioPolicyService) :
+ mAudioPolicyService(audioPolicyService)
{
// load automatic audio effect modules
- if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
+ if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE2, R_OK) == 0) {
+ loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE2);
+ } else if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
} else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
@@ -242,6 +246,8 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
if (idx < 0) {
procDesc = new EffectVector(audioSession);
mOutputSessions.add(audioSession, procDesc);
+
+ mAudioPolicyService->onOutputSessionEffectsUpdate(stream, audioSession, true);
} else {
// EffectVector is existing and we just need to increase ref count
procDesc = mOutputSessions.valueAt(idx);
@@ -289,15 +295,49 @@ status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t outpu
}
EffectVector *procDesc = mOutputSessions.valueAt(index);
+
+ // just in case it already has a death wish
+ if (procDesc->mRefCount == 0) {
+ return NO_ERROR;
+ }
+
procDesc->mRefCount--;
ALOGV("releaseOutputSessionEffects(): session: %d, refCount: %d",
audioSession, procDesc->mRefCount);
+
+ if (procDesc->mRefCount == 0) {
+ mAudioPolicyService->releaseOutputSessionEffectsDelayed(
+ output, stream, audioSession, 10000);
+ }
+
+ return status;
+}
+
+status_t AudioPolicyEffects::doReleaseOutputSessionEffects(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int audioSession)
+{
+ status_t status = NO_ERROR;
+ (void) output; // argument not used for now
+
+ Mutex::Autolock _l(mLock);
+ ssize_t index = mOutputSessions.indexOfKey(audioSession);
+ if (index < 0) {
+ ALOGV("doReleaseOutputSessionEffects: no output processing was attached to this stream");
+ return NO_ERROR;
+ }
+
+ EffectVector *procDesc = mOutputSessions.valueAt(index);
+ ALOGV("doReleaseOutputSessionEffects(): session: %d, refCount: %d",
+ audioSession, procDesc->mRefCount);
+
if (procDesc->mRefCount == 0) {
procDesc->setProcessorEnabled(false);
procDesc->mEffects.clear();
delete procDesc;
mOutputSessions.removeItemsAt(index);
- ALOGV("releaseOutputSessionEffects(): output processing released from session: %d",
+ mAudioPolicyService->onOutputSessionEffectsUpdate(stream, audioSession, false);
+ ALOGV("doReleaseOutputSessionEffects(): output processing released from session: %d",
audioSession);
}
return status;
@@ -442,6 +482,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..7988515 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -27,8 +27,12 @@
#include <utils/Vector.h>
#include <utils/SortedVector.h>
+#include <media/stagefright/foundation/ADebug.h>
+
namespace android {
+class AudioPolicyService;
+
// ----------------------------------------------------------------------------
// AudioPolicyEffects class
@@ -42,7 +46,7 @@ public:
// The constructor will parse audio_effects.conf
// First it will look whether vendor specific file exists,
// otherwise it will parse the system default file.
- AudioPolicyEffects();
+ AudioPolicyEffects(AudioPolicyService *audioPolicyService);
virtual ~AudioPolicyEffects();
// NOTE: methods on AudioPolicyEffects should never be called with the AudioPolicyService
@@ -82,6 +86,12 @@ public:
audio_stream_type_t stream,
int audioSession);
+ // For deferred release
+ status_t doReleaseOutputSessionEffects(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int audioSession);
+
+
private:
// class to store the description of an effects and its parameters
@@ -102,6 +112,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
@@ -189,6 +200,8 @@ private:
KeyedVector< audio_stream_type_t, EffectDescVector* > mOutputStreams;
// Automatic output effects are unique for audiosession ID
KeyedVector< int32_t, EffectVector* > mOutputSessions;
+
+ AudioPolicyService *mAudioPolicyService;
};
}; // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index ca365a5..c0d3866 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -187,6 +187,20 @@ status_t AudioPolicyService::startOutput(audio_io_handle_t output,
return NO_INIT;
}
ALOGV("startOutput()");
+ return mOutputCommandThread->startOutputCommand(output, stream, session);
+}
+
+status_t AudioPolicyService::doStartOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ audio_session_t session)
+{
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ return BAD_VALUE;
+ }
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ ALOGV("doStartOutput()");
sp<AudioPolicyEffects>audioPolicyEffects;
{
Mutex::Autolock _l(mLock);
@@ -463,6 +477,7 @@ audio_devices_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stre
if (mAudioPolicyManager == NULL) {
return AUDIO_DEVICE_NONE;
}
+ Mutex::Autolock _l(mLock);
return mAudioPolicyManager->getDevicesForStream(stream);
}
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
index 13af3ef..318c6d2 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
@@ -158,13 +158,27 @@ status_t AudioPolicyService::startOutput(audio_io_handle_t output,
return NO_INIT;
}
ALOGV("startOutput()");
- // create audio processors according to stream
+ return mOutputCommandThread->startOutputCommand(output, stream, session);
+}
+
+status_t AudioPolicyService::doStartOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ audio_session_t session)
+{
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ return BAD_VALUE;
+ }
+ if (mpAudioPolicy == NULL) {
+ return NO_INIT;
+ }
+ ALOGV("doStartOutput()");
sp<AudioPolicyEffects>audioPolicyEffects;
{
Mutex::Autolock _l(mLock);
audioPolicyEffects = mAudioPolicyEffects;
}
if (audioPolicyEffects != 0) {
+ // create audio processors according to stream
status_t status = audioPolicyEffects->addOutputSessionEffects(output, stream, session);
if (status != NO_ERROR && status != ALREADY_EXISTS) {
ALOGW("Failed to add effects on session %d", session);
@@ -261,6 +275,11 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
return BAD_VALUE;
}
+#ifdef HAVE_PRE_KITKAT_AUDIO_POLICY_BLOB
+ if (inputSource == AUDIO_SOURCE_HOTWORD)
+ inputSource = AUDIO_SOURCE_VOICE_RECOGNITION;
+#endif
+
sp<AudioPolicyEffects>audioPolicyEffects;
{
Mutex::Autolock _l(mLock);
@@ -510,6 +529,9 @@ status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession,
bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info)
{
+#ifdef HAVE_PRE_KITKAT_AUDIO_POLICY_BLOB
+ return false;
+#else
if (mpAudioPolicy == NULL) {
ALOGV("mpAudioPolicy == NULL");
return false;
@@ -521,6 +543,7 @@ bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info)
}
return mpAudioPolicy->is_offload_supported(mpAudioPolicy, &info);
+#endif
}
status_t AudioPolicyService::listAudioPorts(audio_port_role_t role __unused,
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index c77cc45..58cfe37 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -116,7 +116,7 @@ void AudioPolicyService::onFirstRef()
#endif
}
// load audio processing modules
- sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects();
+ sp<AudioPolicyEffects>audioPolicyEffects = new AudioPolicyEffects(this);
{
Mutex::Autolock _l(mLock);
mAudioPolicyEffects = audioPolicyEffects;
@@ -177,6 +177,23 @@ void AudioPolicyService::setAudioPortCallbacksEnabled(bool enabled)
mNotificationClients.valueFor(uid)->setAudioPortCallbacksEnabled(enabled);
}
+status_t AudioPolicyService::setEffectSessionCallbacksEnabled(bool enabled)
+{
+ Mutex::Autolock _l(mNotificationClientsLock);
+
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ if (mNotificationClients.indexOfKey(uid) < 0) {
+ return NO_INIT;
+ }
+ if (!modifyAudioRoutingAllowed()) {
+ ALOGE("setEffectSessionCallbacksEnabled requires MODIFY_AUDIO_ROUTING");
+ return PERMISSION_DENIED;
+ }
+ mNotificationClients.valueFor(uid)->setEffectSessionCallbacksEnabled(enabled);
+ return OK;
+}
+
+
// removeNotificationClient() is called when the client process dies.
void AudioPolicyService::removeNotificationClient(uid_t uid)
{
@@ -254,11 +271,31 @@ status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_co
return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs);
}
+void AudioPolicyService::onOutputSessionEffectsUpdate(audio_stream_type_t stream,
+ audio_unique_id_t sessionId,
+ bool added)
+{
+ ALOGV("AudioPolicyService::onOutputSessionEffectsUpdate(%d, %d, %d)",
+ stream, sessionId, added);
+ mOutputCommandThread->effectSessionUpdateCommand(stream, sessionId, added);
+}
+
+void AudioPolicyService::doOnOutputSessionEffectsUpdate(audio_stream_type_t stream,
+ audio_unique_id_t sessionId,
+ bool added)
+{
+ Mutex::Autolock _l(mNotificationClientsLock);
+ for (size_t i = 0; i < mNotificationClients.size(); i++) {
+ mNotificationClients.valueAt(i)->onOutputSessionEffectsUpdate(stream, sessionId, added);
+ }
+}
+
AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service,
const sp<IAudioPolicyServiceClient>& client,
uid_t uid)
: mService(service), mUid(uid), mAudioPolicyServiceClient(client),
- mAudioPortCallbacksEnabled(false)
+ mAudioPortCallbacksEnabled(false),
+ mEffectSessionCallbacksEnabled(false)
{
}
@@ -289,6 +326,14 @@ void AudioPolicyService::NotificationClient::onAudioPatchListUpdate()
}
}
+void AudioPolicyService::NotificationClient::onOutputSessionEffectsUpdate(
+ audio_stream_type_t stream, audio_unique_id_t sessionId, bool added)
+{
+ if (mAudioPolicyServiceClient != 0 && mEffectSessionCallbacksEnabled) {
+ mAudioPolicyServiceClient->onOutputSessionEffectsUpdate(stream, sessionId, added);
+ }
+}
+
void AudioPolicyService::NotificationClient::onDynamicPolicyMixStateUpdate(
String8 regId, int32_t state)
{
@@ -302,12 +347,23 @@ void AudioPolicyService::NotificationClient::setAudioPortCallbacksEnabled(bool e
mAudioPortCallbacksEnabled = enabled;
}
+void AudioPolicyService::NotificationClient::setEffectSessionCallbacksEnabled(bool enabled)
+{
+ mEffectSessionCallbacksEnabled = enabled;
+}
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
ALOGW("binderDied() %p, calling pid %d", who.unsafe_get(),
IPCThreadState::self()->getCallingPid());
}
+void AudioPolicyService::releaseOutputSessionEffectsDelayed(
+ audio_io_handle_t output, audio_stream_type_t stream,
+ audio_unique_id_t sessionId, int delayMs)
+{
+ mAudioCommandThread->releaseOutputSessionEffectsCommand(output, stream, sessionId, delayMs);
+}
+
static bool tryLock(Mutex& mutex)
{
bool locked = false;
@@ -478,6 +534,19 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
data->mVolume);
command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
}break;
+ case START_OUTPUT: {
+ StartOutputData *data = (StartOutputData *)command->mParam.get();
+ ALOGV("AudioCommandThread() processing start output %d",
+ data->mIO);
+ svc = mService.promote();
+ if (svc == 0) {
+ command->mStatus = UNKNOWN_ERROR;
+ break;
+ }
+ mLock.unlock();
+ command->mStatus = svc->doStartOutput(data->mIO, data->mStream, data->mSession);
+ mLock.lock();
+ }break;
case STOP_OUTPUT: {
StopOutputData *data = (StopOutputData *)command->mParam.get();
ALOGV("AudioCommandThread() processing stop output %d",
@@ -566,6 +635,35 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
svc->doOnDynamicPolicyMixStateUpdate(data->mRegId, data->mState);
mLock.lock();
} break;
+ case EFFECT_SESSION_UPDATE: {
+ EffectSessionUpdateData *data =
+ (EffectSessionUpdateData *)command->mParam.get();
+ ALOGV("AudioCommandThread() processing effect session update %d %d %d",
+ data->mStream, data->mSessionId, data->mAdded);
+ svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->doOnOutputSessionEffectsUpdate(data->mStream, data->mSessionId, data->mAdded);
+ mLock.lock();
+ } break;
+ case RELEASE_OUTPUT_SESSION_EFFECTS: {
+ ReleaseOutputSessionEffectsData *data =
+ (ReleaseOutputSessionEffectsData *)command->mParam.get();
+ ALOGV("AudioCommandThread() processing release output session effects %d %d %d",
+ data->mOutput, data->mStream, data->mSessionId);
+ svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->mAudioPolicyEffects->doReleaseOutputSessionEffects(
+ data->mOutput, data->mStream, data->mSessionId);
+ mLock.lock();
+ } break;
+
+
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
}
@@ -714,6 +812,22 @@ status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume
return sendCommand(command, delayMs);
}
+status_t AudioPolicyService::AudioCommandThread::startOutputCommand(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ audio_session_t session)
+{
+ sp<AudioCommand> command = new AudioCommand();
+ command->mCommand = START_OUTPUT;
+ sp<StartOutputData> data = new StartOutputData();
+ data->mIO = output;
+ data->mStream = stream;
+ data->mSession = session;
+ command->mParam = data;
+ command->mWaitStatus = true;
+ ALOGV("AudioCommandThread() adding start output %d", output);
+ return sendCommand(command);
+}
+
void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_io_handle_t output,
audio_stream_type_t stream,
audio_session_t session)
@@ -822,6 +936,38 @@ void AudioPolicyService::AudioCommandThread::dynamicPolicyMixStateUpdateCommand(
sendCommand(command);
}
+void AudioPolicyService::AudioCommandThread::effectSessionUpdateCommand(
+ audio_stream_type_t stream, audio_unique_id_t sessionId, bool added)
+{
+ sp<AudioCommand> command = new AudioCommand();
+ command->mCommand = EFFECT_SESSION_UPDATE;
+ EffectSessionUpdateData *data = new EffectSessionUpdateData();
+ data->mStream = stream;
+ data->mSessionId = sessionId;
+ data->mAdded = added;
+ command->mParam = data;
+ ALOGV("AudioCommandThread() sending effect session update (id=%d) for stream %d (added=%d)",
+ stream, sessionId, added);
+ sendCommand(command);
+}
+
+void AudioPolicyService::AudioCommandThread::releaseOutputSessionEffectsCommand(
+ audio_io_handle_t output, audio_stream_type_t stream,
+ audio_unique_id_t sessionId, int delayMs)
+{
+ sp<AudioCommand> command = new AudioCommand();
+ command->mCommand = RELEASE_OUTPUT_SESSION_EFFECTS;
+ ReleaseOutputSessionEffectsData *data = new ReleaseOutputSessionEffectsData();
+ data->mOutput = output;
+ data->mStream = stream;
+ data->mSessionId = sessionId;
+ command->mParam = data;
+ ALOGV("AudioCommandThread() sending release output session effects (id=%d) for stream %d",
+ sessionId, stream);
+ sendCommand(command, delayMs);
+}
+
+
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
{
@@ -899,10 +1045,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/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index a0d5aa2..9b17a26 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -202,6 +202,11 @@ public:
audio_io_handle_t *handle);
virtual status_t stopAudioSource(audio_io_handle_t handle);
+ virtual status_t setEffectSessionCallbacksEnabled(bool enabled);
+
+ status_t doStartOutput(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ audio_session_t session);
status_t doStopOutput(audio_io_handle_t output,
audio_stream_type_t stream,
audio_session_t session);
@@ -226,6 +231,15 @@ public:
void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
void doOnDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
+ void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
+ audio_unique_id_t sessionId, bool added);
+ void doOnOutputSessionEffectsUpdate(audio_stream_type_t stream,
+ audio_unique_id_t sessionId, bool added);
+ void releaseOutputSessionEffectsDelayed(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ audio_unique_id_t sessionId,
+ int delayMs);
+
private:
AudioPolicyService() ANDROID_API;
virtual ~AudioPolicyService();
@@ -249,6 +263,7 @@ private:
SET_VOLUME,
SET_PARAMETERS,
SET_VOICE_VOLUME,
+ START_OUTPUT,
STOP_OUTPUT,
RELEASE_OUTPUT,
CREATE_AUDIO_PATCH,
@@ -256,7 +271,9 @@ private:
UPDATE_AUDIOPORT_LIST,
UPDATE_AUDIOPATCH_LIST,
SET_AUDIOPORT_CONFIG,
- DYN_POLICY_MIX_STATE_UPDATE
+ DYN_POLICY_MIX_STATE_UPDATE,
+ EFFECT_SESSION_UPDATE,
+ RELEASE_OUTPUT_SESSION_EFFECTS,
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -277,6 +294,9 @@ private:
status_t parametersCommand(audio_io_handle_t ioHandle,
const char *keyValuePairs, int delayMs = 0);
status_t voiceVolumeCommand(float volume, int delayMs = 0);
+ status_t startOutputCommand(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ audio_session_t session);
void stopOutputCommand(audio_io_handle_t output,
audio_stream_type_t stream,
audio_session_t session);
@@ -296,6 +316,12 @@ private:
int delayMs);
void dynamicPolicyMixStateUpdateCommand(String8 regId, int32_t state);
void insertCommand_l(AudioCommand *command, int delayMs = 0);
+ void effectSessionUpdateCommand(audio_stream_type_t stream,
+ audio_unique_id_t sessionId, bool added);
+ void releaseOutputSessionEffectsCommand(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ audio_unique_id_t sessionId,
+ int delayMs = 0);
private:
class AudioCommandData;
@@ -349,6 +375,13 @@ private:
float mVolume;
};
+ class StartOutputData : public AudioCommandData {
+ public:
+ audio_io_handle_t mIO;
+ audio_stream_type_t mStream;
+ audio_session_t mSession;
+ };
+
class StopOutputData : public AudioCommandData {
public:
audio_io_handle_t mIO;
@@ -385,6 +418,20 @@ private:
int32_t mState;
};
+ class EffectSessionUpdateData : public AudioCommandData {
+ public:
+ audio_stream_type_t mStream;
+ audio_unique_id_t mSessionId;
+ bool mAdded;
+ };
+
+ class ReleaseOutputSessionEffectsData : public AudioCommandData {
+ public:
+ audio_io_handle_t mOutput;
+ audio_stream_type_t mStream;
+ audio_unique_id_t mSessionId;
+ };
+
Mutex mLock;
Condition mWaitWorkCV;
Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands
@@ -494,6 +541,9 @@ private:
virtual audio_unique_id_t newAudioUniqueId();
+ virtual void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
+ audio_unique_id_t sessionId, bool added);
+
private:
AudioPolicyService *mAudioPolicyService;
};
@@ -510,7 +560,9 @@ private:
void onAudioPatchListUpdate();
void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
void setAudioPortCallbacksEnabled(bool enabled);
-
+ void setEffectSessionCallbacksEnabled(bool enabled);
+ void onOutputSessionEffectsUpdate(audio_stream_type_t stream,
+ audio_unique_id_t sessionId, bool added);
// IBinder::DeathRecipient
virtual void binderDied(const wp<IBinder>& who);
@@ -522,6 +574,7 @@ private:
const uid_t mUid;
const sp<IAudioPolicyServiceClient> mAudioPolicyServiceClient;
bool mAudioPortCallbacksEnabled;
+ bool mEffectSessionCallbacksEnabled;
};
// Internal dump utilities.
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.h b/services/camera/libcameraservice/CameraService.h
index d2c1bd3..ee4c3f9 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/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index fbd4034..96266ed 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -1745,8 +1745,6 @@ void Camera2Client::notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCod
err = CAMERA_ERROR_RELEASED;
break;
case ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE:
- err = CAMERA_ERROR_UNKNOWN;
- break;
case ICameraDeviceCallbacks::ERROR_CAMERA_SERVICE:
err = CAMERA_ERROR_SERVER_DIED;
break;
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index 6020e35..55555fd 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);
}
@@ -364,12 +367,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);
}
@@ -377,7 +382,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;
@@ -557,6 +561,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();
}
@@ -659,6 +667,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);
@@ -801,7 +823,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
@@ -886,7 +910,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 17999a5..d2cb64a 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -164,6 +164,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;
}