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    // Iterate in reverse order as models are removed from list inside the loop.
548    for (size_t i = mModels.size(); i > 0; i--) {
549        sp<Model> model = mModels.valueAt(i - 1);
550        if (moduleClient == model->mModuleClient) {
551            mModels.removeItemsAt(i - 1);
552            ALOGV("detach() unloading model %d", model->mHandle);
553            if (mHalInterface != 0) {
554                if (model->mState == Model::STATE_ACTIVE) {
555                    mHalInterface->stopRecognition(model->mHandle);
556                }
557                mHalInterface->unloadSoundModel(model->mHandle);
558            }
559            AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
560            mHalInterface->unloadSoundModel(model->mHandle);
561        }
562    }
563}
564
565status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
566                                                       sp<ModuleClient> moduleClient,
567                                                       sound_model_handle_t *handle)
568{
569    ALOGV("loadSoundModel() handle");
570    if (mHalInterface == 0) {
571        return NO_INIT;
572    }
573    if (modelMemory == 0 || modelMemory->pointer() == NULL) {
574        ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()");
575        return BAD_VALUE;
576    }
577    struct sound_trigger_sound_model *sound_model =
578            (struct sound_trigger_sound_model *)modelMemory->pointer();
579
580    size_t structSize;
581    if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
582        structSize = sizeof(struct sound_trigger_phrase_sound_model);
583    } else {
584        structSize = sizeof(struct sound_trigger_sound_model);
585    }
586
587    if (sound_model->data_offset < structSize ||
588           sound_model->data_size > (UINT_MAX - sound_model->data_offset) ||
589           modelMemory->size() < sound_model->data_offset ||
590           sound_model->data_size > (modelMemory->size() - sound_model->data_offset)) {
591        android_errorWriteLog(0x534e4554, "30148546");
592        ALOGE("loadSoundModel() data_size is too big");
593        return BAD_VALUE;
594    }
595
596    AutoMutex lock(mLock);
597
598    if (mModels.size() >= mDescriptor.properties.max_sound_models) {
599        ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded",
600              mDescriptor.properties.max_sound_models);
601        return INVALID_OPERATION;
602    }
603
604    status_t status = mHalInterface->loadSoundModel(sound_model,
605                                                  SoundTriggerHwService::soundModelCallback,
606                                                  this, handle);
607
608    if (status != NO_ERROR) {
609        return status;
610    }
611    audio_session_t session;
612    audio_io_handle_t ioHandle;
613    audio_devices_t device;
614
615    status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
616    if (status != NO_ERROR) {
617        return status;
618    }
619
620    sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type,
621                                moduleClient);
622    mModels.replaceValueFor(*handle, model);
623
624    return status;
625}
626
627status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
628{
629    ALOGV("unloadSoundModel() model handle %d", handle);
630    AutoMutex lock(mLock);
631    return unloadSoundModel_l(handle);
632}
633
634status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle)
635{
636    if (mHalInterface == 0) {
637        return NO_INIT;
638    }
639    ssize_t index = mModels.indexOfKey(handle);
640    if (index < 0) {
641        return BAD_VALUE;
642    }
643    sp<Model> model = mModels.valueAt(index);
644    mModels.removeItem(handle);
645    if (model->mState == Model::STATE_ACTIVE) {
646        mHalInterface->stopRecognition(model->mHandle);
647        model->mState = Model::STATE_IDLE;
648    }
649    AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
650    return mHalInterface->unloadSoundModel(handle);
651}
652
653status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
654                                 const sp<IMemory>& dataMemory)
655{
656    ALOGV("startRecognition() model handle %d", handle);
657    if (mHalInterface == 0) {
658        return NO_INIT;
659    }
660    if (dataMemory == 0 || dataMemory->pointer() == NULL) {
661        ALOGE("startRecognition() dataMemory is 0 or has NULL pointer()");
662        return BAD_VALUE;
663
664    }
665
666    struct sound_trigger_recognition_config *config =
667            (struct sound_trigger_recognition_config *)dataMemory->pointer();
668
669    if (config->data_offset < sizeof(struct sound_trigger_recognition_config) ||
670            config->data_size > (UINT_MAX - config->data_offset) ||
671            dataMemory->size() < config->data_offset ||
672            config->data_size > (dataMemory->size() - config->data_offset)) {
673        ALOGE("startRecognition() data_size is too big");
674        return BAD_VALUE;
675    }
676
677    AutoMutex lock(mLock);
678    if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
679        return INVALID_OPERATION;
680    }
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
690
691    //TODO: get capture handle and device from audio policy service
692    config->capture_handle = model->mCaptureIOHandle;
693    config->capture_device = model->mCaptureDevice;
694    status_t status = mHalInterface->startRecognition(handle, config,
695                                        SoundTriggerHwService::recognitionCallback,
696                                        this);
697
698    if (status == NO_ERROR) {
699        model->mState = Model::STATE_ACTIVE;
700        model->mConfig = *config;
701    }
702
703    return status;
704}
705
706status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
707{
708    ALOGV("stopRecognition() model handle %d", handle);
709    if (mHalInterface == 0) {
710        return NO_INIT;
711    }
712    AutoMutex lock(mLock);
713    sp<Model> model = getModel(handle);
714    if (model == 0) {
715        return BAD_VALUE;
716    }
717
718    if (model->mState != Model::STATE_ACTIVE) {
719        return INVALID_OPERATION;
720    }
721    mHalInterface->stopRecognition(handle);
722    model->mState = Model::STATE_IDLE;
723    return NO_ERROR;
724}
725
726void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
727{
728    ALOGV("onCallbackEvent type %d", event->mType);
729
730    sp<IMemory> eventMemory = event->mMemory;
731
732    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
733        return;
734    }
735    if (mModuleClients.isEmpty()) {
736        ALOGI("%s no clients", __func__);
737        return;
738    }
739
740    switch (event->mType) {
741    case CallbackEvent::TYPE_RECOGNITION: {
742        struct sound_trigger_recognition_event *recognitionEvent =
743                (struct sound_trigger_recognition_event *)eventMemory->pointer();
744        sp<ISoundTriggerClient> client;
745        {
746            AutoMutex lock(mLock);
747            sp<Model> model = getModel(recognitionEvent->model);
748            if (model == 0) {
749                ALOGW("%s model == 0", __func__);
750                return;
751            }
752            if (model->mState != Model::STATE_ACTIVE) {
753                ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
754                return;
755            }
756
757            recognitionEvent->capture_session = model->mCaptureSession;
758            model->mState = Model::STATE_IDLE;
759            client = model->mModuleClient->client();
760        }
761        if (client != 0) {
762            client->onRecognitionEvent(eventMemory);
763        }
764    } break;
765    case CallbackEvent::TYPE_SOUNDMODEL: {
766        struct sound_trigger_model_event *soundmodelEvent =
767                (struct sound_trigger_model_event *)eventMemory->pointer();
768        sp<ISoundTriggerClient> client;
769        {
770            AutoMutex lock(mLock);
771            sp<Model> model = getModel(soundmodelEvent->model);
772            if (model == 0) {
773                ALOGW("%s model == 0", __func__);
774                return;
775            }
776            client = model->mModuleClient->client();
777        }
778        if (client != 0) {
779            client->onSoundModelEvent(eventMemory);
780        }
781    } break;
782    case CallbackEvent::TYPE_SERVICE_STATE: {
783        Vector< sp<ISoundTriggerClient> > clients;
784        {
785            AutoMutex lock(mLock);
786            for (size_t i = 0; i < mModuleClients.size(); i++) {
787                if (mModuleClients[i] != 0) {
788                    clients.add(mModuleClients[i]->client());
789                }
790            }
791        }
792        for (size_t i = 0; i < clients.size(); i++) {
793            clients[i]->onServiceStateChange(eventMemory);
794        }
795    } break;
796    default:
797        LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
798    }
799}
800
801sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
802        sound_model_handle_t handle)
803{
804    sp<Model> model;
805    ssize_t index = mModels.indexOfKey(handle);
806    if (index >= 0) {
807        model = mModels.valueAt(index);
808    }
809    return model;
810}
811
812// Called with mServiceLock held
813void SoundTriggerHwService::Module::setCaptureState_l(bool active)
814{
815    ALOGV("Module::setCaptureState_l %d", active);
816    sp<SoundTriggerHwService> service;
817    sound_trigger_service_state_t state;
818
819    Vector< sp<IMemory> > events;
820    {
821        AutoMutex lock(mLock);
822        state = (active && !mDescriptor.properties.concurrent_capture) ?
823                                        SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
824
825        if (state == mServiceState) {
826            return;
827        }
828
829        mServiceState = state;
830
831        service = mService.promote();
832        if (service == 0) {
833            return;
834        }
835
836        if (state == SOUND_TRIGGER_STATE_ENABLED) {
837            goto exit;
838        }
839
840        const bool supports_stop_all =
841                (mHalInterface != 0) && (mHalInterface->stopAllRecognitions() == ENOSYS);
842
843        for (size_t i = 0; i < mModels.size(); i++) {
844            sp<Model> model = mModels.valueAt(i);
845            if (model->mState == Model::STATE_ACTIVE) {
846                if (mHalInterface != 0 && !supports_stop_all) {
847                    mHalInterface->stopRecognition(model->mHandle);
848                }
849                // keep model in ACTIVE state so that event is processed by onCallbackEvent()
850                if (model->mType == SOUND_MODEL_TYPE_KEYPHRASE) {
851                    struct sound_trigger_phrase_recognition_event event;
852                    memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
853                    event.num_phrases = model->mConfig.num_phrases;
854                    for (size_t i = 0; i < event.num_phrases; i++) {
855                        event.phrase_extras[i] = model->mConfig.phrases[i];
856                    }
857                    event.common.status = RECOGNITION_STATUS_ABORT;
858                    event.common.type = model->mType;
859                    event.common.model = model->mHandle;
860                    event.common.data_size = 0;
861                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
862                    if (eventMemory != 0) {
863                        events.add(eventMemory);
864                    }
865                } else if (model->mType == SOUND_MODEL_TYPE_GENERIC) {
866                    struct sound_trigger_generic_recognition_event event;
867                    memset(&event, 0, sizeof(struct sound_trigger_generic_recognition_event));
868                    event.common.status = RECOGNITION_STATUS_ABORT;
869                    event.common.type = model->mType;
870                    event.common.model = model->mHandle;
871                    event.common.data_size = 0;
872                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
873                    if (eventMemory != 0) {
874                        events.add(eventMemory);
875                    }
876                } else if (model->mType == SOUND_MODEL_TYPE_UNKNOWN) {
877                    struct sound_trigger_phrase_recognition_event event;
878                    memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
879                    event.common.status = RECOGNITION_STATUS_ABORT;
880                    event.common.type = model->mType;
881                    event.common.model = model->mHandle;
882                    event.common.data_size = 0;
883                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
884                    if (eventMemory != 0) {
885                        events.add(eventMemory);
886                    }
887                } else {
888                    goto exit;
889                }
890            }
891        }
892    }
893
894    for (size_t i = 0; i < events.size(); i++) {
895        sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
896                                                            events[i]);
897        callbackEvent->setModule(this);
898        service->sendCallbackEvent_l(callbackEvent);
899    }
900
901exit:
902    service->sendServiceStateEvent_l(state, this);
903}
904
905
906SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
907                                    audio_io_handle_t ioHandle, audio_devices_t device,
908                                    sound_trigger_sound_model_type_t type,
909                                    sp<ModuleClient>& moduleClient) :
910    mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
911    mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type),
912    mModuleClient(moduleClient)
913{
914}
915
916#undef LOG_TAG
917#define LOG_TAG "SoundTriggerHwService::ModuleClient"
918
919SoundTriggerHwService::ModuleClient::ModuleClient(const sp<Module>& module,
920                                                  const sp<ISoundTriggerClient>& client)
921 : mModule(module), mClient(client)
922{
923}
924
925void SoundTriggerHwService::ModuleClient::onFirstRef()
926{
927    sp<IBinder> binder = IInterface::asBinder(mClient);
928    if (binder != 0) {
929        binder->linkToDeath(this);
930    }
931}
932
933SoundTriggerHwService::ModuleClient::~ModuleClient()
934{
935}
936
937status_t SoundTriggerHwService::ModuleClient::dump(int fd __unused,
938                                                   const Vector<String16>& args __unused) {
939    String8 result;
940    return NO_ERROR;
941}
942
943void SoundTriggerHwService::ModuleClient::detach() {
944    ALOGV("detach()");
945    if (!captureHotwordAllowed()) {
946        return;
947    }
948
949    {
950        AutoMutex lock(mLock);
951        if (mClient != 0) {
952            IInterface::asBinder(mClient)->unlinkToDeath(this);
953            mClient.clear();
954        }
955    }
956
957    sp<Module> module = mModule.promote();
958    if (module == 0) {
959        return;
960    }
961    module->detach(this);
962}
963
964status_t SoundTriggerHwService::ModuleClient::loadSoundModel(const sp<IMemory>& modelMemory,
965                                sound_model_handle_t *handle)
966{
967    ALOGV("loadSoundModel() handle");
968    if (!captureHotwordAllowed()) {
969        return PERMISSION_DENIED;
970    }
971
972    sp<Module> module = mModule.promote();
973    if (module == 0) {
974        return NO_INIT;
975    }
976    return module->loadSoundModel(modelMemory, this, handle);
977}
978
979status_t SoundTriggerHwService::ModuleClient::unloadSoundModel(sound_model_handle_t handle)
980{
981    ALOGV("unloadSoundModel() model handle %d", handle);
982    if (!captureHotwordAllowed()) {
983        return PERMISSION_DENIED;
984    }
985
986    sp<Module> module = mModule.promote();
987    if (module == 0) {
988        return NO_INIT;
989    }
990    return module->unloadSoundModel(handle);
991}
992
993status_t SoundTriggerHwService::ModuleClient::startRecognition(sound_model_handle_t handle,
994                                 const sp<IMemory>& dataMemory)
995{
996    ALOGV("startRecognition() model handle %d", handle);
997    if (!captureHotwordAllowed()) {
998        return PERMISSION_DENIED;
999    }
1000
1001    sp<Module> module = mModule.promote();
1002    if (module == 0) {
1003        return NO_INIT;
1004    }
1005    return module->startRecognition(handle, dataMemory);
1006}
1007
1008status_t SoundTriggerHwService::ModuleClient::stopRecognition(sound_model_handle_t handle)
1009{
1010    ALOGV("stopRecognition() model handle %d", handle);
1011    if (!captureHotwordAllowed()) {
1012        return PERMISSION_DENIED;
1013    }
1014
1015    sp<Module> module = mModule.promote();
1016    if (module == 0) {
1017        return NO_INIT;
1018    }
1019    return module->stopRecognition(handle);
1020}
1021
1022void SoundTriggerHwService::ModuleClient::setCaptureState_l(bool active)
1023{
1024    ALOGV("ModuleClient::setCaptureState_l %d", active);
1025    sp<SoundTriggerHwService> service;
1026    sound_trigger_service_state_t state;
1027
1028    sp<Module> module = mModule.promote();
1029    if (module == 0) {
1030        return;
1031    }
1032    {
1033        AutoMutex lock(mLock);
1034        state = (active && !module->isConcurrentCaptureAllowed()) ?
1035                                        SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
1036
1037        service = module->service().promote();
1038        if (service == 0) {
1039            return;
1040        }
1041    }
1042    service->sendServiceStateEvent_l(state, this);
1043}
1044
1045void SoundTriggerHwService::ModuleClient::onCallbackEvent(const sp<CallbackEvent>& event)
1046{
1047    ALOGV("ModuleClient onCallbackEvent type %d", event->mType);
1048
1049    sp<IMemory> eventMemory = event->mMemory;
1050
1051    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
1052        return;
1053    }
1054
1055    switch (event->mType) {
1056    case CallbackEvent::TYPE_SERVICE_STATE: {
1057        sp<ISoundTriggerClient> client;
1058        {
1059            AutoMutex lock(mLock);
1060            client = mClient;
1061        }
1062        if (client !=0 ) {
1063            client->onServiceStateChange(eventMemory);
1064        }
1065    } break;
1066    default:
1067        LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
1068    }
1069}
1070
1071void SoundTriggerHwService::ModuleClient::binderDied(
1072    const wp<IBinder> &who __unused) {
1073    ALOGW("client binder died for client %p", this);
1074    detach();
1075}
1076
1077}; // namespace android
1078