summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2014-07-27 18:39:40 -0700
committerEric Laurent <elaurent@google.com>2014-08-05 12:10:27 -0700
commitdf3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871 (patch)
treee54724362f700e3e72fc72604a3b5f568d8cee7b
parentd0fded31e473e909c018f534d3019fb5168bdcd6 (diff)
downloadframeworks_av-df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871.zip
frameworks_av-df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871.tar.gz
frameworks_av-df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871.tar.bz2
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
-rw-r--r--include/media/AudioSystem.h6
-rw-r--r--include/media/IAudioPolicyService.h6
-rw-r--r--include/soundtrigger/ISoundTriggerClient.h4
-rw-r--r--include/soundtrigger/ISoundTriggerHwService.h2
-rw-r--r--include/soundtrigger/SoundTrigger.h8
-rw-r--r--include/soundtrigger/SoundTriggerCallback.h4
-rw-r--r--media/libmedia/AudioSystem.cpp15
-rw-r--r--media/libmedia/IAudioPolicyService.cpp67
-rw-r--r--services/audiopolicy/Android.mk5
-rw-r--r--services/audiopolicy/AudioPolicyClientImpl.cpp1
-rw-r--r--services/audiopolicy/AudioPolicyInterface.h5
-rw-r--r--services/audiopolicy/AudioPolicyInterfaceImpl.cpp20
-rw-r--r--services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp15
-rw-r--r--services/audiopolicy/AudioPolicyManager.cpp62
-rw-r--r--services/audiopolicy/AudioPolicyManager.h31
-rw-r--r--services/audiopolicy/AudioPolicyService.h6
-rw-r--r--services/soundtrigger/Android.mk3
-rw-r--r--services/soundtrigger/SoundTriggerHwService.cpp460
-rw-r--r--services/soundtrigger/SoundTriggerHwService.h71
-rw-r--r--soundtrigger/ISoundTriggerClient.cpp35
-rw-r--r--soundtrigger/ISoundTriggerHwService.cpp20
-rw-r--r--soundtrigger/SoundTrigger.cpp35
22 files changed, 715 insertions, 166 deletions
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index cf34991..f22792f 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -309,6 +309,12 @@ public:
/* Set audio port configuration */
static status_t setAudioPortConfig(const struct audio_port_config *config);
+
+ static status_t acquireSoundTriggerSession(audio_session_t *session,
+ audio_io_handle_t *ioHandle,
+ audio_devices_t *device);
+ static status_t releaseSoundTriggerSession(audio_session_t session);
+
// ----------------------------------------------------------------------------
class AudioPortCallback : public RefBase
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index abbda32..c251439 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -136,6 +136,12 @@ public:
virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
virtual void registerClient(const sp<IAudioPolicyServiceClient>& client) = 0;
+
+ virtual status_t acquireSoundTriggerSession(audio_session_t *session,
+ audio_io_handle_t *ioHandle,
+ audio_devices_t *device) = 0;
+
+ virtual status_t releaseSoundTriggerSession(audio_session_t session) = 0;
};
diff --git a/include/soundtrigger/ISoundTriggerClient.h b/include/soundtrigger/ISoundTriggerClient.h
index 7f86d02..480429a 100644
--- a/include/soundtrigger/ISoundTriggerClient.h
+++ b/include/soundtrigger/ISoundTriggerClient.h
@@ -31,6 +31,10 @@ public:
virtual void onRecognitionEvent(const sp<IMemory>& eventMemory) = 0;
+ virtual void onSoundModelEvent(const sp<IMemory>& eventMemory) = 0;
+
+ virtual void onServiceStateChange(const sp<IMemory>& eventMemory) = 0;
+
};
// ----------------------------------------------------------------------------
diff --git a/include/soundtrigger/ISoundTriggerHwService.h b/include/soundtrigger/ISoundTriggerHwService.h
index 05a764a..ae0cb01 100644
--- a/include/soundtrigger/ISoundTriggerHwService.h
+++ b/include/soundtrigger/ISoundTriggerHwService.h
@@ -39,6 +39,8 @@ public:
virtual status_t attach(const sound_trigger_module_handle_t handle,
const sp<ISoundTriggerClient>& client,
sp<ISoundTrigger>& module) = 0;
+
+ virtual status_t setCaptureState(bool active) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/soundtrigger/SoundTrigger.h b/include/soundtrigger/SoundTrigger.h
index 1f7f286..bf5e1de 100644
--- a/include/soundtrigger/SoundTrigger.h
+++ b/include/soundtrigger/SoundTrigger.h
@@ -18,6 +18,7 @@
#define ANDROID_HARDWARE_SOUNDTRIGGER_H
#include <binder/IBinder.h>
+#include <utils/threads.h>
#include <soundtrigger/SoundTriggerCallback.h>
#include <soundtrigger/ISoundTrigger.h>
#include <soundtrigger/ISoundTriggerHwService.h>
@@ -32,12 +33,15 @@ class SoundTrigger : public BnSoundTriggerClient,
public IBinder::DeathRecipient
{
public:
+
+ virtual ~SoundTrigger();
+
static status_t listModules(struct sound_trigger_module_descriptor *modules,
uint32_t *numModules);
static sp<SoundTrigger> attach(const sound_trigger_module_handle_t module,
const sp<SoundTriggerCallback>& callback);
- virtual ~SoundTrigger();
+ static status_t setCaptureState(bool active);
void detach();
@@ -51,6 +55,8 @@ public:
// BpSoundTriggerClient
virtual void onRecognitionEvent(const sp<IMemory>& eventMemory);
+ virtual void onSoundModelEvent(const sp<IMemory>& eventMemory);
+ virtual void onServiceStateChange(const sp<IMemory>& eventMemory);
//IBinder::DeathRecipient
virtual void binderDied(const wp<IBinder>& who);
diff --git a/include/soundtrigger/SoundTriggerCallback.h b/include/soundtrigger/SoundTriggerCallback.h
index 8a5ba02..b5277f2 100644
--- a/include/soundtrigger/SoundTriggerCallback.h
+++ b/include/soundtrigger/SoundTriggerCallback.h
@@ -31,6 +31,10 @@ public:
virtual void onRecognitionEvent(struct sound_trigger_recognition_event *event) = 0;
+ virtual void onSoundModelEvent(struct sound_trigger_model_event *event) = 0;
+
+ virtual void onServiceStateChange(sound_trigger_service_state_t state) = 0;
+
virtual void onServiceDied() = 0;
};
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 365a594..172b056 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -913,6 +913,21 @@ void AudioSystem::setAudioPortCallback(sp<AudioPortCallback> callBack)
gAudioPortCallback = callBack;
}
+status_t AudioSystem::acquireSoundTriggerSession(audio_session_t *session,
+ audio_io_handle_t *ioHandle,
+ audio_devices_t *device)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->acquireSoundTriggerSession(session, ioHandle, device);
+}
+
+status_t AudioSystem::releaseSoundTriggerSession(audio_session_t session)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->releaseSoundTriggerSession(session);
+}
// ---------------------------------------------------------------------------
void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who __unused)
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 1593b17..b57f747 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -65,7 +65,9 @@ enum {
LIST_AUDIO_PATCHES,
SET_AUDIO_PORT_CONFIG,
REGISTER_CLIENT,
- GET_OUTPUT_FOR_ATTR
+ GET_OUTPUT_FOR_ATTR,
+ ACQUIRE_SOUNDTRIGGER_SESSION,
+ RELEASE_SOUNDTRIGGER_SESSION
};
class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
@@ -563,6 +565,7 @@ public:
}
return status;
}
+
virtual void registerClient(const sp<IAudioPolicyServiceClient>& client)
{
Parcel data, reply;
@@ -570,6 +573,40 @@ public:
data.writeStrongBinder(client->asBinder());
remote()->transact(REGISTER_CLIENT, data, &reply);
}
+
+ virtual status_t acquireSoundTriggerSession(audio_session_t *session,
+ audio_io_handle_t *ioHandle,
+ audio_devices_t *device)
+ {
+ if (session == NULL || ioHandle == NULL || device == NULL) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ status_t status = remote()->transact(ACQUIRE_SOUNDTRIGGER_SESSION, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = (status_t)reply.readInt32();
+ if (status == NO_ERROR) {
+ *session = (audio_session_t)reply.readInt32();
+ *ioHandle = (audio_io_handle_t)reply.readInt32();
+ *device = (audio_devices_t)reply.readInt32();
+ }
+ return status;
+ }
+
+ virtual status_t releaseSoundTriggerSession(audio_session_t session)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(session);
+ status_t status = remote()->transact(RELEASE_SOUNDTRIGGER_SESSION, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return (status_t)reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -984,6 +1021,7 @@ status_t BnAudioPolicyService::onTransact(
reply->writeInt32(status);
return NO_ERROR;
}
+
case REGISTER_CLIENT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>(
@@ -992,6 +1030,33 @@ status_t BnAudioPolicyService::onTransact(
return NO_ERROR;
} break;
+ case ACQUIRE_SOUNDTRIGGER_SESSION: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>(
+ data.readStrongBinder());
+ audio_session_t session;
+ audio_io_handle_t ioHandle;
+ audio_devices_t device;
+ status_t status = acquireSoundTriggerSession(&session, &ioHandle, &device);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->writeInt32(session);
+ reply->writeInt32(ioHandle);
+ reply->writeInt32(device);
+ }
+ return NO_ERROR;
+ } break;
+
+ case RELEASE_SOUNDTRIGGER_SESSION: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ sp<IAudioPolicyServiceClient> client = interface_cast<IAudioPolicyServiceClient>(
+ data.readStrongBinder());
+ audio_session_t session = (audio_session_t)data.readInt32();
+ status_t status = releaseSoundTriggerSession(session);
+ reply->writeInt32(status);
+ return NO_ERROR;
+ } break;
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index f3be42d..6512c38 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -30,7 +30,7 @@ LOCAL_SHARED_LIBRARIES := \
libbinder \
libmedia \
libhardware \
- libhardware_legacy \
+ libhardware_legacy
ifneq ($(USE_LEGACY_AUDIO_POLICY), 1)
LOCAL_SHARED_LIBRARIES += \
@@ -58,7 +58,8 @@ LOCAL_SRC_FILES:= \
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
- liblog
+ liblog \
+ libsoundtrigger
LOCAL_STATIC_LIBRARIES := \
libmedia_helper
diff --git a/services/audiopolicy/AudioPolicyClientImpl.cpp b/services/audiopolicy/AudioPolicyClientImpl.cpp
index c0019d1..3e090e9 100644
--- a/services/audiopolicy/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/AudioPolicyClientImpl.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "AudioPolicyClientImpl"
//#define LOG_NDEBUG 0
+#include <soundtrigger/SoundTrigger.h>
#include <utils/Log.h>
#include "AudioPolicyService.h"
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 50ee803..5524463 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -190,6 +190,11 @@ public:
virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
virtual void clearAudioPatches(uid_t uid) = 0;
+ virtual status_t acquireSoundTriggerSession(audio_session_t *session,
+ audio_io_handle_t *ioHandle,
+ audio_devices_t *device) = 0;
+
+ virtual status_t releaseSoundTriggerSession(audio_session_t session) = 0;
};
diff --git a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
index 75745b3..2c51e25 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImpl.cpp
@@ -531,4 +531,24 @@ status_t AudioPolicyService::setAudioPortConfig(const struct audio_port_config *
return mAudioPolicyManager->setAudioPortConfig(config);
}
+status_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session,
+ audio_io_handle_t *ioHandle,
+ audio_devices_t *device)
+{
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+
+ return mAudioPolicyManager->acquireSoundTriggerSession(session, ioHandle, device);
+}
+
+status_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session)
+{
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+
+ return mAudioPolicyManager->releaseSoundTriggerSession(session);
+}
+
}; // namespace android
diff --git a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
index aa46ace..f20c070 100644
--- a/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
+++ b/services/audiopolicy/AudioPolicyInterfaceImplLegacy.cpp
@@ -496,10 +496,21 @@ audio_io_handle_t AudioPolicyService::getOutputForAttr(const audio_attributes_t
audio_output_flags_t flags,
const audio_offload_info_t *offloadInfo)
{
- //FIXME: temporary to fix build with USE_LEGACY_AUDIO_POLICY
- audio_stream_type_t stream = AUDIO_STREAM_MUSIC;
+ audio_stream_type_t stream = audio_attributes_to_stream_type(attr);
+
return getOutput(stream, samplingRate, format, channelMask, flags, offloadInfo);
}
+status_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session,
+ audio_io_handle_t *ioHandle,
+ audio_devices_t *device)
+{
+ return INVALID_OPERATION;
+}
+
+status_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session)
+{
+ return INVALID_OPERATION;
+}
}; // namespace android
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 @@ audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource,
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 @@ audio_io_handle_t AudioPolicyManager::getInput(audio_source_t inputSource,
inputDesc->mChannelMask = channelMask;
inputDesc->mDevice = device;
inputDesc->mSessions.add(session);
+ inputDesc->mIsSoundTrigger = isSoundTrigger;
addInput(input, inputDesc);
mpClientInterface->onAudioPortListUpdate();
@@ -1194,6 +1207,9 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input,
}
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 @@ status_t AudioPolicyManager::stopInput(audio_io_handle_t input,
}
resetInputDevice(input);
+
+ if (activeInputsCount() == 0) {
+ SoundTrigger::setCaptureState(false);
+ }
}
return NO_ERROR;
}
@@ -2253,6 +2273,31 @@ void AudioPolicyManager::clearAudioPatches(uid_t uid)
}
}
+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 @@ status_t AudioPolicyManager::setInputDevice(audio_io_handle_t input,
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 @@ audio_io_handle_t AudioPolicyManager::getActiveInput(bool ignoreVirtualInputs)
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 @@ status_t AudioPolicyManager::AudioOutputDescriptor::dump(int fd)
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;
diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h
index e28a362..dd0f00f 100644
--- a/services/audiopolicy/AudioPolicyManager.h
+++ b/services/audiopolicy/AudioPolicyManager.h
@@ -172,6 +172,12 @@ public:
virtual status_t setAudioPortConfig(const struct audio_port_config *config);
virtual void clearAudioPatches(uid_t uid);
+ virtual status_t acquireSoundTriggerSession(audio_session_t *session,
+ audio_io_handle_t *ioHandle,
+ audio_devices_t *device);
+
+ virtual status_t releaseSoundTriggerSession(audio_session_t session);
+
protected:
enum routing_strategy {
@@ -477,15 +483,18 @@ protected:
status_t dump(int fd);
- audio_port_handle_t mId;
- audio_io_handle_t mIoHandle; // input handle
- audio_devices_t mDevice; // current device this input is routed to
- audio_patch_handle_t mPatchHandle;
- uint32_t mRefCount; // number of AudioRecord clients using this output
- uint32_t mOpenRefCount;
- audio_source_t mInputSource; // input source selected by application (mediarecorder.h)
- const sp<IOProfile> mProfile; // I/O profile this output derives from
- SortedVector<audio_session_t> mSessions; // audio sessions attached to this input
+ audio_port_handle_t mId;
+ audio_io_handle_t mIoHandle; // input handle
+ audio_devices_t mDevice; // current device this input is routed to
+ audio_patch_handle_t mPatchHandle;
+ uint32_t mRefCount; // number of AudioRecord clients using
+ // this input
+ uint32_t mOpenRefCount;
+ audio_source_t mInputSource; // input source selected by application
+ //(mediarecorder.h)
+ const sp<IOProfile> mProfile; // I/O profile this output derives from
+ SortedVector<audio_session_t> mSessions; // audio sessions attached to this input
+ bool mIsSoundTrigger; // used by a soundtrigger capture
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
@@ -569,6 +578,8 @@ protected:
// ignoreVirtualInputs is true.
audio_io_handle_t getActiveInput(bool ignoreVirtualInputs = true);
+ uint32_t activeInputsCount() const;
+
// initialize volume curves for each strategy and device category
void initializeVolumeCurves();
@@ -769,6 +780,8 @@ protected:
DefaultKeyedVector<audio_patch_handle_t, sp<AudioPatch> > mAudioPatches;
+ DefaultKeyedVector<audio_session_t, audio_io_handle_t> mSoundTriggerSessions;
+
#ifdef AUDIO_POLICY_TEST
Mutex mLock;
Condition mWaitWorkCV;
diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h
index 97236e3..0044e7a 100644
--- a/services/audiopolicy/AudioPolicyService.h
+++ b/services/audiopolicy/AudioPolicyService.h
@@ -168,6 +168,12 @@ public:
virtual void registerClient(const sp<IAudioPolicyServiceClient>& client);
+ virtual status_t acquireSoundTriggerSession(audio_session_t *session,
+ audio_io_handle_t *ioHandle,
+ audio_devices_t *device);
+
+ virtual status_t releaseSoundTriggerSession(audio_session_t session);
+
status_t doStopOutput(audio_io_handle_t output,
audio_stream_type_t stream,
int session = 0);
diff --git a/services/soundtrigger/Android.mk b/services/soundtrigger/Android.mk
index 51eb845..572ae56 100644
--- a/services/soundtrigger/Android.mk
+++ b/services/soundtrigger/Android.mk
@@ -31,7 +31,8 @@ LOCAL_SHARED_LIBRARIES:= \
libbinder \
libcutils \
libhardware \
- libsoundtrigger
+ libsoundtrigger \
+ libmedia
LOCAL_STATIC_LIBRARIES := \
libserviceutility
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index 3654136..2502e0d 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -25,12 +25,13 @@
#include <system/sound_trigger.h>
#include <cutils/atomic.h>
#include <cutils/properties.h>
+#include <hardware/hardware.h>
+#include <media/AudioSystem.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <binder/IServiceManager.h>
#include <binder/MemoryBase.h>
#include <binder/MemoryHeapBase.h>
-#include <hardware/hardware.h>
#include <hardware/sound_trigger.h>
#include <ServiceUtilities.h>
#include "SoundTriggerHwService.h"
@@ -45,7 +46,9 @@ namespace android {
SoundTriggerHwService::SoundTriggerHwService()
: BnSoundTriggerHwService(),
- mNextUniqueId(1)
+ mNextUniqueId(1),
+ mMemoryDealer(new MemoryDealer(1024 * 1024, "SoundTriggerHwService")),
+ mCaptureState(false)
{
}
@@ -143,15 +146,31 @@ status_t SoundTriggerHwService::attach(const sound_trigger_module_handle_t handl
client->asBinder()->linkToDeath(module);
moduleInterface = module;
+ module->setCaptureState_l(mCaptureState);
+
return NO_ERROR;
}
-void SoundTriggerHwService::detachModule(sp<Module> module) {
+status_t SoundTriggerHwService::setCaptureState(bool active)
+{
+ ALOGV("setCaptureState %d", active);
+ AutoMutex lock(mServiceLock);
+ mCaptureState = active;
+ for (size_t i = 0; i < mModules.size(); i++) {
+ mModules.valueAt(i)->setCaptureState_l(active);
+ }
+ return NO_ERROR;
+}
+
+
+void SoundTriggerHwService::detachModule(sp<Module> module)
+{
ALOGV("detachModule");
AutoMutex lock(mServiceLock);
module->clearClient();
}
+
static const int kDumpLockRetries = 50;
static const int kDumpLockSleep = 60000;
@@ -200,18 +219,175 @@ void SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition
if (module == NULL) {
return;
}
- module->sendRecognitionEvent(event);
+ sp<SoundTriggerHwService> service = module->service().promote();
+ if (service == 0) {
+ return;
+ }
+
+ service->sendRecognitionEvent(event, module);
+}
+
+sp<IMemory> SoundTriggerHwService::prepareRecognitionEvent_l(
+ struct sound_trigger_recognition_event *event)
+{
+ sp<IMemory> eventMemory;
+
+ //sanitize event
+ switch (event->type) {
+ case SOUND_MODEL_TYPE_KEYPHRASE:
+ ALOGW_IF(event->data_size != 0 && event->data_offset !=
+ sizeof(struct sound_trigger_phrase_recognition_event),
+ "prepareRecognitionEvent_l(): invalid data offset %u for keyphrase event type",
+ event->data_offset);
+ event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
+ break;
+ case SOUND_MODEL_TYPE_UNKNOWN:
+ ALOGW_IF(event->data_size != 0 && event->data_offset !=
+ sizeof(struct sound_trigger_recognition_event),
+ "prepareRecognitionEvent_l(): invalid data offset %u for unknown event type",
+ event->data_offset);
+ event->data_offset = sizeof(struct sound_trigger_recognition_event);
+ break;
+ default:
+ return eventMemory;
+ }
+
+ size_t size = event->data_offset + event->data_size;
+ eventMemory = mMemoryDealer->allocate(size);
+ if (eventMemory == 0 || eventMemory->pointer() == NULL) {
+ eventMemory.clear();
+ return eventMemory;
+ }
+ memcpy(eventMemory->pointer(), event, size);
+
+ return eventMemory;
+}
+
+void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event,
+ Module *module)
+ {
+ AutoMutex lock(mServiceLock);
+ if (module == NULL) {
+ return;
+ }
+ sp<IMemory> eventMemory = prepareRecognitionEvent_l(event);
+ if (eventMemory == 0) {
+ return;
+ }
+ sp<Module> strongModule;
+ for (size_t i = 0; i < mModules.size(); i++) {
+ if (mModules.valueAt(i).get() == module) {
+ strongModule = mModules.valueAt(i);
+ break;
+ }
+ }
+ if (strongModule == 0) {
+ return;
+ }
+
+ sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
+ eventMemory, strongModule));
}
+// static
+void SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event,
+ void *cookie)
+{
+ Module *module = (Module *)cookie;
+ if (module == NULL) {
+ return;
+ }
+ sp<SoundTriggerHwService> service = module->service().promote();
+ if (service == 0) {
+ return;
+ }
+
+ service->sendSoundModelEvent(event, module);
+}
-void SoundTriggerHwService::sendRecognitionEvent(const sp<RecognitionEvent>& event)
+sp<IMemory> SoundTriggerHwService::prepareSoundModelEvent_l(struct sound_trigger_model_event *event)
{
- mCallbackThread->sendRecognitionEvent(event);
+ sp<IMemory> eventMemory;
+
+ size_t size = event->data_offset + event->data_size;
+ eventMemory = mMemoryDealer->allocate(size);
+ if (eventMemory == 0 || eventMemory->pointer() == NULL) {
+ eventMemory.clear();
+ return eventMemory;
+ }
+ memcpy(eventMemory->pointer(), event, size);
+
+ return eventMemory;
}
-void SoundTriggerHwService::onRecognitionEvent(const sp<RecognitionEvent>& event)
+void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event,
+ Module *module)
{
- ALOGV("onRecognitionEvent");
+ AutoMutex lock(mServiceLock);
+ sp<IMemory> eventMemory = prepareSoundModelEvent_l(event);
+ if (eventMemory == 0) {
+ return;
+ }
+ sp<Module> strongModule;
+ for (size_t i = 0; i < mModules.size(); i++) {
+ if (mModules.valueAt(i).get() == module) {
+ strongModule = mModules.valueAt(i);
+ break;
+ }
+ }
+ if (strongModule == 0) {
+ return;
+ }
+ sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL,
+ eventMemory, strongModule));
+}
+
+
+sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
+{
+ sp<IMemory> eventMemory;
+
+ size_t size = sizeof(sound_trigger_service_state_t);
+ eventMemory = mMemoryDealer->allocate(size);
+ if (eventMemory == 0 || eventMemory->pointer() == NULL) {
+ eventMemory.clear();
+ return eventMemory;
+ }
+ *((sound_trigger_service_state_t *)eventMemory->pointer()) = state;
+ return eventMemory;
+}
+
+// call with mServiceLock held
+void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
+ Module *module)
+{
+ sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
+ if (eventMemory == 0) {
+ return;
+ }
+ sp<Module> strongModule;
+ for (size_t i = 0; i < mModules.size(); i++) {
+ if (mModules.valueAt(i).get() == module) {
+ strongModule = mModules.valueAt(i);
+ break;
+ }
+ }
+ if (strongModule == 0) {
+ return;
+ }
+ sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
+ eventMemory, strongModule));
+}
+
+// call with mServiceLock held
+void SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event)
+{
+ mCallbackThread->sendCallbackEvent(event);
+}
+
+void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event)
+{
+ ALOGV("onCallbackEvent");
sp<Module> module;
{
AutoMutex lock(mServiceLock);
@@ -220,15 +396,12 @@ void SoundTriggerHwService::onRecognitionEvent(const sp<RecognitionEvent>& event
return;
}
}
- module->onRecognitionEvent(event->mEventMemory);
-}
-
-// static
-void SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event __unused,
- void *cookie)
-{
- Module *module = (Module *)cookie;
-
+ module->onCallbackEvent(event);
+ {
+ AutoMutex lock(mServiceLock);
+ // clear now to execute with mServiceLock locked
+ event->mMemory.clear();
+ }
}
#undef LOG_TAG
@@ -241,7 +414,10 @@ SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwSer
SoundTriggerHwService::CallbackThread::~CallbackThread()
{
- mEventQueue.clear();
+ while (!mEventQueue.isEmpty()) {
+ mEventQueue[0]->mMemory.clear();
+ mEventQueue.removeAt(0);
+ }
}
void SoundTriggerHwService::CallbackThread::onFirstRef()
@@ -252,7 +428,7 @@ void SoundTriggerHwService::CallbackThread::onFirstRef()
bool SoundTriggerHwService::CallbackThread::threadLoop()
{
while (!exitPending()) {
- sp<RecognitionEvent> event;
+ sp<CallbackEvent> event;
sp<SoundTriggerHwService> service;
{
Mutex::Autolock _l(mCallbackLock);
@@ -269,7 +445,7 @@ bool SoundTriggerHwService::CallbackThread::threadLoop()
service = mService.promote();
}
if (service != 0) {
- service->onRecognitionEvent(event);
+ service->onCallbackEvent(event);
}
}
return false;
@@ -282,25 +458,25 @@ void SoundTriggerHwService::CallbackThread::exit()
mCallbackCond.broadcast();
}
-void SoundTriggerHwService::CallbackThread::sendRecognitionEvent(
- const sp<SoundTriggerHwService::RecognitionEvent>& event)
+void SoundTriggerHwService::CallbackThread::sendCallbackEvent(
+ const sp<SoundTriggerHwService::CallbackEvent>& event)
{
AutoMutex lock(mCallbackLock);
mEventQueue.add(event);
mCallbackCond.signal();
}
-SoundTriggerHwService::RecognitionEvent::RecognitionEvent(
- sp<IMemory> eventMemory,
- wp<Module> module)
- : mEventMemory(eventMemory), mModule(module)
+SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory,
+ wp<Module> module)
+ : mType(type), mMemory(memory), mModule(module)
{
}
-SoundTriggerHwService::RecognitionEvent::~RecognitionEvent()
+SoundTriggerHwService::CallbackEvent::~CallbackEvent()
{
}
+
#undef LOG_TAG
#define LOG_TAG "SoundTriggerHwService::Module"
@@ -309,7 +485,7 @@ SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
sound_trigger_module_descriptor descriptor,
const sp<ISoundTriggerClient>& client)
: mService(service), mHwDevice(hwDevice), mDescriptor(descriptor),
- mClient(client)
+ mClient(client), mServiceState(SOUND_TRIGGER_STATE_NO_INIT)
{
}
@@ -328,7 +504,6 @@ void SoundTriggerHwService::Module::detach() {
ALOGV("detach() unloading model %d", model->mHandle);
if (model->mState == Model::STATE_ACTIVE) {
mHwDevice->stop_recognition(mHwDevice, model->mHandle);
- model->deallocateMemory();
}
mHwDevice->unload_sound_model(mHwDevice, model->mHandle);
}
@@ -365,10 +540,21 @@ status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelM
SoundTriggerHwService::soundModelCallback,
this,
handle);
- if (status == NO_ERROR) {
- mModels.replaceValueFor(*handle, new Model(*handle));
+ if (status != NO_ERROR) {
+ return status;
+ }
+ audio_session_t session;
+ audio_io_handle_t ioHandle;
+ audio_devices_t device;
+
+ status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
+ if (status != NO_ERROR) {
+ return status;
}
+ sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type);
+ mModels.replaceValueFor(*handle, model);
+
return status;
}
@@ -388,8 +574,8 @@ status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t ha
mModels.removeItem(handle);
if (model->mState == Model::STATE_ACTIVE) {
mHwDevice->stop_recognition(mHwDevice, model->mHandle);
- model->deallocateMemory();
}
+ AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
return mHwDevice->unload_sound_model(mHwDevice, handle);
}
@@ -407,6 +593,9 @@ status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t ha
}
AutoMutex lock(mLock);
+ if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
+ return INVALID_OPERATION;
+ }
sp<Model> model = getModel(handle);
if (model == 0) {
return BAD_VALUE;
@@ -419,17 +608,23 @@ status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t ha
if (model->mState == Model::STATE_ACTIVE) {
return INVALID_OPERATION;
}
- model->mState = Model::STATE_ACTIVE;
struct sound_trigger_recognition_config *config =
(struct sound_trigger_recognition_config *)dataMemory->pointer();
//TODO: get capture handle and device from audio policy service
- config->capture_handle = AUDIO_IO_HANDLE_NONE;
- config->capture_device = AUDIO_DEVICE_NONE;
- return mHwDevice->start_recognition(mHwDevice, handle, config,
+ config->capture_handle = model->mCaptureIOHandle;
+ config->capture_device = model->mCaptureDevice;
+ status_t status = mHwDevice->start_recognition(mHwDevice, handle, config,
SoundTriggerHwService::recognitionCallback,
this);
+
+ if (status == NO_ERROR) {
+ model->mState = Model::STATE_ACTIVE;
+ model->mConfig = *config;
+ }
+
+ return status;
}
status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
@@ -449,93 +644,62 @@ status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t han
return INVALID_OPERATION;
}
mHwDevice->stop_recognition(mHwDevice, handle);
- model->deallocateMemory();
model->mState = Model::STATE_IDLE;
return NO_ERROR;
}
-void SoundTriggerHwService::Module::sendRecognitionEvent(
- struct sound_trigger_recognition_event *event)
-{
- sp<SoundTriggerHwService> service;
- sp<IMemory> eventMemory;
- ALOGV("sendRecognitionEvent for model %d", event->model);
- {
- AutoMutex lock(mLock);
- sp<Model> model = getModel(event->model);
- if (model == 0) {
- return;
- }
- if (model->mState != Model::STATE_ACTIVE) {
- ALOGV("sendRecognitionEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
- return;
- }
- if (mClient == 0) {
- return;
- }
- service = mService.promote();
- if (service == 0) {
- return;
- }
-
- //sanitize event
- switch (event->type) {
- case SOUND_MODEL_TYPE_KEYPHRASE:
- ALOGW_IF(event->data_offset !=
- sizeof(struct sound_trigger_phrase_recognition_event),
- "sendRecognitionEvent(): invalid data offset %u for keyphrase event type",
- event->data_offset);
- event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
- break;
- case SOUND_MODEL_TYPE_UNKNOWN:
- ALOGW_IF(event->data_offset !=
- sizeof(struct sound_trigger_recognition_event),
- "sendRecognitionEvent(): invalid data offset %u for unknown event type",
- event->data_offset);
- event->data_offset = sizeof(struct sound_trigger_recognition_event);
- break;
- default:
- return;
- }
-
- size_t size = event->data_offset + event->data_size;
- eventMemory = model->allocateMemory(size);
- if (eventMemory == 0 || eventMemory->pointer() == NULL) {
- return;
- }
- memcpy(eventMemory->pointer(), event, size);
- }
- service->sendRecognitionEvent(new RecognitionEvent(eventMemory, this));
-}
-void SoundTriggerHwService::Module::onRecognitionEvent(sp<IMemory> eventMemory)
+void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
{
- ALOGV("Module::onRecognitionEvent");
+ ALOGV("onCallbackEvent type %d", event->mType);
AutoMutex lock(mLock);
+ sp<IMemory> eventMemory = event->mMemory;
if (eventMemory == 0 || eventMemory->pointer() == NULL) {
return;
}
- struct sound_trigger_recognition_event *event =
- (struct sound_trigger_recognition_event *)eventMemory->pointer();
-
- sp<Model> model = getModel(event->model);
- if (model == 0) {
- ALOGI("%s model == 0", __func__);
- return;
- }
- if (model->mState != Model::STATE_ACTIVE) {
- ALOGV("onRecognitionEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
- return;
- }
if (mClient == 0) {
ALOGI("%s mClient == 0", __func__);
return;
}
- mClient->onRecognitionEvent(eventMemory);
- model->mState = Model::STATE_IDLE;
- model->deallocateMemory();
+
+ switch (event->mType) {
+ case CallbackEvent::TYPE_RECOGNITION: {
+ struct sound_trigger_recognition_event *recognitionEvent =
+ (struct sound_trigger_recognition_event *)eventMemory->pointer();
+
+ sp<Model> model = getModel(recognitionEvent->model);
+ if (model == 0) {
+ ALOGW("%s model == 0", __func__);
+ return;
+ }
+ if (model->mState != Model::STATE_ACTIVE) {
+ ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
+ return;
+ }
+
+ recognitionEvent->capture_session = model->mCaptureSession;
+ mClient->onRecognitionEvent(eventMemory);
+ model->mState = Model::STATE_IDLE;
+ } break;
+ case CallbackEvent::TYPE_SOUNDMODEL: {
+ struct sound_trigger_model_event *soundmodelEvent =
+ (struct sound_trigger_model_event *)eventMemory->pointer();
+
+ sp<Model> model = getModel(soundmodelEvent->model);
+ if (model == 0) {
+ ALOGW("%s model == 0", __func__);
+ return;
+ }
+ mClient->onSoundModelEvent(eventMemory);
+ } break;
+ case CallbackEvent::TYPE_SERVICE_STATE: {
+ mClient->onServiceStateChange(eventMemory);
+ } break;
+ default:
+ LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
+ }
}
sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
@@ -555,30 +719,80 @@ void SoundTriggerHwService::Module::binderDied(
detach();
}
-
-SoundTriggerHwService::Model::Model(sound_model_handle_t handle) :
- mHandle(handle), mState(STATE_IDLE), mInputHandle(AUDIO_IO_HANDLE_NONE),
- mCaptureSession(AUDIO_SESSION_ALLOCATE),
- mMemoryDealer(new MemoryDealer(sizeof(struct sound_trigger_recognition_event),
- "SoundTriggerHwService::Event"))
+// Called with mServiceLock held
+void SoundTriggerHwService::Module::setCaptureState_l(bool active)
{
+ ALOGV("Module::setCaptureState_l %d", active);
+ sp<SoundTriggerHwService> service;
+ sound_trigger_service_state_t state;
-}
+ Vector< sp<IMemory> > events;
+ {
+ AutoMutex lock(mLock);
+ state = (active && !mDescriptor.properties.concurrent_capture) ?
+ SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
+ if (state == mServiceState) {
+ return;
+ }
-sp<IMemory> SoundTriggerHwService::Model::allocateMemory(size_t size)
-{
- sp<IMemory> memory;
- if (mMemoryDealer->getMemoryHeap()->getSize() < size) {
- mMemoryDealer = new MemoryDealer(size, "SoundTriggerHwService::Event");
+ mServiceState = state;
+
+ service = mService.promote();
+ if (service == 0) {
+ return;
+ }
+
+ if (state == SOUND_TRIGGER_STATE_ENABLED) {
+ goto exit;
+ }
+
+ for (size_t i = 0; i < mModels.size(); i++) {
+ sp<Model> model = mModels.valueAt(i);
+ if (model->mState == Model::STATE_ACTIVE) {
+ mHwDevice->stop_recognition(mHwDevice, model->mHandle);
+ // keep model in ACTIVE state so that event is processed by onCallbackEvent()
+ struct sound_trigger_phrase_recognition_event phraseEvent;
+ switch (model->mType) {
+ case SOUND_MODEL_TYPE_KEYPHRASE:
+ phraseEvent.num_phrases = model->mConfig.num_phrases;
+ for (size_t i = 0; i < phraseEvent.num_phrases; i++) {
+ phraseEvent.phrase_extras[i] = model->mConfig.phrases[i];
+ }
+ break;
+ case SOUND_MODEL_TYPE_UNKNOWN:
+ default:
+ break;
+ }
+ phraseEvent.common.status = RECOGNITION_STATUS_ABORT;
+ phraseEvent.common.type = model->mType;
+ phraseEvent.common.model = model->mHandle;
+ phraseEvent.common.data_size = 0;
+ sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&phraseEvent.common);
+ if (eventMemory != 0) {
+ events.add(eventMemory);
+ }
+ }
+ }
}
- memory = mMemoryDealer->allocate(size);
- return memory;
+
+ for (size_t i = 0; i < events.size(); i++) {
+ service->sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i],
+ this));
+ }
+
+exit:
+ service->sendServiceStateEvent_l(state, this);
}
-void SoundTriggerHwService::Model::deallocateMemory()
+
+SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
+ audio_io_handle_t ioHandle, audio_devices_t device,
+ sound_trigger_sound_model_type_t type) :
+ mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
+ mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type)
{
- mMemoryDealer->deallocate(0);
+
}
status_t SoundTriggerHwService::Module::dump(int fd __unused,
diff --git a/services/soundtrigger/SoundTriggerHwService.h b/services/soundtrigger/SoundTriggerHwService.h
index 377f2a1..d05dacd 100644
--- a/services/soundtrigger/SoundTriggerHwService.h
+++ b/services/soundtrigger/SoundTriggerHwService.h
@@ -53,6 +53,8 @@ public:
const sp<ISoundTriggerClient>& client,
sp<ISoundTrigger>& module);
+ virtual status_t setCaptureState(bool active);
+
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
@@ -66,17 +68,33 @@ public:
STATE_ACTIVE
};
- Model(sound_model_handle_t handle);
+ Model(sound_model_handle_t handle, audio_session_t session, audio_io_handle_t ioHandle,
+ audio_devices_t device, sound_trigger_sound_model_type_t type);
~Model() {}
- sp<IMemory> allocateMemory(size_t size);
- void deallocateMemory();
-
sound_model_handle_t mHandle;
int mState;
- audio_io_handle_t mInputHandle;
audio_session_t mCaptureSession;
- sp<MemoryDealer> mMemoryDealer;
+ audio_io_handle_t mCaptureIOHandle;
+ audio_devices_t mCaptureDevice;
+ sound_trigger_sound_model_type_t mType;
+ struct sound_trigger_recognition_config mConfig;
+ };
+
+ class CallbackEvent : public RefBase {
+ public:
+ typedef enum {
+ TYPE_RECOGNITION,
+ TYPE_SOUNDMODEL,
+ TYPE_SERVICE_STATE,
+ } event_type;
+ CallbackEvent(event_type type, sp<IMemory> memory, wp<Module> module);
+
+ virtual ~CallbackEvent();
+
+ event_type mType;
+ sp<IMemory> mMemory;
+ wp<Module> mModule;
};
class Module : public virtual RefBase,
@@ -109,36 +127,29 @@ public:
struct sound_trigger_module_descriptor descriptor() { return mDescriptor; }
void setClient(sp<ISoundTriggerClient> client) { mClient = client; }
void clearClient() { mClient.clear(); }
- sp<ISoundTriggerClient> client() { return mClient; }
+ sp<ISoundTriggerClient> client() const { return mClient; }
+ wp<SoundTriggerHwService> service() const { return mService; }
- void sendRecognitionEvent(struct sound_trigger_recognition_event *event);
- void onRecognitionEvent(sp<IMemory> eventMemory);
+ void onCallbackEvent(const sp<CallbackEvent>& event);
sp<Model> getModel(sound_model_handle_t handle);
+ void setCaptureState_l(bool active);
+
// IBinder::DeathRecipient implementation
virtual void binderDied(const wp<IBinder> &who);
private:
+
Mutex mLock;
wp<SoundTriggerHwService> mService;
struct sound_trigger_hw_device* mHwDevice;
struct sound_trigger_module_descriptor mDescriptor;
sp<ISoundTriggerClient> mClient;
DefaultKeyedVector< sound_model_handle_t, sp<Model> > mModels;
+ sound_trigger_service_state_t mServiceState;
}; // class Module
- class RecognitionEvent : public RefBase {
- public:
-
- RecognitionEvent(sp<IMemory> eventMemory, wp<Module> module);
-
- virtual ~RecognitionEvent();
-
- sp<IMemory> mEventMemory;
- wp<Module> mModule;
- };
-
class CallbackThread : public Thread {
public:
@@ -153,22 +164,30 @@ public:
virtual void onFirstRef();
void exit();
- void sendRecognitionEvent(const sp<RecognitionEvent>& event);
+ void sendCallbackEvent(const sp<CallbackEvent>& event);
private:
wp<SoundTriggerHwService> mService;
Condition mCallbackCond;
Mutex mCallbackLock;
- Vector< sp<RecognitionEvent> > mEventQueue;
+ Vector< sp<CallbackEvent> > mEventQueue;
};
- void detachModule(sp<Module> module);
+ void detachModule(sp<Module> module);
static void recognitionCallback(struct sound_trigger_recognition_event *event, void *cookie);
- void sendRecognitionEvent(const sp<RecognitionEvent>& event);
- void onRecognitionEvent(const sp<RecognitionEvent>& event);
+ sp<IMemory> prepareRecognitionEvent_l(struct sound_trigger_recognition_event *event);
+ void sendRecognitionEvent(struct sound_trigger_recognition_event *event, Module *module);
static void soundModelCallback(struct sound_trigger_model_event *event, void *cookie);
+ sp<IMemory> prepareSoundModelEvent_l(struct sound_trigger_model_event *event);
+ void sendSoundModelEvent(struct sound_trigger_model_event *event, Module *module);
+
+ sp<IMemory> prepareServiceStateEvent_l(sound_trigger_service_state_t state);
+ void sendServiceStateEvent_l(sound_trigger_service_state_t state, Module *module);
+
+ void sendCallbackEvent_l(const sp<CallbackEvent>& event);
+ void onCallbackEvent(const sp<CallbackEvent>& event);
private:
@@ -178,6 +197,8 @@ private:
volatile int32_t mNextUniqueId;
DefaultKeyedVector< sound_trigger_module_handle_t, sp<Module> > mModules;
sp<CallbackThread> mCallbackThread;
+ sp<MemoryDealer> mMemoryDealer;
+ bool mCaptureState;
};
} // namespace android
diff --git a/soundtrigger/ISoundTriggerClient.cpp b/soundtrigger/ISoundTriggerClient.cpp
index 1d0c0ec..b0b4428 100644
--- a/soundtrigger/ISoundTriggerClient.cpp
+++ b/soundtrigger/ISoundTriggerClient.cpp
@@ -27,6 +27,8 @@ namespace android {
enum {
ON_RECOGNITION_EVENT = IBinder::FIRST_CALL_TRANSACTION,
+ ON_SOUNDMODEL_EVENT,
+ ON_SERVICE_STATE_CHANGE
};
class BpSoundTriggerClient: public BpInterface<ISoundTriggerClient>
@@ -47,6 +49,25 @@ public:
data,
&reply);
}
+
+ virtual void onSoundModelEvent(const sp<IMemory>& eventMemory)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISoundTriggerClient::getInterfaceDescriptor());
+ data.writeStrongBinder(eventMemory->asBinder());
+ remote()->transact(ON_SOUNDMODEL_EVENT,
+ data,
+ &reply);
+ }
+ virtual void onServiceStateChange(const sp<IMemory>& eventMemory)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISoundTriggerClient::getInterfaceDescriptor());
+ data.writeStrongBinder(eventMemory->asBinder());
+ remote()->transact(ON_SERVICE_STATE_CHANGE,
+ data,
+ &reply);
+ }
};
IMPLEMENT_META_INTERFACE(SoundTriggerClient,
@@ -65,6 +86,20 @@ status_t BnSoundTriggerClient::onTransact(
onRecognitionEvent(eventMemory);
return NO_ERROR;
} break;
+ case ON_SOUNDMODEL_EVENT: {
+ CHECK_INTERFACE(ISoundTriggerClient, data, reply);
+ sp<IMemory> eventMemory = interface_cast<IMemory>(
+ data.readStrongBinder());
+ onSoundModelEvent(eventMemory);
+ return NO_ERROR;
+ } break;
+ case ON_SERVICE_STATE_CHANGE: {
+ CHECK_INTERFACE(ISoundTriggerClient, data, reply);
+ sp<IMemory> eventMemory = interface_cast<IMemory>(
+ data.readStrongBinder());
+ onServiceStateChange(eventMemory);
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/soundtrigger/ISoundTriggerHwService.cpp b/soundtrigger/ISoundTriggerHwService.cpp
index c9a0c24..05728e9 100644
--- a/soundtrigger/ISoundTriggerHwService.cpp
+++ b/soundtrigger/ISoundTriggerHwService.cpp
@@ -37,6 +37,7 @@ namespace android {
enum {
LIST_MODULES = IBinder::FIRST_CALL_TRANSACTION,
ATTACH,
+ SET_CAPTURE_STATE,
};
class BpSoundTriggerHwService: public BpInterface<ISoundTriggerHwService>
@@ -90,6 +91,18 @@ public:
return status;
}
+ virtual status_t setCaptureState(bool active)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISoundTriggerHwService::getInterfaceDescriptor());
+ data.writeInt32(active);
+ status_t status = remote()->transact(SET_CAPTURE_STATE, data, &reply);
+ if (status == NO_ERROR) {
+ status = reply.readInt32();
+ }
+ return status;
+ }
+
};
IMPLEMENT_META_INTERFACE(SoundTriggerHwService, "android.hardware.ISoundTriggerHwService");
@@ -140,6 +153,13 @@ status_t BnSoundTriggerHwService::onTransact(
}
return NO_ERROR;
} break;
+
+ case SET_CAPTURE_STATE: {
+ CHECK_INTERFACE(ISoundTriggerHwService, data, reply);
+ reply->writeInt32(setCaptureState((bool)data.readInt32()));
+ return NO_ERROR;
+ } break;
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/soundtrigger/SoundTrigger.cpp b/soundtrigger/SoundTrigger.cpp
index e43acd0..0015c30 100644
--- a/soundtrigger/SoundTrigger.cpp
+++ b/soundtrigger/SoundTrigger.cpp
@@ -113,6 +113,16 @@ sp<SoundTrigger> SoundTrigger::attach(const sound_trigger_module_handle_t module
}
+status_t SoundTrigger::setCaptureState(bool active)
+{
+ ALOGV("setCaptureState(%d)", active);
+ const sp<ISoundTriggerHwService>& service = getSoundTriggerHwService();
+ if (service == 0) {
+ return NO_INIT;
+ }
+ return service->setCaptureState(active);
+}
+
// SoundTrigger
SoundTrigger::SoundTrigger(sound_trigger_module_handle_t module,
const sp<SoundTriggerCallback>& callback)
@@ -192,6 +202,31 @@ void SoundTrigger::onRecognitionEvent(const sp<IMemory>& eventMemory)
}
}
+void SoundTrigger::onSoundModelEvent(const sp<IMemory>& eventMemory)
+{
+ Mutex::Autolock _l(mLock);
+ if (eventMemory == 0 || eventMemory->pointer() == NULL) {
+ return;
+ }
+
+ if (mCallback != 0) {
+ mCallback->onSoundModelEvent(
+ (struct sound_trigger_model_event *)eventMemory->pointer());
+ }
+}
+
+void SoundTrigger::onServiceStateChange(const sp<IMemory>& eventMemory)
+{
+ Mutex::Autolock _l(mLock);
+ if (eventMemory == 0 || eventMemory->pointer() == NULL) {
+ return;
+ }
+
+ if (mCallback != 0) {
+ mCallback->onServiceStateChange(
+ *((sound_trigger_service_state_t *)eventMemory->pointer()));
+ }
+}
//IBinder::DeathRecipient
void SoundTrigger::binderDied(const wp<IBinder>& who __unused) {