Home | History | Annotate | Download | only in soundtrigger
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "SoundTriggerHwService"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include <stdio.h>
     21 #include <string.h>
     22 #include <sys/types.h>
     23 #include <pthread.h>
     24 
     25 #include <system/sound_trigger.h>
     26 #include <cutils/atomic.h>
     27 #include <cutils/properties.h>
     28 #include <hardware/hardware.h>
     29 #include <media/AudioSystem.h>
     30 #include <utils/Errors.h>
     31 #include <utils/Log.h>
     32 #include <binder/IServiceManager.h>
     33 #include <binder/MemoryBase.h>
     34 #include <binder/MemoryHeapBase.h>
     35 #include <hardware/sound_trigger.h>
     36 #include <ServiceUtilities.h>
     37 #include "SoundTriggerHwService.h"
     38 
     39 namespace android {
     40 
     41 #ifdef SOUND_TRIGGER_USE_STUB_MODULE
     42 #define HW_MODULE_PREFIX "stub"
     43 #else
     44 #define HW_MODULE_PREFIX "primary"
     45 #endif
     46 
     47 SoundTriggerHwService::SoundTriggerHwService()
     48     : BnSoundTriggerHwService(),
     49       mNextUniqueId(1),
     50       mMemoryDealer(new MemoryDealer(1024 * 1024, "SoundTriggerHwService")),
     51       mCaptureState(false)
     52 {
     53 }
     54 
     55 void SoundTriggerHwService::onFirstRef()
     56 {
     57     const hw_module_t *mod;
     58     int rc;
     59     sound_trigger_hw_device *dev;
     60 
     61     rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, HW_MODULE_PREFIX, &mod);
     62     if (rc != 0) {
     63         ALOGE("couldn't load sound trigger module %s.%s (%s)",
     64               SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", strerror(-rc));
     65         return;
     66     }
     67     rc = sound_trigger_hw_device_open(mod, &dev);
     68     if (rc != 0) {
     69         ALOGE("couldn't open sound trigger hw device in %s.%s (%s)",
     70               SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", strerror(-rc));
     71         return;
     72     }
     73     if (dev->common.version != SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
     74         ALOGE("wrong sound trigger hw device version %04x", dev->common.version);
     75         return;
     76     }
     77 
     78     sound_trigger_module_descriptor descriptor;
     79     rc = dev->get_properties(dev, &descriptor.properties);
     80     if (rc != 0) {
     81         ALOGE("could not read implementation properties");
     82         return;
     83     }
     84     descriptor.handle =
     85             (sound_trigger_module_handle_t)android_atomic_inc(&mNextUniqueId);
     86     ALOGI("loaded default module %s, handle %d", descriptor.properties.description,
     87                                                  descriptor.handle);
     88 
     89     sp<ISoundTriggerClient> client;
     90     sp<Module> module = new Module(this, dev, descriptor, client);
     91     mModules.add(descriptor.handle, module);
     92     mCallbackThread = new CallbackThread(this);
     93 }
     94 
     95 SoundTriggerHwService::~SoundTriggerHwService()
     96 {
     97     if (mCallbackThread != 0) {
     98         mCallbackThread->exit();
     99     }
    100     for (size_t i = 0; i < mModules.size(); i++) {
    101         sound_trigger_hw_device_close(mModules.valueAt(i)->hwDevice());
    102     }
    103 }
    104 
    105 status_t SoundTriggerHwService::listModules(struct sound_trigger_module_descriptor *modules,
    106                              uint32_t *numModules)
    107 {
    108     ALOGV("listModules");
    109     if (!captureHotwordAllowed()) {
    110         return PERMISSION_DENIED;
    111     }
    112 
    113     AutoMutex lock(mServiceLock);
    114     if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
    115         return BAD_VALUE;
    116     }
    117     size_t maxModules = *numModules;
    118     *numModules = mModules.size();
    119     for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
    120         modules[i] = mModules.valueAt(i)->descriptor();
    121     }
    122     return NO_ERROR;
    123 }
    124 
    125 status_t SoundTriggerHwService::attach(const sound_trigger_module_handle_t handle,
    126                         const sp<ISoundTriggerClient>& client,
    127                         sp<ISoundTrigger>& moduleInterface)
    128 {
    129     ALOGV("attach module %d", handle);
    130     if (!captureHotwordAllowed()) {
    131         return PERMISSION_DENIED;
    132     }
    133 
    134     AutoMutex lock(mServiceLock);
    135     moduleInterface.clear();
    136     if (client == 0) {
    137         return BAD_VALUE;
    138     }
    139     ssize_t index = mModules.indexOfKey(handle);
    140     if (index < 0) {
    141         return BAD_VALUE;
    142     }
    143     sp<Module> module = mModules.valueAt(index);
    144 
    145     module->setClient(client);
    146     client->asBinder()->linkToDeath(module);
    147     moduleInterface = module;
    148 
    149     module->setCaptureState_l(mCaptureState);
    150 
    151     return NO_ERROR;
    152 }
    153 
    154 status_t SoundTriggerHwService::setCaptureState(bool active)
    155 {
    156     ALOGV("setCaptureState %d", active);
    157     AutoMutex lock(mServiceLock);
    158     mCaptureState = active;
    159     for (size_t i = 0; i < mModules.size(); i++) {
    160         mModules.valueAt(i)->setCaptureState_l(active);
    161     }
    162     return NO_ERROR;
    163 }
    164 
    165 
    166 void SoundTriggerHwService::detachModule(sp<Module> module)
    167 {
    168     ALOGV("detachModule");
    169     AutoMutex lock(mServiceLock);
    170     module->clearClient();
    171 }
    172 
    173 
    174 static const int kDumpLockRetries = 50;
    175 static const int kDumpLockSleep = 60000;
    176 
    177 static bool tryLock(Mutex& mutex)
    178 {
    179     bool locked = false;
    180     for (int i = 0; i < kDumpLockRetries; ++i) {
    181         if (mutex.tryLock() == NO_ERROR) {
    182             locked = true;
    183             break;
    184         }
    185         usleep(kDumpLockSleep);
    186     }
    187     return locked;
    188 }
    189 
    190 status_t SoundTriggerHwService::dump(int fd, const Vector<String16>& args __unused) {
    191     String8 result;
    192     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
    193         result.appendFormat("Permission Denial: can't dump SoundTriggerHwService");
    194         write(fd, result.string(), result.size());
    195     } else {
    196         bool locked = tryLock(mServiceLock);
    197         // failed to lock - SoundTriggerHwService is probably deadlocked
    198         if (!locked) {
    199             result.append("SoundTriggerHwService may be deadlocked\n");
    200             write(fd, result.string(), result.size());
    201         }
    202 
    203         if (locked) mServiceLock.unlock();
    204     }
    205     return NO_ERROR;
    206 }
    207 
    208 status_t SoundTriggerHwService::onTransact(
    209     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
    210     return BnSoundTriggerHwService::onTransact(code, data, reply, flags);
    211 }
    212 
    213 
    214 // static
    215 void SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition_event *event,
    216                                                 void *cookie)
    217 {
    218     Module *module = (Module *)cookie;
    219     if (module == NULL) {
    220         return;
    221     }
    222     sp<SoundTriggerHwService> service = module->service().promote();
    223     if (service == 0) {
    224         return;
    225     }
    226 
    227     service->sendRecognitionEvent(event, module);
    228 }
    229 
    230 sp<IMemory> SoundTriggerHwService::prepareRecognitionEvent_l(
    231                                                     struct sound_trigger_recognition_event *event)
    232 {
    233     sp<IMemory> eventMemory;
    234 
    235     //sanitize event
    236     switch (event->type) {
    237     case SOUND_MODEL_TYPE_KEYPHRASE:
    238         ALOGW_IF(event->data_size != 0 && event->data_offset !=
    239                     sizeof(struct sound_trigger_phrase_recognition_event),
    240                     "prepareRecognitionEvent_l(): invalid data offset %u for keyphrase event type",
    241                     event->data_offset);
    242         event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
    243         break;
    244     case SOUND_MODEL_TYPE_UNKNOWN:
    245         ALOGW_IF(event->data_size != 0 && event->data_offset !=
    246                     sizeof(struct sound_trigger_recognition_event),
    247                     "prepareRecognitionEvent_l(): invalid data offset %u for unknown event type",
    248                     event->data_offset);
    249         event->data_offset = sizeof(struct sound_trigger_recognition_event);
    250         break;
    251     default:
    252         return eventMemory;
    253     }
    254 
    255     size_t size = event->data_offset + event->data_size;
    256     eventMemory = mMemoryDealer->allocate(size);
    257     if (eventMemory == 0 || eventMemory->pointer() == NULL) {
    258         eventMemory.clear();
    259         return eventMemory;
    260     }
    261     memcpy(eventMemory->pointer(), event, size);
    262 
    263     return eventMemory;
    264 }
    265 
    266 void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event,
    267                                                  Module *module)
    268  {
    269      AutoMutex lock(mServiceLock);
    270      if (module == NULL) {
    271          return;
    272      }
    273      sp<IMemory> eventMemory = prepareRecognitionEvent_l(event);
    274      if (eventMemory == 0) {
    275          return;
    276      }
    277      sp<Module> strongModule;
    278      for (size_t i = 0; i < mModules.size(); i++) {
    279          if (mModules.valueAt(i).get() == module) {
    280              strongModule = mModules.valueAt(i);
    281              break;
    282          }
    283      }
    284      if (strongModule == 0) {
    285          return;
    286      }
    287 
    288      sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
    289                                                   eventMemory, strongModule));
    290 }
    291 
    292 // static
    293 void SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event,
    294                                                void *cookie)
    295 {
    296     Module *module = (Module *)cookie;
    297     if (module == NULL) {
    298         return;
    299     }
    300     sp<SoundTriggerHwService> service = module->service().promote();
    301     if (service == 0) {
    302         return;
    303     }
    304 
    305     service->sendSoundModelEvent(event, module);
    306 }
    307 
    308 sp<IMemory> SoundTriggerHwService::prepareSoundModelEvent_l(struct sound_trigger_model_event *event)
    309 {
    310     sp<IMemory> eventMemory;
    311 
    312     size_t size = event->data_offset + event->data_size;
    313     eventMemory = mMemoryDealer->allocate(size);
    314     if (eventMemory == 0 || eventMemory->pointer() == NULL) {
    315         eventMemory.clear();
    316         return eventMemory;
    317     }
    318     memcpy(eventMemory->pointer(), event, size);
    319 
    320     return eventMemory;
    321 }
    322 
    323 void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event,
    324                                                 Module *module)
    325 {
    326     AutoMutex lock(mServiceLock);
    327     sp<IMemory> eventMemory = prepareSoundModelEvent_l(event);
    328     if (eventMemory == 0) {
    329         return;
    330     }
    331     sp<Module> strongModule;
    332     for (size_t i = 0; i < mModules.size(); i++) {
    333         if (mModules.valueAt(i).get() == module) {
    334             strongModule = mModules.valueAt(i);
    335             break;
    336         }
    337     }
    338     if (strongModule == 0) {
    339         return;
    340     }
    341     sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL,
    342                                                  eventMemory, strongModule));
    343 }
    344 
    345 
    346 sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
    347 {
    348     sp<IMemory> eventMemory;
    349 
    350     size_t size = sizeof(sound_trigger_service_state_t);
    351     eventMemory = mMemoryDealer->allocate(size);
    352     if (eventMemory == 0 || eventMemory->pointer() == NULL) {
    353         eventMemory.clear();
    354         return eventMemory;
    355     }
    356     *((sound_trigger_service_state_t *)eventMemory->pointer()) = state;
    357     return eventMemory;
    358 }
    359 
    360 // call with mServiceLock held
    361 void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
    362                                                   Module *module)
    363 {
    364     sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
    365     if (eventMemory == 0) {
    366         return;
    367     }
    368     sp<Module> strongModule;
    369     for (size_t i = 0; i < mModules.size(); i++) {
    370         if (mModules.valueAt(i).get() == module) {
    371             strongModule = mModules.valueAt(i);
    372             break;
    373         }
    374     }
    375     if (strongModule == 0) {
    376         return;
    377     }
    378     sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
    379                                                  eventMemory, strongModule));
    380 }
    381 
    382 // call with mServiceLock held
    383 void SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event)
    384 {
    385     mCallbackThread->sendCallbackEvent(event);
    386 }
    387 
    388 void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event)
    389 {
    390     ALOGV("onCallbackEvent");
    391     sp<Module> module;
    392     {
    393         AutoMutex lock(mServiceLock);
    394         module = event->mModule.promote();
    395         if (module == 0) {
    396             return;
    397         }
    398     }
    399     module->onCallbackEvent(event);
    400     {
    401         AutoMutex lock(mServiceLock);
    402         // clear now to execute with mServiceLock locked
    403         event->mMemory.clear();
    404     }
    405 }
    406 
    407 #undef LOG_TAG
    408 #define LOG_TAG "SoundTriggerHwService::CallbackThread"
    409 
    410 SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
    411     : mService(service)
    412 {
    413 }
    414 
    415 SoundTriggerHwService::CallbackThread::~CallbackThread()
    416 {
    417     while (!mEventQueue.isEmpty()) {
    418         mEventQueue[0]->mMemory.clear();
    419         mEventQueue.removeAt(0);
    420     }
    421 }
    422 
    423 void SoundTriggerHwService::CallbackThread::onFirstRef()
    424 {
    425     run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
    426 }
    427 
    428 bool SoundTriggerHwService::CallbackThread::threadLoop()
    429 {
    430     while (!exitPending()) {
    431         sp<CallbackEvent> event;
    432         sp<SoundTriggerHwService> service;
    433         {
    434             Mutex::Autolock _l(mCallbackLock);
    435             while (mEventQueue.isEmpty() && !exitPending()) {
    436                 ALOGV("CallbackThread::threadLoop() sleep");
    437                 mCallbackCond.wait(mCallbackLock);
    438                 ALOGV("CallbackThread::threadLoop() wake up");
    439             }
    440             if (exitPending()) {
    441                 break;
    442             }
    443             event = mEventQueue[0];
    444             mEventQueue.removeAt(0);
    445             service = mService.promote();
    446         }
    447         if (service != 0) {
    448             service->onCallbackEvent(event);
    449         }
    450     }
    451     return false;
    452 }
    453 
    454 void SoundTriggerHwService::CallbackThread::exit()
    455 {
    456     Mutex::Autolock _l(mCallbackLock);
    457     requestExit();
    458     mCallbackCond.broadcast();
    459 }
    460 
    461 void SoundTriggerHwService::CallbackThread::sendCallbackEvent(
    462                         const sp<SoundTriggerHwService::CallbackEvent>& event)
    463 {
    464     AutoMutex lock(mCallbackLock);
    465     mEventQueue.add(event);
    466     mCallbackCond.signal();
    467 }
    468 
    469 SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory,
    470                                                     wp<Module> module)
    471     : mType(type), mMemory(memory), mModule(module)
    472 {
    473 }
    474 
    475 SoundTriggerHwService::CallbackEvent::~CallbackEvent()
    476 {
    477 }
    478 
    479 
    480 #undef LOG_TAG
    481 #define LOG_TAG "SoundTriggerHwService::Module"
    482 
    483 SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
    484                                       sound_trigger_hw_device* hwDevice,
    485                                       sound_trigger_module_descriptor descriptor,
    486                                       const sp<ISoundTriggerClient>& client)
    487  : mService(service), mHwDevice(hwDevice), mDescriptor(descriptor),
    488    mClient(client), mServiceState(SOUND_TRIGGER_STATE_NO_INIT)
    489 {
    490 }
    491 
    492 SoundTriggerHwService::Module::~Module() {
    493 }
    494 
    495 void SoundTriggerHwService::Module::detach() {
    496     ALOGV("detach()");
    497     if (!captureHotwordAllowed()) {
    498         return;
    499     }
    500     {
    501         AutoMutex lock(mLock);
    502         for (size_t i = 0; i < mModels.size(); i++) {
    503             sp<Model> model = mModels.valueAt(i);
    504             ALOGV("detach() unloading model %d", model->mHandle);
    505             if (model->mState == Model::STATE_ACTIVE) {
    506                 mHwDevice->stop_recognition(mHwDevice, model->mHandle);
    507             }
    508             mHwDevice->unload_sound_model(mHwDevice, model->mHandle);
    509         }
    510         mModels.clear();
    511     }
    512     if (mClient != 0) {
    513         mClient->asBinder()->unlinkToDeath(this);
    514     }
    515     sp<SoundTriggerHwService> service = mService.promote();
    516     if (service == 0) {
    517         return;
    518     }
    519     service->detachModule(this);
    520 }
    521 
    522 status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
    523                                 sound_model_handle_t *handle)
    524 {
    525     ALOGV("loadSoundModel() handle");
    526     if (!captureHotwordAllowed()) {
    527         return PERMISSION_DENIED;
    528     }
    529 
    530     if (modelMemory == 0 || modelMemory->pointer() == NULL) {
    531         ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()");
    532         return BAD_VALUE;
    533     }
    534     struct sound_trigger_sound_model *sound_model =
    535             (struct sound_trigger_sound_model *)modelMemory->pointer();
    536 
    537     AutoMutex lock(mLock);
    538     status_t status = mHwDevice->load_sound_model(mHwDevice,
    539                                                   sound_model,
    540                                                   SoundTriggerHwService::soundModelCallback,
    541                                                   this,
    542                                                   handle);
    543     if (status != NO_ERROR) {
    544         return status;
    545     }
    546     audio_session_t session;
    547     audio_io_handle_t ioHandle;
    548     audio_devices_t device;
    549 
    550     status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
    551     if (status != NO_ERROR) {
    552         return status;
    553     }
    554 
    555     sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type);
    556     mModels.replaceValueFor(*handle, model);
    557 
    558     return status;
    559 }
    560 
    561 status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
    562 {
    563     ALOGV("unloadSoundModel() model handle %d", handle);
    564     if (!captureHotwordAllowed()) {
    565         return PERMISSION_DENIED;
    566     }
    567 
    568     AutoMutex lock(mLock);
    569     ssize_t index = mModels.indexOfKey(handle);
    570     if (index < 0) {
    571         return BAD_VALUE;
    572     }
    573     sp<Model> model = mModels.valueAt(index);
    574     mModels.removeItem(handle);
    575     if (model->mState == Model::STATE_ACTIVE) {
    576         mHwDevice->stop_recognition(mHwDevice, model->mHandle);
    577     }
    578     AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
    579     return mHwDevice->unload_sound_model(mHwDevice, handle);
    580 }
    581 
    582 status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
    583                                  const sp<IMemory>& dataMemory)
    584 {
    585     ALOGV("startRecognition() model handle %d", handle);
    586     if (!captureHotwordAllowed()) {
    587         return PERMISSION_DENIED;
    588     }
    589 
    590     if (dataMemory != 0 && dataMemory->pointer() == NULL) {
    591         ALOGE("startRecognition() dataMemory is non-0 but has NULL pointer()");
    592         return BAD_VALUE;
    593 
    594     }
    595     AutoMutex lock(mLock);
    596     if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
    597         return INVALID_OPERATION;
    598     }
    599     sp<Model> model = getModel(handle);
    600     if (model == 0) {
    601         return BAD_VALUE;
    602     }
    603     if ((dataMemory == 0) ||
    604             (dataMemory->size() < sizeof(struct sound_trigger_recognition_config))) {
    605         return BAD_VALUE;
    606     }
    607 
    608     if (model->mState == Model::STATE_ACTIVE) {
    609         return INVALID_OPERATION;
    610     }
    611 
    612     struct sound_trigger_recognition_config *config =
    613             (struct sound_trigger_recognition_config *)dataMemory->pointer();
    614 
    615     //TODO: get capture handle and device from audio policy service
    616     config->capture_handle = model->mCaptureIOHandle;
    617     config->capture_device = model->mCaptureDevice;
    618     status_t status = mHwDevice->start_recognition(mHwDevice, handle, config,
    619                                         SoundTriggerHwService::recognitionCallback,
    620                                         this);
    621 
    622     if (status == NO_ERROR) {
    623         model->mState = Model::STATE_ACTIVE;
    624         model->mConfig = *config;
    625     }
    626 
    627     return status;
    628 }
    629 
    630 status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
    631 {
    632     ALOGV("stopRecognition() model handle %d", handle);
    633     if (!captureHotwordAllowed()) {
    634         return PERMISSION_DENIED;
    635     }
    636 
    637     AutoMutex lock(mLock);
    638     sp<Model> model = getModel(handle);
    639     if (model == 0) {
    640         return BAD_VALUE;
    641     }
    642 
    643     if (model->mState != Model::STATE_ACTIVE) {
    644         return INVALID_OPERATION;
    645     }
    646     mHwDevice->stop_recognition(mHwDevice, handle);
    647     model->mState = Model::STATE_IDLE;
    648     return NO_ERROR;
    649 }
    650 
    651 
    652 void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
    653 {
    654     ALOGV("onCallbackEvent type %d", event->mType);
    655 
    656     sp<IMemory> eventMemory = event->mMemory;
    657 
    658     if (eventMemory == 0 || eventMemory->pointer() == NULL) {
    659         return;
    660     }
    661     if (mClient == 0) {
    662         ALOGI("%s mClient == 0", __func__);
    663         return;
    664     }
    665 
    666     switch (event->mType) {
    667     case CallbackEvent::TYPE_RECOGNITION: {
    668         struct sound_trigger_recognition_event *recognitionEvent =
    669                 (struct sound_trigger_recognition_event *)eventMemory->pointer();
    670         sp<ISoundTriggerClient> client;
    671         {
    672             AutoMutex lock(mLock);
    673             sp<Model> model = getModel(recognitionEvent->model);
    674             if (model == 0) {
    675                 ALOGW("%s model == 0", __func__);
    676                 return;
    677             }
    678             if (model->mState != Model::STATE_ACTIVE) {
    679                 ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
    680                 return;
    681             }
    682 
    683             recognitionEvent->capture_session = model->mCaptureSession;
    684             model->mState = Model::STATE_IDLE;
    685             client = mClient;
    686         }
    687         if (client != 0) {
    688             client->onRecognitionEvent(eventMemory);
    689         }
    690     } break;
    691     case CallbackEvent::TYPE_SOUNDMODEL: {
    692         struct sound_trigger_model_event *soundmodelEvent =
    693                 (struct sound_trigger_model_event *)eventMemory->pointer();
    694         sp<ISoundTriggerClient> client;
    695         {
    696             AutoMutex lock(mLock);
    697             sp<Model> model = getModel(soundmodelEvent->model);
    698             if (model == 0) {
    699                 ALOGW("%s model == 0", __func__);
    700                 return;
    701             }
    702             client = mClient;
    703         }
    704         if (client != 0) {
    705             client->onSoundModelEvent(eventMemory);
    706         }
    707     } break;
    708     case CallbackEvent::TYPE_SERVICE_STATE: {
    709         sp<ISoundTriggerClient> client;
    710         {
    711             AutoMutex lock(mLock);
    712             client = mClient;
    713         }
    714         if (client != 0) {
    715             client->onServiceStateChange(eventMemory);
    716         }
    717     } break;
    718     default:
    719         LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
    720     }
    721 }
    722 
    723 sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
    724         sound_model_handle_t handle)
    725 {
    726     sp<Model> model;
    727     ssize_t index = mModels.indexOfKey(handle);
    728     if (index >= 0) {
    729         model = mModels.valueAt(index);
    730     }
    731     return model;
    732 }
    733 
    734 void SoundTriggerHwService::Module::binderDied(
    735     const wp<IBinder> &who __unused) {
    736     ALOGW("client binder died for module %d", mDescriptor.handle);
    737     detach();
    738 }
    739 
    740 // Called with mServiceLock held
    741 void SoundTriggerHwService::Module::setCaptureState_l(bool active)
    742 {
    743     ALOGV("Module::setCaptureState_l %d", active);
    744     sp<SoundTriggerHwService> service;
    745     sound_trigger_service_state_t state;
    746 
    747     Vector< sp<IMemory> > events;
    748     {
    749         AutoMutex lock(mLock);
    750         state = (active && !mDescriptor.properties.concurrent_capture) ?
    751                                         SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
    752 
    753         if (state == mServiceState) {
    754             return;
    755         }
    756 
    757         mServiceState = state;
    758 
    759         service = mService.promote();
    760         if (service == 0) {
    761             return;
    762         }
    763 
    764         if (state == SOUND_TRIGGER_STATE_ENABLED) {
    765             goto exit;
    766         }
    767 
    768         for (size_t i = 0; i < mModels.size(); i++) {
    769             sp<Model> model = mModels.valueAt(i);
    770             if (model->mState == Model::STATE_ACTIVE) {
    771                 mHwDevice->stop_recognition(mHwDevice, model->mHandle);
    772                 // keep model in ACTIVE state so that event is processed by onCallbackEvent()
    773                 struct sound_trigger_phrase_recognition_event phraseEvent;
    774                 switch (model->mType) {
    775                 case SOUND_MODEL_TYPE_KEYPHRASE:
    776                     phraseEvent.num_phrases = model->mConfig.num_phrases;
    777                     for (size_t i = 0; i < phraseEvent.num_phrases; i++) {
    778                         phraseEvent.phrase_extras[i] = model->mConfig.phrases[i];
    779                     }
    780                     break;
    781                 case SOUND_MODEL_TYPE_UNKNOWN:
    782                 default:
    783                     break;
    784                 }
    785                 phraseEvent.common.status = RECOGNITION_STATUS_ABORT;
    786                 phraseEvent.common.type = model->mType;
    787                 phraseEvent.common.model = model->mHandle;
    788                 phraseEvent.common.data_size = 0;
    789                 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&phraseEvent.common);
    790                 if (eventMemory != 0) {
    791                     events.add(eventMemory);
    792                 }
    793             }
    794         }
    795     }
    796 
    797     for (size_t i = 0; i < events.size(); i++) {
    798         service->sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i],
    799                                                      this));
    800     }
    801 
    802 exit:
    803     service->sendServiceStateEvent_l(state, this);
    804 }
    805 
    806 
    807 SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
    808                                     audio_io_handle_t ioHandle, audio_devices_t device,
    809                                     sound_trigger_sound_model_type_t type) :
    810     mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
    811     mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type)
    812 {
    813 
    814 }
    815 
    816 status_t SoundTriggerHwService::Module::dump(int fd __unused,
    817                                              const Vector<String16>& args __unused) {
    818     String8 result;
    819     return NO_ERROR;
    820 }
    821 
    822 }; // namespace android
    823