Loading services/soundtrigger/SoundTriggerHwService.cpp +270 −82 Original line number Diff line number Diff line Loading @@ -73,8 +73,7 @@ void SoundTriggerHwService::onFirstRef() ALOGI("loaded default module %s, handle %d", descriptor.properties.description, descriptor.handle); sp<ISoundTriggerClient> client; sp<Module> module = new Module(this, halInterface, descriptor, client); sp<Module> module = new Module(this, halInterface, descriptor); mModules.add(descriptor.handle, module); mCallbackThread = new CallbackThread(this); } Loading Loading @@ -126,11 +125,13 @@ status_t SoundTriggerHwService::attach(const sound_trigger_module_handle_t handl } sp<Module> module = mModules.valueAt(index); module->setClient(client); IInterface::asBinder(client)->linkToDeath(module); moduleInterface = module; sp<ModuleClient> moduleClient = module->addClient(client); if (moduleClient == 0) { return NO_INIT; } module->setCaptureState_l(mCaptureState); moduleClient->setCaptureState_l(mCaptureState); moduleInterface = moduleClient; return NO_ERROR; } Loading @@ -147,14 +148,6 @@ status_t SoundTriggerHwService::setCaptureState(bool active) } void SoundTriggerHwService::detachModule(const sp<Module>& module) { ALOGV("detachModule"); AutoMutex lock(mServiceLock); module->clearClient(); } static const int kDumpLockRetries = 50; static const int kDumpLockSleep = 60000; Loading Loading @@ -276,8 +269,10 @@ void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognitio return; } sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, eventMemory, strongModule)); sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, eventMemory); callbackEvent->setModule(strongModule); sendCallbackEvent_l(callbackEvent); } // static Loading Loading @@ -329,8 +324,10 @@ void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event if (strongModule == 0) { return; } sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL, eventMemory, strongModule)); sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL, eventMemory); callbackEvent->setModule(strongModule); sendCallbackEvent_l(callbackEvent); } Loading Loading @@ -366,8 +363,23 @@ void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_ if (strongModule == 0) { return; } sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE, eventMemory, strongModule)); sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE, eventMemory); callbackEvent->setModule(strongModule); sendCallbackEvent_l(callbackEvent); } void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state, ModuleClient *moduleClient) { sp<IMemory> eventMemory = prepareServiceStateEvent_l(state); if (eventMemory == 0) { return; } sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE, eventMemory); callbackEvent->setModuleClient(moduleClient); sendCallbackEvent_l(callbackEvent); } // call with mServiceLock held Loading @@ -380,14 +392,25 @@ void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event) { ALOGV("onCallbackEvent"); sp<Module> module; sp<ModuleClient> moduleClient; { AutoMutex lock(mServiceLock); //CallbackEvent is either for Module or ModuleClient module = event->mModule.promote(); if (module == 0) { moduleClient = event->mModuleClient.promote(); if (moduleClient == 0) { return; } } } if (module != 0) { ALOGV("onCallbackEvent for module"); module->onCallbackEvent(event); } else if (moduleClient != 0) { ALOGV("onCallbackEvent for moduleClient"); moduleClient->onCallbackEvent(event); } { AutoMutex lock(mServiceLock); // clear now to execute with mServiceLock locked Loading Loading @@ -457,9 +480,8 @@ void SoundTriggerHwService::CallbackThread::sendCallbackEvent( mCallbackCond.signal(); } SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory, wp<Module> module) : mType(type), mMemory(memory), mModule(module) SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory) : mType(type), mMemory(memory) { } Loading @@ -473,25 +495,59 @@ SoundTriggerHwService::CallbackEvent::~CallbackEvent() SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service, const sp<SoundTriggerHalInterface>& halInterface, sound_trigger_module_descriptor descriptor, const sp<ISoundTriggerClient>& client) sound_trigger_module_descriptor descriptor) : mService(service), mHalInterface(halInterface), mDescriptor(descriptor), mClient(client), mServiceState(SOUND_TRIGGER_STATE_NO_INIT) mServiceState(SOUND_TRIGGER_STATE_NO_INIT) { } SoundTriggerHwService::Module::~Module() { mModuleClients.clear(); } void SoundTriggerHwService::Module::detach() { ALOGV("detach()"); if (!captureHotwordAllowed()) { return; sp<SoundTriggerHwService::ModuleClient> SoundTriggerHwService::Module::addClient(const sp<ISoundTriggerClient>& client) { AutoMutex lock(mLock); sp<ModuleClient> moduleClient; for (size_t i = 0; i < mModuleClients.size(); i++) { if (mModuleClients[i]->client() == client) { // Client already present, reuse client return moduleClient; } } moduleClient = new ModuleClient(this, client); ALOGV("addClient() client %p", moduleClient.get()); mModuleClients.add(moduleClient); return moduleClient; } void SoundTriggerHwService::Module::detach(const sp<ModuleClient>& moduleClient) { ALOGV("Module::detach()"); AutoMutex lock(mLock); ssize_t index = -1; for (size_t i = 0; i < mModuleClients.size(); i++) { if (mModuleClients[i] == moduleClient) { index = i; break; } } if (index == -1) { return; } ALOGV("remove client %p", moduleClient.get()); mModuleClients.removeAt(index); for (size_t i = 0; i < mModels.size(); i++) { sp<Model> model = mModels.valueAt(i); if (moduleClient == model->mModuleClient) { mModels.removeItemsAt(i); ALOGV("detach() unloading model %d", model->mHandle); if (mHalInterface != 0) { if (model->mState == Model::STATE_ACTIVE) { Loading @@ -499,29 +555,20 @@ void SoundTriggerHwService::Module::detach() { } mHalInterface->unloadSoundModel(model->mHandle); } AudioSystem::releaseSoundTriggerSession(model->mCaptureSession); mHalInterface->unloadSoundModel(model->mHandle); } mModels.clear(); } if (mClient != 0) { IInterface::asBinder(mClient)->unlinkToDeath(this); } sp<SoundTriggerHwService> service = mService.promote(); if (service == 0) { return; } service->detachModule(this); } status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory, sp<ModuleClient> moduleClient, sound_model_handle_t *handle) { ALOGV("loadSoundModel() handle"); if (mHalInterface == 0) { return NO_INIT; } if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } if (modelMemory == 0 || modelMemory->pointer() == NULL) { ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()"); return BAD_VALUE; Loading Loading @@ -569,7 +616,8 @@ status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelM return status; } sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type); sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type, moduleClient); mModels.replaceValueFor(*handle, model); return status; Loading @@ -578,10 +626,6 @@ status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelM status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle) { ALOGV("unloadSoundModel() model handle %d", handle); if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } AutoMutex lock(mLock); return unloadSoundModel_l(handle); } Loading Loading @@ -612,10 +656,6 @@ status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t ha if (mHalInterface == 0) { return NO_INIT; } if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } if (dataMemory == 0 || dataMemory->pointer() == NULL) { ALOGE("startRecognition() dataMemory is 0 or has NULL pointer()"); return BAD_VALUE; Loading Loading @@ -668,10 +708,6 @@ status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t han if (mHalInterface == 0) { return NO_INIT; } if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } AutoMutex lock(mLock); sp<Model> model = getModel(handle); if (model == 0) { Loading @@ -686,7 +722,6 @@ status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t han return NO_ERROR; } void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event) { ALOGV("onCallbackEvent type %d", event->mType); Loading @@ -696,8 +731,8 @@ void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& eve if (eventMemory == 0 || eventMemory->pointer() == NULL) { return; } if (mClient == 0) { ALOGI("%s mClient == 0", __func__); if (mModuleClients.isEmpty()) { ALOGI("%s no clients", __func__); return; } Loading @@ -720,7 +755,7 @@ void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& eve recognitionEvent->capture_session = model->mCaptureSession; model->mState = Model::STATE_IDLE; client = mClient; client = model->mModuleClient->client(); } if (client != 0) { client->onRecognitionEvent(eventMemory); Loading @@ -737,20 +772,24 @@ void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& eve ALOGW("%s model == 0", __func__); return; } client = mClient; client = model->mModuleClient->client(); } if (client != 0) { client->onSoundModelEvent(eventMemory); } } break; case CallbackEvent::TYPE_SERVICE_STATE: { sp<ISoundTriggerClient> client; Vector< sp<ISoundTriggerClient> > clients; { AutoMutex lock(mLock); client = mClient; for (size_t i = 0; i < mModuleClients.size(); i++) { if (mModuleClients[i] != 0) { clients.add(mModuleClients[i]->client()); } if (client != 0) { client->onServiceStateChange(eventMemory); } } for (size_t i = 0; i < clients.size(); i++) { clients[i]->onServiceStateChange(eventMemory); } } break; default: Loading @@ -769,12 +808,6 @@ sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel( return model; } void SoundTriggerHwService::Module::binderDied( const wp<IBinder> &who __unused) { ALOGW("client binder died for module %d", mDescriptor.handle); detach(); } // Called with mServiceLock held void SoundTriggerHwService::Module::setCaptureState_l(bool active) { Loading Loading @@ -858,8 +891,10 @@ void SoundTriggerHwService::Module::setCaptureState_l(bool active) } for (size_t i = 0; i < events.size(); i++) { service->sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i], this)); sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i]); callbackEvent->setModule(this); service->sendCallbackEvent_l(callbackEvent); } exit: Loading @@ -869,17 +904,170 @@ exit: 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) : sound_trigger_sound_model_type_t type, sp<ModuleClient>& moduleClient) : mHandle(handle), mState(STATE_IDLE), mCaptureSession(session), mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type) mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type), mModuleClient(moduleClient) { } #undef LOG_TAG #define LOG_TAG "SoundTriggerHwService::ModuleClient" SoundTriggerHwService::ModuleClient::ModuleClient(const sp<Module>& module, const sp<ISoundTriggerClient>& client) : mModule(module), mClient(client) { } void SoundTriggerHwService::ModuleClient::onFirstRef() { IInterface::asBinder(mClient)->linkToDeath(this); } SoundTriggerHwService::ModuleClient::~ModuleClient() { } status_t SoundTriggerHwService::Module::dump(int fd __unused, status_t SoundTriggerHwService::ModuleClient::dump(int fd __unused, const Vector<String16>& args __unused) { String8 result; return NO_ERROR; } void SoundTriggerHwService::ModuleClient::detach() { ALOGV("detach()"); if (!captureHotwordAllowed()) { return; } { AutoMutex lock(mLock); if (mClient != 0) { IInterface::asBinder(mClient)->unlinkToDeath(this); mClient.clear(); } } sp<Module> module = mModule.promote(); if (module == 0) { return; } module->detach(this); } status_t SoundTriggerHwService::ModuleClient::loadSoundModel(const sp<IMemory>& modelMemory, sound_model_handle_t *handle) { ALOGV("loadSoundModel() handle"); if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } sp<Module> module = mModule.promote(); if (module == 0) { return NO_INIT; } return module->loadSoundModel(modelMemory, this, handle); } status_t SoundTriggerHwService::ModuleClient::unloadSoundModel(sound_model_handle_t handle) { ALOGV("unloadSoundModel() model handle %d", handle); if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } sp<Module> module = mModule.promote(); if (module == 0) { return NO_INIT; } return module->unloadSoundModel(handle); } status_t SoundTriggerHwService::ModuleClient::startRecognition(sound_model_handle_t handle, const sp<IMemory>& dataMemory) { ALOGV("startRecognition() model handle %d", handle); if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } sp<Module> module = mModule.promote(); if (module == 0) { return NO_INIT; } return module->startRecognition(handle, dataMemory); } status_t SoundTriggerHwService::ModuleClient::stopRecognition(sound_model_handle_t handle) { ALOGV("stopRecognition() model handle %d", handle); if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } sp<Module> module = mModule.promote(); if (module == 0) { return NO_INIT; } return module->stopRecognition(handle); } void SoundTriggerHwService::ModuleClient::setCaptureState_l(bool active) { ALOGV("ModuleClient::setCaptureState_l %d", active); sp<SoundTriggerHwService> service; sound_trigger_service_state_t state; sp<Module> module = mModule.promote(); if (module == 0) { return; } { AutoMutex lock(mLock); state = (active && !module->isConcurrentCaptureAllowed()) ? SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED; service = module->service().promote(); if (service == 0) { return; } } service->sendServiceStateEvent_l(state, this); } void SoundTriggerHwService::ModuleClient::onCallbackEvent(const sp<CallbackEvent>& event) { ALOGV("ModuleClient onCallbackEvent type %d", event->mType); sp<IMemory> eventMemory = event->mMemory; if (eventMemory == 0 || eventMemory->pointer() == NULL) { return; } switch (event->mType) { case CallbackEvent::TYPE_SERVICE_STATE: { sp<ISoundTriggerClient> client; { AutoMutex lock(mLock); client = mClient; } if (client !=0 ) { client->onServiceStateChange(eventMemory); } } break; default: LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType); } } void SoundTriggerHwService::ModuleClient::binderDied( const wp<IBinder> &who __unused) { ALOGW("client binder died for client %p", this); detach(); } }; // namespace android services/soundtrigger/SoundTriggerHwService.h +64 −24 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ class SoundTriggerHwService : friend class BinderService<SoundTriggerHwService>; public: class Module; class ModuleClient; static char const* getServiceName() { return "media.sound_trigger_hw"; } Loading Loading @@ -69,7 +70,8 @@ public: }; 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); audio_devices_t device, sound_trigger_sound_model_type_t type, sp<ModuleClient>& moduleClient); ~Model() {} sound_model_handle_t mHandle; Loading @@ -79,6 +81,7 @@ public: audio_devices_t mCaptureDevice; sound_trigger_sound_model_type_t mType; struct sound_trigger_recognition_config mConfig; sp<ModuleClient> mModuleClient; }; class CallbackEvent : public RefBase { Loading @@ -88,30 +91,30 @@ public: TYPE_SOUNDMODEL, TYPE_SERVICE_STATE, } event_type; CallbackEvent(event_type type, sp<IMemory> memory, wp<Module> module); CallbackEvent(event_type type, sp<IMemory> memory); virtual ~CallbackEvent(); void setModule(wp<Module> module) { mModule = module; } void setModuleClient(wp<ModuleClient> moduleClient) { mModuleClient = moduleClient; } event_type mType; sp<IMemory> mMemory; wp<Module> mModule; wp<ModuleClient> mModuleClient; }; class Module : public virtual RefBase, public BnSoundTrigger, public IBinder::DeathRecipient { class Module : public RefBase { public: Module(const sp<SoundTriggerHwService>& service, const sp<SoundTriggerHalInterface>& halInterface, sound_trigger_module_descriptor descriptor, const sp<ISoundTriggerClient>& client); sound_trigger_module_descriptor descriptor); virtual ~Module(); virtual void detach(); virtual status_t loadSoundModel(const sp<IMemory>& modelMemory, sp<ModuleClient> moduleClient, sound_model_handle_t *handle); virtual status_t unloadSoundModel(sound_model_handle_t handle); Loading @@ -120,38 +123,75 @@ public: const sp<IMemory>& dataMemory); virtual status_t stopRecognition(sound_model_handle_t handle); virtual status_t dump(int fd, const Vector<String16>& args); sp<SoundTriggerHalInterface> halInterface() const { return mHalInterface; } struct sound_trigger_module_descriptor descriptor() { return mDescriptor; } void setClient(const sp<ISoundTriggerClient>& client) { mClient = client; } void clearClient() { mClient.clear(); } sp<ISoundTriggerClient> client() const { return mClient; } wp<SoundTriggerHwService> service() const { return mService; } void onCallbackEvent(const sp<CallbackEvent>& event); bool isConcurrentCaptureAllowed() const { return mDescriptor.properties.concurrent_capture; } sp<Model> getModel(sound_model_handle_t handle); void setCaptureState_l(bool active); // IBinder::DeathRecipient implementation virtual void binderDied(const wp<IBinder> &who); sp<ModuleClient> addClient(const sp<ISoundTriggerClient>& client); void detach(const sp<ModuleClient>& moduleClient); void onCallbackEvent(const sp<CallbackEvent>& event); private: status_t unloadSoundModel_l(sound_model_handle_t handle); Mutex mLock; wp<SoundTriggerHwService> mService; sp<SoundTriggerHalInterface> mHalInterface; struct sound_trigger_module_descriptor mDescriptor; sp<ISoundTriggerClient> mClient; Vector< sp<ModuleClient> > mModuleClients; DefaultKeyedVector< sound_model_handle_t, sp<Model> > mModels; sound_trigger_service_state_t mServiceState; }; // class Module class ModuleClient : public virtual RefBase, public BnSoundTrigger, public IBinder::DeathRecipient { public: ModuleClient(const sp<Module>& module, const sp<ISoundTriggerClient>& client); virtual ~ModuleClient(); virtual void detach(); virtual status_t loadSoundModel(const sp<IMemory>& modelMemory, sound_model_handle_t *handle); virtual status_t unloadSoundModel(sound_model_handle_t handle); virtual status_t startRecognition(sound_model_handle_t handle, const sp<IMemory>& dataMemory); virtual status_t stopRecognition(sound_model_handle_t handle); virtual status_t dump(int fd, const Vector<String16>& args); virtual void onFirstRef(); // IBinder::DeathRecipient implementation virtual void binderDied(const wp<IBinder> &who); void onCallbackEvent(const sp<CallbackEvent>& event); void setCaptureState_l(bool active); sp<ISoundTriggerClient> client() const { return mClient; } private: mutable Mutex mLock; wp<Module> mModule; sp<ISoundTriggerClient> mClient; }; // class ModuleClient class CallbackThread : public Thread { public: Loading @@ -175,8 +215,6 @@ public: Vector< sp<CallbackEvent> > mEventQueue; }; void detachModule(const sp<Module>& module); static void recognitionCallback(struct sound_trigger_recognition_event *event, void *cookie); sp<IMemory> prepareRecognitionEvent_l(struct sound_trigger_recognition_event *event); void sendRecognitionEvent(struct sound_trigger_recognition_event *event, Module *module); Loading @@ -187,6 +225,8 @@ public: sp<IMemory> prepareServiceStateEvent_l(sound_trigger_service_state_t state); void sendServiceStateEvent_l(sound_trigger_service_state_t state, Module *module); void sendServiceStateEvent_l(sound_trigger_service_state_t state, ModuleClient *moduleClient); void sendCallbackEvent_l(const sp<CallbackEvent>& event); void onCallbackEvent(const sp<CallbackEvent>& event); Loading Loading
services/soundtrigger/SoundTriggerHwService.cpp +270 −82 Original line number Diff line number Diff line Loading @@ -73,8 +73,7 @@ void SoundTriggerHwService::onFirstRef() ALOGI("loaded default module %s, handle %d", descriptor.properties.description, descriptor.handle); sp<ISoundTriggerClient> client; sp<Module> module = new Module(this, halInterface, descriptor, client); sp<Module> module = new Module(this, halInterface, descriptor); mModules.add(descriptor.handle, module); mCallbackThread = new CallbackThread(this); } Loading Loading @@ -126,11 +125,13 @@ status_t SoundTriggerHwService::attach(const sound_trigger_module_handle_t handl } sp<Module> module = mModules.valueAt(index); module->setClient(client); IInterface::asBinder(client)->linkToDeath(module); moduleInterface = module; sp<ModuleClient> moduleClient = module->addClient(client); if (moduleClient == 0) { return NO_INIT; } module->setCaptureState_l(mCaptureState); moduleClient->setCaptureState_l(mCaptureState); moduleInterface = moduleClient; return NO_ERROR; } Loading @@ -147,14 +148,6 @@ status_t SoundTriggerHwService::setCaptureState(bool active) } void SoundTriggerHwService::detachModule(const sp<Module>& module) { ALOGV("detachModule"); AutoMutex lock(mServiceLock); module->clearClient(); } static const int kDumpLockRetries = 50; static const int kDumpLockSleep = 60000; Loading Loading @@ -276,8 +269,10 @@ void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognitio return; } sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, eventMemory, strongModule)); sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, eventMemory); callbackEvent->setModule(strongModule); sendCallbackEvent_l(callbackEvent); } // static Loading Loading @@ -329,8 +324,10 @@ void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event if (strongModule == 0) { return; } sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL, eventMemory, strongModule)); sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL, eventMemory); callbackEvent->setModule(strongModule); sendCallbackEvent_l(callbackEvent); } Loading Loading @@ -366,8 +363,23 @@ void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_ if (strongModule == 0) { return; } sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE, eventMemory, strongModule)); sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE, eventMemory); callbackEvent->setModule(strongModule); sendCallbackEvent_l(callbackEvent); } void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state, ModuleClient *moduleClient) { sp<IMemory> eventMemory = prepareServiceStateEvent_l(state); if (eventMemory == 0) { return; } sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE, eventMemory); callbackEvent->setModuleClient(moduleClient); sendCallbackEvent_l(callbackEvent); } // call with mServiceLock held Loading @@ -380,14 +392,25 @@ void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event) { ALOGV("onCallbackEvent"); sp<Module> module; sp<ModuleClient> moduleClient; { AutoMutex lock(mServiceLock); //CallbackEvent is either for Module or ModuleClient module = event->mModule.promote(); if (module == 0) { moduleClient = event->mModuleClient.promote(); if (moduleClient == 0) { return; } } } if (module != 0) { ALOGV("onCallbackEvent for module"); module->onCallbackEvent(event); } else if (moduleClient != 0) { ALOGV("onCallbackEvent for moduleClient"); moduleClient->onCallbackEvent(event); } { AutoMutex lock(mServiceLock); // clear now to execute with mServiceLock locked Loading Loading @@ -457,9 +480,8 @@ void SoundTriggerHwService::CallbackThread::sendCallbackEvent( mCallbackCond.signal(); } SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory, wp<Module> module) : mType(type), mMemory(memory), mModule(module) SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory) : mType(type), mMemory(memory) { } Loading @@ -473,25 +495,59 @@ SoundTriggerHwService::CallbackEvent::~CallbackEvent() SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service, const sp<SoundTriggerHalInterface>& halInterface, sound_trigger_module_descriptor descriptor, const sp<ISoundTriggerClient>& client) sound_trigger_module_descriptor descriptor) : mService(service), mHalInterface(halInterface), mDescriptor(descriptor), mClient(client), mServiceState(SOUND_TRIGGER_STATE_NO_INIT) mServiceState(SOUND_TRIGGER_STATE_NO_INIT) { } SoundTriggerHwService::Module::~Module() { mModuleClients.clear(); } void SoundTriggerHwService::Module::detach() { ALOGV("detach()"); if (!captureHotwordAllowed()) { return; sp<SoundTriggerHwService::ModuleClient> SoundTriggerHwService::Module::addClient(const sp<ISoundTriggerClient>& client) { AutoMutex lock(mLock); sp<ModuleClient> moduleClient; for (size_t i = 0; i < mModuleClients.size(); i++) { if (mModuleClients[i]->client() == client) { // Client already present, reuse client return moduleClient; } } moduleClient = new ModuleClient(this, client); ALOGV("addClient() client %p", moduleClient.get()); mModuleClients.add(moduleClient); return moduleClient; } void SoundTriggerHwService::Module::detach(const sp<ModuleClient>& moduleClient) { ALOGV("Module::detach()"); AutoMutex lock(mLock); ssize_t index = -1; for (size_t i = 0; i < mModuleClients.size(); i++) { if (mModuleClients[i] == moduleClient) { index = i; break; } } if (index == -1) { return; } ALOGV("remove client %p", moduleClient.get()); mModuleClients.removeAt(index); for (size_t i = 0; i < mModels.size(); i++) { sp<Model> model = mModels.valueAt(i); if (moduleClient == model->mModuleClient) { mModels.removeItemsAt(i); ALOGV("detach() unloading model %d", model->mHandle); if (mHalInterface != 0) { if (model->mState == Model::STATE_ACTIVE) { Loading @@ -499,29 +555,20 @@ void SoundTriggerHwService::Module::detach() { } mHalInterface->unloadSoundModel(model->mHandle); } AudioSystem::releaseSoundTriggerSession(model->mCaptureSession); mHalInterface->unloadSoundModel(model->mHandle); } mModels.clear(); } if (mClient != 0) { IInterface::asBinder(mClient)->unlinkToDeath(this); } sp<SoundTriggerHwService> service = mService.promote(); if (service == 0) { return; } service->detachModule(this); } status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory, sp<ModuleClient> moduleClient, sound_model_handle_t *handle) { ALOGV("loadSoundModel() handle"); if (mHalInterface == 0) { return NO_INIT; } if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } if (modelMemory == 0 || modelMemory->pointer() == NULL) { ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()"); return BAD_VALUE; Loading Loading @@ -569,7 +616,8 @@ status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelM return status; } sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type); sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type, moduleClient); mModels.replaceValueFor(*handle, model); return status; Loading @@ -578,10 +626,6 @@ status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelM status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle) { ALOGV("unloadSoundModel() model handle %d", handle); if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } AutoMutex lock(mLock); return unloadSoundModel_l(handle); } Loading Loading @@ -612,10 +656,6 @@ status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t ha if (mHalInterface == 0) { return NO_INIT; } if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } if (dataMemory == 0 || dataMemory->pointer() == NULL) { ALOGE("startRecognition() dataMemory is 0 or has NULL pointer()"); return BAD_VALUE; Loading Loading @@ -668,10 +708,6 @@ status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t han if (mHalInterface == 0) { return NO_INIT; } if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } AutoMutex lock(mLock); sp<Model> model = getModel(handle); if (model == 0) { Loading @@ -686,7 +722,6 @@ status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t han return NO_ERROR; } void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event) { ALOGV("onCallbackEvent type %d", event->mType); Loading @@ -696,8 +731,8 @@ void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& eve if (eventMemory == 0 || eventMemory->pointer() == NULL) { return; } if (mClient == 0) { ALOGI("%s mClient == 0", __func__); if (mModuleClients.isEmpty()) { ALOGI("%s no clients", __func__); return; } Loading @@ -720,7 +755,7 @@ void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& eve recognitionEvent->capture_session = model->mCaptureSession; model->mState = Model::STATE_IDLE; client = mClient; client = model->mModuleClient->client(); } if (client != 0) { client->onRecognitionEvent(eventMemory); Loading @@ -737,20 +772,24 @@ void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& eve ALOGW("%s model == 0", __func__); return; } client = mClient; client = model->mModuleClient->client(); } if (client != 0) { client->onSoundModelEvent(eventMemory); } } break; case CallbackEvent::TYPE_SERVICE_STATE: { sp<ISoundTriggerClient> client; Vector< sp<ISoundTriggerClient> > clients; { AutoMutex lock(mLock); client = mClient; for (size_t i = 0; i < mModuleClients.size(); i++) { if (mModuleClients[i] != 0) { clients.add(mModuleClients[i]->client()); } if (client != 0) { client->onServiceStateChange(eventMemory); } } for (size_t i = 0; i < clients.size(); i++) { clients[i]->onServiceStateChange(eventMemory); } } break; default: Loading @@ -769,12 +808,6 @@ sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel( return model; } void SoundTriggerHwService::Module::binderDied( const wp<IBinder> &who __unused) { ALOGW("client binder died for module %d", mDescriptor.handle); detach(); } // Called with mServiceLock held void SoundTriggerHwService::Module::setCaptureState_l(bool active) { Loading Loading @@ -858,8 +891,10 @@ void SoundTriggerHwService::Module::setCaptureState_l(bool active) } for (size_t i = 0; i < events.size(); i++) { service->sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i], this)); sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i]); callbackEvent->setModule(this); service->sendCallbackEvent_l(callbackEvent); } exit: Loading @@ -869,17 +904,170 @@ exit: 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) : sound_trigger_sound_model_type_t type, sp<ModuleClient>& moduleClient) : mHandle(handle), mState(STATE_IDLE), mCaptureSession(session), mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type) mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type), mModuleClient(moduleClient) { } #undef LOG_TAG #define LOG_TAG "SoundTriggerHwService::ModuleClient" SoundTriggerHwService::ModuleClient::ModuleClient(const sp<Module>& module, const sp<ISoundTriggerClient>& client) : mModule(module), mClient(client) { } void SoundTriggerHwService::ModuleClient::onFirstRef() { IInterface::asBinder(mClient)->linkToDeath(this); } SoundTriggerHwService::ModuleClient::~ModuleClient() { } status_t SoundTriggerHwService::Module::dump(int fd __unused, status_t SoundTriggerHwService::ModuleClient::dump(int fd __unused, const Vector<String16>& args __unused) { String8 result; return NO_ERROR; } void SoundTriggerHwService::ModuleClient::detach() { ALOGV("detach()"); if (!captureHotwordAllowed()) { return; } { AutoMutex lock(mLock); if (mClient != 0) { IInterface::asBinder(mClient)->unlinkToDeath(this); mClient.clear(); } } sp<Module> module = mModule.promote(); if (module == 0) { return; } module->detach(this); } status_t SoundTriggerHwService::ModuleClient::loadSoundModel(const sp<IMemory>& modelMemory, sound_model_handle_t *handle) { ALOGV("loadSoundModel() handle"); if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } sp<Module> module = mModule.promote(); if (module == 0) { return NO_INIT; } return module->loadSoundModel(modelMemory, this, handle); } status_t SoundTriggerHwService::ModuleClient::unloadSoundModel(sound_model_handle_t handle) { ALOGV("unloadSoundModel() model handle %d", handle); if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } sp<Module> module = mModule.promote(); if (module == 0) { return NO_INIT; } return module->unloadSoundModel(handle); } status_t SoundTriggerHwService::ModuleClient::startRecognition(sound_model_handle_t handle, const sp<IMemory>& dataMemory) { ALOGV("startRecognition() model handle %d", handle); if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } sp<Module> module = mModule.promote(); if (module == 0) { return NO_INIT; } return module->startRecognition(handle, dataMemory); } status_t SoundTriggerHwService::ModuleClient::stopRecognition(sound_model_handle_t handle) { ALOGV("stopRecognition() model handle %d", handle); if (!captureHotwordAllowed()) { return PERMISSION_DENIED; } sp<Module> module = mModule.promote(); if (module == 0) { return NO_INIT; } return module->stopRecognition(handle); } void SoundTriggerHwService::ModuleClient::setCaptureState_l(bool active) { ALOGV("ModuleClient::setCaptureState_l %d", active); sp<SoundTriggerHwService> service; sound_trigger_service_state_t state; sp<Module> module = mModule.promote(); if (module == 0) { return; } { AutoMutex lock(mLock); state = (active && !module->isConcurrentCaptureAllowed()) ? SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED; service = module->service().promote(); if (service == 0) { return; } } service->sendServiceStateEvent_l(state, this); } void SoundTriggerHwService::ModuleClient::onCallbackEvent(const sp<CallbackEvent>& event) { ALOGV("ModuleClient onCallbackEvent type %d", event->mType); sp<IMemory> eventMemory = event->mMemory; if (eventMemory == 0 || eventMemory->pointer() == NULL) { return; } switch (event->mType) { case CallbackEvent::TYPE_SERVICE_STATE: { sp<ISoundTriggerClient> client; { AutoMutex lock(mLock); client = mClient; } if (client !=0 ) { client->onServiceStateChange(eventMemory); } } break; default: LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType); } } void SoundTriggerHwService::ModuleClient::binderDied( const wp<IBinder> &who __unused) { ALOGW("client binder died for client %p", this); detach(); } }; // namespace android
services/soundtrigger/SoundTriggerHwService.h +64 −24 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ class SoundTriggerHwService : friend class BinderService<SoundTriggerHwService>; public: class Module; class ModuleClient; static char const* getServiceName() { return "media.sound_trigger_hw"; } Loading Loading @@ -69,7 +70,8 @@ public: }; 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); audio_devices_t device, sound_trigger_sound_model_type_t type, sp<ModuleClient>& moduleClient); ~Model() {} sound_model_handle_t mHandle; Loading @@ -79,6 +81,7 @@ public: audio_devices_t mCaptureDevice; sound_trigger_sound_model_type_t mType; struct sound_trigger_recognition_config mConfig; sp<ModuleClient> mModuleClient; }; class CallbackEvent : public RefBase { Loading @@ -88,30 +91,30 @@ public: TYPE_SOUNDMODEL, TYPE_SERVICE_STATE, } event_type; CallbackEvent(event_type type, sp<IMemory> memory, wp<Module> module); CallbackEvent(event_type type, sp<IMemory> memory); virtual ~CallbackEvent(); void setModule(wp<Module> module) { mModule = module; } void setModuleClient(wp<ModuleClient> moduleClient) { mModuleClient = moduleClient; } event_type mType; sp<IMemory> mMemory; wp<Module> mModule; wp<ModuleClient> mModuleClient; }; class Module : public virtual RefBase, public BnSoundTrigger, public IBinder::DeathRecipient { class Module : public RefBase { public: Module(const sp<SoundTriggerHwService>& service, const sp<SoundTriggerHalInterface>& halInterface, sound_trigger_module_descriptor descriptor, const sp<ISoundTriggerClient>& client); sound_trigger_module_descriptor descriptor); virtual ~Module(); virtual void detach(); virtual status_t loadSoundModel(const sp<IMemory>& modelMemory, sp<ModuleClient> moduleClient, sound_model_handle_t *handle); virtual status_t unloadSoundModel(sound_model_handle_t handle); Loading @@ -120,38 +123,75 @@ public: const sp<IMemory>& dataMemory); virtual status_t stopRecognition(sound_model_handle_t handle); virtual status_t dump(int fd, const Vector<String16>& args); sp<SoundTriggerHalInterface> halInterface() const { return mHalInterface; } struct sound_trigger_module_descriptor descriptor() { return mDescriptor; } void setClient(const sp<ISoundTriggerClient>& client) { mClient = client; } void clearClient() { mClient.clear(); } sp<ISoundTriggerClient> client() const { return mClient; } wp<SoundTriggerHwService> service() const { return mService; } void onCallbackEvent(const sp<CallbackEvent>& event); bool isConcurrentCaptureAllowed() const { return mDescriptor.properties.concurrent_capture; } sp<Model> getModel(sound_model_handle_t handle); void setCaptureState_l(bool active); // IBinder::DeathRecipient implementation virtual void binderDied(const wp<IBinder> &who); sp<ModuleClient> addClient(const sp<ISoundTriggerClient>& client); void detach(const sp<ModuleClient>& moduleClient); void onCallbackEvent(const sp<CallbackEvent>& event); private: status_t unloadSoundModel_l(sound_model_handle_t handle); Mutex mLock; wp<SoundTriggerHwService> mService; sp<SoundTriggerHalInterface> mHalInterface; struct sound_trigger_module_descriptor mDescriptor; sp<ISoundTriggerClient> mClient; Vector< sp<ModuleClient> > mModuleClients; DefaultKeyedVector< sound_model_handle_t, sp<Model> > mModels; sound_trigger_service_state_t mServiceState; }; // class Module class ModuleClient : public virtual RefBase, public BnSoundTrigger, public IBinder::DeathRecipient { public: ModuleClient(const sp<Module>& module, const sp<ISoundTriggerClient>& client); virtual ~ModuleClient(); virtual void detach(); virtual status_t loadSoundModel(const sp<IMemory>& modelMemory, sound_model_handle_t *handle); virtual status_t unloadSoundModel(sound_model_handle_t handle); virtual status_t startRecognition(sound_model_handle_t handle, const sp<IMemory>& dataMemory); virtual status_t stopRecognition(sound_model_handle_t handle); virtual status_t dump(int fd, const Vector<String16>& args); virtual void onFirstRef(); // IBinder::DeathRecipient implementation virtual void binderDied(const wp<IBinder> &who); void onCallbackEvent(const sp<CallbackEvent>& event); void setCaptureState_l(bool active); sp<ISoundTriggerClient> client() const { return mClient; } private: mutable Mutex mLock; wp<Module> mModule; sp<ISoundTriggerClient> mClient; }; // class ModuleClient class CallbackThread : public Thread { public: Loading @@ -175,8 +215,6 @@ public: Vector< sp<CallbackEvent> > mEventQueue; }; void detachModule(const sp<Module>& module); static void recognitionCallback(struct sound_trigger_recognition_event *event, void *cookie); sp<IMemory> prepareRecognitionEvent_l(struct sound_trigger_recognition_event *event); void sendRecognitionEvent(struct sound_trigger_recognition_event *event, Module *module); Loading @@ -187,6 +225,8 @@ public: sp<IMemory> prepareServiceStateEvent_l(sound_trigger_service_state_t state); void sendServiceStateEvent_l(sound_trigger_service_state_t state, Module *module); void sendServiceStateEvent_l(sound_trigger_service_state_t state, ModuleClient *moduleClient); void sendCallbackEvent_l(const sp<CallbackEvent>& event); void onCallbackEvent(const sp<CallbackEvent>& event); Loading