summaryrefslogtreecommitdiffstats
path: root/services/audiopolicy
diff options
context:
space:
mode:
Diffstat (limited to 'services/audiopolicy')
-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
-rw-r--r--services/audiopolicy/engineconfigurable/parameter-framework/Android.mk2
-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.cpp40
-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.cpp116
-rw-r--r--services/audiopolicy/service/AudioPolicyEffects.h24
-rw-r--r--services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp81
-rw-r--r--services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp30
-rw-r--r--services/audiopolicy/service/AudioPolicyService.cpp93
-rw-r--r--services/audiopolicy/service/AudioPolicyService.h36
23 files changed, 540 insertions, 62 deletions
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..93e6266 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(sp<AudioSessionInfo>& streamInfo, 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/parameter-framework/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/Android.mk
index c402fd5..be86231 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/Android.mk
@@ -4,4 +4,4 @@ LOCAL_PATH := $(call my-dir)
# Recursive call sub-folder Android.mk
#######################################################################
-include $(call all-makefiles-under,$(LOCAL_PATH))
+include $(LOCAL_PATH)/plugin/Android.mk
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..13499ae 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -351,6 +351,14 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs
AUDIO_OUTPUT_FLAG_NONE,
AUDIO_FORMAT_INVALID);
if (output != AUDIO_IO_HANDLE_NONE) {
+ // close active input (if any) before opening new input
+ audio_io_handle_t activeInput = mInputs.getActiveInput();
+ if (activeInput != 0) {
+ ALOGV("updateCallRouting() close active input before opening new input");
+ sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
+ stopInput(activeInput, activeDesc->mSessions.itemAt(0));
+ releaseInput(activeInput, activeDesc->mSessions.itemAt(0));
+ }
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
ALOG_ASSERT(!outputDesc->isDuplicated(),
"updateCallRouting() RX device output is duplicated");
@@ -608,7 +616,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 +1365,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 +1391,6 @@ status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
} else {
*inputType = API_INPUT_LEGACY;
}
- // adapt channel selection to input source
- switch (inputSource) {
- case AUDIO_SOURCE_VOICE_UPLINK:
- channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK;
- break;
- case AUDIO_SOURCE_VOICE_DOWNLINK:
- channelMask = AUDIO_CHANNEL_IN_VOICE_DNLINK;
- break;
- case AUDIO_SOURCE_VOICE_CALL:
- channelMask = AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK;
- break;
- default:
- break;
- }
if (inputSource == AUDIO_SOURCE_HOTWORD) {
ssize_t index = mSoundTriggerSessions.indexOfKey(session);
if (index >= 0) {
@@ -1802,6 +1803,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 +1811,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 +1824,9 @@ audio_io_handle_t AudioPolicyManager::selectOutputForEffects(
if (outputOffloaded != 0) {
return outputOffloaded;
}
+ if (outputDirectPcm != 0) {
+ return outputDirectPcm;
+ }
if (outputDeepBuffer != 0) {
return outputDeepBuffer;
}
@@ -3810,7 +3818,7 @@ void AudioPolicyManager::checkOutputForStrategy(routing_strategy strategy)
{
audio_devices_t oldDevice = getDeviceForStrategy(strategy, true /*fromCache*/);
audio_devices_t newDevice = getDeviceForStrategy(strategy, false /*fromCache*/);
- SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevice(oldDevice, mPreviousOutputs);
+ SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevice(oldDevice, mOutputs);
SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevice(newDevice, mOutputs);
// also take into account external policy-related changes: add all outputs which are
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index bbdf396..c40a435 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -350,7 +350,7 @@ protected:
// handle special cases for sonification strategy while in call: mute streams or replace by
// a special tone in the device used for communication
- void handleIncallSonification(audio_stream_type_t stream, bool starting, bool stateChange);
+ virtual void handleIncallSonification(audio_stream_type_t stream, bool starting, bool stateChange);
audio_mode_t getPhoneState();
@@ -397,7 +397,7 @@ protected:
// must be called every time a condition that affects the device choice for a given output is
// changed: connected device, phone state, force use, output start, output stop..
// see getDeviceForStrategy() for the use of fromCache parameter
- audio_devices_t getNewOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
+ virtual audio_devices_t getNewOutputDevice(const sp<AudioOutputDescriptor>& outputDesc,
bool fromCache);
// updates cache of device used by all strategies (mDeviceForStrategy[])
@@ -484,11 +484,11 @@ protected:
// if argument "device" is different from AUDIO_DEVICE_NONE, startSource() will force
// the re-evaluation of the output device.
- status_t startSource(sp<AudioOutputDescriptor> outputDesc,
+ virtual status_t startSource(sp<AudioOutputDescriptor> outputDesc,
audio_stream_type_t stream,
audio_devices_t device,
uint32_t *delayMs);
- status_t stopSource(sp<AudioOutputDescriptor> outputDesc,
+ virtual status_t stopSource(sp<AudioOutputDescriptor> outputDesc,
audio_stream_type_t stream,
bool forceDeviceUpdate);
@@ -571,7 +571,7 @@ protected:
// Audio Policy Engine Interface.
AudioPolicyManagerInterface *mEngine;
-private:
+protected:
// updates device caching and output for streams that can influence the
// routing of notifications
void handleNotificationRoutingForStream(audio_stream_type_t stream);
@@ -586,7 +586,7 @@ private:
SortedVector<audio_io_handle_t>& outputs /*out*/);
uint32_t curAudioPortGeneration() const { return mAudioPortGeneration; }
// internal method to return the output handle for the given device and format
- audio_io_handle_t getOutputForDevice(
+ virtual audio_io_handle_t getOutputForDevice(
audio_devices_t device,
audio_session_t session,
audio_stream_type_t stream,
@@ -610,7 +610,7 @@ private:
AudioMix **policyMix = NULL);
// Called by setDeviceConnectionState().
- status_t setDeviceConnectionStateInt(audio_devices_t device,
+ virtual status_t setDeviceConnectionStateInt(audio_devices_t device,
audio_policy_dev_state_t state,
const char *device_address,
const char *device_name);
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 489a9be..82720f4 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(
+ sp<AudioSessionInfo>& info, bool added)
+{
+ mAudioPolicyService->onOutputSessionEffectsUpdate(info, 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..31b1637 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);
@@ -224,6 +228,8 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
{
status_t status = NO_ERROR;
+ ALOGV("addOutputSessionEffects %d", audioSession);
+
Mutex::Autolock _l(mLock);
// create audio processors according to stream
// FIXME: should we have specific post processing settings for internal streams?
@@ -231,6 +237,22 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
if (stream >= AUDIO_STREAM_PUBLIC_CNT) {
stream = AUDIO_STREAM_MUSIC;
}
+
+ // send the streaminfo notification only once
+ ssize_t sidx = mOutputAudioSessionInfo.indexOfKey(audioSession);
+ if (sidx >= 0) {
+ // AudioSessionInfo is existing and we just need to increase ref count
+ sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(sidx);
+ info->mRefCount++;
+
+ if (info->mRefCount == 1) {
+ mAudioPolicyService->onOutputSessionEffectsUpdate(info, true);
+ }
+ ALOGV("addOutputSessionEffects(): session info %d refCount=%d", audioSession, info->mRefCount);
+ } else {
+ ALOGV("addOutputSessionEffects(): no output stream info found for stream");
+ }
+
ssize_t index = mOutputStreams.indexOfKey(stream);
if (index < 0) {
ALOGV("addOutputSessionEffects(): no output processing needed for this stream");
@@ -273,6 +295,81 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output,
return status;
}
+status_t AudioPolicyEffects::releaseOutputAudioSessionInfo(audio_io_handle_t /* output */,
+ audio_stream_type_t stream,
+ int session)
+{
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock _l(mLock);
+
+ ssize_t idx = mOutputAudioSessionInfo.indexOfKey(session);
+ if (idx >= 0) {
+ sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(idx);
+ if (info->mRefCount == 0) {
+ mOutputAudioSessionInfo.removeItemsAt(idx);
+ }
+ ALOGV("releaseOutputAudioSessionInfo() sessionId=%d refcount=%d",
+ session, info->mRefCount);
+ } else {
+ ALOGV("releaseOutputAudioSessionInfo() no session info found");
+ }
+ return NO_ERROR;
+}
+
+status_t AudioPolicyEffects::updateOutputAudioSessionInfo(audio_io_handle_t /* output */,
+ audio_stream_type_t stream,
+ int session,
+ audio_output_flags_t flags,
+ audio_channel_mask_t channelMask, uid_t uid)
+{
+ if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock _l(mLock);
+
+ // update AudioSessionInfo. This is used in the stream open/close path
+ // to notify userspace applications about session creation and
+ // teardown, allowing the app to make decisions about effects for
+ // a particular stream. This is independent of the current
+ // output_session_processing feature which forcibly attaches a
+ // static list of effects to a stream.
+ ssize_t idx = mOutputAudioSessionInfo.indexOfKey(session);
+ sp<AudioSessionInfo> info;
+ if (idx < 0) {
+ info = new AudioSessionInfo(session, stream, flags, channelMask, uid);
+ mOutputAudioSessionInfo.add(session, info);
+ } else {
+ // the streaminfo may actually change
+ info = mOutputAudioSessionInfo.valueAt(idx);
+ info->mFlags = flags;
+ info->mChannelMask = channelMask;
+ }
+
+ ALOGV("updateOutputAudioSessionInfo() sessionId=%d, flags=0x%x, channelMask=0x%x uid=%d refCount=%d",
+ info->mSessionId, info->mFlags, info->mChannelMask, info->mUid, info->mRefCount);
+
+ return NO_ERROR;
+}
+
+status_t AudioPolicyEffects::listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions)
+{
+ ALOGV("listAudioSessions() streams %d", streams);
+
+ for (unsigned int i = 0; i < mOutputAudioSessionInfo.size(); i++) {
+ sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(i);
+ if (streams == -1 || info->mStream == streams) {
+ sessions.push_back(info);
+ }
+ }
+
+ return NO_ERROR;
+}
+
status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t output,
audio_stream_type_t stream,
int audioSession)
@@ -282,7 +379,19 @@ status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t outpu
(void) stream; // argument not used for now
Mutex::Autolock _l(mLock);
- ssize_t index = mOutputSessions.indexOfKey(audioSession);
+ ssize_t index = mOutputAudioSessionInfo.indexOfKey(audioSession);
+ if (index >= 0) {
+ sp<AudioSessionInfo> info = mOutputAudioSessionInfo.valueAt(index);
+ info->mRefCount--;
+ if (info->mRefCount == 0) {
+ mAudioPolicyService->onOutputSessionEffectsUpdate(info, false);
+ }
+ ALOGV("releaseOutputSessionEffects(): session=%d refCount=%d", info->mSessionId, info->mRefCount);
+ } else {
+ ALOGV("releaseOutputSessionEffects: no stream info was attached to this stream");
+ }
+
+ index = mOutputSessions.indexOfKey(audioSession);
if (index < 0) {
ALOGV("releaseOutputSessionEffects: no output processing was attached to this stream");
return NO_ERROR;
@@ -442,6 +551,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..a95d49f 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,19 @@ public:
audio_stream_type_t stream,
int audioSession);
+ status_t updateOutputAudioSessionInfo(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int audioSession,
+ audio_output_flags_t flags,
+ audio_channel_mask_t channelMask, uid_t uid);
+
+ status_t releaseOutputAudioSessionInfo(audio_io_handle_t output,
+ audio_stream_type_t stream,
+ int audioSession);
+
+ status_t listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions);
+
private:
// class to store the description of an effects and its parameters
@@ -102,6 +119,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 +207,10 @@ private:
KeyedVector< audio_stream_type_t, EffectDescVector* > mOutputStreams;
// Automatic output effects are unique for audiosession ID
KeyedVector< int32_t, EffectVector* > mOutputSessions;
+ // Stream info for session events
+ KeyedVector< int32_t, sp<AudioSessionInfo> > mOutputAudioSessionInfo;
+
+ AudioPolicyService *mAudioPolicyService;
};
}; // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index ca365a5..f0be341 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -161,19 +161,32 @@ status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr,
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
- ALOGV("getOutput()");
- Mutex::Autolock _l(mLock);
+ ALOGV("getOutputForAttr()");
+ status_t status = NO_ERROR;
+ sp<AudioPolicyEffects> audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
- // if the caller is us, trust the specified uid
- if (IPCThreadState::self()->getCallingPid() != getpid_cached || uid == (uid_t)-1) {
- uid_t newclientUid = IPCThreadState::self()->getCallingUid();
- if (uid != (uid_t)-1 && uid != newclientUid) {
- ALOGW("%s uid %d tried to pass itself off as %d", __FUNCTION__, newclientUid, uid);
+ // if the caller is us, trust the specified uid
+ if (IPCThreadState::self()->getCallingPid() != getpid_cached || uid == (uid_t)-1) {
+ uid_t newclientUid = IPCThreadState::self()->getCallingUid();
+ if (uid != (uid_t)-1 && uid != newclientUid) {
+ ALOGW("%s uid %d tried to pass itself off as %d", __FUNCTION__, newclientUid, uid);
+ }
+ uid = newclientUid;
}
- uid = newclientUid;
+ status = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid, samplingRate,
+ format, channelMask, flags, selectedDeviceId, offloadInfo);
+
+ audioPolicyEffects = mAudioPolicyEffects;
+ }
+
+ if (status == NO_ERROR && audioPolicyEffects != 0) {
+ audioPolicyEffects->updateOutputAudioSessionInfo(*output,
+ *stream, session, flags, channelMask, uid);
}
- return mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid, samplingRate,
- format, channelMask, flags, selectedDeviceId, offloadInfo);
+
+ return status;
}
status_t AudioPolicyService::startOutput(audio_io_handle_t output,
@@ -187,6 +200,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);
@@ -255,8 +282,16 @@ void AudioPolicyService::doReleaseOutput(audio_io_handle_t output,
audio_session_t session)
{
ALOGV("doReleaseOutput from tid %d", gettid());
- Mutex::Autolock _l(mLock);
- mAudioPolicyManager->releaseOutput(output, stream, session);
+ sp<AudioPolicyEffects>audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ audioPolicyEffects = mAudioPolicyEffects;
+ mAudioPolicyManager->releaseOutput(output, stream, session);
+ }
+ if (audioPolicyEffects != 0) {
+ audioPolicyEffects->releaseOutputAudioSessionInfo(output,
+ stream, session);
+ }
}
status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr,
@@ -463,6 +498,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);
}
@@ -702,4 +738,25 @@ status_t AudioPolicyService::stopAudioSource(audio_io_handle_t handle)
return mAudioPolicyManager->stopAudioSource(handle);
}
+status_t AudioPolicyService::listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions)
+{
+ sp<AudioPolicyEffects> audioPolicyEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ audioPolicyEffects = mAudioPolicyEffects;
+ }
+
+ if (audioPolicyEffects != 0) {
+ return audioPolicyEffects->listAudioSessions(streams, sessions);
+ }
+
+ // no errors here if effects are not available
+ return NO_ERROR;
+}
+
+
}; // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImplLegacy.cpp
index 13af3ef..0aad54d 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,
@@ -619,4 +642,9 @@ status_t AudioPolicyService::stopAudioSource(audio_io_handle_t handle)
return INVALID_OPERATION;
}
+status_t AudioPolicyService::listAudioSessions(audio_stream_type_t streams,
+ Vector< sp<AudioSessionInfo>> &sessions)
+{
+ return INVALID_OPERATION;
+}
}; // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index c77cc45..79370f4 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;
@@ -254,6 +254,21 @@ status_t AudioPolicyService::clientSetAudioPortConfig(const struct audio_port_co
return mAudioCommandThread->setAudioPortConfigCommand(config, delayMs);
}
+void AudioPolicyService::onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added)
+{
+ ALOGV("AudioPolicyService::onOutputSessionEffectsUpdate(%d, %d, %d)",
+ info->mStream, info->mSessionId, added);
+ mOutputCommandThread->effectSessionUpdateCommand(info, added);
+}
+
+void AudioPolicyService::doOnOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added)
+{
+ Mutex::Autolock _l(mNotificationClientsLock);
+ for (size_t i = 0; i < mNotificationClients.size(); i++) {
+ mNotificationClients.valueAt(i)->onOutputSessionEffectsUpdate(info, added);
+ }
+}
+
AudioPolicyService::NotificationClient::NotificationClient(const sp<AudioPolicyService>& service,
const sp<IAudioPolicyServiceClient>& client,
uid_t uid)
@@ -289,6 +304,14 @@ void AudioPolicyService::NotificationClient::onAudioPatchListUpdate()
}
}
+void AudioPolicyService::NotificationClient::onOutputSessionEffectsUpdate(
+ sp<AudioSessionInfo>& info, bool added)
+{
+ if (mAudioPolicyServiceClient != 0) {
+ mAudioPolicyServiceClient->onOutputSessionEffectsUpdate(info, added);
+ }
+}
+
void AudioPolicyService::NotificationClient::onDynamicPolicyMixStateUpdate(
String8 regId, int32_t state)
{
@@ -478,6 +501,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 +602,21 @@ 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->mAudioSessionInfo->mStream, data->mAudioSessionInfo->mSessionId,
+ data->mAdded);
+ svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->doOnOutputSessionEffectsUpdate(data->mAudioSessionInfo, data->mAdded);
+ mLock.lock();
+ } break;
+
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
}
@@ -714,6 +765,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 +889,20 @@ void AudioPolicyService::AudioCommandThread::dynamicPolicyMixStateUpdateCommand(
sendCommand(command);
}
+void AudioPolicyService::AudioCommandThread::effectSessionUpdateCommand(
+ sp<AudioSessionInfo>& streamInfo, bool added)
+{
+ sp<AudioCommand> command = new AudioCommand();
+ command->mCommand = EFFECT_SESSION_UPDATE;
+ EffectSessionUpdateData *data = new EffectSessionUpdateData();
+ data->mAudioSessionInfo = streamInfo;
+ data->mAdded = added;
+ command->mParam = data;
+ ALOGV("AudioCommandThread() sending effect session update (id=%d) for stream %d (added=%d)",
+ streamInfo->mStream, streamInfo->mSessionId, added);
+ sendCommand(command);
+}
+
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
{
@@ -899,10 +980,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..b7f55ae 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -202,6 +202,12 @@ public:
audio_io_handle_t *handle);
virtual status_t stopAudioSource(audio_io_handle_t handle);
+ virtual status_t listAudioSessions(audio_stream_type_t stream,
+ Vector< sp<AudioSessionInfo>>& sessions);
+
+ 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 +232,9 @@ public:
void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
void doOnDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
+ void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added);
+ void doOnOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added);
+
private:
AudioPolicyService() ANDROID_API;
virtual ~AudioPolicyService();
@@ -249,6 +258,7 @@ private:
SET_VOLUME,
SET_PARAMETERS,
SET_VOICE_VOLUME,
+ START_OUTPUT,
STOP_OUTPUT,
RELEASE_OUTPUT,
CREATE_AUDIO_PATCH,
@@ -256,7 +266,8 @@ private:
UPDATE_AUDIOPORT_LIST,
UPDATE_AUDIOPATCH_LIST,
SET_AUDIOPORT_CONFIG,
- DYN_POLICY_MIX_STATE_UPDATE
+ DYN_POLICY_MIX_STATE_UPDATE,
+ EFFECT_SESSION_UPDATE,
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -277,6 +288,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 +310,7 @@ private:
int delayMs);
void dynamicPolicyMixStateUpdateCommand(String8 regId, int32_t state);
void insertCommand_l(AudioCommand *command, int delayMs = 0);
+ void effectSessionUpdateCommand(sp<AudioSessionInfo>& info, bool added);
private:
class AudioCommandData;
@@ -349,6 +364,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 +407,12 @@ private:
int32_t mState;
};
+ class EffectSessionUpdateData : public AudioCommandData {
+ public:
+ sp<AudioSessionInfo> mAudioSessionInfo;
+ bool mAdded;
+ };
+
Mutex mLock;
Condition mWaitWorkCV;
Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands
@@ -494,6 +522,9 @@ private:
virtual audio_unique_id_t newAudioUniqueId();
+ virtual void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info, bool added);
+
+
private:
AudioPolicyService *mAudioPolicyService;
};
@@ -510,7 +541,8 @@ private:
void onAudioPatchListUpdate();
void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
void setAudioPortCallbacksEnabled(bool enabled);
-
+ void onOutputSessionEffectsUpdate(sp<AudioSessionInfo>& info,
+ bool added);
// IBinder::DeathRecipient
virtual void binderDied(const wp<IBinder>& who);