1b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent/*
2b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * Copyright (C) 2014 The Android Open Source Project
3b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent *
4b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
5b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * you may not use this file except in compliance with the License.
6b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * You may obtain a copy of the License at
7b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent *
8b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
9b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent *
10b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * Unless required by applicable law or agreed to in writing, software
11b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
12b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * See the License for the specific language governing permissions and
14b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent * limitations under the License.
15b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent */
16b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
17b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define LOG_TAG "SoundTriggerHwService"
18b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent//#define LOG_NDEBUG 0
19b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
20b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include <stdio.h>
21b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include <string.h>
22b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include <sys/types.h>
23b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include <pthread.h>
24b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
258ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent#include <system/sound_trigger.h>
26936c84a5b743dce2a2572fdf54b37b187bc88b60Eric Laurent#include <cutils/atomic.h>
27936c84a5b743dce2a2572fdf54b37b187bc88b60Eric Laurent#include <cutils/properties.h>
28df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent#include <hardware/hardware.h>
29df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent#include <media/AudioSystem.h>
30936c84a5b743dce2a2572fdf54b37b187bc88b60Eric Laurent#include <utils/Errors.h>
31936c84a5b743dce2a2572fdf54b37b187bc88b60Eric Laurent#include <utils/Log.h>
328ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent#include <binder/IServiceManager.h>
338ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent#include <binder/MemoryBase.h>
348ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent#include <binder/MemoryHeapBase.h>
357a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent#include <system/sound_trigger.h>
368ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent#include <ServiceUtilities.h>
378ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent#include "SoundTriggerHwService.h"
38b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
39b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#ifdef SOUND_TRIGGER_USE_STUB_MODULE
40b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define HW_MODULE_PREFIX "stub"
41b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#else
42b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define HW_MODULE_PREFIX "primary"
43b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#endif
447a544b44b7872b300f50e16fef480f76e9145fbbEric Laurentnamespace android {
45b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
46b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::SoundTriggerHwService()
47b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    : BnSoundTriggerHwService(),
48df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent      mNextUniqueId(1),
49df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent      mMemoryDealer(new MemoryDealer(1024 * 1024, "SoundTriggerHwService")),
50df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent      mCaptureState(false)
51b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
52b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
53b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
54b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::onFirstRef()
55b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
56b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    int rc;
57b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
587a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    sp<SoundTriggerHalInterface> halInterface =
597a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent            SoundTriggerHalInterface::connectModule(HW_MODULE_PREFIX);
607a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent
617a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    if (halInterface == 0) {
627a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent        ALOGW("could not connect to HAL");
63b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
64b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
65b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sound_trigger_module_descriptor descriptor;
667a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    rc = halInterface->getProperties(&descriptor.properties);
67b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (rc != 0) {
68b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("could not read implementation properties");
69b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
70b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
71b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    descriptor.handle =
72b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            (sound_trigger_module_handle_t)android_atomic_inc(&mNextUniqueId);
73b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGI("loaded default module %s, handle %d", descriptor.properties.description,
74b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                 descriptor.handle);
75b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
76e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<Module> module = new Module(this, halInterface, descriptor);
77b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mModules.add(descriptor.handle, module);
78b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mCallbackThread = new CallbackThread(this);
79b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
80b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
81b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::~SoundTriggerHwService()
82b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
83b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (mCallbackThread != 0) {
84b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        mCallbackThread->exit();
85b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
86b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
87b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
88b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::listModules(struct sound_trigger_module_descriptor *modules,
89b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                             uint32_t *numModules)
90b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
91b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("listModules");
928ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    if (!captureHotwordAllowed()) {
938ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent        return PERMISSION_DENIED;
948ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    }
958ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent
96b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mServiceLock);
97b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
98b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
99b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
100b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    size_t maxModules = *numModules;
101b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    *numModules = mModules.size();
102b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
103b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        modules[i] = mModules.valueAt(i)->descriptor();
104b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
105b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
106b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
107b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
108b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::attach(const sound_trigger_module_handle_t handle,
109b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        const sp<ISoundTriggerClient>& client,
110b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        sp<ISoundTrigger>& moduleInterface)
111b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
112b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("attach module %d", handle);
1138ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    if (!captureHotwordAllowed()) {
1148ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent        return PERMISSION_DENIED;
1158ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    }
1168ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent
117b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mServiceLock);
118b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    moduleInterface.clear();
119b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (client == 0) {
120b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
121b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
122b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ssize_t index = mModules.indexOfKey(handle);
123b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (index < 0) {
124b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
125b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
126b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Module> module = mModules.valueAt(index);
127b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
128e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<ModuleClient> moduleClient = module->addClient(client);
129e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (moduleClient == 0) {
130e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return NO_INIT;
131e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
132b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
133e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    moduleClient->setCaptureState_l(mCaptureState);
134e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    moduleInterface = moduleClient;
135df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
136b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
137b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
138b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
139df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentstatus_t SoundTriggerHwService::setCaptureState(bool active)
140df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
141df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    ALOGV("setCaptureState %d", active);
142df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    AutoMutex lock(mServiceLock);
143df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    mCaptureState = active;
144df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    for (size_t i = 0; i < mModules.size(); i++) {
145df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        mModules.valueAt(i)->setCaptureState_l(active);
146df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
147df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return NO_ERROR;
148df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
149df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
150df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
151b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatic const int kDumpLockRetries = 50;
152b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatic const int kDumpLockSleep = 60000;
153b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
154b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatic bool tryLock(Mutex& mutex)
155b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
156b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    bool locked = false;
157b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    for (int i = 0; i < kDumpLockRetries; ++i) {
158b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (mutex.tryLock() == NO_ERROR) {
159b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            locked = true;
160b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            break;
161b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
162b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        usleep(kDumpLockSleep);
163b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
164b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return locked;
165b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
166b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
167b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::dump(int fd, const Vector<String16>& args __unused) {
168b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    String8 result;
169b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
170b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        result.appendFormat("Permission Denial: can't dump SoundTriggerHwService");
171b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        write(fd, result.string(), result.size());
172b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    } else {
173b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        bool locked = tryLock(mServiceLock);
174b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        // failed to lock - SoundTriggerHwService is probably deadlocked
175b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (!locked) {
176b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            result.append("SoundTriggerHwService may be deadlocked\n");
177b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            write(fd, result.string(), result.size());
178b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
179b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
180b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (locked) mServiceLock.unlock();
181b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
182b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
183b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
184b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
185b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::onTransact(
186b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
187b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return BnSoundTriggerHwService::onTransact(code, data, reply, flags);
188b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
189b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
190b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
191b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent// static
192b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition_event *event,
193b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                void *cookie)
194b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
195b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    Module *module = (Module *)cookie;
196b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (module == NULL) {
197b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
198b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
199df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<SoundTriggerHwService> service = module->service().promote();
200df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (service == 0) {
201df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
202df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
203df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
204df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    service->sendRecognitionEvent(event, module);
205df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
206df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
207df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentsp<IMemory> SoundTriggerHwService::prepareRecognitionEvent_l(
208df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                    struct sound_trigger_recognition_event *event)
209df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
210df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory;
211df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
212df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    //sanitize event
213df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    switch (event->type) {
214df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case SOUND_MODEL_TYPE_KEYPHRASE:
215df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        ALOGW_IF(event->data_size != 0 && event->data_offset !=
216df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    sizeof(struct sound_trigger_phrase_recognition_event),
217df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    "prepareRecognitionEvent_l(): invalid data offset %u for keyphrase event type",
218df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    event->data_offset);
219df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
220df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        break;
22100a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta    case SOUND_MODEL_TYPE_GENERIC:
22200a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta        ALOGW_IF(event->data_size != 0 && event->data_offset !=
22300a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    sizeof(struct sound_trigger_generic_recognition_event),
22400a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    "prepareRecognitionEvent_l(): invalid data offset %u for generic event type",
22500a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event->data_offset);
22600a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta        event->data_offset = sizeof(struct sound_trigger_generic_recognition_event);
22700a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta        break;
228df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case SOUND_MODEL_TYPE_UNKNOWN:
229df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        ALOGW_IF(event->data_size != 0 && event->data_offset !=
230df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    sizeof(struct sound_trigger_recognition_event),
231df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    "prepareRecognitionEvent_l(): invalid data offset %u for unknown event type",
232df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    event->data_offset);
233df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        event->data_offset = sizeof(struct sound_trigger_recognition_event);
234df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        break;
235df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    default:
236886561f06ddaea86a51def1e918367430240b5acEric Laurent        return eventMemory;
237df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
238df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
239df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    size_t size = event->data_offset + event->data_size;
240df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    eventMemory = mMemoryDealer->allocate(size);
241df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
242df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        eventMemory.clear();
243df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return eventMemory;
244df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
245df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    memcpy(eventMemory->pointer(), event, size);
246df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
247df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return eventMemory;
248df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
249df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
250df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event,
251df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                 Module *module)
252df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent {
253df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     AutoMutex lock(mServiceLock);
254df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     if (module == NULL) {
255df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         return;
256df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     }
257df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     sp<IMemory> eventMemory = prepareRecognitionEvent_l(event);
258df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     if (eventMemory == 0) {
259df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         return;
260df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     }
261df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     sp<Module> strongModule;
262df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     for (size_t i = 0; i < mModules.size(); i++) {
263df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         if (mModules.valueAt(i).get() == module) {
264df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent             strongModule = mModules.valueAt(i);
265df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent             break;
266df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         }
267df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     }
268df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     if (strongModule == 0) {
269df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         return;
270df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     }
271df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
272e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
273e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                        eventMemory);
274e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    callbackEvent->setModule(strongModule);
275e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sendCallbackEvent_l(callbackEvent);
276b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
277b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
278df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent// static
279df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event,
280df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                               void *cookie)
281df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
282df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    Module *module = (Module *)cookie;
283df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (module == NULL) {
284df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
285df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
286df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<SoundTriggerHwService> service = module->service().promote();
287df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (service == 0) {
288df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
289df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
290df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
291df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    service->sendSoundModelEvent(event, module);
292df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
293b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
294df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentsp<IMemory> SoundTriggerHwService::prepareSoundModelEvent_l(struct sound_trigger_model_event *event)
295b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
296df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory;
297df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
298df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    size_t size = event->data_offset + event->data_size;
299df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    eventMemory = mMemoryDealer->allocate(size);
300df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
301df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        eventMemory.clear();
302df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return eventMemory;
303df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
304df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    memcpy(eventMemory->pointer(), event, size);
305df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
306df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return eventMemory;
307b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
308b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
309df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event,
310df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                Module *module)
311b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
312df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    AutoMutex lock(mServiceLock);
313df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory = prepareSoundModelEvent_l(event);
314df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0) {
315df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
316df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
317df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<Module> strongModule;
318df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    for (size_t i = 0; i < mModules.size(); i++) {
319df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (mModules.valueAt(i).get() == module) {
320df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            strongModule = mModules.valueAt(i);
321df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            break;
322df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
323df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
324df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (strongModule == 0) {
325df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
326df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
327e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL,
328e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                        eventMemory);
329e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    callbackEvent->setModule(strongModule);
330e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sendCallbackEvent_l(callbackEvent);
331df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
332df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
333df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
334df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentsp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
335df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
336df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory;
337df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
338df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    size_t size = sizeof(sound_trigger_service_state_t);
339df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    eventMemory = mMemoryDealer->allocate(size);
340df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
341df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        eventMemory.clear();
342df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return eventMemory;
343df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
344df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    *((sound_trigger_service_state_t *)eventMemory->pointer()) = state;
345df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return eventMemory;
346df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
347df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
348df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent// call with mServiceLock held
349df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
350df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                  Module *module)
351df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
352df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
353df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0) {
354df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
355df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
356df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<Module> strongModule;
357df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    for (size_t i = 0; i < mModules.size(); i++) {
358df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (mModules.valueAt(i).get() == module) {
359df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            strongModule = mModules.valueAt(i);
360df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            break;
361df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
362df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
363df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (strongModule == 0) {
364df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
365df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
366e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
367e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                        eventMemory);
368e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    callbackEvent->setModule(strongModule);
369e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sendCallbackEvent_l(callbackEvent);
370e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
371e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
372e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgevoid SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
373e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                    ModuleClient *moduleClient)
374e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
375e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
376e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (eventMemory == 0) {
377e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return;
378e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
379e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
380e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                        eventMemory);
381e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    callbackEvent->setModuleClient(moduleClient);
382e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sendCallbackEvent_l(callbackEvent);
383df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
384df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
385df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent// call with mServiceLock held
386df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event)
387df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
388df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    mCallbackThread->sendCallbackEvent(event);
389df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
390df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
391df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event)
392df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
393df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    ALOGV("onCallbackEvent");
394b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Module> module;
395e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<ModuleClient> moduleClient;
396b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    {
397b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        AutoMutex lock(mServiceLock);
398e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        //CallbackEvent is either for Module or ModuleClient
399b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        module = event->mModule.promote();
400b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (module == 0) {
401e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            moduleClient = event->mModuleClient.promote();
402e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            if (moduleClient == 0) {
403e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                return;
404e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            }
405b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
406b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
407e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (module != 0) {
408e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        ALOGV("onCallbackEvent for module");
409e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        module->onCallbackEvent(event);
410e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    } else if (moduleClient != 0) {
411e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        ALOGV("onCallbackEvent for moduleClient");
412e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        moduleClient->onCallbackEvent(event);
413e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
414df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    {
415df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        AutoMutex lock(mServiceLock);
416df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        // clear now to execute with mServiceLock locked
417df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        event->mMemory.clear();
418df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
419b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
420b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
421b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#undef LOG_TAG
422b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define LOG_TAG "SoundTriggerHwService::CallbackThread"
423b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
424b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
425b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    : mService(service)
426b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
427b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
428b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
429b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::CallbackThread::~CallbackThread()
430b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
431df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    while (!mEventQueue.isEmpty()) {
432df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        mEventQueue[0]->mMemory.clear();
433df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        mEventQueue.removeAt(0);
434df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
435b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
436b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
437b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::CallbackThread::onFirstRef()
438b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
439b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
440b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
441b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
442b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentbool SoundTriggerHwService::CallbackThread::threadLoop()
443b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
444b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    while (!exitPending()) {
445df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        sp<CallbackEvent> event;
446b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        sp<SoundTriggerHwService> service;
447b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        {
448b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            Mutex::Autolock _l(mCallbackLock);
449b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            while (mEventQueue.isEmpty() && !exitPending()) {
450b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                ALOGV("CallbackThread::threadLoop() sleep");
451b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                mCallbackCond.wait(mCallbackLock);
452b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                ALOGV("CallbackThread::threadLoop() wake up");
453b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            }
454b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            if (exitPending()) {
455b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                break;
456b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            }
457b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            event = mEventQueue[0];
458b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            mEventQueue.removeAt(0);
459b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            service = mService.promote();
460b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
461b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (service != 0) {
462df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            service->onCallbackEvent(event);
463b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
464b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
465b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return false;
466b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
467b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
468b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::CallbackThread::exit()
469b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
470b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    Mutex::Autolock _l(mCallbackLock);
471b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    requestExit();
472b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mCallbackCond.broadcast();
473b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
474b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
475df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::CallbackThread::sendCallbackEvent(
476df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                        const sp<SoundTriggerHwService::CallbackEvent>& event)
477b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
478b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mCallbackLock);
479b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mEventQueue.add(event);
480b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mCallbackCond.signal();
481b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
482b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
483e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew GeorgeSoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory)
484e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    : mType(type), mMemory(memory)
485b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
486b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
487b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
488df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric LaurentSoundTriggerHwService::CallbackEvent::~CallbackEvent()
489b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
490b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
491b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
492df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
493b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#undef LOG_TAG
494b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define LOG_TAG "SoundTriggerHwService::Module"
495b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
496b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
4977a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent                                      const sp<SoundTriggerHalInterface>& halInterface,
498e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                      sound_trigger_module_descriptor descriptor)
4997a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent : mService(service), mHalInterface(halInterface), mDescriptor(descriptor),
500e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George   mServiceState(SOUND_TRIGGER_STATE_NO_INIT)
501b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
502b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
503b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
504b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::Module::~Module() {
505e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    mModuleClients.clear();
506b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
507b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
508e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgesp<SoundTriggerHwService::ModuleClient>
509e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew GeorgeSoundTriggerHwService::Module::addClient(const sp<ISoundTriggerClient>& client)
510e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
511e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    AutoMutex lock(mLock);
512e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<ModuleClient> moduleClient;
513e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
514e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    for (size_t i = 0; i < mModuleClients.size(); i++) {
515e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        if (mModuleClients[i]->client() == client) {
516e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            // Client already present, reuse client
517e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            return moduleClient;
518e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        }
519e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
520e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    moduleClient = new ModuleClient(this, client);
521e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
522e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("addClient() client %p", moduleClient.get());
523e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    mModuleClients.add(moduleClient);
524e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
525e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    return moduleClient;
526e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
527e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
528e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgevoid SoundTriggerHwService::Module::detach(const sp<ModuleClient>& moduleClient)
529e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
530e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("Module::detach()");
531e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    AutoMutex lock(mLock);
532e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ssize_t index = -1;
533e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
534e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    for (size_t i = 0; i < mModuleClients.size(); i++) {
535e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        if (mModuleClients[i] == moduleClient) {
536e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            index = i;
537e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            break;
538e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        }
539e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
540e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (index == -1) {
5418ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent        return;
5428ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    }
543e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
544e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("remove client %p", moduleClient.get());
545e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    mModuleClients.removeAt(index);
546e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
5470012417ddc1320c6df79258266da1e869036b211Dhananjay Kumar    // Iterate in reverse order as models are removed from list inside the loop.
5480012417ddc1320c6df79258266da1e869036b211Dhananjay Kumar    for (size_t i = mModels.size(); i > 0; i--) {
5490012417ddc1320c6df79258266da1e869036b211Dhananjay Kumar        sp<Model> model = mModels.valueAt(i - 1);
550e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        if (moduleClient == model->mModuleClient) {
5510012417ddc1320c6df79258266da1e869036b211Dhananjay Kumar            mModels.removeItemsAt(i - 1);
552b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            ALOGV("detach() unloading model %d", model->mHandle);
5537a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent            if (mHalInterface != 0) {
5547a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent                if (model->mState == Model::STATE_ACTIVE) {
5557a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent                    mHalInterface->stopRecognition(model->mHandle);
5567a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent                }
5577a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent                mHalInterface->unloadSoundModel(model->mHandle);
558b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            }
559e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
560e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            mHalInterface->unloadSoundModel(model->mHandle);
561b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
562b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
563b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
564b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
565b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
566e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                       sp<ModuleClient> moduleClient,
567e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                       sound_model_handle_t *handle)
568b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
569b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("loadSoundModel() handle");
5707a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    if (mHalInterface == 0) {
5717a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent        return NO_INIT;
5727a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    }
573b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (modelMemory == 0 || modelMemory->pointer() == NULL) {
574b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()");
575b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
576b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
577b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    struct sound_trigger_sound_model *sound_model =
578b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            (struct sound_trigger_sound_model *)modelMemory->pointer();
579b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
580bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    size_t structSize;
581bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
582bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        structSize = sizeof(struct sound_trigger_phrase_sound_model);
583bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    } else {
584bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        structSize = sizeof(struct sound_trigger_sound_model);
585bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    }
586bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent
587bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    if (sound_model->data_offset < structSize ||
588bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent           sound_model->data_size > (UINT_MAX - sound_model->data_offset) ||
589bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent           modelMemory->size() < sound_model->data_offset ||
590bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent           sound_model->data_size > (modelMemory->size() - sound_model->data_offset)) {
591bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        android_errorWriteLog(0x534e4554, "30148546");
592bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        ALOGE("loadSoundModel() data_size is too big");
593bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        return BAD_VALUE;
594bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    }
595bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent
596b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
59702eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent
59802eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent    if (mModels.size() >= mDescriptor.properties.max_sound_models) {
599ad65899e5f7d46e30a4dcca07aa0503fc014a3b9Ryan Bavetta        ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded",
600ad65899e5f7d46e30a4dcca07aa0503fc014a3b9Ryan Bavetta              mDescriptor.properties.max_sound_models);
601ad65899e5f7d46e30a4dcca07aa0503fc014a3b9Ryan Bavetta        return INVALID_OPERATION;
60202eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent    }
60302eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent
6047a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    status_t status = mHalInterface->loadSoundModel(sound_model,
605b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                  SoundTriggerHwService::soundModelCallback,
6062c561209f00320f7ca2b75998bbe72ecec527210Ryan Bavetta                                                  this, handle);
6072c561209f00320f7ca2b75998bbe72ecec527210Ryan Bavetta
608df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (status != NO_ERROR) {
609df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return status;
610df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
611df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    audio_session_t session;
612df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    audio_io_handle_t ioHandle;
613df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    audio_devices_t device;
614df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
615df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
616df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (status != NO_ERROR) {
617df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return status;
618b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
619b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
620e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type,
621e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                moduleClient);
622df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    mModels.replaceValueFor(*handle, model);
623df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
624b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return status;
625b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
626b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
627b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
628b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
629b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("unloadSoundModel() model handle %d", handle);
630b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
63102eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent    return unloadSoundModel_l(handle);
63202eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent}
63302eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent
63402eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurentstatus_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle)
63502eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent{
6367a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    if (mHalInterface == 0) {
6377a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent        return NO_INIT;
6387a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    }
639b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ssize_t index = mModels.indexOfKey(handle);
640b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (index < 0) {
641b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
642b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
6431a1cba8f9a93db188b09d9754987354029129113Eric Laurent    sp<Model> model = mModels.valueAt(index);
644b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mModels.removeItem(handle);
6451a1cba8f9a93db188b09d9754987354029129113Eric Laurent    if (model->mState == Model::STATE_ACTIVE) {
6467a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent        mHalInterface->stopRecognition(model->mHandle);
64702eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent        model->mState = Model::STATE_IDLE;
6481a1cba8f9a93db188b09d9754987354029129113Eric Laurent    }
649df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
6507a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    return mHalInterface->unloadSoundModel(handle);
651b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
652b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
653b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
6540832b2d7d190f4fbe6f134446b2610df0cccdbbbEric Laurent                                 const sp<IMemory>& dataMemory)
655b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
656b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("startRecognition() model handle %d", handle);
6577a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    if (mHalInterface == 0) {
6587a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent        return NO_INIT;
6597a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    }
660bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    if (dataMemory == 0 || dataMemory->pointer() == NULL) {
661bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        ALOGE("startRecognition() dataMemory is 0 or has NULL pointer()");
662b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
663b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
664b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
665bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent
666bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    struct sound_trigger_recognition_config *config =
667bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent            (struct sound_trigger_recognition_config *)dataMemory->pointer();
668bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent
669bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    if (config->data_offset < sizeof(struct sound_trigger_recognition_config) ||
670bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent            config->data_size > (UINT_MAX - config->data_offset) ||
671bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent            dataMemory->size() < config->data_offset ||
672bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent            config->data_size > (dataMemory->size() - config->data_offset)) {
673bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        ALOGE("startRecognition() data_size is too big");
674bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        return BAD_VALUE;
675bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    }
676bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent
677b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
678df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
679df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return INVALID_OPERATION;
680df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
681b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model = getModel(handle);
682b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model == 0) {
683b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
684b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
685b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
686b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model->mState == Model::STATE_ACTIVE) {
687b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return INVALID_OPERATION;
688b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
689b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
690b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
691b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    //TODO: get capture handle and device from audio policy service
692df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    config->capture_handle = model->mCaptureIOHandle;
693df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    config->capture_device = model->mCaptureDevice;
6947a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    status_t status = mHalInterface->startRecognition(handle, config,
695b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                        SoundTriggerHwService::recognitionCallback,
6960832b2d7d190f4fbe6f134446b2610df0cccdbbbEric Laurent                                        this);
697df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
698df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (status == NO_ERROR) {
699df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        model->mState = Model::STATE_ACTIVE;
700df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        model->mConfig = *config;
701df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
702df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
703df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return status;
704b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
705b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
706b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
707b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
708b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("stopRecognition() model handle %d", handle);
7097a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    if (mHalInterface == 0) {
7107a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent        return NO_INIT;
7117a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    }
712b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
713b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model = getModel(handle);
714b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model == 0) {
715b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
716b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
717b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
718b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model->mState != Model::STATE_ACTIVE) {
719b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return INVALID_OPERATION;
720b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
7217a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    mHalInterface->stopRecognition(handle);
722b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    model->mState = Model::STATE_IDLE;
723b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
724b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
725b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
726df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
727b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
728df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    ALOGV("onCallbackEvent type %d", event->mType);
729b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
730df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory = event->mMemory;
731b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
732b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
733b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
734b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
735e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (mModuleClients.isEmpty()) {
736e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        ALOGI("%s no clients", __func__);
737b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
738b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
739df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
740df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    switch (event->mType) {
741df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case CallbackEvent::TYPE_RECOGNITION: {
742df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        struct sound_trigger_recognition_event *recognitionEvent =
743df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                (struct sound_trigger_recognition_event *)eventMemory->pointer();
744886561f06ddaea86a51def1e918367430240b5acEric Laurent        sp<ISoundTriggerClient> client;
745886561f06ddaea86a51def1e918367430240b5acEric Laurent        {
746886561f06ddaea86a51def1e918367430240b5acEric Laurent            AutoMutex lock(mLock);
747886561f06ddaea86a51def1e918367430240b5acEric Laurent            sp<Model> model = getModel(recognitionEvent->model);
748886561f06ddaea86a51def1e918367430240b5acEric Laurent            if (model == 0) {
749886561f06ddaea86a51def1e918367430240b5acEric Laurent                ALOGW("%s model == 0", __func__);
750886561f06ddaea86a51def1e918367430240b5acEric Laurent                return;
751886561f06ddaea86a51def1e918367430240b5acEric Laurent            }
752886561f06ddaea86a51def1e918367430240b5acEric Laurent            if (model->mState != Model::STATE_ACTIVE) {
753886561f06ddaea86a51def1e918367430240b5acEric Laurent                ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
754886561f06ddaea86a51def1e918367430240b5acEric Laurent                return;
755886561f06ddaea86a51def1e918367430240b5acEric Laurent            }
756df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
757886561f06ddaea86a51def1e918367430240b5acEric Laurent            recognitionEvent->capture_session = model->mCaptureSession;
758886561f06ddaea86a51def1e918367430240b5acEric Laurent            model->mState = Model::STATE_IDLE;
759e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            client = model->mModuleClient->client();
760df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
761886561f06ddaea86a51def1e918367430240b5acEric Laurent        if (client != 0) {
762886561f06ddaea86a51def1e918367430240b5acEric Laurent            client->onRecognitionEvent(eventMemory);
763df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
764df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    } break;
765df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case CallbackEvent::TYPE_SOUNDMODEL: {
766df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        struct sound_trigger_model_event *soundmodelEvent =
767df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                (struct sound_trigger_model_event *)eventMemory->pointer();
768886561f06ddaea86a51def1e918367430240b5acEric Laurent        sp<ISoundTriggerClient> client;
769886561f06ddaea86a51def1e918367430240b5acEric Laurent        {
770886561f06ddaea86a51def1e918367430240b5acEric Laurent            AutoMutex lock(mLock);
771886561f06ddaea86a51def1e918367430240b5acEric Laurent            sp<Model> model = getModel(soundmodelEvent->model);
772886561f06ddaea86a51def1e918367430240b5acEric Laurent            if (model == 0) {
773886561f06ddaea86a51def1e918367430240b5acEric Laurent                ALOGW("%s model == 0", __func__);
774886561f06ddaea86a51def1e918367430240b5acEric Laurent                return;
775886561f06ddaea86a51def1e918367430240b5acEric Laurent            }
776e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            client = model->mModuleClient->client();
777886561f06ddaea86a51def1e918367430240b5acEric Laurent        }
778886561f06ddaea86a51def1e918367430240b5acEric Laurent        if (client != 0) {
779886561f06ddaea86a51def1e918367430240b5acEric Laurent            client->onSoundModelEvent(eventMemory);
780df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
781df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    } break;
782df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case CallbackEvent::TYPE_SERVICE_STATE: {
783e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        Vector< sp<ISoundTriggerClient> > clients;
784886561f06ddaea86a51def1e918367430240b5acEric Laurent        {
785886561f06ddaea86a51def1e918367430240b5acEric Laurent            AutoMutex lock(mLock);
786e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            for (size_t i = 0; i < mModuleClients.size(); i++) {
787e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                if (mModuleClients[i] != 0) {
788e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                    clients.add(mModuleClients[i]->client());
789e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                }
790e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            }
791886561f06ddaea86a51def1e918367430240b5acEric Laurent        }
792e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        for (size_t i = 0; i < clients.size(); i++) {
793e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            clients[i]->onServiceStateChange(eventMemory);
794886561f06ddaea86a51def1e918367430240b5acEric Laurent        }
795df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    } break;
796df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    default:
797df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
798df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
799b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
800b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
801b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentsp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
802b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        sound_model_handle_t handle)
803b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
804b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model;
805b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ssize_t index = mModels.indexOfKey(handle);
806b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (index >= 0) {
807b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        model = mModels.valueAt(index);
808b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
809b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return model;
810b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
811b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
812df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent// Called with mServiceLock held
813df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::Module::setCaptureState_l(bool active)
814b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
815df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    ALOGV("Module::setCaptureState_l %d", active);
816df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<SoundTriggerHwService> service;
817df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sound_trigger_service_state_t state;
818b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
819df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    Vector< sp<IMemory> > events;
820df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    {
821df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        AutoMutex lock(mLock);
822df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        state = (active && !mDescriptor.properties.concurrent_capture) ?
823df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                        SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
824b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
825df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (state == mServiceState) {
826df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            return;
827df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
828b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
829df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        mServiceState = state;
830df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
831df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        service = mService.promote();
832df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (service == 0) {
833df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            return;
834df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
835df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
836df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (state == SOUND_TRIGGER_STATE_ENABLED) {
837df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            goto exit;
838df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
839df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
840efcf16c9fd2a2f0d865a2bcca98527d3804f83d6Chris Thornton        const bool supports_stop_all =
8417a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent                (mHalInterface != 0) && (mHalInterface->stopAllRecognitions() == ENOSYS);
842efcf16c9fd2a2f0d865a2bcca98527d3804f83d6Chris Thornton
843df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        for (size_t i = 0; i < mModels.size(); i++) {
844df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            sp<Model> model = mModels.valueAt(i);
845df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            if (model->mState == Model::STATE_ACTIVE) {
8467a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent                if (mHalInterface != 0 && !supports_stop_all) {
8477a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent                    mHalInterface->stopRecognition(model->mHandle);
848efcf16c9fd2a2f0d865a2bcca98527d3804f83d6Chris Thornton                }
849df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                // keep model in ACTIVE state so that event is processed by onCallbackEvent()
85000a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                if (model->mType == SOUND_MODEL_TYPE_KEYPHRASE) {
85100a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    struct sound_trigger_phrase_recognition_event event;
85200a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
85300a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.num_phrases = model->mConfig.num_phrases;
85400a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    for (size_t i = 0; i < event.num_phrases; i++) {
85500a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                        event.phrase_extras[i] = model->mConfig.phrases[i];
856df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    }
85700a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.status = RECOGNITION_STATUS_ABORT;
85800a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.type = model->mType;
85900a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.model = model->mHandle;
86000a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.data_size = 0;
86100a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
86200a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    if (eventMemory != 0) {
86300a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                        events.add(eventMemory);
86400a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    }
86500a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                } else if (model->mType == SOUND_MODEL_TYPE_GENERIC) {
86600a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    struct sound_trigger_generic_recognition_event event;
86700a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    memset(&event, 0, sizeof(struct sound_trigger_generic_recognition_event));
86800a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.status = RECOGNITION_STATUS_ABORT;
86900a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.type = model->mType;
87000a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.model = model->mHandle;
87100a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.data_size = 0;
87200a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
87300a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    if (eventMemory != 0) {
87400a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                        events.add(eventMemory);
8759609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    }
8769609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                } else if (model->mType == SOUND_MODEL_TYPE_UNKNOWN) {
8779609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    struct sound_trigger_phrase_recognition_event event;
8789609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
8799609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    event.common.status = RECOGNITION_STATUS_ABORT;
8809609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    event.common.type = model->mType;
8819609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    event.common.model = model->mHandle;
8829609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    event.common.data_size = 0;
8839609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
8849609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    if (eventMemory != 0) {
8859609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                        events.add(eventMemory);
88600a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    }
88700a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                } else {
88800a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    goto exit;
889df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                }
890df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            }
891df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
892b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
893df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
894df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    for (size_t i = 0; i < events.size(); i++) {
895e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
896e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                            events[i]);
897e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        callbackEvent->setModule(this);
898e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        service->sendCallbackEvent_l(callbackEvent);
899df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
900df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
901df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentexit:
902df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    service->sendServiceStateEvent_l(state, this);
903b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
904b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
905df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
906df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric LaurentSoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
907df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                    audio_io_handle_t ioHandle, audio_devices_t device,
908e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                    sound_trigger_sound_model_type_t type,
909e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                    sp<ModuleClient>& moduleClient) :
910df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
911e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type),
912e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    mModuleClient(moduleClient)
913e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
914e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
915e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
916e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George#undef LOG_TAG
917e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George#define LOG_TAG "SoundTriggerHwService::ModuleClient"
918e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
919e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew GeorgeSoundTriggerHwService::ModuleClient::ModuleClient(const sp<Module>& module,
920e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                  const sp<ISoundTriggerClient>& client)
921e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George : mModule(module), mClient(client)
922b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
923e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
924df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
925e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgevoid SoundTriggerHwService::ModuleClient::onFirstRef()
926e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
927c8a9f4ad35f24ac59645bb262bd8f16fd4f6f0d8Chris Thornton    sp<IBinder> binder = IInterface::asBinder(mClient);
928c8a9f4ad35f24ac59645bb262bd8f16fd4f6f0d8Chris Thornton    if (binder != 0) {
929c8a9f4ad35f24ac59645bb262bd8f16fd4f6f0d8Chris Thornton        binder->linkToDeath(this);
930c8a9f4ad35f24ac59645bb262bd8f16fd4f6f0d8Chris Thornton    }
931b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
932b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
933e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew GeorgeSoundTriggerHwService::ModuleClient::~ModuleClient()
934e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
935e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
936e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
937e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgestatus_t SoundTriggerHwService::ModuleClient::dump(int fd __unused,
938e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                   const Vector<String16>& args __unused) {
939b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    String8 result;
940b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
941b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
942b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
943e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgevoid SoundTriggerHwService::ModuleClient::detach() {
944e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("detach()");
945e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (!captureHotwordAllowed()) {
946e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return;
947e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
948e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
949e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    {
950e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        AutoMutex lock(mLock);
951e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        if (mClient != 0) {
952e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            IInterface::asBinder(mClient)->unlinkToDeath(this);
953e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            mClient.clear();
954e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        }
955e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
956e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
957e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<Module> module = mModule.promote();
958e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (module == 0) {
959e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return;
960e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
961e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    module->detach(this);
962e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
963e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
964e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgestatus_t SoundTriggerHwService::ModuleClient::loadSoundModel(const sp<IMemory>& modelMemory,
965e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                sound_model_handle_t *handle)
966e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
967e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("loadSoundModel() handle");
968e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (!captureHotwordAllowed()) {
969e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return PERMISSION_DENIED;
970e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
971e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
972e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<Module> module = mModule.promote();
973e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (module == 0) {
974e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return NO_INIT;
975e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
976e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    return module->loadSoundModel(modelMemory, this, handle);
977e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
978e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
979e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgestatus_t SoundTriggerHwService::ModuleClient::unloadSoundModel(sound_model_handle_t handle)
980e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
981e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("unloadSoundModel() model handle %d", handle);
982e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (!captureHotwordAllowed()) {
983e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return PERMISSION_DENIED;
984e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
985e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
986e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<Module> module = mModule.promote();
987e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (module == 0) {
988e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return NO_INIT;
989e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
990e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    return module->unloadSoundModel(handle);
991e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
992e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
993e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgestatus_t SoundTriggerHwService::ModuleClient::startRecognition(sound_model_handle_t handle,
994e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                 const sp<IMemory>& dataMemory)
995e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
996e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("startRecognition() model handle %d", handle);
997e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (!captureHotwordAllowed()) {
998e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return PERMISSION_DENIED;
999e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1000e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1001e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<Module> module = mModule.promote();
1002e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (module == 0) {
1003e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return NO_INIT;
1004e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1005e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    return module->startRecognition(handle, dataMemory);
1006e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
1007e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1008e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgestatus_t SoundTriggerHwService::ModuleClient::stopRecognition(sound_model_handle_t handle)
1009e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
1010e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("stopRecognition() model handle %d", handle);
1011e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (!captureHotwordAllowed()) {
1012e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return PERMISSION_DENIED;
1013e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1014e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1015e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<Module> module = mModule.promote();
1016e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (module == 0) {
1017e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return NO_INIT;
1018e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1019e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    return module->stopRecognition(handle);
1020e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
1021e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1022e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgevoid SoundTriggerHwService::ModuleClient::setCaptureState_l(bool active)
1023e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
1024e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("ModuleClient::setCaptureState_l %d", active);
1025e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<SoundTriggerHwService> service;
1026e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sound_trigger_service_state_t state;
1027e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1028e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<Module> module = mModule.promote();
1029e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (module == 0) {
1030e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return;
1031e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1032e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    {
1033e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        AutoMutex lock(mLock);
1034e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        state = (active && !module->isConcurrentCaptureAllowed()) ?
1035e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                        SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
1036e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1037e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        service = module->service().promote();
1038e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        if (service == 0) {
1039e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            return;
1040e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        }
1041e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1042e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    service->sendServiceStateEvent_l(state, this);
1043e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
1044e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1045e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgevoid SoundTriggerHwService::ModuleClient::onCallbackEvent(const sp<CallbackEvent>& event)
1046e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
1047e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("ModuleClient onCallbackEvent type %d", event->mType);
1048e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1049e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<IMemory> eventMemory = event->mMemory;
1050e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1051e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
1052e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return;
1053e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1054e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1055e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    switch (event->mType) {
1056e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    case CallbackEvent::TYPE_SERVICE_STATE: {
1057e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        sp<ISoundTriggerClient> client;
1058e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        {
1059e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            AutoMutex lock(mLock);
1060e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            client = mClient;
1061e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        }
1062e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        if (client !=0 ) {
1063e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            client->onServiceStateChange(eventMemory);
1064e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        }
1065e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    } break;
1066e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    default:
1067e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
1068e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1069e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
1070e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1071e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgevoid SoundTriggerHwService::ModuleClient::binderDied(
1072e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    const wp<IBinder> &who __unused) {
1073e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGW("client binder died for client %p", this);
1074e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    detach();
1075e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
1076e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1077b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}; // namespace android
1078