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