summaryrefslogtreecommitdiffstats
path: root/services/audiopolicy
diff options
context:
space:
mode:
Diffstat (limited to 'services/audiopolicy')
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h12
-rw-r--r--services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h8
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp20
-rw-r--r--services/audiopolicy/common/managerdefinitions/src/StreamDescriptor.cpp5
-rwxr-xr-xservices/audiopolicy/enginedefault/src/Engine.cpp8
-rw-r--r--services/audiopolicy/enginedefault/src/Gains.cpp8
-rw-r--r--services/audiopolicy/managerdefault/AudioPolicyManager.cpp69
-rw-r--r--services/audiopolicy/managerdefault/AudioPolicyManager.h1
-rw-r--r--services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp6
9 files changed, 125 insertions, 12 deletions
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 18bcfdb..48d09ed 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -56,9 +56,21 @@ public:
const struct audio_port_config *srcConfig = NULL) const;
virtual sp<AudioPort> getAudioPort() const { return mProfile; }
void toAudioPort(struct audio_port *port) const;
+ void setPreemptedSessions(const SortedVector<audio_session_t>& sessions);
+ SortedVector<audio_session_t> getPreemptedSessions() const;
+ bool hasPreemptedSession(audio_session_t session) const;
+ void clearPreemptedSessions();
private:
audio_port_handle_t mId;
+ // Because a preemtible capture session can preempt another one, we end up in an endless loop
+ // situation were each session is allowed to restart after being preempted,
+ // thus preempting the other one which restarts and so on.
+ // To avoid this situation, we store which audio session was preempted when
+ // a particular input started and prevent preemption of this active input by this session.
+ // We also inherit sessions from the preempted input to avoid a 3 way preemption loop etc...
+ SortedVector<audio_session_t> mPreemptedSessions;
+
};
class AudioInputCollection :
diff --git a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
index 4a394bb..03b45c2 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h
@@ -99,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[] = {
@@ -248,6 +251,11 @@ const StringToEnum sInChannelsNameToEnumTable[] = {
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/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 937160b..626fdae 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -93,6 +93,26 @@ void AudioInputDescriptor::toAudioPort(struct audio_port *port) const
port->ext.mix.latency_class = AUDIO_LATENCY_NORMAL;
}
+void AudioInputDescriptor::setPreemptedSessions(const SortedVector<audio_session_t>& sessions)
+{
+ mPreemptedSessions = sessions;
+}
+
+SortedVector<audio_session_t> AudioInputDescriptor::getPreemptedSessions() const
+{
+ return mPreemptedSessions;
+}
+
+bool AudioInputDescriptor::hasPreemptedSession(audio_session_t session) const
+{
+ return (mPreemptedSessions.indexOf(session) >= 0);
+}
+
+void AudioInputDescriptor::clearPreemptedSessions()
+{
+ mPreemptedSessions.clear();
+}
+
status_t AudioInputDescriptor::dump(int fd)
{
const size_t SIZE = 256;
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/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 8b4a085..71f6b51 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());
@@ -647,6 +651,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) &&
@@ -684,6 +691,7 @@ audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) cons
}
break;
}
+#endif
break;
case AUDIO_SOURCE_VOICE_RECOGNITION:
diff --git a/services/audiopolicy/enginedefault/src/Gains.cpp b/services/audiopolicy/enginedefault/src/Gains.cpp
index 78f2909..d06365c 100644
--- a/services/audiopolicy/enginedefault/src/Gains.cpp
+++ b/services/audiopolicy/enginedefault/src/Gains.cpp
@@ -171,10 +171,10 @@ const VolumeCurvePoint *Gains::sVolumeProfiles[AUDIO_STREAM_CNT]
},
{ // AUDIO_STREAM_TTS
// "Transmitted Through Speaker": always silent except on DEVICE_CATEGORY_SPEAKER
- Gains::sSilentVolumeCurve, // DEVICE_CATEGORY_HEADSET
- Gains::sLinearVolumeCurve, // DEVICE_CATEGORY_SPEAKER
- Gains::sSilentVolumeCurve, // DEVICE_CATEGORY_EARPIECE
- Gains::sSilentVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
+ Gains::sSilentVolumeCurve, // DEVICE_CATEGORY_HEADSET
+ Gains::sFullScaleVolumeCurve, // DEVICE_CATEGORY_SPEAKER
+ Gains::sSilentVolumeCurve, // DEVICE_CATEGORY_EARPIECE
+ Gains::sSilentVolumeCurve // DEVICE_CATEGORY_EXT_MEDIA
},
{ // AUDIO_STREAM_ACCESSIBILITY
Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_HEADSET
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 483855f..ee3b72e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -88,6 +88,14 @@ status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t device,
}
ALOGV("setDeviceConnectionState() connecting device %x", device);
+#ifdef LEGACY_ALSA_AUDIO
+ 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 +147,14 @@ 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_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 +321,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
@@ -1074,7 +1094,7 @@ status_t AudioPolicyManager::startSource(sp<AudioOutputDescriptor> outputDesc,
*delayMs = 0;
if (stream == AUDIO_STREAM_TTS) {
ALOGV("\t found BEACON stream");
- if (mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
+ if (!mTtsOutputAvailable && mOutputs.isAnyOutputActive(AUDIO_STREAM_TTS /*streamToIgnore*/)) {
return INVALID_OPERATION;
} else {
beaconMuteLatency = handleEventForBeacon(STARTING_BEACON);
@@ -1370,6 +1390,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;
+ 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;
+ }
+#endif
if (inputSource == AUDIO_SOURCE_HOTWORD) {
ssize_t index = mSoundTriggerSessions.indexOfKey(session);
if (index >= 0) {
@@ -1485,10 +1521,15 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input,
// If the already active input uses AUDIO_SOURCE_HOTWORD then it is closed,
// otherwise the active input continues and the new input cannot be started.
sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
- if (activeDesc->mInputSource == AUDIO_SOURCE_HOTWORD) {
+ if ((activeDesc->mInputSource == AUDIO_SOURCE_HOTWORD) &&
+ !activeDesc->hasPreemptedSession(session)) {
ALOGW("startInput(%d) preempting low-priority input %d", input, activeInput);
- stopInput(activeInput, activeDesc->mSessions.itemAt(0));
- releaseInput(activeInput, activeDesc->mSessions.itemAt(0));
+ audio_session_t activeSession = activeDesc->mSessions.itemAt(0);
+ SortedVector<audio_session_t> sessions = activeDesc->getPreemptedSessions();
+ sessions.add(activeSession);
+ inputDesc->setPreemptedSessions(sessions);
+ stopInput(activeInput, activeSession);
+ releaseInput(activeInput, activeSession);
} else {
ALOGE("startInput(%d) failed: other input %d already started", input, activeInput);
return INVALID_OPERATION;
@@ -1592,6 +1633,7 @@ status_t AudioPolicyManager::stopInput(audio_io_handle_t input,
if (mInputs.activeInputsCount() == 0) {
SoundTrigger::setCaptureState(false);
}
+ inputDesc->clearPreemptedSessions();
}
return NO_ERROR;
}
@@ -1718,7 +1760,9 @@ status_t AudioPolicyManager::setStreamVolumeIndex(audio_stream_type_t stream,
status = volStatus;
}
}
- if ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & accessibilityDevice) != 0)) {
+ if ((accessibilityDevice != AUDIO_DEVICE_NONE) &&
+ ((device == AUDIO_DEVICE_OUT_DEFAULT) || ((curDevice & accessibilityDevice) != 0)))
+ {
status_t volStatus = checkAndSetVolume(AUDIO_STREAM_ACCESSIBILITY,
index, desc, curDevice);
}
@@ -2007,6 +2051,9 @@ status_t AudioPolicyManager::dump(int fd)
snprintf(buffer, SIZE, " Force use for hdmi system audio %d\n",
mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO));
result.append(buffer);
+ snprintf(buffer, SIZE, " TTS output %s\n", mTtsOutputAvailable ? "available" : "not available");
+ result.append(buffer);
+
write(fd, result.string(), result.size());
mAvailableOutputDevices.dump(fd, String8("output"));
@@ -2687,7 +2734,8 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
mAudioPortGeneration(1),
mBeaconMuteRefCount(0),
mBeaconPlayingRefCount(0),
- mBeaconMuted(false)
+ mBeaconMuted(false),
+ mTtsOutputAvailable(false)
{
audio_policy::EngineInstance *engineInstance = audio_policy::EngineInstance::getInstance();
if (!engineInstance) {
@@ -2744,6 +2792,9 @@ AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterfa
ALOGW("Output profile contains no device on module %s", mHwModules[i]->mName);
continue;
}
+ if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_TTS) != 0) {
+ mTtsOutputAvailable = true;
+ }
if ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
continue;
@@ -4043,6 +4094,12 @@ void AudioPolicyManager::handleNotificationRoutingForStream(audio_stream_type_t
}
uint32_t AudioPolicyManager::handleEventForBeacon(int event) {
+
+ // skip beacon mute management if a dedicated TTS output is available
+ if (mTtsOutputAvailable) {
+ return 0;
+ }
+
switch(event) {
case STARTING_OUTPUT:
mBeaconMuteRefCount++;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 80c41c8..c40a435 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -548,6 +548,7 @@ protected:
uint32_t mBeaconMuteRefCount; // ref count for stream that would mute beacon
uint32_t mBeaconPlayingRefCount;// ref count for the playing beacon streams
bool mBeaconMuted; // has STREAM_TTS been muted
+ bool mTtsOutputAvailable; // true if a dedicated output for TTS stream is available
AudioPolicyMixCollection mPolicyMixes; // list of registered mixes
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 58ecb11..a228798 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -76,10 +76,14 @@ status_t AudioPolicyService::setPhoneState(audio_mode_t state)
ALOGV("setPhoneState()");
+ // acquire lock before calling setMode() so that setMode() + setPhoneState() are an atomic
+ // operation from policy manager standpoint (no other operation (e.g track start or stop)
+ // can be interleaved).
+ Mutex::Autolock _l(mLock);
+
// TODO: check if it is more appropriate to do it in platform specific policy manager
AudioSystem::setMode(state);
- Mutex::Autolock _l(mLock);
mAudioPolicyManager->setPhoneState(state);
mPhoneState = state;
return NO_ERROR;