SoundTriggerHwService.cpp revision 2c561209f00320f7ca2b75998bbe72ecec527210
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
39namespace 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
47SoundTriggerHwService::SoundTriggerHwService()
48    : BnSoundTriggerHwService(),
49      mNextUniqueId(1),
50      mMemoryDealer(new MemoryDealer(1024 * 1024, "SoundTriggerHwService")),
51      mCaptureState(false)
52{
53}
54
55void 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_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
95SoundTriggerHwService::~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
105status_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
125status_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    IInterface::asBinder(client)->linkToDeath(module);
147    moduleInterface = module;
148
149    module->setCaptureState_l(mCaptureState);
150
151    return NO_ERROR;
152}
153
154status_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
166void SoundTriggerHwService::detachModule(sp<Module> module)
167{
168    ALOGV("detachModule");
169    AutoMutex lock(mServiceLock);
170    module->clearClient();
171}
172
173
174static const int kDumpLockRetries = 50;
175static const int kDumpLockSleep = 60000;
176
177static 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
190status_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
208status_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
215void 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
230sp<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_GENERIC:
245        ALOGW_IF(event->data_size != 0 && event->data_offset !=
246                    sizeof(struct sound_trigger_generic_recognition_event),
247                    "prepareRecognitionEvent_l(): invalid data offset %u for generic event type",
248                    event->data_offset);
249        event->data_offset = sizeof(struct sound_trigger_generic_recognition_event);
250        break;
251    case SOUND_MODEL_TYPE_UNKNOWN:
252        ALOGW_IF(event->data_size != 0 && event->data_offset !=
253                    sizeof(struct sound_trigger_recognition_event),
254                    "prepareRecognitionEvent_l(): invalid data offset %u for unknown event type",
255                    event->data_offset);
256        event->data_offset = sizeof(struct sound_trigger_recognition_event);
257        break;
258    default:
259        return eventMemory;
260    }
261
262    size_t size = event->data_offset + event->data_size;
263    eventMemory = mMemoryDealer->allocate(size);
264    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
265        eventMemory.clear();
266        return eventMemory;
267    }
268    memcpy(eventMemory->pointer(), event, size);
269
270    return eventMemory;
271}
272
273void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event,
274                                                 Module *module)
275 {
276     AutoMutex lock(mServiceLock);
277     if (module == NULL) {
278         return;
279     }
280     sp<IMemory> eventMemory = prepareRecognitionEvent_l(event);
281     if (eventMemory == 0) {
282         return;
283     }
284     sp<Module> strongModule;
285     for (size_t i = 0; i < mModules.size(); i++) {
286         if (mModules.valueAt(i).get() == module) {
287             strongModule = mModules.valueAt(i);
288             break;
289         }
290     }
291     if (strongModule == 0) {
292         return;
293     }
294
295     sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
296                                                  eventMemory, strongModule));
297}
298
299// static
300void SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event,
301                                               void *cookie)
302{
303    Module *module = (Module *)cookie;
304    if (module == NULL) {
305        return;
306    }
307    sp<SoundTriggerHwService> service = module->service().promote();
308    if (service == 0) {
309        return;
310    }
311
312    service->sendSoundModelEvent(event, module);
313}
314
315sp<IMemory> SoundTriggerHwService::prepareSoundModelEvent_l(struct sound_trigger_model_event *event)
316{
317    sp<IMemory> eventMemory;
318
319    size_t size = event->data_offset + event->data_size;
320    eventMemory = mMemoryDealer->allocate(size);
321    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
322        eventMemory.clear();
323        return eventMemory;
324    }
325    memcpy(eventMemory->pointer(), event, size);
326
327    return eventMemory;
328}
329
330void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event,
331                                                Module *module)
332{
333    AutoMutex lock(mServiceLock);
334    sp<IMemory> eventMemory = prepareSoundModelEvent_l(event);
335    if (eventMemory == 0) {
336        return;
337    }
338    sp<Module> strongModule;
339    for (size_t i = 0; i < mModules.size(); i++) {
340        if (mModules.valueAt(i).get() == module) {
341            strongModule = mModules.valueAt(i);
342            break;
343        }
344    }
345    if (strongModule == 0) {
346        return;
347    }
348    sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL,
349                                                 eventMemory, strongModule));
350}
351
352
353sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
354{
355    sp<IMemory> eventMemory;
356
357    size_t size = sizeof(sound_trigger_service_state_t);
358    eventMemory = mMemoryDealer->allocate(size);
359    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
360        eventMemory.clear();
361        return eventMemory;
362    }
363    *((sound_trigger_service_state_t *)eventMemory->pointer()) = state;
364    return eventMemory;
365}
366
367// call with mServiceLock held
368void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
369                                                  Module *module)
370{
371    sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
372    if (eventMemory == 0) {
373        return;
374    }
375    sp<Module> strongModule;
376    for (size_t i = 0; i < mModules.size(); i++) {
377        if (mModules.valueAt(i).get() == module) {
378            strongModule = mModules.valueAt(i);
379            break;
380        }
381    }
382    if (strongModule == 0) {
383        return;
384    }
385    sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
386                                                 eventMemory, strongModule));
387}
388
389// call with mServiceLock held
390void SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event)
391{
392    mCallbackThread->sendCallbackEvent(event);
393}
394
395void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event)
396{
397    ALOGV("onCallbackEvent");
398    sp<Module> module;
399    {
400        AutoMutex lock(mServiceLock);
401        module = event->mModule.promote();
402        if (module == 0) {
403            return;
404        }
405    }
406    module->onCallbackEvent(event);
407    {
408        AutoMutex lock(mServiceLock);
409        // clear now to execute with mServiceLock locked
410        event->mMemory.clear();
411    }
412}
413
414#undef LOG_TAG
415#define LOG_TAG "SoundTriggerHwService::CallbackThread"
416
417SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
418    : mService(service)
419{
420}
421
422SoundTriggerHwService::CallbackThread::~CallbackThread()
423{
424    while (!mEventQueue.isEmpty()) {
425        mEventQueue[0]->mMemory.clear();
426        mEventQueue.removeAt(0);
427    }
428}
429
430void SoundTriggerHwService::CallbackThread::onFirstRef()
431{
432    run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
433}
434
435bool SoundTriggerHwService::CallbackThread::threadLoop()
436{
437    while (!exitPending()) {
438        sp<CallbackEvent> event;
439        sp<SoundTriggerHwService> service;
440        {
441            Mutex::Autolock _l(mCallbackLock);
442            while (mEventQueue.isEmpty() && !exitPending()) {
443                ALOGV("CallbackThread::threadLoop() sleep");
444                mCallbackCond.wait(mCallbackLock);
445                ALOGV("CallbackThread::threadLoop() wake up");
446            }
447            if (exitPending()) {
448                break;
449            }
450            event = mEventQueue[0];
451            mEventQueue.removeAt(0);
452            service = mService.promote();
453        }
454        if (service != 0) {
455            service->onCallbackEvent(event);
456        }
457    }
458    return false;
459}
460
461void SoundTriggerHwService::CallbackThread::exit()
462{
463    Mutex::Autolock _l(mCallbackLock);
464    requestExit();
465    mCallbackCond.broadcast();
466}
467
468void SoundTriggerHwService::CallbackThread::sendCallbackEvent(
469                        const sp<SoundTriggerHwService::CallbackEvent>& event)
470{
471    AutoMutex lock(mCallbackLock);
472    mEventQueue.add(event);
473    mCallbackCond.signal();
474}
475
476SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory,
477                                                    wp<Module> module)
478    : mType(type), mMemory(memory), mModule(module)
479{
480}
481
482SoundTriggerHwService::CallbackEvent::~CallbackEvent()
483{
484}
485
486
487#undef LOG_TAG
488#define LOG_TAG "SoundTriggerHwService::Module"
489
490SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
491                                      sound_trigger_hw_device* hwDevice,
492                                      sound_trigger_module_descriptor descriptor,
493                                      const sp<ISoundTriggerClient>& client)
494 : mService(service), mHwDevice(hwDevice), mDescriptor(descriptor),
495   mClient(client), mServiceState(SOUND_TRIGGER_STATE_NO_INIT)
496{
497}
498
499SoundTriggerHwService::Module::~Module() {
500}
501
502void SoundTriggerHwService::Module::detach() {
503    ALOGV("detach()");
504    if (!captureHotwordAllowed()) {
505        return;
506    }
507    {
508        AutoMutex lock(mLock);
509        for (size_t i = 0; i < mModels.size(); i++) {
510            sp<Model> model = mModels.valueAt(i);
511            ALOGV("detach() unloading model %d", model->mHandle);
512            if (model->mState == Model::STATE_ACTIVE) {
513                mHwDevice->stop_recognition(mHwDevice, model->mHandle);
514            }
515            mHwDevice->unload_sound_model(mHwDevice, model->mHandle);
516        }
517        mModels.clear();
518    }
519    if (mClient != 0) {
520        IInterface::asBinder(mClient)->unlinkToDeath(this);
521    }
522    sp<SoundTriggerHwService> service = mService.promote();
523    if (service == 0) {
524        return;
525    }
526    service->detachModule(this);
527}
528
529status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
530                                sound_model_handle_t *handle)
531{
532    ALOGV("loadSoundModel() handle");
533    if (!captureHotwordAllowed()) {
534        return PERMISSION_DENIED;
535    }
536
537    if (modelMemory == 0 || modelMemory->pointer() == NULL) {
538        ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()");
539        return BAD_VALUE;
540    }
541    struct sound_trigger_sound_model *sound_model =
542            (struct sound_trigger_sound_model *)modelMemory->pointer();
543
544    AutoMutex lock(mLock);
545
546    if (mModels.size() >= mDescriptor.properties.max_sound_models) {
547        /* Make space for a keyphrase sound model by first trying to swap out a previously loaded
548         * keyphrase sound model, or if needed, another sound model. This decision would optimally
549         * happen in SoundTriggerHelper, but is happening here because state tracking isn't good
550         * enough in SoundTriggerHelper to ensure that state is consistent between it and the HAL,
551         * nor does sufficient error handling exist to recover from inconsistencies.
552         * Once that exists:
553         * TODO: we should return an error instead of unloading a previous sound model here.
554         */
555        if (mModels.size() == 0) {
556            return INVALID_OPERATION;
557        }
558        if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
559            ALOGW("loadSoundModel() max number of models exceeded %d making room for a new one",
560                  mDescriptor.properties.max_sound_models);
561            sound_model_handle_t unload_handle = mModels.valueAt(0)->mHandle;
562            for (size_t i = 0; i < mModels.size(); i++) {
563                if (mModels.valueAt(i)->mType == SOUND_MODEL_TYPE_KEYPHRASE) {
564                    unload_handle = mModels.keyAt(i);
565                    break;
566                }
567            }
568            unloadSoundModel_l(unload_handle);
569        } else {
570            ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded",
571                  mDescriptor.properties.max_sound_models);
572            return INVALID_OPERATION;
573        }
574    }
575
576    status_t status = mHwDevice->load_sound_model(mHwDevice, sound_model,
577                                                  SoundTriggerHwService::soundModelCallback,
578                                                  this, handle);
579
580    if (status != NO_ERROR) {
581        return status;
582    }
583    audio_session_t session;
584    audio_io_handle_t ioHandle;
585    audio_devices_t device;
586
587    status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
588    if (status != NO_ERROR) {
589        return status;
590    }
591
592    sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type);
593    mModels.replaceValueFor(*handle, model);
594
595    return status;
596}
597
598status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
599{
600    ALOGV("unloadSoundModel() model handle %d", handle);
601    if (!captureHotwordAllowed()) {
602        return PERMISSION_DENIED;
603    }
604
605    AutoMutex lock(mLock);
606    return unloadSoundModel_l(handle);
607}
608
609status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle)
610{
611    ssize_t index = mModels.indexOfKey(handle);
612    if (index < 0) {
613        return BAD_VALUE;
614    }
615    sp<Model> model = mModels.valueAt(index);
616    mModels.removeItem(handle);
617    if (model->mState == Model::STATE_ACTIVE) {
618        mHwDevice->stop_recognition(mHwDevice, model->mHandle);
619        model->mState = Model::STATE_IDLE;
620    }
621    AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
622    return mHwDevice->unload_sound_model(mHwDevice, handle);
623}
624
625status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
626                                 const sp<IMemory>& dataMemory)
627{
628    ALOGV("startRecognition() model handle %d", handle);
629    if (!captureHotwordAllowed()) {
630        return PERMISSION_DENIED;
631    }
632
633    if (dataMemory != 0 && dataMemory->pointer() == NULL) {
634        ALOGE("startRecognition() dataMemory is non-0 but has NULL pointer()");
635        return BAD_VALUE;
636
637    }
638    AutoMutex lock(mLock);
639    if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
640        return INVALID_OPERATION;
641    }
642    sp<Model> model = getModel(handle);
643    if (model == 0) {
644        return BAD_VALUE;
645    }
646    if ((dataMemory == 0) ||
647            (dataMemory->size() < sizeof(struct sound_trigger_recognition_config))) {
648        return BAD_VALUE;
649    }
650
651    if (model->mState == Model::STATE_ACTIVE) {
652        return INVALID_OPERATION;
653    }
654
655    struct sound_trigger_recognition_config *config =
656            (struct sound_trigger_recognition_config *)dataMemory->pointer();
657
658    //TODO: get capture handle and device from audio policy service
659    config->capture_handle = model->mCaptureIOHandle;
660    config->capture_device = model->mCaptureDevice;
661    status_t status = mHwDevice->start_recognition(mHwDevice, handle, config,
662                                        SoundTriggerHwService::recognitionCallback,
663                                        this);
664
665    if (status == NO_ERROR) {
666        model->mState = Model::STATE_ACTIVE;
667        model->mConfig = *config;
668    }
669
670    return status;
671}
672
673status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
674{
675    ALOGV("stopRecognition() model handle %d", handle);
676    if (!captureHotwordAllowed()) {
677        return PERMISSION_DENIED;
678    }
679
680    AutoMutex lock(mLock);
681    sp<Model> model = getModel(handle);
682    if (model == 0) {
683        return BAD_VALUE;
684    }
685
686    if (model->mState != Model::STATE_ACTIVE) {
687        return INVALID_OPERATION;
688    }
689    mHwDevice->stop_recognition(mHwDevice, handle);
690    model->mState = Model::STATE_IDLE;
691    return NO_ERROR;
692}
693
694
695void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
696{
697    ALOGV("onCallbackEvent type %d", event->mType);
698
699    sp<IMemory> eventMemory = event->mMemory;
700
701    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
702        return;
703    }
704    if (mClient == 0) {
705        ALOGI("%s mClient == 0", __func__);
706        return;
707    }
708
709    switch (event->mType) {
710    case CallbackEvent::TYPE_RECOGNITION: {
711        struct sound_trigger_recognition_event *recognitionEvent =
712                (struct sound_trigger_recognition_event *)eventMemory->pointer();
713        sp<ISoundTriggerClient> client;
714        {
715            AutoMutex lock(mLock);
716            sp<Model> model = getModel(recognitionEvent->model);
717            if (model == 0) {
718                ALOGW("%s model == 0", __func__);
719                return;
720            }
721            if (model->mState != Model::STATE_ACTIVE) {
722                ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
723                return;
724            }
725
726            recognitionEvent->capture_session = model->mCaptureSession;
727            model->mState = Model::STATE_IDLE;
728            client = mClient;
729        }
730        if (client != 0) {
731            client->onRecognitionEvent(eventMemory);
732        }
733    } break;
734    case CallbackEvent::TYPE_SOUNDMODEL: {
735        struct sound_trigger_model_event *soundmodelEvent =
736                (struct sound_trigger_model_event *)eventMemory->pointer();
737        sp<ISoundTriggerClient> client;
738        {
739            AutoMutex lock(mLock);
740            sp<Model> model = getModel(soundmodelEvent->model);
741            if (model == 0) {
742                ALOGW("%s model == 0", __func__);
743                return;
744            }
745            client = mClient;
746        }
747        if (client != 0) {
748            client->onSoundModelEvent(eventMemory);
749        }
750    } break;
751    case CallbackEvent::TYPE_SERVICE_STATE: {
752        sp<ISoundTriggerClient> client;
753        {
754            AutoMutex lock(mLock);
755            client = mClient;
756        }
757        if (client != 0) {
758            client->onServiceStateChange(eventMemory);
759        }
760    } break;
761    default:
762        LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
763    }
764}
765
766sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
767        sound_model_handle_t handle)
768{
769    sp<Model> model;
770    ssize_t index = mModels.indexOfKey(handle);
771    if (index >= 0) {
772        model = mModels.valueAt(index);
773    }
774    return model;
775}
776
777void SoundTriggerHwService::Module::binderDied(
778    const wp<IBinder> &who __unused) {
779    ALOGW("client binder died for module %d", mDescriptor.handle);
780    detach();
781}
782
783// Called with mServiceLock held
784void SoundTriggerHwService::Module::setCaptureState_l(bool active)
785{
786    ALOGV("Module::setCaptureState_l %d", active);
787    sp<SoundTriggerHwService> service;
788    sound_trigger_service_state_t state;
789
790    Vector< sp<IMemory> > events;
791    {
792        AutoMutex lock(mLock);
793        state = (active && !mDescriptor.properties.concurrent_capture) ?
794                                        SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
795
796        if (state == mServiceState) {
797            return;
798        }
799
800        mServiceState = state;
801
802        service = mService.promote();
803        if (service == 0) {
804            return;
805        }
806
807        if (state == SOUND_TRIGGER_STATE_ENABLED) {
808            goto exit;
809        }
810
811        for (size_t i = 0; i < mModels.size(); i++) {
812            sp<Model> model = mModels.valueAt(i);
813            if (model->mState == Model::STATE_ACTIVE) {
814                mHwDevice->stop_recognition(mHwDevice, model->mHandle);
815                // keep model in ACTIVE state so that event is processed by onCallbackEvent()
816                if (model->mType == SOUND_MODEL_TYPE_KEYPHRASE) {
817                    struct sound_trigger_phrase_recognition_event event;
818                    memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
819                    event.num_phrases = model->mConfig.num_phrases;
820                    for (size_t i = 0; i < event.num_phrases; i++) {
821                        event.phrase_extras[i] = model->mConfig.phrases[i];
822                    }
823                    event.common.status = RECOGNITION_STATUS_ABORT;
824                    event.common.type = model->mType;
825                    event.common.model = model->mHandle;
826                    event.common.data_size = 0;
827                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
828                    if (eventMemory != 0) {
829                        events.add(eventMemory);
830                    }
831                } else if (model->mType == SOUND_MODEL_TYPE_GENERIC) {
832                    struct sound_trigger_generic_recognition_event event;
833                    memset(&event, 0, sizeof(struct sound_trigger_generic_recognition_event));
834                    event.common.status = RECOGNITION_STATUS_ABORT;
835                    event.common.type = model->mType;
836                    event.common.model = model->mHandle;
837                    event.common.data_size = 0;
838                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
839                    if (eventMemory != 0) {
840                        events.add(eventMemory);
841                    }
842                } else if (model->mType == SOUND_MODEL_TYPE_UNKNOWN) {
843                    struct sound_trigger_phrase_recognition_event event;
844                    memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
845                    event.common.status = RECOGNITION_STATUS_ABORT;
846                    event.common.type = model->mType;
847                    event.common.model = model->mHandle;
848                    event.common.data_size = 0;
849                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
850                    if (eventMemory != 0) {
851                        events.add(eventMemory);
852                    }
853                } else {
854                    goto exit;
855                }
856            }
857        }
858    }
859
860    for (size_t i = 0; i < events.size(); i++) {
861        service->sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i],
862                                                     this));
863    }
864
865exit:
866    service->sendServiceStateEvent_l(state, this);
867}
868
869
870SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
871                                    audio_io_handle_t ioHandle, audio_devices_t device,
872                                    sound_trigger_sound_model_type_t type) :
873    mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
874    mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type)
875{
876
877}
878
879status_t SoundTriggerHwService::Module::dump(int fd __unused,
880                                             const Vector<String16>& args __unused) {
881    String8 result;
882    return NO_ERROR;
883}
884
885}; // namespace android
886