Add sound trigger control by audio policy
Audio policy:
- Added active capture indication to sound trigger service:
recognition stops if concurrent capture is not supported.
- Added generation of reserved I/O handle and session ID for
utterance capture.
Sound trigger service
- Added sound model update callback handling.
- Added service state callback
- Simplified callback shared memory allocation.
Bug: 12378680.
Change-Id: Ib0292c2733e6df90fdae480633dd9953d0016ef1
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 440f5d0..f716358 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -43,6 +43,7 @@
#include <hardware/audio.h>
#include <hardware/audio_effect.h>
#include <media/AudioParameter.h>
+#include <soundtrigger/SoundTrigger.h>
#include "AudioPolicyManager.h"
#include "audio_policy_conf.h"
@@ -1119,6 +1120,17 @@
config.channel_mask = channelMask;
config.format = format;
audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
+
+ bool isSoundTrigger = false;
+ if (inputSource == AUDIO_SOURCE_HOTWORD) {
+ ssize_t index = mSoundTriggerSessions.indexOfKey(session);
+ if (index >= 0) {
+ input = mSoundTriggerSessions.valueFor(session);
+ isSoundTrigger = true;
+ ALOGV("SoundTrigger capture on session %d input %d", session, input);
+ }
+ }
+
status_t status = mpClientInterface->openInput(profile->mModule->mHandle,
&input,
&config,
@@ -1149,6 +1161,7 @@
inputDesc->mChannelMask = channelMask;
inputDesc->mDevice = device;
inputDesc->mSessions.add(session);
+ inputDesc->mIsSoundTrigger = isSoundTrigger;
addInput(input, inputDesc);
mpClientInterface->onAudioPortListUpdate();
@@ -1194,6 +1207,9 @@
}
if (inputDesc->mRefCount == 0) {
+ if (activeInputsCount() == 0) {
+ SoundTrigger::setCaptureState(true);
+ }
setInputDevice(input, getNewInputDevice(input), true /* force */);
// Automatically enable the remote submix output when input is started.
@@ -1242,6 +1258,10 @@
}
resetInputDevice(input);
+
+ if (activeInputsCount() == 0) {
+ SoundTrigger::setCaptureState(false);
+ }
}
return NO_ERROR;
}
@@ -2253,6 +2273,31 @@
}
}
+status_t AudioPolicyManager::acquireSoundTriggerSession(audio_session_t *session,
+ audio_io_handle_t *ioHandle,
+ audio_devices_t *device)
+{
+ *session = (audio_session_t)mpClientInterface->newAudioUniqueId();
+ *ioHandle = (audio_io_handle_t)mpClientInterface->newAudioUniqueId();
+ *device = getDeviceForInputSource(AUDIO_SOURCE_HOTWORD);
+
+ mSoundTriggerSessions.add(*session, *ioHandle);
+
+ return NO_ERROR;
+}
+
+status_t AudioPolicyManager::releaseSoundTriggerSession(audio_session_t session)
+{
+ ssize_t index = mSoundTriggerSessions.indexOfKey(session);
+ if (index < 0) {
+ ALOGW("acquireSoundTriggerSession() session %d not registered", session);
+ return BAD_VALUE;
+ }
+
+ mSoundTriggerSessions.removeItem(session);
+ return NO_ERROR;
+}
+
status_t AudioPolicyManager::addAudioPatch(audio_patch_handle_t handle,
const sp<AudioPatch>& patch)
{
@@ -4013,7 +4058,8 @@
inputDesc->toAudioPortConfig(&patch.sinks[0]);
// AUDIO_SOURCE_HOTWORD is for internal use only:
// handled as AUDIO_SOURCE_VOICE_RECOGNITION by the audio HAL
- if (patch.sinks[0].ext.mix.usecase.source == AUDIO_SOURCE_HOTWORD) {
+ if (patch.sinks[0].ext.mix.usecase.source == AUDIO_SOURCE_HOTWORD &&
+ !inputDesc->mIsSoundTrigger) {
patch.sinks[0].ext.mix.usecase.source = AUDIO_SOURCE_VOICE_RECOGNITION;
}
patch.num_sinks = 1;
@@ -4198,6 +4244,18 @@
return 0;
}
+uint32_t AudioPolicyManager::activeInputsCount() const
+{
+ uint32_t count = 0;
+ for (size_t i = 0; i < mInputs.size(); i++) {
+ const sp<AudioInputDescriptor> desc = mInputs.valueAt(i);
+ if (desc->mRefCount > 0) {
+ return count++;
+ }
+ }
+ return count;
+}
+
audio_devices_t AudioPolicyManager::getDeviceForVolume(audio_devices_t device)
{
@@ -4883,7 +4941,7 @@
AudioPolicyManager::AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile)
: mId(0), mIoHandle(0),
mDevice(AUDIO_DEVICE_NONE), mPatchHandle(0), mRefCount(0),
- mInputSource(AUDIO_SOURCE_DEFAULT), mProfile(profile)
+ mInputSource(AUDIO_SOURCE_DEFAULT), mProfile(profile), mIsSoundTrigger(false)
{
if (profile != NULL) {
mAudioPort = profile;