diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index cf34991aae8..f22792fab12 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -309,6 +309,12 @@ class AudioSystem /* 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 abbda3229ed..c25143917b0 100644 --- a/include/media/IAudioPolicyService.h +++ b/include/media/IAudioPolicyService.h @@ -136,6 +136,12 @@ class IAudioPolicyService : public IInterface virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0; virtual void registerClient(const sp& 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 7f86d025869..480429a4903 100644 --- a/include/soundtrigger/ISoundTriggerClient.h +++ b/include/soundtrigger/ISoundTriggerClient.h @@ -31,6 +31,10 @@ class ISoundTriggerClient : public IInterface virtual void onRecognitionEvent(const sp& eventMemory) = 0; + virtual void onSoundModelEvent(const sp& eventMemory) = 0; + + virtual void onServiceStateChange(const sp& eventMemory) = 0; + }; // ---------------------------------------------------------------------------- diff --git a/include/soundtrigger/ISoundTriggerHwService.h b/include/soundtrigger/ISoundTriggerHwService.h index 05a764a9452..ae0cb01dbd8 100644 --- a/include/soundtrigger/ISoundTriggerHwService.h +++ b/include/soundtrigger/ISoundTriggerHwService.h @@ -39,6 +39,8 @@ class ISoundTriggerHwService : public IInterface virtual status_t attach(const sound_trigger_module_handle_t handle, const sp& client, sp& module) = 0; + + virtual status_t setCaptureState(bool active) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/soundtrigger/SoundTrigger.h b/include/soundtrigger/SoundTrigger.h index 1f7f286bbd0..bf5e1de4083 100644 --- a/include/soundtrigger/SoundTrigger.h +++ b/include/soundtrigger/SoundTrigger.h @@ -18,6 +18,7 @@ #define ANDROID_HARDWARE_SOUNDTRIGGER_H #include +#include #include #include #include @@ -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 attach(const sound_trigger_module_handle_t module, const sp& callback); - virtual ~SoundTrigger(); + static status_t setCaptureState(bool active); void detach(); @@ -51,6 +55,8 @@ class SoundTrigger : public BnSoundTriggerClient, // BpSoundTriggerClient virtual void onRecognitionEvent(const sp& eventMemory); + virtual void onSoundModelEvent(const sp& eventMemory); + virtual void onServiceStateChange(const sp& eventMemory); //IBinder::DeathRecipient virtual void binderDied(const wp& who); diff --git a/include/soundtrigger/SoundTriggerCallback.h b/include/soundtrigger/SoundTriggerCallback.h index 8a5ba028987..b5277f20068 100644 --- a/include/soundtrigger/SoundTriggerCallback.h +++ b/include/soundtrigger/SoundTriggerCallback.h @@ -31,6 +31,10 @@ class SoundTriggerCallback : public RefBase 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 365a5942922..172b05630f6 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -913,6 +913,21 @@ void AudioSystem::setAudioPortCallback(sp callBack) gAudioPortCallback = callBack; } +status_t AudioSystem::acquireSoundTriggerSession(audio_session_t *session, + audio_io_handle_t *ioHandle, + audio_devices_t *device) +{ + const sp& 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& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return PERMISSION_DENIED; + return aps->releaseSoundTriggerSession(session); +} // --------------------------------------------------------------------------- void AudioSystem::AudioPolicyServiceClient::binderDied(const wp& who __unused) diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp index 1593b17aa7a..b57f747c0c2 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 @@ -563,6 +565,7 @@ class BpAudioPolicyService : public BpInterface } return status; } + virtual void registerClient(const sp& client) { Parcel data, reply; @@ -570,6 +573,40 @@ class BpAudioPolicyService : public BpInterface 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 client = interface_cast( @@ -992,6 +1030,33 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } break; + case ACQUIRE_SOUNDTRIGGER_SESSION: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + sp client = interface_cast( + 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 client = interface_cast( + 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 f3be42d503f..6512c382603 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 c0019d1e6a6..3e090e977b6 100644 --- a/services/audiopolicy/AudioPolicyClientImpl.cpp +++ b/services/audiopolicy/AudioPolicyClientImpl.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "AudioPolicyClientImpl" //#define LOG_NDEBUG 0 +#include #include #include "AudioPolicyService.h" diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h index 50ee803b3e1..552446312e0 100644 --- a/services/audiopolicy/AudioPolicyInterface.h +++ b/services/audiopolicy/AudioPolicyInterface.h @@ -190,6 +190,11 @@ class AudioPolicyInterface 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 75745b39e11..2c51e25b345 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 aa46acebe65..f20c070dbc1 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 440f5d0ed8a..f716358ba3d 100644 --- a/services/audiopolicy/AudioPolicyManager.cpp +++ b/services/audiopolicy/AudioPolicyManager.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #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& 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 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& 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 e28a3628b24..dd0f00ff7e9 100644 --- a/services/audiopolicy/AudioPolicyManager.h +++ b/services/audiopolicy/AudioPolicyManager.h @@ -172,6 +172,12 @@ class AudioPolicyManager: public AudioPolicyInterface 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 @@ class AudioPolicyManager: public AudioPolicyInterface 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 mProfile; // I/O profile this output derives from - SortedVector 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 mProfile; // I/O profile this output derives from + SortedVector 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 @@ class AudioPolicyManager: public AudioPolicyInterface // 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 @@ class AudioPolicyManager: public AudioPolicyInterface DefaultKeyedVector > mAudioPatches; + DefaultKeyedVector mSoundTriggerSessions; + #ifdef AUDIO_POLICY_TEST Mutex mLock; Condition mWaitWorkCV; diff --git a/services/audiopolicy/AudioPolicyService.h b/services/audiopolicy/AudioPolicyService.h index 97236e343f1..0044e7a068a 100644 --- a/services/audiopolicy/AudioPolicyService.h +++ b/services/audiopolicy/AudioPolicyService.h @@ -168,6 +168,12 @@ class AudioPolicyService : virtual void registerClient(const sp& 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 51eb845fbd2..572ae567858 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 3654136b336..2502e0d12f9 100644 --- a/services/soundtrigger/SoundTriggerHwService.cpp +++ b/services/soundtrigger/SoundTriggerHwService.cpp @@ -25,12 +25,13 @@ #include #include #include +#include +#include #include #include #include #include #include -#include #include #include #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) { +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) +{ 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 service = module->service().promote(); + if (service == 0) { + return; + } + + service->sendRecognitionEvent(event, module); +} + +sp SoundTriggerHwService::prepareRecognitionEvent_l( + struct sound_trigger_recognition_event *event) +{ + sp 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 eventMemory = prepareRecognitionEvent_l(event); + if (eventMemory == 0) { + return; + } + sp 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 service = module->service().promote(); + if (service == 0) { + return; + } + + service->sendSoundModelEvent(event, module); +} -void SoundTriggerHwService::sendRecognitionEvent(const sp& event) +sp SoundTriggerHwService::prepareSoundModelEvent_l(struct sound_trigger_model_event *event) { - mCallbackThread->sendRecognitionEvent(event); + sp 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& event) +void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event, + Module *module) { - ALOGV("onRecognitionEvent"); + AutoMutex lock(mServiceLock); + sp eventMemory = prepareSoundModelEvent_l(event); + if (eventMemory == 0) { + return; + } + sp 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 SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state) +{ + sp 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 eventMemory = prepareServiceStateEvent_l(state); + if (eventMemory == 0) { + return; + } + sp 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& event) +{ + mCallbackThread->sendCallbackEvent(event); +} + +void SoundTriggerHwService::onCallbackEvent(const sp& event) +{ + ALOGV("onCallbackEvent"); sp module; { AutoMutex lock(mServiceLock); @@ -220,15 +396,12 @@ void SoundTriggerHwService::onRecognitionEvent(const sp& 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 wpmMemory.clear(); + mEventQueue.removeAt(0); + } } void SoundTriggerHwService::CallbackThread::onFirstRef() @@ -252,7 +428,7 @@ void SoundTriggerHwService::CallbackThread::onFirstRef() bool SoundTriggerHwService::CallbackThread::threadLoop() { while (!exitPending()) { - sp event; + sp event; sp 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& event) +void SoundTriggerHwService::CallbackThread::sendCallbackEvent( + const sp& event) { AutoMutex lock(mCallbackLock); mEventQueue.add(event); mCallbackCond.signal(); } -SoundTriggerHwService::RecognitionEvent::RecognitionEvent( - sp eventMemory, - wp module) - : mEventMemory(eventMemory), mModule(module) +SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp memory, + wp 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& service, sound_trigger_module_descriptor descriptor, const sp& 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& 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 = 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 = 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 service; - sp eventMemory; - ALOGV("sendRecognitionEvent for model %d", event->model); - { - AutoMutex lock(mLock); - sp 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 eventMemory) +void SoundTriggerHwService::Module::onCallbackEvent(const sp& event) { - ALOGV("Module::onRecognitionEvent"); + ALOGV("onCallbackEvent type %d", event->mType); AutoMutex lock(mLock); + sp 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 = 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 = 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 = 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::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 service; + sound_trigger_service_state_t state; -} + Vector< sp > events; + { + AutoMutex lock(mLock); + state = (active && !mDescriptor.properties.concurrent_capture) ? + SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED; + if (state == mServiceState) { + return; + } -sp SoundTriggerHwService::Model::allocateMemory(size_t size) -{ - sp 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 = 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 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 377f2a1faec..d05dacdb7f2 100644 --- a/services/soundtrigger/SoundTriggerHwService.h +++ b/services/soundtrigger/SoundTriggerHwService.h @@ -53,6 +53,8 @@ class SoundTriggerHwService : const sp& client, sp& 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 @@ class SoundTriggerHwService : 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 allocateMemory(size_t size); - void deallocateMemory(); - sound_model_handle_t mHandle; int mState; - audio_io_handle_t mInputHandle; audio_session_t mCaptureSession; - sp 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 memory, wp module); + + virtual ~CallbackEvent(); + + event_type mType; + sp mMemory; + wp mModule; }; class Module : public virtual RefBase, @@ -109,36 +127,29 @@ class SoundTriggerHwService : struct sound_trigger_module_descriptor descriptor() { return mDescriptor; } void setClient(sp client) { mClient = client; } void clearClient() { mClient.clear(); } - sp client() { return mClient; } + sp client() const { return mClient; } + wp service() const { return mService; } - void sendRecognitionEvent(struct sound_trigger_recognition_event *event); - void onRecognitionEvent(sp eventMemory); + void onCallbackEvent(const sp& event); sp getModel(sound_model_handle_t handle); + void setCaptureState_l(bool active); + // IBinder::DeathRecipient implementation virtual void binderDied(const wp &who); private: + Mutex mLock; wp mService; struct sound_trigger_hw_device* mHwDevice; struct sound_trigger_module_descriptor mDescriptor; sp mClient; DefaultKeyedVector< sound_model_handle_t, sp > mModels; + sound_trigger_service_state_t mServiceState; }; // class Module - class RecognitionEvent : public RefBase { - public: - - RecognitionEvent(sp eventMemory, wp module); - - virtual ~RecognitionEvent(); - - sp mEventMemory; - wp mModule; - }; - class CallbackThread : public Thread { public: @@ -153,22 +164,30 @@ class SoundTriggerHwService : virtual void onFirstRef(); void exit(); - void sendRecognitionEvent(const sp& event); + void sendCallbackEvent(const sp& event); private: wp mService; Condition mCallbackCond; Mutex mCallbackLock; - Vector< sp > mEventQueue; + Vector< sp > mEventQueue; }; - void detachModule(sp module); + void detachModule(sp module); static void recognitionCallback(struct sound_trigger_recognition_event *event, void *cookie); - void sendRecognitionEvent(const sp& event); - void onRecognitionEvent(const sp& event); + sp 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 prepareSoundModelEvent_l(struct sound_trigger_model_event *event); + void sendSoundModelEvent(struct sound_trigger_model_event *event, Module *module); + + sp prepareServiceStateEvent_l(sound_trigger_service_state_t state); + void sendServiceStateEvent_l(sound_trigger_service_state_t state, Module *module); + + void sendCallbackEvent_l(const sp& event); + void onCallbackEvent(const sp& event); private: @@ -178,6 +197,8 @@ class SoundTriggerHwService : volatile int32_t mNextUniqueId; DefaultKeyedVector< sound_trigger_module_handle_t, sp > mModules; sp mCallbackThread; + sp mMemoryDealer; + bool mCaptureState; }; } // namespace android diff --git a/soundtrigger/ISoundTriggerClient.cpp b/soundtrigger/ISoundTriggerClient.cpp index 1d0c0ec6a37..b0b4428e179 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 @@ -47,6 +49,25 @@ class BpSoundTriggerClient: public BpInterface data, &reply); } + + virtual void onSoundModelEvent(const sp& eventMemory) + { + Parcel data, reply; + data.writeInterfaceToken(ISoundTriggerClient::getInterfaceDescriptor()); + data.writeStrongBinder(eventMemory->asBinder()); + remote()->transact(ON_SOUNDMODEL_EVENT, + data, + &reply); + } + virtual void onServiceStateChange(const sp& 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 eventMemory = interface_cast( + data.readStrongBinder()); + onSoundModelEvent(eventMemory); + return NO_ERROR; + } break; + case ON_SERVICE_STATE_CHANGE: { + CHECK_INTERFACE(ISoundTriggerClient, data, reply); + sp eventMemory = interface_cast( + 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 c9a0c24415a..05728e90420 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 @@ -90,6 +91,18 @@ class BpSoundTriggerHwService: public BpInterface 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 e43acd0d5b0..0015c306cdb 100644 --- a/soundtrigger/SoundTrigger.cpp +++ b/soundtrigger/SoundTrigger.cpp @@ -113,6 +113,16 @@ sp SoundTrigger::attach(const sound_trigger_module_handle_t module } +status_t SoundTrigger::setCaptureState(bool active) +{ + ALOGV("setCaptureState(%d)", active); + const sp& service = getSoundTriggerHwService(); + if (service == 0) { + return NO_INIT; + } + return service->setCaptureState(active); +} + // SoundTrigger SoundTrigger::SoundTrigger(sound_trigger_module_handle_t module, const sp& callback) @@ -192,6 +202,31 @@ void SoundTrigger::onRecognitionEvent(const sp& eventMemory) } } +void SoundTrigger::onSoundModelEvent(const sp& 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& 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& who __unused) {