prevent preempting overlapping sound trigger audio streams
If the sound trigger hal indicates that concurrent_capture is true, the
stream should not be preempted when when another sound trigger stream is
opened.
Test: Verify that multiple streams are not closed when triggered by
different engines.
Bug: 35956563
Change-Id: I3d5df136403e47fcc1280f63b25216f326b74d6f
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index b509759..f26a204 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1815,6 +1815,40 @@
return true;
}
+// FIXME: remove when concurrent capture is ready. This is a hack to work around bug b/63083537.
+bool AudioPolicyManager::soundTriggerSupportsConcurrentCapture() {
+ if (!mHasComputedSoundTriggerSupportsConcurrentCapture) {
+ bool soundTriggerSupportsConcurrentCapture = false;
+ unsigned int numModules = 0;
+ struct sound_trigger_module_descriptor* nModules = NULL;
+
+ status_t status = SoundTrigger::listModules(nModules, &numModules);
+ if (status == NO_ERROR && numModules != 0) {
+ nModules = (struct sound_trigger_module_descriptor*) calloc(
+ numModules, sizeof(struct sound_trigger_module_descriptor));
+ if (nModules == NULL) {
+ // We failed to malloc the buffer, so just say no for now, and hope that we have more
+ // ram the next time this function is called.
+ ALOGE("Failed to allocate buffer for module descriptors");
+ return false;
+ }
+
+ status = SoundTrigger::listModules(nModules, &numModules);
+ if (status == NO_ERROR) {
+ soundTriggerSupportsConcurrentCapture = true;
+ for (size_t i = 0; i < numModules; ++i) {
+ soundTriggerSupportsConcurrentCapture &=
+ nModules[i].properties.concurrent_capture;
+ }
+ }
+ free(nModules);
+ }
+ mSoundTriggerSupportsConcurrentCapture = soundTriggerSupportsConcurrentCapture;
+ mHasComputedSoundTriggerSupportsConcurrentCapture = true;
+ }
+ return mSoundTriggerSupportsConcurrentCapture;
+}
+
status_t AudioPolicyManager::startInput(audio_io_handle_t input,
audio_session_t session,
@@ -1887,6 +1921,12 @@
}
}
+ // We only need to check if the sound trigger session supports concurrent capture if the
+ // input is also a sound trigger input. Otherwise, we should preempt any hotword stream
+ // that's running.
+ const bool allowConcurrentWithSoundTrigger =
+ inputDesc->isSoundTrigger() ? soundTriggerSupportsConcurrentCapture() : false;
+
// if capture is allowed, preempt currently active HOTWORD captures
for (size_t i = 0; i < activeInputs.size(); i++) {
sp<AudioInputDescriptor> activeDesc = activeInputs[i];
@@ -1895,6 +1935,10 @@
continue;
}
+ if (allowConcurrentWithSoundTrigger && activeDesc->isSoundTrigger()) {
+ continue;
+ }
+
audio_source_t activeSource = activeDesc->inputSource(true);
if (activeSource == AUDIO_SOURCE_HOTWORD) {
AudioSessionCollection activeSessions =
@@ -3490,7 +3534,8 @@
mBeaconMuted(false),
mTtsOutputAvailable(false),
mMasterMono(false),
- mMusicEffectOutput(AUDIO_IO_HANDLE_NONE)
+ mMusicEffectOutput(AUDIO_IO_HANDLE_NONE),
+ mHasComputedSoundTriggerSupportsConcurrentCapture(false)
{
mUidCached = getuid();
mpClientInterface = clientInterface;