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");
927504b9eb4561df88550f874cf0ce95b6f4d09927Eric Laurent    if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
937504b9eb4561df88550f874cf0ce95b6f4d09927Eric Laurent                               IPCThreadState::self()->getCallingUid())) {
948ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent        return PERMISSION_DENIED;
958ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    }
968ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent
97b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mServiceLock);
98b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
99b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
100b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
101b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    size_t maxModules = *numModules;
102b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    *numModules = mModules.size();
103b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
104b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        modules[i] = mModules.valueAt(i)->descriptor();
105b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
106b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
107b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
108b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
109b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::attach(const sound_trigger_module_handle_t handle,
110b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        const sp<ISoundTriggerClient>& client,
111b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        sp<ISoundTrigger>& moduleInterface)
112b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
113b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("attach module %d", handle);
1147504b9eb4561df88550f874cf0ce95b6f4d09927Eric Laurent    if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
1157504b9eb4561df88550f874cf0ce95b6f4d09927Eric Laurent                               IPCThreadState::self()->getCallingUid())) {
1168ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent        return PERMISSION_DENIED;
1178ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    }
1188ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent
119b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mServiceLock);
120b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    moduleInterface.clear();
121b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (client == 0) {
122b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
123b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
124b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ssize_t index = mModules.indexOfKey(handle);
125b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (index < 0) {
126b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
127b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
128b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Module> module = mModules.valueAt(index);
129b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
130e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<ModuleClient> moduleClient = module->addClient(client);
131e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (moduleClient == 0) {
132e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return NO_INIT;
133e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
134b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
135e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    moduleClient->setCaptureState_l(mCaptureState);
136e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    moduleInterface = moduleClient;
137df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
138b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
139b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
140b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
141df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentstatus_t SoundTriggerHwService::setCaptureState(bool active)
142df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
143df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    ALOGV("setCaptureState %d", active);
144df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    AutoMutex lock(mServiceLock);
145df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    mCaptureState = active;
146df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    for (size_t i = 0; i < mModules.size(); i++) {
147df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        mModules.valueAt(i)->setCaptureState_l(active);
148df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
149df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return NO_ERROR;
150df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
151df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
152df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
153b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatic const int kDumpLockRetries = 50;
154b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatic const int kDumpLockSleep = 60000;
155b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
156b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatic bool tryLock(Mutex& mutex)
157b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
158b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    bool locked = false;
159b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    for (int i = 0; i < kDumpLockRetries; ++i) {
160b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (mutex.tryLock() == NO_ERROR) {
161b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            locked = true;
162b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            break;
163b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
164b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        usleep(kDumpLockSleep);
165b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
166b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return locked;
167b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
168b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
169b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::dump(int fd, const Vector<String16>& args __unused) {
170b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    String8 result;
171b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
172b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        result.appendFormat("Permission Denial: can't dump SoundTriggerHwService");
173b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        write(fd, result.string(), result.size());
174b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    } else {
175b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        bool locked = tryLock(mServiceLock);
176b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        // failed to lock - SoundTriggerHwService is probably deadlocked
177b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (!locked) {
178b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            result.append("SoundTriggerHwService may be deadlocked\n");
179b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            write(fd, result.string(), result.size());
180b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
181b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
182b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (locked) mServiceLock.unlock();
183b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
184b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
185b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
186b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
187b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::onTransact(
188b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
189b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return BnSoundTriggerHwService::onTransact(code, data, reply, flags);
190b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
191b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
192b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
193b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent// static
194b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition_event *event,
195b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                void *cookie)
196b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
197b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    Module *module = (Module *)cookie;
198b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (module == NULL) {
199b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
200b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
201df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<SoundTriggerHwService> service = module->service().promote();
202df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (service == 0) {
203df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
204df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
205df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
206df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    service->sendRecognitionEvent(event, module);
207df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
208df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
209df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentsp<IMemory> SoundTriggerHwService::prepareRecognitionEvent_l(
210df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                    struct sound_trigger_recognition_event *event)
211df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
212df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory;
213df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
214df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    //sanitize event
215df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    switch (event->type) {
216df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case SOUND_MODEL_TYPE_KEYPHRASE:
217df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        ALOGW_IF(event->data_size != 0 && event->data_offset !=
218df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    sizeof(struct sound_trigger_phrase_recognition_event),
219df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    "prepareRecognitionEvent_l(): invalid data offset %u for keyphrase event type",
220df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    event->data_offset);
221df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
222df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        break;
22300a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta    case SOUND_MODEL_TYPE_GENERIC:
22400a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta        ALOGW_IF(event->data_size != 0 && event->data_offset !=
22500a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    sizeof(struct sound_trigger_generic_recognition_event),
22600a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    "prepareRecognitionEvent_l(): invalid data offset %u for generic event type",
22700a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event->data_offset);
22800a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta        event->data_offset = sizeof(struct sound_trigger_generic_recognition_event);
22900a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta        break;
230df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case SOUND_MODEL_TYPE_UNKNOWN:
231df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        ALOGW_IF(event->data_size != 0 && event->data_offset !=
232df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    sizeof(struct sound_trigger_recognition_event),
233df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    "prepareRecognitionEvent_l(): invalid data offset %u for unknown event type",
234df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    event->data_offset);
235df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        event->data_offset = sizeof(struct sound_trigger_recognition_event);
236df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        break;
237df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    default:
238886561f06ddaea86a51def1e918367430240b5acEric Laurent        return eventMemory;
239df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
240df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
241df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    size_t size = event->data_offset + event->data_size;
242df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    eventMemory = mMemoryDealer->allocate(size);
243df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
244df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        eventMemory.clear();
245df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return eventMemory;
246df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
247df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    memcpy(eventMemory->pointer(), event, size);
248df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
249df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return eventMemory;
250df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
251df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
252df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event,
253df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                 Module *module)
254df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent {
255df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     AutoMutex lock(mServiceLock);
256df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     if (module == NULL) {
257df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         return;
258df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     }
259df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     sp<IMemory> eventMemory = prepareRecognitionEvent_l(event);
260df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     if (eventMemory == 0) {
261df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         return;
262df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     }
263df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     sp<Module> strongModule;
264df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     for (size_t i = 0; i < mModules.size(); i++) {
265df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         if (mModules.valueAt(i).get() == module) {
266df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent             strongModule = mModules.valueAt(i);
267df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent             break;
268df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         }
269df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     }
270df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     if (strongModule == 0) {
271df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         return;
272df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     }
273df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
274e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
275e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                        eventMemory);
276e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    callbackEvent->setModule(strongModule);
277e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sendCallbackEvent_l(callbackEvent);
278b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
279b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
280df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent// static
281df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event,
282df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                               void *cookie)
283df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
284df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    Module *module = (Module *)cookie;
285df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (module == NULL) {
286df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
287df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
288df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<SoundTriggerHwService> service = module->service().promote();
289df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (service == 0) {
290df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
291df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
292df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
293df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    service->sendSoundModelEvent(event, module);
294df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
295b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
296df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentsp<IMemory> SoundTriggerHwService::prepareSoundModelEvent_l(struct sound_trigger_model_event *event)
297b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
298df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory;
299df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
300df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    size_t size = event->data_offset + event->data_size;
301df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    eventMemory = mMemoryDealer->allocate(size);
302df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
303df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        eventMemory.clear();
304df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return eventMemory;
305df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
306df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    memcpy(eventMemory->pointer(), event, size);
307df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
308df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return eventMemory;
309b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
310b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
311df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event,
312df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                Module *module)
313b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
314df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    AutoMutex lock(mServiceLock);
315df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory = prepareSoundModelEvent_l(event);
316df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0) {
317df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
318df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
319df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<Module> strongModule;
320df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    for (size_t i = 0; i < mModules.size(); i++) {
321df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (mModules.valueAt(i).get() == module) {
322df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            strongModule = mModules.valueAt(i);
323df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            break;
324df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
325df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
326df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (strongModule == 0) {
327df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
328df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
329e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL,
330e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                        eventMemory);
331e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    callbackEvent->setModule(strongModule);
332e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sendCallbackEvent_l(callbackEvent);
333df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
334df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
335df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
336df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentsp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
337df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
338df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory;
339df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
340df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    size_t size = sizeof(sound_trigger_service_state_t);
341df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    eventMemory = mMemoryDealer->allocate(size);
342df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
343df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        eventMemory.clear();
344df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return eventMemory;
345df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
346df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    *((sound_trigger_service_state_t *)eventMemory->pointer()) = state;
347df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return eventMemory;
348df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
349df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
350df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent// call with mServiceLock held
351df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
352df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                  Module *module)
353df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
354df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
355df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0) {
356df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
357df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
358df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<Module> strongModule;
359df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    for (size_t i = 0; i < mModules.size(); i++) {
360df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (mModules.valueAt(i).get() == module) {
361df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            strongModule = mModules.valueAt(i);
362df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            break;
363df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
364df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
365df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (strongModule == 0) {
366df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
367df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
368e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
369e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                        eventMemory);
370e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    callbackEvent->setModule(strongModule);
371e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sendCallbackEvent_l(callbackEvent);
372e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
373e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
374e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgevoid SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
375e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                    ModuleClient *moduleClient)
376e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
377e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
378e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (eventMemory == 0) {
379e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return;
380e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
381e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
382e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                        eventMemory);
383e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    callbackEvent->setModuleClient(moduleClient);
384e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sendCallbackEvent_l(callbackEvent);
385df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
386df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
387df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent// call with mServiceLock held
388df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event)
389df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
390df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    mCallbackThread->sendCallbackEvent(event);
391df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
392df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
393df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event)
394df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
395df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    ALOGV("onCallbackEvent");
396b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Module> module;
397e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<ModuleClient> moduleClient;
398b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    {
399b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        AutoMutex lock(mServiceLock);
400e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        //CallbackEvent is either for Module or ModuleClient
401b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        module = event->mModule.promote();
402b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (module == 0) {
403e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            moduleClient = event->mModuleClient.promote();
404e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            if (moduleClient == 0) {
405e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                return;
406e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            }
407b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
408b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
409e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (module != 0) {
410e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        ALOGV("onCallbackEvent for module");
411e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        module->onCallbackEvent(event);
412e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    } else if (moduleClient != 0) {
413e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        ALOGV("onCallbackEvent for moduleClient");
414e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        moduleClient->onCallbackEvent(event);
415e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
416df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    {
417df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        AutoMutex lock(mServiceLock);
418df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        // clear now to execute with mServiceLock locked
419df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        event->mMemory.clear();
420df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
421b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
422b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
423b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#undef LOG_TAG
424b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define LOG_TAG "SoundTriggerHwService::CallbackThread"
425b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
426b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
427b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    : mService(service)
428b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
429b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
430b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
431b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::CallbackThread::~CallbackThread()
432b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
433df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    while (!mEventQueue.isEmpty()) {
434df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        mEventQueue[0]->mMemory.clear();
435df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        mEventQueue.removeAt(0);
436df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
437b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
438b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
439b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::CallbackThread::onFirstRef()
440b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
441b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
442b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
443b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
444b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentbool SoundTriggerHwService::CallbackThread::threadLoop()
445b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
446b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    while (!exitPending()) {
447df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        sp<CallbackEvent> event;
448b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        sp<SoundTriggerHwService> service;
449b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        {
450b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            Mutex::Autolock _l(mCallbackLock);
451b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            while (mEventQueue.isEmpty() && !exitPending()) {
452b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                ALOGV("CallbackThread::threadLoop() sleep");
453b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                mCallbackCond.wait(mCallbackLock);
454b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                ALOGV("CallbackThread::threadLoop() wake up");
455b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            }
456b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            if (exitPending()) {
457b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                break;
458b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            }
459b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            event = mEventQueue[0];
460b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            mEventQueue.removeAt(0);
461b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            service = mService.promote();
462b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
463b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (service != 0) {
464df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            service->onCallbackEvent(event);
465b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
466b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
467b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return false;
468b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
469b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
470b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::CallbackThread::exit()
471b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
472b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    Mutex::Autolock _l(mCallbackLock);
473b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    requestExit();
474b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mCallbackCond.broadcast();
475b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
476b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
477df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::CallbackThread::sendCallbackEvent(
478df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                        const sp<SoundTriggerHwService::CallbackEvent>& event)
479b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
480b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mCallbackLock);
481b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mEventQueue.add(event);
482b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mCallbackCond.signal();
483b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
484b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
485e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew GeorgeSoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory)
486e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    : mType(type), mMemory(memory)
487b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
488b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
489b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
490df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric LaurentSoundTriggerHwService::CallbackEvent::~CallbackEvent()
491b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
492b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
493b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
494df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
495b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#undef LOG_TAG
496b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define LOG_TAG "SoundTriggerHwService::Module"
497b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
498b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
4997a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent                                      const sp<SoundTriggerHalInterface>& halInterface,
500e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                      sound_trigger_module_descriptor descriptor)
5017a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent : mService(service), mHalInterface(halInterface), mDescriptor(descriptor),
502e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George   mServiceState(SOUND_TRIGGER_STATE_NO_INIT)
503b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
504b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
505b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
506b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::Module::~Module() {
507e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    mModuleClients.clear();
508b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
509b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
510e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgesp<SoundTriggerHwService::ModuleClient>
511e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew GeorgeSoundTriggerHwService::Module::addClient(const sp<ISoundTriggerClient>& client)
512e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
513e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    AutoMutex lock(mLock);
514e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<ModuleClient> moduleClient;
515e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
516e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    for (size_t i = 0; i < mModuleClients.size(); i++) {
517e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        if (mModuleClients[i]->client() == client) {
518e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            // Client already present, reuse client
519e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            return moduleClient;
520e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        }
521e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
522e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    moduleClient = new ModuleClient(this, client);
523e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
524e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("addClient() client %p", moduleClient.get());
525e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    mModuleClients.add(moduleClient);
526e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
527e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    return moduleClient;
528e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
529e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
530e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgevoid SoundTriggerHwService::Module::detach(const sp<ModuleClient>& moduleClient)
531e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
532e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("Module::detach()");
533338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    Vector<audio_session_t> releasedSessions;
534e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
535338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    {
536338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        AutoMutex lock(mLock);
537338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        ssize_t index = -1;
538e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
539338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        for (size_t i = 0; i < mModuleClients.size(); i++) {
540338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent            if (mModuleClients[i] == moduleClient) {
541338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent                index = i;
542338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent                break;
543338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent            }
544338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        }
545338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        if (index == -1) {
546338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent            return;
547338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        }
548e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
549338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        ALOGV("remove client %p", moduleClient.get());
550338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        mModuleClients.removeAt(index);
551338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent
552338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        // Iterate in reverse order as models are removed from list inside the loop.
553338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        for (size_t i = mModels.size(); i > 0; i--) {
554338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent            sp<Model> model = mModels.valueAt(i - 1);
555338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent            if (moduleClient == model->mModuleClient) {
556338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent                mModels.removeItemsAt(i - 1);
557338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent                ALOGV("detach() unloading model %d", model->mHandle);
558338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent                if (mHalInterface != 0) {
559338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent                    if (model->mState == Model::STATE_ACTIVE) {
560338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent                        mHalInterface->stopRecognition(model->mHandle);
561338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent                    }
562338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent                    mHalInterface->unloadSoundModel(model->mHandle);
5637a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent                }
564338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent                releasedSessions.add(model->mCaptureSession);
565b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            }
566b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
567b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
568338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent
569338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    for (size_t i = 0; i < releasedSessions.size(); i++) {
570338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        // do not call AudioSystem methods with mLock held
571338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        AudioSystem::releaseSoundTriggerSession(releasedSessions[i]);
572338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    }
573b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
574b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
575b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
576e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                       sp<ModuleClient> moduleClient,
577e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                       sound_model_handle_t *handle)
578b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
579b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("loadSoundModel() handle");
5807a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    if (mHalInterface == 0) {
5817a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent        return NO_INIT;
5827a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    }
583b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (modelMemory == 0 || modelMemory->pointer() == NULL) {
584b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()");
585b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
586b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
587b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    struct sound_trigger_sound_model *sound_model =
588b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            (struct sound_trigger_sound_model *)modelMemory->pointer();
589b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
590bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    size_t structSize;
591bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
592bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        structSize = sizeof(struct sound_trigger_phrase_sound_model);
593bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    } else {
594bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        structSize = sizeof(struct sound_trigger_sound_model);
595bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    }
596bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent
597bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    if (sound_model->data_offset < structSize ||
598bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent           sound_model->data_size > (UINT_MAX - sound_model->data_offset) ||
599bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent           modelMemory->size() < sound_model->data_offset ||
600bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent           sound_model->data_size > (modelMemory->size() - sound_model->data_offset)) {
601bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        android_errorWriteLog(0x534e4554, "30148546");
602bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        ALOGE("loadSoundModel() data_size is too big");
603bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        return BAD_VALUE;
604bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    }
605bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent
606df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    audio_session_t session;
607df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    audio_io_handle_t ioHandle;
608df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    audio_devices_t device;
609338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    // do not call AudioSystem methods with mLock held
610338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    status_t status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
611df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (status != NO_ERROR) {
612df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return status;
613b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
614b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
615338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    {
616338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        AutoMutex lock(mLock);
617338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent
618338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        if (mModels.size() >= mDescriptor.properties.max_sound_models) {
619338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent            ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded",
620338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent                  mDescriptor.properties.max_sound_models);
621338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent            status = INVALID_OPERATION;
622338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent            goto exit;
623338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        }
624df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
625338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        status = mHalInterface->loadSoundModel(sound_model,
626338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent                                                      SoundTriggerHwService::soundModelCallback,
627338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent                                                      this, handle);
628338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        if (status != NO_ERROR) {
629338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent            goto exit;
630338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        }
631338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent
632338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type,
633338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent                                    moduleClient);
634338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        mModels.replaceValueFor(*handle, model);
635338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    }
636338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurentexit:
637338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    if (status != NO_ERROR) {
638338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        // do not call AudioSystem methods with mLock held
639338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        AudioSystem::releaseSoundTriggerSession(session);
640338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    }
641b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return status;
642b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
643b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
644b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
645b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
646b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("unloadSoundModel() model handle %d", handle);
647338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    status_t status;
648338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    audio_session_t session;
64902eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent
650338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    {
651338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        AutoMutex lock(mLock);
652338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        if (mHalInterface == 0) {
653338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent            return NO_INIT;
654338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        }
655338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        ssize_t index = mModels.indexOfKey(handle);
656338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        if (index < 0) {
657338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent            return BAD_VALUE;
658338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        }
659338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        sp<Model> model = mModels.valueAt(index);
660338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        mModels.removeItem(handle);
661338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        if (model->mState == Model::STATE_ACTIVE) {
662338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent            mHalInterface->stopRecognition(model->mHandle);
663338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent            model->mState = Model::STATE_IDLE;
664338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        }
665338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        status = mHalInterface->unloadSoundModel(handle);
666338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent        session = model->mCaptureSession;
6671a1cba8f9a93db188b09d9754987354029129113Eric Laurent    }
668338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    // do not call AudioSystem methods with mLock held
669338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    AudioSystem::releaseSoundTriggerSession(session);
670338e8ba374432cc4ee853f4fcefcf7bd7bae3bb9Eric Laurent    return status;
671b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
672b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
673b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
6740832b2d7d190f4fbe6f134446b2610df0cccdbbbEric Laurent                                 const sp<IMemory>& dataMemory)
675b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
676b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("startRecognition() model handle %d", handle);
6777a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    if (mHalInterface == 0) {
6787a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent        return NO_INIT;
6797a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    }
680bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    if (dataMemory == 0 || dataMemory->pointer() == NULL) {
681bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        ALOGE("startRecognition() dataMemory is 0 or has NULL pointer()");
682b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
683b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
684b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
685bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent
686bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    struct sound_trigger_recognition_config *config =
687bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent            (struct sound_trigger_recognition_config *)dataMemory->pointer();
688bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent
689bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    if (config->data_offset < sizeof(struct sound_trigger_recognition_config) ||
690bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent            config->data_size > (UINT_MAX - config->data_offset) ||
691bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent            dataMemory->size() < config->data_offset ||
692bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent            config->data_size > (dataMemory->size() - config->data_offset)) {
693bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        ALOGE("startRecognition() data_size is too big");
694bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent        return BAD_VALUE;
695bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent    }
696bb00d8f139ff51336ab3c810d35685003949bcf8Eric Laurent
697b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
698df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
699df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return INVALID_OPERATION;
700df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
701b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model = getModel(handle);
702b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model == 0) {
703b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
704b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
705b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
706b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model->mState == Model::STATE_ACTIVE) {
707b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return INVALID_OPERATION;
708b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
709b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
710b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
711b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    //TODO: get capture handle and device from audio policy service
712df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    config->capture_handle = model->mCaptureIOHandle;
713df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    config->capture_device = model->mCaptureDevice;
7147a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    status_t status = mHalInterface->startRecognition(handle, config,
715b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                        SoundTriggerHwService::recognitionCallback,
7160832b2d7d190f4fbe6f134446b2610df0cccdbbbEric Laurent                                        this);
717df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
718df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (status == NO_ERROR) {
719df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        model->mState = Model::STATE_ACTIVE;
720df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        model->mConfig = *config;
721df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
722df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
723df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return status;
724b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
725b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
726b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
727b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
728b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("stopRecognition() model handle %d", handle);
7297a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    if (mHalInterface == 0) {
7307a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent        return NO_INIT;
7317a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    }
732b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
733b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model = getModel(handle);
734b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model == 0) {
735b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
736b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
737b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
738b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model->mState != Model::STATE_ACTIVE) {
739b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return INVALID_OPERATION;
740b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
7417a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent    mHalInterface->stopRecognition(handle);
742b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    model->mState = Model::STATE_IDLE;
743b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
744b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
745b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
746df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
747b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
748df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    ALOGV("onCallbackEvent type %d", event->mType);
749b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
750df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory = event->mMemory;
751b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
752b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
753b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
754b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
755e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (mModuleClients.isEmpty()) {
756e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        ALOGI("%s no clients", __func__);
757b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
758b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
759df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
760df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    switch (event->mType) {
761df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case CallbackEvent::TYPE_RECOGNITION: {
762df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        struct sound_trigger_recognition_event *recognitionEvent =
763df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                (struct sound_trigger_recognition_event *)eventMemory->pointer();
764886561f06ddaea86a51def1e918367430240b5acEric Laurent        sp<ISoundTriggerClient> client;
765886561f06ddaea86a51def1e918367430240b5acEric Laurent        {
766886561f06ddaea86a51def1e918367430240b5acEric Laurent            AutoMutex lock(mLock);
767886561f06ddaea86a51def1e918367430240b5acEric Laurent            sp<Model> model = getModel(recognitionEvent->model);
768886561f06ddaea86a51def1e918367430240b5acEric Laurent            if (model == 0) {
769886561f06ddaea86a51def1e918367430240b5acEric Laurent                ALOGW("%s model == 0", __func__);
770886561f06ddaea86a51def1e918367430240b5acEric Laurent                return;
771886561f06ddaea86a51def1e918367430240b5acEric Laurent            }
772886561f06ddaea86a51def1e918367430240b5acEric Laurent            if (model->mState != Model::STATE_ACTIVE) {
773886561f06ddaea86a51def1e918367430240b5acEric Laurent                ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
774886561f06ddaea86a51def1e918367430240b5acEric Laurent                return;
775886561f06ddaea86a51def1e918367430240b5acEric Laurent            }
776df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
777886561f06ddaea86a51def1e918367430240b5acEric Laurent            recognitionEvent->capture_session = model->mCaptureSession;
778886561f06ddaea86a51def1e918367430240b5acEric Laurent            model->mState = Model::STATE_IDLE;
779e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            client = model->mModuleClient->client();
780df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
781886561f06ddaea86a51def1e918367430240b5acEric Laurent        if (client != 0) {
782886561f06ddaea86a51def1e918367430240b5acEric Laurent            client->onRecognitionEvent(eventMemory);
783df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
784df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    } break;
785df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case CallbackEvent::TYPE_SOUNDMODEL: {
786df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        struct sound_trigger_model_event *soundmodelEvent =
787df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                (struct sound_trigger_model_event *)eventMemory->pointer();
788886561f06ddaea86a51def1e918367430240b5acEric Laurent        sp<ISoundTriggerClient> client;
789886561f06ddaea86a51def1e918367430240b5acEric Laurent        {
790886561f06ddaea86a51def1e918367430240b5acEric Laurent            AutoMutex lock(mLock);
791886561f06ddaea86a51def1e918367430240b5acEric Laurent            sp<Model> model = getModel(soundmodelEvent->model);
792886561f06ddaea86a51def1e918367430240b5acEric Laurent            if (model == 0) {
793886561f06ddaea86a51def1e918367430240b5acEric Laurent                ALOGW("%s model == 0", __func__);
794886561f06ddaea86a51def1e918367430240b5acEric Laurent                return;
795886561f06ddaea86a51def1e918367430240b5acEric Laurent            }
796e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            client = model->mModuleClient->client();
797886561f06ddaea86a51def1e918367430240b5acEric Laurent        }
798886561f06ddaea86a51def1e918367430240b5acEric Laurent        if (client != 0) {
799886561f06ddaea86a51def1e918367430240b5acEric Laurent            client->onSoundModelEvent(eventMemory);
800df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
801df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    } break;
802df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case CallbackEvent::TYPE_SERVICE_STATE: {
803e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        Vector< sp<ISoundTriggerClient> > clients;
804886561f06ddaea86a51def1e918367430240b5acEric Laurent        {
805886561f06ddaea86a51def1e918367430240b5acEric Laurent            AutoMutex lock(mLock);
806e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            for (size_t i = 0; i < mModuleClients.size(); i++) {
807e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                if (mModuleClients[i] != 0) {
808e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                    clients.add(mModuleClients[i]->client());
809e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                }
810e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            }
811886561f06ddaea86a51def1e918367430240b5acEric Laurent        }
812e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        for (size_t i = 0; i < clients.size(); i++) {
813e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            clients[i]->onServiceStateChange(eventMemory);
814886561f06ddaea86a51def1e918367430240b5acEric Laurent        }
815df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    } break;
816df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    default:
817df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
818df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
819b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
820b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
821b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentsp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
822b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        sound_model_handle_t handle)
823b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
824b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model;
825b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ssize_t index = mModels.indexOfKey(handle);
826b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (index >= 0) {
827b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        model = mModels.valueAt(index);
828b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
829b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return model;
830b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
831b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
832df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent// Called with mServiceLock held
833df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::Module::setCaptureState_l(bool active)
834b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
835df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    ALOGV("Module::setCaptureState_l %d", active);
836df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<SoundTriggerHwService> service;
837df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sound_trigger_service_state_t state;
838b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
839df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    Vector< sp<IMemory> > events;
840df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    {
841df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        AutoMutex lock(mLock);
842df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        state = (active && !mDescriptor.properties.concurrent_capture) ?
843df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                        SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
844b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
845df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (state == mServiceState) {
846df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            return;
847df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
848b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
849df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        mServiceState = state;
850df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
851df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        service = mService.promote();
852df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (service == 0) {
853df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            return;
854df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
855df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
856df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (state == SOUND_TRIGGER_STATE_ENABLED) {
857df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            goto exit;
858df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
859df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
860efcf16c9fd2a2f0d865a2bcca98527d3804f83d6Chris Thornton        const bool supports_stop_all =
861de22f8acdc8e3adf94a9770b867b355e3ca88f62Chris Thornton                (mHalInterface != 0) && (mHalInterface->stopAllRecognitions() != -ENOSYS);
862efcf16c9fd2a2f0d865a2bcca98527d3804f83d6Chris Thornton
863df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        for (size_t i = 0; i < mModels.size(); i++) {
864df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            sp<Model> model = mModels.valueAt(i);
865df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            if (model->mState == Model::STATE_ACTIVE) {
8667a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent                if (mHalInterface != 0 && !supports_stop_all) {
8677a544b44b7872b300f50e16fef480f76e9145fbbEric Laurent                    mHalInterface->stopRecognition(model->mHandle);
868efcf16c9fd2a2f0d865a2bcca98527d3804f83d6Chris Thornton                }
869df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                // keep model in ACTIVE state so that event is processed by onCallbackEvent()
87000a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                if (model->mType == SOUND_MODEL_TYPE_KEYPHRASE) {
87100a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    struct sound_trigger_phrase_recognition_event event;
87200a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
87300a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.num_phrases = model->mConfig.num_phrases;
87400a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    for (size_t i = 0; i < event.num_phrases; i++) {
87500a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                        event.phrase_extras[i] = model->mConfig.phrases[i];
876df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    }
87700a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.status = RECOGNITION_STATUS_ABORT;
87800a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.type = model->mType;
87900a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.model = model->mHandle;
88000a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.data_size = 0;
88100a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
88200a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    if (eventMemory != 0) {
88300a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                        events.add(eventMemory);
88400a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    }
88500a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                } else if (model->mType == SOUND_MODEL_TYPE_GENERIC) {
88600a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    struct sound_trigger_generic_recognition_event event;
88700a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    memset(&event, 0, sizeof(struct sound_trigger_generic_recognition_event));
88800a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.status = RECOGNITION_STATUS_ABORT;
88900a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.type = model->mType;
89000a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.model = model->mHandle;
89100a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    event.common.data_size = 0;
89200a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
89300a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    if (eventMemory != 0) {
89400a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                        events.add(eventMemory);
8959609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    }
8969609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                } else if (model->mType == SOUND_MODEL_TYPE_UNKNOWN) {
8979609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    struct sound_trigger_phrase_recognition_event event;
8989609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event));
8999609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    event.common.status = RECOGNITION_STATUS_ABORT;
9009609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    event.common.type = model->mType;
9019609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    event.common.model = model->mHandle;
9029609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    event.common.data_size = 0;
9039609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common);
9049609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                    if (eventMemory != 0) {
9059609a91f8560622735f6725f7f597be47a8e2f5fRyan Bavetta                        events.add(eventMemory);
90600a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    }
90700a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                } else {
90800a727c430c474f77f8835675a9d773f0314fb68Ryan Bavetta                    goto exit;
909df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                }
910df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            }
911df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
912b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
913df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
914df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    for (size_t i = 0; i < events.size(); i++) {
915e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        sp<CallbackEvent> callbackEvent = new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
916e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                            events[i]);
917e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        callbackEvent->setModule(this);
918e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        service->sendCallbackEvent_l(callbackEvent);
919df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
920df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
921df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentexit:
922df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    service->sendServiceStateEvent_l(state, this);
923b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
924b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
925df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
926df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric LaurentSoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
927df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                    audio_io_handle_t ioHandle, audio_devices_t device,
928e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                    sound_trigger_sound_model_type_t type,
929e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                    sp<ModuleClient>& moduleClient) :
930df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
931e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type),
932e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    mModuleClient(moduleClient)
933e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
934e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
935e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
936e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George#undef LOG_TAG
937e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George#define LOG_TAG "SoundTriggerHwService::ModuleClient"
938e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
939e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew GeorgeSoundTriggerHwService::ModuleClient::ModuleClient(const sp<Module>& module,
940e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                  const sp<ISoundTriggerClient>& client)
941e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George : mModule(module), mClient(client)
942b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
943e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
944df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
945e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgevoid SoundTriggerHwService::ModuleClient::onFirstRef()
946e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
947c8a9f4ad35f24ac59645bb262bd8f16fd4f6f0d8Chris Thornton    sp<IBinder> binder = IInterface::asBinder(mClient);
948c8a9f4ad35f24ac59645bb262bd8f16fd4f6f0d8Chris Thornton    if (binder != 0) {
949c8a9f4ad35f24ac59645bb262bd8f16fd4f6f0d8Chris Thornton        binder->linkToDeath(this);
950c8a9f4ad35f24ac59645bb262bd8f16fd4f6f0d8Chris Thornton    }
951b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
952b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
953e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew GeorgeSoundTriggerHwService::ModuleClient::~ModuleClient()
954e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
955e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
956e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
957e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgestatus_t SoundTriggerHwService::ModuleClient::dump(int fd __unused,
958e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                                   const Vector<String16>& args __unused) {
959b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    String8 result;
960b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
961b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
962b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
963e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgevoid SoundTriggerHwService::ModuleClient::detach() {
964e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("detach()");
9657504b9eb4561df88550f874cf0ce95b6f4d09927Eric Laurent    if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
9667504b9eb4561df88550f874cf0ce95b6f4d09927Eric Laurent                               IPCThreadState::self()->getCallingUid())) {
967e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return;
968e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
969e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
970e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    {
971e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        AutoMutex lock(mLock);
972e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        if (mClient != 0) {
973e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            IInterface::asBinder(mClient)->unlinkToDeath(this);
974e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            mClient.clear();
975e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        }
976e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
977e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
978e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<Module> module = mModule.promote();
979e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (module == 0) {
980e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return;
981e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
982e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    module->detach(this);
983e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
984e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
985e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgestatus_t SoundTriggerHwService::ModuleClient::loadSoundModel(const sp<IMemory>& modelMemory,
986e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                sound_model_handle_t *handle)
987e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
988e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("loadSoundModel() handle");
9897504b9eb4561df88550f874cf0ce95b6f4d09927Eric Laurent    if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
9907504b9eb4561df88550f874cf0ce95b6f4d09927Eric Laurent                               IPCThreadState::self()->getCallingUid())) {
991e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return PERMISSION_DENIED;
992e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
993e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
994e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<Module> module = mModule.promote();
995e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (module == 0) {
996e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return NO_INIT;
997e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
998e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    return module->loadSoundModel(modelMemory, this, handle);
999e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
1000e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1001e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgestatus_t SoundTriggerHwService::ModuleClient::unloadSoundModel(sound_model_handle_t handle)
1002e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
1003e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("unloadSoundModel() model handle %d", handle);
10047504b9eb4561df88550f874cf0ce95b6f4d09927Eric Laurent    if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
10057504b9eb4561df88550f874cf0ce95b6f4d09927Eric Laurent                               IPCThreadState::self()->getCallingUid())) {
1006e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return PERMISSION_DENIED;
1007e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1008e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1009e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<Module> module = mModule.promote();
1010e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (module == 0) {
1011e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return NO_INIT;
1012e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1013e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    return module->unloadSoundModel(handle);
1014e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
1015e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1016e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgestatus_t SoundTriggerHwService::ModuleClient::startRecognition(sound_model_handle_t handle,
1017e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                 const sp<IMemory>& dataMemory)
1018e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
1019e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("startRecognition() model handle %d", handle);
10207504b9eb4561df88550f874cf0ce95b6f4d09927Eric Laurent    if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
10217504b9eb4561df88550f874cf0ce95b6f4d09927Eric Laurent                               IPCThreadState::self()->getCallingUid())) {
1022e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return PERMISSION_DENIED;
1023e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1024e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1025e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<Module> module = mModule.promote();
1026e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (module == 0) {
1027e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return NO_INIT;
1028e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1029e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    return module->startRecognition(handle, dataMemory);
1030e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
1031e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1032e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgestatus_t SoundTriggerHwService::ModuleClient::stopRecognition(sound_model_handle_t handle)
1033e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
1034e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("stopRecognition() model handle %d", handle);
10357504b9eb4561df88550f874cf0ce95b6f4d09927Eric Laurent    if (!captureHotwordAllowed(IPCThreadState::self()->getCallingPid(),
10367504b9eb4561df88550f874cf0ce95b6f4d09927Eric Laurent                               IPCThreadState::self()->getCallingUid())) {
1037e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return PERMISSION_DENIED;
1038e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1039e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1040e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<Module> module = mModule.promote();
1041e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (module == 0) {
1042e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return NO_INIT;
1043e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1044e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    return module->stopRecognition(handle);
1045e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
1046e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1047e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgevoid SoundTriggerHwService::ModuleClient::setCaptureState_l(bool active)
1048e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
1049e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("ModuleClient::setCaptureState_l %d", active);
1050e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<SoundTriggerHwService> service;
1051e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sound_trigger_service_state_t state;
1052e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1053e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<Module> module = mModule.promote();
1054e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (module == 0) {
1055e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return;
1056e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1057e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    {
1058e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        AutoMutex lock(mLock);
1059e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        state = (active && !module->isConcurrentCaptureAllowed()) ?
1060e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George                                        SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
1061e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1062e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        service = module->service().promote();
1063e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        if (service == 0) {
1064e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            return;
1065e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        }
1066e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1067e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    service->sendServiceStateEvent_l(state, this);
1068e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
1069e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1070e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgevoid SoundTriggerHwService::ModuleClient::onCallbackEvent(const sp<CallbackEvent>& event)
1071e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George{
1072e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGV("ModuleClient onCallbackEvent type %d", event->mType);
1073e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1074e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    sp<IMemory> eventMemory = event->mMemory;
1075e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1076e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
1077e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        return;
1078e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1079e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1080e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    switch (event->mType) {
1081e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    case CallbackEvent::TYPE_SERVICE_STATE: {
1082e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        sp<ISoundTriggerClient> client;
1083e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        {
1084e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            AutoMutex lock(mLock);
1085e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            client = mClient;
1086e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        }
1087e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        if (client !=0 ) {
1088e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George            client->onServiceStateChange(eventMemory);
1089e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        }
1090e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    } break;
1091e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    default:
1092e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George        LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
1093e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    }
1094e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
1095e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1096e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew Georgevoid SoundTriggerHwService::ModuleClient::binderDied(
1097e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    const wp<IBinder> &who __unused) {
1098e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    ALOGW("client binder died for client %p", this);
1099e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George    detach();
1100e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George}
1101e52c500c096fce010c99e92c4fc3ef51832e67c6Haynes Mathew George
1102b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}; // namespace android
1103