SoundTriggerHwService.cpp revision c8a9f4ad35f24ac59645bb262bd8f16fd4f6f0d8
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 <system/sound_trigger.h>
36#include <ServiceUtilities.h>
37#include "SoundTriggerHwService.h"
38
39#ifdef SOUND_TRIGGER_USE_STUB_MODULE
40#define HW_MODULE_PREFIX "stub"
41#else
42#define HW_MODULE_PREFIX "primary"
43#endif
44namespace android {
45
46SoundTriggerHwService::SoundTriggerHwService()
47    : BnSoundTriggerHwService(),
48      mNextUniqueId(1),
49      mMemoryDealer(new MemoryDealer(1024 * 1024, "SoundTriggerHwService")),
50      mCaptureState(false)
51{
52}
53
54void SoundTriggerHwService::onFirstRef()
55{
56    int rc;
57
58    sp<SoundTriggerHalInterface> halInterface =
59            SoundTriggerHalInterface::connectModule(HW_MODULE_PREFIX);
60
61    if (halInterface == 0) {
62        ALOGW("could not connect to HAL");
63        return;
64    }
65    sound_trigger_module_descriptor descriptor;
66    rc = halInterface->getProperties(&descriptor.properties);
67    if (rc != 0) {
68        ALOGE("could not read implementation properties");
69        return;
70    }
71    descriptor.handle =
72            (sound_trigger_module_handle_t)android_atomic_inc(&mNextUniqueId);
73    ALOGI("loaded default module %s, handle %d", descriptor.properties.description,
74                                                 descriptor.handle);
75
76    sp<Module> module = new Module(this, halInterface, descriptor);
77    mModules.add(descriptor.handle, module);
78    mCallbackThread = new CallbackThread(this);
79}
80
81SoundTriggerHwService::~SoundTriggerHwService()
82{
83    if (mCallbackThread != 0) {
84        mCallbackThread->exit();
85    }
86}
87
88status_t SoundTriggerHwService::listModules(struct sound_trigger_module_descriptor *modules,
89                             uint32_t *numModules)
90{
91    ALOGV("listModules");
92    if (!captureHotwordAllowed()) {
93        return PERMISSION_DENIED;
94    }
95
96    AutoMutex lock(mServiceLock);
97    if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
98        return BAD_VALUE;
99    }
100    size_t maxModules = *numModules;
101    *numModules = mModules.size();
102    for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
103        modules[i] = mModules.valueAt(i)->descriptor();
104    }
105    return NO_ERROR;
106}
107
108status_t SoundTriggerHwService::attach(const sound_trigger_module_handle_t handle,
109                        const sp<ISoundTriggerClient>& client,
110                        sp<ISoundTrigger>& moduleInterface)
111{
112    ALOGV("attach module %d", handle);
113    if (!captureHotwordAllowed()) {
114        return PERMISSION_DENIED;
115    }
116
117    AutoMutex lock(mServiceLock);
118    moduleInterface.clear();
119    if (client == 0) {
120        return BAD_VALUE;
121    }
122    ssize_t index = mModules.indexOfKey(handle);
123    if (index < 0) {
124        return BAD_VALUE;
125    }
126    sp<Module> module = mModules.valueAt(index);
127
128    sp<ModuleClient> moduleClient = module->addClient(client);
129    if (moduleClient == 0) {
130        return NO_INIT;
131    }
132
133    moduleClient->setCaptureState_l(mCaptureState);
134    moduleInterface = moduleClient;
135
136    return NO_ERROR;
137}
138
139status_t SoundTriggerHwService::setCaptureState(bool active)
140{
141    ALOGV("setCaptureState %d", active);
142    AutoMutex lock(mServiceLock);
143    mCaptureState = active;
144    for (size_t i = 0; i < mModules.size(); i++) {
145        mModules.valueAt(i)->setCaptureState_l(active);
146    }
147    return NO_ERROR;
148}
149
150
151static const int kDumpLockRetries = 50;
152static const int kDumpLockSleep = 60000;
153
154static bool tryLock(Mutex& mutex)
155{
156    bool locked = false;
157    for (int i = 0; i < kDumpLockRetries; ++i) {
158        if (mutex.tryLock() == NO_ERROR) {
159            locked = true;
160            break;
161        }
162        usleep(kDumpLockSleep);
163    }
164    return locked;
165}
166
167status_t SoundTriggerHwService::dump(int fd, const Vector<String16>& args __unused) {
168    String8 result;
169    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
170        result.appendFormat("Permission Denial: can't dump SoundTriggerHwService");
171        write(fd, result.string(), result.size());
172    } else {
173        bool locked = tryLock(mServiceLock);
174        // failed to lock - SoundTriggerHwService is probably deadlocked
175        if (!locked) {
176            result.append("SoundTriggerHwService may be deadlocked\n");
177            write(fd, result.string(), result.size());
178        }
179
180        if (locked) mServiceLock.unlock();
181    }
182    return NO_ERROR;
183}
184
185status_t SoundTriggerHwService::onTransact(
186    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
187    return BnSoundTriggerHwService::onTransact(code, data, reply, flags);
188}
189
190
191// static
192void SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition_event *event,
193                                                void *cookie)
194{
195    Module *module = (Module *)cookie;
196    if (module == NULL) {
197        return;
198    }
199    sp<SoundTriggerHwService> service = module->service().promote();
200    if (service == 0) {
201        return;
202    }
203
204    service->sendRecognitionEvent(event, module);
205}
206
207sp<IMemory> SoundTriggerHwService::prepareRecognitionEvent_l(
208                                                    struct sound_trigger_recognition_event *event)
209{
210    sp<IMemory> eventMemory;
211
212    //sanitize event
213    switch (event->type) {
214    case SOUND_MODEL_TYPE_KEYPHRASE:
215        ALOGW_IF(event->data_size != 0 && event->data_offset !=
216                    sizeof(struct sound_trigger_phrase_recognition_event),
217                    "prepareRecognitionEvent_l(): invalid data offset %u for keyphrase event type",
218                    event->data_offset);
219        event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
220        break;
221    case SOUND_MODEL_TYPE_GENERIC:
222        ALOGW_IF(event->data_size != 0 && event->data_offset !=
223                    sizeof(struct sound_trigger_generic_recognition_event),
224                    "prepareRecognitionEvent_l(): invalid data offset %u for generic event type",
225                    event->data_offset);
226        event->data_offset = sizeof(struct sound_trigger_generic_recognition_event);
227        break;
228    case SOUND_MODEL_TYPE_UNKNOWN:
229        ALOGW_IF(event->data_size != 0 && event->data_offset !=
230                    sizeof(struct sound_trigger_recognition_event),
231                    "prepareRecognitionEvent_l(): invalid data offset %u for unknown event type",
232                    event->data_offset);
233        event->data_offset = sizeof(struct sound_trigger_recognition_event);
234        break;
235    default:
236        return eventMemory;
237    }
238
239    size_t size = event->data_offset + event->data_size;
240    eventMemory = mMemoryDealer->allocate(size);
241    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
242        eventMemory.clear();
243        return eventMemory;
244    }
245    memcpy(eventMemory->pointer(), event, size);
246
247    return eventMemory;
248}
249
250void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event,
251                                                 Module *module)
252 {
253     AutoMutex lock(mServiceLock);
254     if (module == NULL) {
255         return;
256     }
257     sp<IMemory> eventMemory = prepareRecognitionEvent_l(event);
258     if (eventMemory == 0) {
259         return;
260     }
261     sp<Module> strongModule;
262     for (size_t i = 0; i < mModules.size(); i++) {
263         if (mModules.valueAt(i).get() == module) {
264             strongModule = mModules.valueAt(i);
265             break;
266         }
267     }
268     if (strongModule == 0) {
269         return;
270     }
271
272    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
273                                                        eventMemory);
274    callbackEvent->setModule(strongModule);
275    sendCallbackEvent_l(callbackEvent);
276}
277
278// static
279void SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event,
280                                               void *cookie)
281{
282    Module *module = (Module *)cookie;
283    if (module == NULL) {
284        return;
285    }
286    sp<SoundTriggerHwService> service = module->service().promote();
287    if (service == 0) {
288        return;
289    }
290
291    service->sendSoundModelEvent(event, module);
292}
293
294sp<IMemory> SoundTriggerHwService::prepareSoundModelEvent_l(struct sound_trigger_model_event *event)
295{
296    sp<IMemory> eventMemory;
297
298    size_t size = event->data_offset + event->data_size;
299    eventMemory = mMemoryDealer->allocate(size);
300    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
301        eventMemory.clear();
302        return eventMemory;
303    }
304    memcpy(eventMemory->pointer(), event, size);
305
306    return eventMemory;
307}
308
309void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event,
310                                                Module *module)
311{
312    AutoMutex lock(mServiceLock);
313    sp<IMemory> eventMemory = prepareSoundModelEvent_l(event);
314    if (eventMemory == 0) {
315        return;
316    }
317    sp<Module> strongModule;
318    for (size_t i = 0; i < mModules.size(); i++) {
319        if (mModules.valueAt(i).get() == module) {
320            strongModule = mModules.valueAt(i);
321            break;
322        }
323    }
324    if (strongModule == 0) {
325        return;
326    }
327    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL,
328                                                        eventMemory);
329    callbackEvent->setModule(strongModule);
330    sendCallbackEvent_l(callbackEvent);
331}
332
333
334sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
335{
336    sp<IMemory> eventMemory;
337
338    size_t size = sizeof(sound_trigger_service_state_t);
339    eventMemory = mMemoryDealer->allocate(size);
340    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
341        eventMemory.clear();
342        return eventMemory;
343    }
344    *((sound_trigger_service_state_t *)eventMemory->pointer()) = state;
345    return eventMemory;
346}
347
348// call with mServiceLock held
349void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
350                                                  Module *module)
351{
352    sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
353    if (eventMemory == 0) {
354        return;
355    }
356    sp<Module> strongModule;
357    for (size_t i = 0; i < mModules.size(); i++) {
358        if (mModules.valueAt(i).get() == module) {
359            strongModule = mModules.valueAt(i);
360            break;
361        }
362    }
363    if (strongModule == 0) {
364        return;
365    }
366    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
367                                                        eventMemory);
368    callbackEvent->setModule(strongModule);
369    sendCallbackEvent_l(callbackEvent);
370}
371
372void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
373                                                    ModuleClient *moduleClient)
374{
375    sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
376    if (eventMemory == 0) {
377        return;
378    }
379    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
380                                                        eventMemory);
381    callbackEvent->setModuleClient(moduleClient);
382    sendCallbackEvent_l(callbackEvent);
383}
384
385// call with mServiceLock held
386void SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event)
387{
388    mCallbackThread->sendCallbackEvent(event);
389}
390
391void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event)
392{
393    ALOGV("onCallbackEvent");
394    sp<Module> module;
395    sp<ModuleClient> moduleClient;
396    {
397        AutoMutex lock(mServiceLock);
398        //CallbackEvent is either for Module or ModuleClient
399        module = event->mModule.promote();
400        if (module == 0) {
401            moduleClient = event->mModuleClient.promote();
402            if (moduleClient == 0) {
403                return;
404            }
405        }
406    }
407    if (module != 0) {
408        ALOGV("onCallbackEvent for module");
409        module->onCallbackEvent(event);
410    } else if (moduleClient != 0) {
411        ALOGV("onCallbackEvent for moduleClient");
412        moduleClient->onCallbackEvent(event);
413    }
414    {
415        AutoMutex lock(mServiceLock);
416        // clear now to execute with mServiceLock locked
417        event->mMemory.clear();
418    }
419}
420
421#undef LOG_TAG
422#define LOG_TAG "SoundTriggerHwService::CallbackThread"
423
424SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
425    : mService(service)
426{
427}
428
429SoundTriggerHwService::CallbackThread::~CallbackThread()
430{
431    while (!mEventQueue.isEmpty()) {
432        mEventQueue[0]->mMemory.clear();
433        mEventQueue.removeAt(0);
434    }
435}
436
437void SoundTriggerHwService::CallbackThread::onFirstRef()
438{
439    run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
440}
441
442bool SoundTriggerHwService::CallbackThread::threadLoop()
443{
444    while (!exitPending()) {
445        sp<CallbackEvent> event;
446        sp<SoundTriggerHwService> service;
447        {
448            Mutex::Autolock _l(mCallbackLock);
449            while (mEventQueue.isEmpty() && !exitPending()) {
450                ALOGV("CallbackThread::threadLoop() sleep");
451                mCallbackCond.wait(mCallbackLock);
452                ALOGV("CallbackThread::threadLoop() wake up");
453            }
454            if (exitPending()) {
455                break;
456            }
457            event = mEventQueue[0];
458            mEventQueue.removeAt(0);
459            service = mService.promote();
460        }
461        if (service != 0) {
462            service->onCallbackEvent(event);
463        }
464    }
465    return false;
466}
467
468void SoundTriggerHwService::CallbackThread::exit()
469{
470    Mutex::Autolock _l(mCallbackLock);
471    requestExit();
472    mCallbackCond.broadcast();
473}
474
475void SoundTriggerHwService::CallbackThread::sendCallbackEvent(
476                        const sp<SoundTriggerHwService::CallbackEvent>& event)
477{
478    AutoMutex lock(mCallbackLock);
479    mEventQueue.add(event);
480    mCallbackCond.signal();
481}
482
483SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory)
484    : mType(type), mMemory(memory)
485{
486}
487
488SoundTriggerHwService::CallbackEvent::~CallbackEvent()
489{
490}
491
492
493#undef LOG_TAG
494#define LOG_TAG "SoundTriggerHwService::Module"
495
496SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
497                                      const sp<SoundTriggerHalInterface>& halInterface,
498                                      sound_trigger_module_descriptor descriptor)
499 : mService(service), mHalInterface(halInterface), mDescriptor(descriptor),
500   mServiceState(SOUND_TRIGGER_STATE_NO_INIT)
501{
502}
503
504SoundTriggerHwService::Module::~Module() {
505    mModuleClients.clear();
506}
507
508sp<SoundTriggerHwService::ModuleClient>
509SoundTriggerHwService::Module::addClient(const sp<ISoundTriggerClient>& client)
510{
511    AutoMutex lock(mLock);
512    sp<ModuleClient> moduleClient;
513
514    for (size_t i = 0; i < mModuleClients.size(); i++) {
515        if (mModuleClients[i]->client() == client) {
516            // Client already present, reuse client
517            return moduleClient;
518        }
519    }
520    moduleClient = new ModuleClient(this, client);
521
522    ALOGV("addClient() client %p", moduleClient.get());
523    mModuleClients.add(moduleClient);
524
525    return moduleClient;
526}
527
528void SoundTriggerHwService::Module::detach(const sp<ModuleClient>& moduleClient)
529{
530    ALOGV("Module::detach()");
531    AutoMutex lock(mLock);
532    ssize_t index = -1;
533
534    for (size_t i = 0; i < mModuleClients.size(); i++) {
535        if (mModuleClients[i] == moduleClient) {
536            index = i;
537            break;
538        }
539    }
540    if (index == -1) {
541        return;
542    }
543
544    ALOGV("remove client %p", moduleClient.get());
545    mModuleClients.removeAt(index);
546
547    for (size_t i = 0; i < mModels.size(); i++) {
548        sp<Model> model = mModels.valueAt(i);
549        if (moduleClient == model->mModuleClient) {
550            mModels.removeItemsAt(i);
551            ALOGV("detach() unloading model %d", model->mHandle);
552            if (mHalInterface != 0) {
553                if (model->mState == Model::STATE_ACTIVE) {
554                    mHalInterface->stopRecognition(model->mHandle);
555                }
556                mHalInterface->unloadSoundModel(model->mHandle);
557            }
558            AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
559            mHalInterface->unloadSoundModel(model->mHandle);
560        }
561    }
562}
563
564status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
565                                                       sp<ModuleClient> moduleClient,
566                                                       sound_model_handle_t *handle)
567{
568    ALOGV("loadSoundModel() handle");
569    if (mHalInterface == 0) {
570        return NO_INIT;
571    }
572    if (modelMemory == 0 || modelMemory->pointer() == NULL) {
573        ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()");
574        return BAD_VALUE;
575    }
576    struct sound_trigger_sound_model *sound_model =
577            (struct sound_trigger_sound_model *)modelMemory->pointer();
578
579    size_t structSize;
580    if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
581        structSize = sizeof(struct sound_trigger_phrase_sound_model);
582    } else {
583        structSize = sizeof(struct sound_trigger_sound_model);
584    }
585
586    if (sound_model->data_offset < structSize ||
587           sound_model->data_size > (UINT_MAX - sound_model->data_offset) ||
588           modelMemory->size() < sound_model->data_offset ||
589           sound_model->data_size > (modelMemory->size() - sound_model->data_offset)) {
590        android_errorWriteLog(0x534e4554, "30148546");
591        ALOGE("loadSoundModel() data_size is too big");
592        return BAD_VALUE;
593    }
594
595    AutoMutex lock(mLock);
596
597    if (mModels.size() >= mDescriptor.properties.max_sound_models) {
598        ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded",
599              mDescriptor.properties.max_sound_models);
600        return INVALID_OPERATION;
601    }
602
603    status_t status = mHalInterface->loadSoundModel(sound_model,
604                                                  SoundTriggerHwService::soundModelCallback,
605                                                  this, handle);
606
607    if (status != NO_ERROR) {
608        return status;
609    }
610    audio_session_t session;
611    audio_io_handle_t ioHandle;
612    audio_devices_t device;
613
614    status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
615    if (status != NO_ERROR) {
616        return status;
617    }
618
619    sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type,
620                                moduleClient);
621    mModels.replaceValueFor(*handle, model);
622
623    return status;
624}
625
626status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
627{
628    ALOGV("unloadSoundModel() model handle %d", handle);
629    AutoMutex lock(mLock);
630    return unloadSoundModel_l(handle);
631}
632
633status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle)
634{
635    if (mHalInterface == 0) {
636        return NO_INIT;
637    }
638    ssize_t index = mModels.indexOfKey(handle);
639    if (index < 0) {
640        return BAD_VALUE;
641    }
642    sp<Model> model = mModels.valueAt(index);
643    mModels.removeItem(handle);
644    if (model->mState == Model::STATE_ACTIVE) {
645        mHalInterface->stopRecognition(model->mHandle);
646        model->mState = Model::STATE_IDLE;
647    }
648    AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
649    return mHalInterface->unloadSoundModel(handle);
650}
651
652status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
653                                 const sp<IMemory>& dataMemory)
654{
655    ALOGV("startRecognition() model handle %d", handle);
656    if (mHalInterface == 0) {
657        return NO_INIT;
658    }
659    if (dataMemory == 0 || dataMemory->pointer() == NULL) {
660        ALOGE("startRecognition() dataMemory is 0 or has NULL pointer()");
661        return BAD_VALUE;
662
663    }
664
665    struct sound_trigger_recognition_config *config =
666            (struct sound_trigger_recognition_config *)dataMemory->pointer();
667
668    if (config->data_offset < sizeof(struct sound_trigger_recognition_config) ||
669            config->data_size > (UINT_MAX - config->data_offset) ||
670            dataMemory->size() < config->data_offset ||
671            config->data_size > (dataMemory->size() - config->data_offset)) {
672        ALOGE("startRecognition() data_size is too big");
673        return BAD_VALUE;
674    }
675
676    AutoMutex lock(mLock);
677    if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
678        return INVALID_OPERATION;
679    }
680    sp<Model> model = getModel(handle);
681    if (model == 0) {
682        return BAD_VALUE;
683    }
684
685    if (model->mState == Model::STATE_ACTIVE) {
686        return INVALID_OPERATION;
687    }
688
689
690    //TODO: get capture handle and device from audio policy service
691    config->capture_handle = model->mCaptureIOHandle;
692    config->capture_device = model->mCaptureDevice;
693    status_t status = mHalInterface->startRecognition(handle, config,
694                                        SoundTriggerHwService::recognitionCallback,
695                                        this);
696
697    if (status == NO_ERROR) {
698        model->mState = Model::STATE_ACTIVE;
699        model->mConfig = *config;
700    }
701
702    return status;
703}
704
705status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
706{
707    ALOGV("stopRecognition() model handle %d", handle);
708    if (mHalInterface == 0) {
709        return NO_INIT;
710    }
711    AutoMutex lock(mLock);
712    sp<Model> model = getModel(handle);
713    if (model == 0) {
714        return BAD_VALUE;
715    }
716
717    if (model->mState != Model::STATE_ACTIVE) {
718        return INVALID_OPERATION;
719    }
720    mHalInterface->stopRecognition(handle);
721    model->mState = Model::STATE_IDLE;
722    return NO_ERROR;
723}
724
725void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
726{
727    ALOGV("onCallbackEvent type %d", event->mType);
728
729    sp<IMemory> eventMemory = event->mMemory;
730
731    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
732        return;
733    }
734    if (mModuleClients.isEmpty()) {
735        ALOGI("%s no clients", __func__);
736        return;
737    }
738
739    switch (event->mType) {
740    case CallbackEvent::TYPE_RECOGNITION: {
741        struct sound_trigger_recognition_event *recognitionEvent =
742                (struct sound_trigger_recognition_event *)eventMemory->pointer();
743        sp<ISoundTriggerClient> client;
744        {
745            AutoMutex lock(mLock);
746            sp<Model> model = getModel(recognitionEvent->model);
747            if (model == 0) {
748                ALOGW("%s model == 0", __func__);
749                return;
750            }
751            if (model->mState != Model::STATE_ACTIVE) {
752                ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
753                return;
754            }
755
756            recognitionEvent->capture_session = model->mCaptureSession;
757            model->mState = Model::STATE_IDLE;
758            client = model->mModuleClient->client();
759        }
760        if (client != 0) {
761            client->onRecognitionEvent(eventMemory);
762        }
763    } break;
764    case CallbackEvent::TYPE_SOUNDMODEL: {
765        struct sound_trigger_model_event *soundmodelEvent =
766                (struct sound_trigger_model_event *)eventMemory->pointer();
767        sp<ISoundTriggerClient> client;
768        {
769            AutoMutex lock(mLock);
770            sp<Model> model = getModel(soundmodelEvent->model);
771            if (model == 0) {
772                ALOGW("%s model == 0", __func__);
773                return;
774            }
775            client = model->mModuleClient->client();
776        }
777        if (client != 0) {
778            client->onSoundModelEvent(eventMemory);
779        }
780    } break;
781    case CallbackEvent::TYPE_SERVICE_STATE: {
782        Vector< sp<ISoundTriggerClient> > clients;
783        {
784            AutoMutex lock(mLock);
785            for (size_t i = 0; i < mModuleClients.size(); i++) {
786                if (mModuleClients[i] != 0) {
787                    clients.add(mModuleClients[i]->client());
788                }
789            }
790        }
791        for (size_t i = 0; i < clients.size(); i++) {
792            clients[i]->onServiceStateChange(eventMemory);
793        }
794    } break;
795    default:
796        LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
797    }
798}
799
800sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
801        sound_model_handle_t handle)
802{
803    sp<Model> model;
804    ssize_t index = mModels.indexOfKey(handle);
805    if (index >= 0) {
806        model = mModels.valueAt(index);
807    }
808    return model;
809}
810
811// Called with mServiceLock held
812void SoundTriggerHwService::Module::setCaptureState_l(bool active)
813{
814    ALOGV("Module::setCaptureState_l %d", active);
815    sp<SoundTriggerHwService> service;
816    sound_trigger_service_state_t state;
817
818    Vector< sp<IMemory> > events;
819    {
820        AutoMutex lock(mLock);
821        state = (active && !mDescriptor.properties.concurrent_capture) ?
822                                        SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
823
824        if (state == mServiceState) {
825            return;
826        }
827
828        mServiceState = state;
829
830        service = mService.promote();
831        if (service == 0) {
832            return;
833        }
834
835        if (state == SOUND_TRIGGER_STATE_ENABLED) {
836            goto exit;
837        }
838
839        const bool supports_stop_all =
840                (mHalInterface != 0) && (mHalInterface->stopAllRecognitions() == ENOSYS);
841
842        for (size_t i = 0; i < mModels.size(); i++) {
843            sp<Model> model = mModels.valueAt(i);
844            if (model->mState == Model::STATE_ACTIVE) {
845                if (mHalInterface != 0 && !supports_stop_all) {
846                    mHalInterface->stopRecognition(model->mHandle);
847                }
848                // keep model in ACTIVE state so that event is processed by onCallbackEvent()
849                if (model->mType == SOUND_MODEL_TYPE_KEYPHRASE) {
850                    struct sound_trigger_phrase_recognition_event event;
851                    memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
852                    event.num_phrases = model->mConfig.num_phrases;
853                    for (size_t i = 0; i < event.num_phrases; i++) {
854                        event.phrase_extras[i] = model->mConfig.phrases[i];
855                    }
856                    event.common.status = RECOGNITION_STATUS_ABORT;
857                    event.common.type = model->mType;
858                    event.common.model = model->mHandle;
859                    event.common.data_size = 0;
860                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
861                    if (eventMemory != 0) {
862                        events.add(eventMemory);
863                    }
864                } else if (model->mType == SOUND_MODEL_TYPE_GENERIC) {
865                    struct sound_trigger_generic_recognition_event event;
866                    memset(&event, 0, sizeof(struct sound_trigger_generic_recognition_event));
867                    event.common.status = RECOGNITION_STATUS_ABORT;
868                    event.common.type = model->mType;
869                    event.common.model = model->mHandle;
870                    event.common.data_size = 0;
871                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
872                    if (eventMemory != 0) {
873                        events.add(eventMemory);
874                    }
875                } else if (model->mType == SOUND_MODEL_TYPE_UNKNOWN) {
876                    struct sound_trigger_phrase_recognition_event event;
877                    memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
878                    event.common.status = RECOGNITION_STATUS_ABORT;
879                    event.common.type = model->mType;
880                    event.common.model = model->mHandle;
881                    event.common.data_size = 0;
882                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
883                    if (eventMemory != 0) {
884                        events.add(eventMemory);
885                    }
886                } else {
887                    goto exit;
888                }
889            }
890        }
891    }
892
893    for (size_t i = 0; i < events.size(); i++) {
894        sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
895                                                            events[i]);
896        callbackEvent->setModule(this);
897        service->sendCallbackEvent_l(callbackEvent);
898    }
899
900exit:
901    service->sendServiceStateEvent_l(state, this);
902}
903
904
905SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
906                                    audio_io_handle_t ioHandle, audio_devices_t device,
907                                    sound_trigger_sound_model_type_t type,
908                                    sp<ModuleClient>& moduleClient) :
909    mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
910    mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type),
911    mModuleClient(moduleClient)
912{
913}
914
915#undef LOG_TAG
916#define LOG_TAG "SoundTriggerHwService::ModuleClient"
917
918SoundTriggerHwService::ModuleClient::ModuleClient(const sp<Module>& module,
919                                                  const sp<ISoundTriggerClient>& client)
920 : mModule(module), mClient(client)
921{
922}
923
924void SoundTriggerHwService::ModuleClient::onFirstRef()
925{
926    sp<IBinder> binder = IInterface::asBinder(mClient);
927    if (binder != 0) {
928        binder->linkToDeath(this);
929    }
930}
931
932SoundTriggerHwService::ModuleClient::~ModuleClient()
933{
934}
935
936status_t SoundTriggerHwService::ModuleClient::dump(int fd __unused,
937                                                   const Vector<String16>& args __unused) {
938    String8 result;
939    return NO_ERROR;
940}
941
942void SoundTriggerHwService::ModuleClient::detach() {
943    ALOGV("detach()");
944    if (!captureHotwordAllowed()) {
945        return;
946    }
947
948    {
949        AutoMutex lock(mLock);
950        if (mClient != 0) {
951            IInterface::asBinder(mClient)->unlinkToDeath(this);
952            mClient.clear();
953        }
954    }
955
956    sp<Module> module = mModule.promote();
957    if (module == 0) {
958        return;
959    }
960    module->detach(this);
961}
962
963status_t SoundTriggerHwService::ModuleClient::loadSoundModel(const sp<IMemory>& modelMemory,
964                                sound_model_handle_t *handle)
965{
966    ALOGV("loadSoundModel() handle");
967    if (!captureHotwordAllowed()) {
968        return PERMISSION_DENIED;
969    }
970
971    sp<Module> module = mModule.promote();
972    if (module == 0) {
973        return NO_INIT;
974    }
975    return module->loadSoundModel(modelMemory, this, handle);
976}
977
978status_t SoundTriggerHwService::ModuleClient::unloadSoundModel(sound_model_handle_t handle)
979{
980    ALOGV("unloadSoundModel() model handle %d", handle);
981    if (!captureHotwordAllowed()) {
982        return PERMISSION_DENIED;
983    }
984
985    sp<Module> module = mModule.promote();
986    if (module == 0) {
987        return NO_INIT;
988    }
989    return module->unloadSoundModel(handle);
990}
991
992status_t SoundTriggerHwService::ModuleClient::startRecognition(sound_model_handle_t handle,
993                                 const sp<IMemory>& dataMemory)
994{
995    ALOGV("startRecognition() model handle %d", handle);
996    if (!captureHotwordAllowed()) {
997        return PERMISSION_DENIED;
998    }
999
1000    sp<Module> module = mModule.promote();
1001    if (module == 0) {
1002        return NO_INIT;
1003    }
1004    return module->startRecognition(handle, dataMemory);
1005}
1006
1007status_t SoundTriggerHwService::ModuleClient::stopRecognition(sound_model_handle_t handle)
1008{
1009    ALOGV("stopRecognition() model handle %d", handle);
1010    if (!captureHotwordAllowed()) {
1011        return PERMISSION_DENIED;
1012    }
1013
1014    sp<Module> module = mModule.promote();
1015    if (module == 0) {
1016        return NO_INIT;
1017    }
1018    return module->stopRecognition(handle);
1019}
1020
1021void SoundTriggerHwService::ModuleClient::setCaptureState_l(bool active)
1022{
1023    ALOGV("ModuleClient::setCaptureState_l %d", active);
1024    sp<SoundTriggerHwService> service;
1025    sound_trigger_service_state_t state;
1026
1027    sp<Module> module = mModule.promote();
1028    if (module == 0) {
1029        return;
1030    }
1031    {
1032        AutoMutex lock(mLock);
1033        state = (active && !module->isConcurrentCaptureAllowed()) ?
1034                                        SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
1035
1036        service = module->service().promote();
1037        if (service == 0) {
1038            return;
1039        }
1040    }
1041    service->sendServiceStateEvent_l(state, this);
1042}
1043
1044void SoundTriggerHwService::ModuleClient::onCallbackEvent(const sp<CallbackEvent>& event)
1045{
1046    ALOGV("ModuleClient onCallbackEvent type %d", event->mType);
1047
1048    sp<IMemory> eventMemory = event->mMemory;
1049
1050    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
1051        return;
1052    }
1053
1054    switch (event->mType) {
1055    case CallbackEvent::TYPE_SERVICE_STATE: {
1056        sp<ISoundTriggerClient> client;
1057        {
1058            AutoMutex lock(mLock);
1059            client = mClient;
1060        }
1061        if (client !=0 ) {
1062            client->onServiceStateChange(eventMemory);
1063        }
1064    } break;
1065    default:
1066        LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
1067    }
1068}
1069
1070void SoundTriggerHwService::ModuleClient::binderDied(
1071    const wp<IBinder> &who __unused) {
1072    ALOGW("client binder died for client %p", this);
1073    detach();
1074}
1075
1076}; // namespace android
1077