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>
35936c84a5b743dce2a2572fdf54b37b187bc88b60Eric Laurent#include <hardware/sound_trigger.h>
368ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent#include <ServiceUtilities.h>
378ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent#include "SoundTriggerHwService.h"
38b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
39b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentnamespace android {
40b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
41b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#ifdef SOUND_TRIGGER_USE_STUB_MODULE
42b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define HW_MODULE_PREFIX "stub"
43b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#else
44b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define HW_MODULE_PREFIX "primary"
45b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#endif
46b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
47b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::SoundTriggerHwService()
48b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    : BnSoundTriggerHwService(),
49df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent      mNextUniqueId(1),
50df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent      mMemoryDealer(new MemoryDealer(1024 * 1024, "SoundTriggerHwService")),
51df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent      mCaptureState(false)
52b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
53b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
54b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
55b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::onFirstRef()
56b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
57b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    const hw_module_t *mod;
58b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    int rc;
59b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sound_trigger_hw_device *dev;
60b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
61b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, HW_MODULE_PREFIX, &mod);
62b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (rc != 0) {
63b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("couldn't load sound trigger module %s.%s (%s)",
64b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent              SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", strerror(-rc));
65b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
66b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
67b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    rc = sound_trigger_hw_device_open(mod, &dev);
68b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (rc != 0) {
69b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("couldn't open sound trigger hw device in %s.%s (%s)",
70b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent              SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", strerror(-rc));
71b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
72b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
73b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (dev->common.version != SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
74b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("wrong sound trigger hw device version %04x", dev->common.version);
75b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
76b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
77b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
78b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sound_trigger_module_descriptor descriptor;
79b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    rc = dev->get_properties(dev, &descriptor.properties);
80b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (rc != 0) {
81b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("could not read implementation properties");
82b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
83b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
84b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    descriptor.handle =
85b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            (sound_trigger_module_handle_t)android_atomic_inc(&mNextUniqueId);
86b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGI("loaded default module %s, handle %d", descriptor.properties.description,
87b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                 descriptor.handle);
88b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
89b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<ISoundTriggerClient> client;
90b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Module> module = new Module(this, dev, descriptor, client);
91b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mModules.add(descriptor.handle, module);
92b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mCallbackThread = new CallbackThread(this);
93b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
94b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
95b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::~SoundTriggerHwService()
96b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
97b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (mCallbackThread != 0) {
98b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        mCallbackThread->exit();
99b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
100b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    for (size_t i = 0; i < mModules.size(); i++) {
101b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        sound_trigger_hw_device_close(mModules.valueAt(i)->hwDevice());
102b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
103b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
104b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
105b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::listModules(struct sound_trigger_module_descriptor *modules,
106b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                             uint32_t *numModules)
107b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
108b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("listModules");
1098ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    if (!captureHotwordAllowed()) {
1108ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent        return PERMISSION_DENIED;
1118ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    }
1128ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent
113b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mServiceLock);
114b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
115b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
116b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
117b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    size_t maxModules = *numModules;
118b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    *numModules = mModules.size();
119b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
120b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        modules[i] = mModules.valueAt(i)->descriptor();
121b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
122b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
123b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
124b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
125b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::attach(const sound_trigger_module_handle_t handle,
126b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        const sp<ISoundTriggerClient>& client,
127b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        sp<ISoundTrigger>& moduleInterface)
128b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
129b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("attach module %d", handle);
1308ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    if (!captureHotwordAllowed()) {
1318ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent        return PERMISSION_DENIED;
1328ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    }
1338ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent
134b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mServiceLock);
135b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    moduleInterface.clear();
136b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (client == 0) {
137b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
138b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
139b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ssize_t index = mModules.indexOfKey(handle);
140b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (index < 0) {
141b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
142b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
143b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Module> module = mModules.valueAt(index);
144b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
145b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    module->setClient(client);
146b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    client->asBinder()->linkToDeath(module);
147b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    moduleInterface = module;
148b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
149df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    module->setCaptureState_l(mCaptureState);
150df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
151b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
152b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
153b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
154df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentstatus_t SoundTriggerHwService::setCaptureState(bool active)
155df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
156df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    ALOGV("setCaptureState %d", active);
157df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    AutoMutex lock(mServiceLock);
158df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    mCaptureState = active;
159df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    for (size_t i = 0; i < mModules.size(); i++) {
160df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        mModules.valueAt(i)->setCaptureState_l(active);
161df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
162df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return NO_ERROR;
163df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
164df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
165df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
166df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::detachModule(sp<Module> module)
167df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
168936c84a5b743dce2a2572fdf54b37b187bc88b60Eric Laurent    ALOGV("detachModule");
1698ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    AutoMutex lock(mServiceLock);
170b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    module->clearClient();
171b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
172b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
173df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
174b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatic const int kDumpLockRetries = 50;
175b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatic const int kDumpLockSleep = 60000;
176b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
177b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatic bool tryLock(Mutex& mutex)
178b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
179b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    bool locked = false;
180b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    for (int i = 0; i < kDumpLockRetries; ++i) {
181b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (mutex.tryLock() == NO_ERROR) {
182b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            locked = true;
183b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            break;
184b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
185b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        usleep(kDumpLockSleep);
186b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
187b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return locked;
188b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
189b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
190b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::dump(int fd, const Vector<String16>& args __unused) {
191b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    String8 result;
192b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
193b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        result.appendFormat("Permission Denial: can't dump SoundTriggerHwService");
194b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        write(fd, result.string(), result.size());
195b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    } else {
196b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        bool locked = tryLock(mServiceLock);
197b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        // failed to lock - SoundTriggerHwService is probably deadlocked
198b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (!locked) {
199b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            result.append("SoundTriggerHwService may be deadlocked\n");
200b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            write(fd, result.string(), result.size());
201b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
202b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
203b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (locked) mServiceLock.unlock();
204b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
205b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
206b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
207b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
208b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::onTransact(
209b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
210b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return BnSoundTriggerHwService::onTransact(code, data, reply, flags);
211b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
212b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
213b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
214b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent// static
215b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition_event *event,
216b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                void *cookie)
217b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
218b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    Module *module = (Module *)cookie;
219b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (module == NULL) {
220b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
221b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
222df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<SoundTriggerHwService> service = module->service().promote();
223df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (service == 0) {
224df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
225df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
226df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
227df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    service->sendRecognitionEvent(event, module);
228df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
229df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
230df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentsp<IMemory> SoundTriggerHwService::prepareRecognitionEvent_l(
231df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                    struct sound_trigger_recognition_event *event)
232df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
233df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory;
234df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
235df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    //sanitize event
236df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    switch (event->type) {
237df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case SOUND_MODEL_TYPE_KEYPHRASE:
238df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        ALOGW_IF(event->data_size != 0 && event->data_offset !=
239df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    sizeof(struct sound_trigger_phrase_recognition_event),
240df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    "prepareRecognitionEvent_l(): invalid data offset %u for keyphrase event type",
241df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    event->data_offset);
242df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
243df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        break;
244df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case SOUND_MODEL_TYPE_UNKNOWN:
245df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        ALOGW_IF(event->data_size != 0 && event->data_offset !=
246df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    sizeof(struct sound_trigger_recognition_event),
247df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    "prepareRecognitionEvent_l(): invalid data offset %u for unknown event type",
248df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    event->data_offset);
249df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        event->data_offset = sizeof(struct sound_trigger_recognition_event);
250df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        break;
251df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    default:
252886561f06ddaea86a51def1e918367430240b5acEric Laurent        return eventMemory;
253df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
254df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
255df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    size_t size = event->data_offset + event->data_size;
256df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    eventMemory = mMemoryDealer->allocate(size);
257df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
258df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        eventMemory.clear();
259df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return eventMemory;
260df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
261df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    memcpy(eventMemory->pointer(), event, size);
262df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
263df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return eventMemory;
264df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
265df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
266df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event,
267df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                 Module *module)
268df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent {
269df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     AutoMutex lock(mServiceLock);
270df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     if (module == NULL) {
271df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         return;
272df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     }
273df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     sp<IMemory> eventMemory = prepareRecognitionEvent_l(event);
274df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     if (eventMemory == 0) {
275df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         return;
276df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     }
277df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     sp<Module> strongModule;
278df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     for (size_t i = 0; i < mModules.size(); i++) {
279df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         if (mModules.valueAt(i).get() == module) {
280df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent             strongModule = mModules.valueAt(i);
281df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent             break;
282df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         }
283df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     }
284df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     if (strongModule == 0) {
285df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent         return;
286df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     }
287df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
288df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent     sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION,
289df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                  eventMemory, strongModule));
290b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
291b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
292df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent// static
293df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event,
294df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                               void *cookie)
295df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
296df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    Module *module = (Module *)cookie;
297df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (module == NULL) {
298df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
299df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
300df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<SoundTriggerHwService> service = module->service().promote();
301df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (service == 0) {
302df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
303df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
304df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
305df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    service->sendSoundModelEvent(event, module);
306df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
307b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
308df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentsp<IMemory> SoundTriggerHwService::prepareSoundModelEvent_l(struct sound_trigger_model_event *event)
309b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
310df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory;
311df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
312df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    size_t size = event->data_offset + event->data_size;
313df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    eventMemory = mMemoryDealer->allocate(size);
314df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
315df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        eventMemory.clear();
316df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return eventMemory;
317df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
318df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    memcpy(eventMemory->pointer(), event, size);
319df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
320df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return eventMemory;
321b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
322b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
323df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event,
324df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                Module *module)
325b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
326df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    AutoMutex lock(mServiceLock);
327df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory = prepareSoundModelEvent_l(event);
328df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0) {
329df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
330df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
331df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<Module> strongModule;
332df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    for (size_t i = 0; i < mModules.size(); i++) {
333df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (mModules.valueAt(i).get() == module) {
334df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            strongModule = mModules.valueAt(i);
335df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            break;
336df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
337df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
338df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (strongModule == 0) {
339df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
340df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
341df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL,
342df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                 eventMemory, strongModule));
343df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
344df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
345df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
346df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentsp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state)
347df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
348df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory;
349df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
350df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    size_t size = sizeof(sound_trigger_service_state_t);
351df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    eventMemory = mMemoryDealer->allocate(size);
352df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
353df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        eventMemory.clear();
354df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return eventMemory;
355df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
356df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    *((sound_trigger_service_state_t *)eventMemory->pointer()) = state;
357df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return eventMemory;
358df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
359df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
360df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent// call with mServiceLock held
361df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state,
362df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                  Module *module)
363df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
364df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory = prepareServiceStateEvent_l(state);
365df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (eventMemory == 0) {
366df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
367df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
368df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<Module> strongModule;
369df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    for (size_t i = 0; i < mModules.size(); i++) {
370df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (mModules.valueAt(i).get() == module) {
371df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            strongModule = mModules.valueAt(i);
372df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            break;
373df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
374df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
375df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (strongModule == 0) {
376df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return;
377df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
378df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE,
379df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                 eventMemory, strongModule));
380df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
381df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
382df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent// call with mServiceLock held
383df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event)
384df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
385df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    mCallbackThread->sendCallbackEvent(event);
386df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent}
387df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
388df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event)
389df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent{
390df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    ALOGV("onCallbackEvent");
391b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Module> module;
392b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    {
393b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        AutoMutex lock(mServiceLock);
394b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        module = event->mModule.promote();
395b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (module == 0) {
396b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            return;
397b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
398b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
399df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    module->onCallbackEvent(event);
400df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    {
401df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        AutoMutex lock(mServiceLock);
402df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        // clear now to execute with mServiceLock locked
403df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        event->mMemory.clear();
404df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
405b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
406b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
407b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#undef LOG_TAG
408b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define LOG_TAG "SoundTriggerHwService::CallbackThread"
409b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
410b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
411b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    : mService(service)
412b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
413b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
414b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
415b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::CallbackThread::~CallbackThread()
416b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
417df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    while (!mEventQueue.isEmpty()) {
418df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        mEventQueue[0]->mMemory.clear();
419df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        mEventQueue.removeAt(0);
420df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
421b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
422b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
423b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::CallbackThread::onFirstRef()
424b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
425b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
426b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
427b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
428b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentbool SoundTriggerHwService::CallbackThread::threadLoop()
429b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
430b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    while (!exitPending()) {
431df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        sp<CallbackEvent> event;
432b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        sp<SoundTriggerHwService> service;
433b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        {
434b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            Mutex::Autolock _l(mCallbackLock);
435b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            while (mEventQueue.isEmpty() && !exitPending()) {
436b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                ALOGV("CallbackThread::threadLoop() sleep");
437b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                mCallbackCond.wait(mCallbackLock);
438b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                ALOGV("CallbackThread::threadLoop() wake up");
439b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            }
440b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            if (exitPending()) {
441b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                break;
442b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            }
443b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            event = mEventQueue[0];
444b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            mEventQueue.removeAt(0);
445b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            service = mService.promote();
446b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
447b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (service != 0) {
448df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            service->onCallbackEvent(event);
449b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
450b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
451b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return false;
452b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
453b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
454b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::CallbackThread::exit()
455b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
456b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    Mutex::Autolock _l(mCallbackLock);
457b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    requestExit();
458b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mCallbackCond.broadcast();
459b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
460b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
461df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::CallbackThread::sendCallbackEvent(
462df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                        const sp<SoundTriggerHwService::CallbackEvent>& event)
463b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
464b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mCallbackLock);
465b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mEventQueue.add(event);
466b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mCallbackCond.signal();
467b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
468b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
469df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric LaurentSoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory,
470df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                    wp<Module> module)
471df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    : mType(type), mMemory(memory), mModule(module)
472b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
473b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
474b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
475df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric LaurentSoundTriggerHwService::CallbackEvent::~CallbackEvent()
476b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
477b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
478b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
479df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
480b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#undef LOG_TAG
481b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define LOG_TAG "SoundTriggerHwService::Module"
482b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
483b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
484b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                      sound_trigger_hw_device* hwDevice,
485b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                      sound_trigger_module_descriptor descriptor,
486b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                      const sp<ISoundTriggerClient>& client)
487b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent : mService(service), mHwDevice(hwDevice), mDescriptor(descriptor),
488df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent   mClient(client), mServiceState(SOUND_TRIGGER_STATE_NO_INIT)
489b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
490b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
491b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
492b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::Module::~Module() {
493b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
494b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
495b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::Module::detach() {
496b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("detach()");
4978ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    if (!captureHotwordAllowed()) {
4988ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent        return;
4998ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    }
500b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    {
501b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        AutoMutex lock(mLock);
502b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        for (size_t i = 0; i < mModels.size(); i++) {
503b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            sp<Model> model = mModels.valueAt(i);
504b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            ALOGV("detach() unloading model %d", model->mHandle);
505b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            if (model->mState == Model::STATE_ACTIVE) {
506b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                mHwDevice->stop_recognition(mHwDevice, model->mHandle);
507b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            }
508b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            mHwDevice->unload_sound_model(mHwDevice, model->mHandle);
509b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
510b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        mModels.clear();
511b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
512b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (mClient != 0) {
513b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        mClient->asBinder()->unlinkToDeath(this);
514b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
515b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<SoundTriggerHwService> service = mService.promote();
516b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (service == 0) {
517b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
518b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
519b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    service->detachModule(this);
520b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
521b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
522b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
523b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                sound_model_handle_t *handle)
524b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
525b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("loadSoundModel() handle");
5268ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    if (!captureHotwordAllowed()) {
5278ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent        return PERMISSION_DENIED;
5288ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    }
529b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
530b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (modelMemory == 0 || modelMemory->pointer() == NULL) {
531b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()");
532b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
533b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
534b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    struct sound_trigger_sound_model *sound_model =
535b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            (struct sound_trigger_sound_model *)modelMemory->pointer();
536b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
537b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
53802eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent
53902eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent    if (mModels.size() >= mDescriptor.properties.max_sound_models) {
54002eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent        if (mModels.size() == 0) {
54102eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent            return INVALID_OPERATION;
54202eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent        }
54302eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent        ALOGW("loadSoundModel() max number of models exceeded %d making room for a new one",
54402eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent              mDescriptor.properties.max_sound_models);
54502eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent        unloadSoundModel_l(mModels.valueAt(0)->mHandle);
54602eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent    }
54702eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent
548b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    status_t status = mHwDevice->load_sound_model(mHwDevice,
549b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                  sound_model,
550b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                  SoundTriggerHwService::soundModelCallback,
551b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                  this,
552b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                  handle);
553df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (status != NO_ERROR) {
554df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return status;
555df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
556df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    audio_session_t session;
557df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    audio_io_handle_t ioHandle;
558df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    audio_devices_t device;
559df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
560df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device);
561df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (status != NO_ERROR) {
562df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return status;
563b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
564b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
565df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type);
566df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    mModels.replaceValueFor(*handle, model);
567df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
568b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return status;
569b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
570b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
571b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
572b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
573b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("unloadSoundModel() model handle %d", handle);
5748ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    if (!captureHotwordAllowed()) {
5758ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent        return PERMISSION_DENIED;
5768ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    }
577b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
578b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
57902eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent    return unloadSoundModel_l(handle);
58002eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent}
58102eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent
58202eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurentstatus_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle)
58302eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent{
584b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ssize_t index = mModels.indexOfKey(handle);
585b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (index < 0) {
586b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
587b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
5881a1cba8f9a93db188b09d9754987354029129113Eric Laurent    sp<Model> model = mModels.valueAt(index);
589b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mModels.removeItem(handle);
5901a1cba8f9a93db188b09d9754987354029129113Eric Laurent    if (model->mState == Model::STATE_ACTIVE) {
5911a1cba8f9a93db188b09d9754987354029129113Eric Laurent        mHwDevice->stop_recognition(mHwDevice, model->mHandle);
59202eb47cf18793effe9fc7ab34e1b0fe9ea6635bcEric Laurent        model->mState = Model::STATE_IDLE;
5931a1cba8f9a93db188b09d9754987354029129113Eric Laurent    }
594df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    AudioSystem::releaseSoundTriggerSession(model->mCaptureSession);
595b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return mHwDevice->unload_sound_model(mHwDevice, handle);
596b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
597b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
598b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
5990832b2d7d190f4fbe6f134446b2610df0cccdbbbEric Laurent                                 const sp<IMemory>& dataMemory)
600b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
601b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("startRecognition() model handle %d", handle);
6028ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    if (!captureHotwordAllowed()) {
6038ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent        return PERMISSION_DENIED;
6048ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    }
605b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
606b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (dataMemory != 0 && dataMemory->pointer() == NULL) {
607b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("startRecognition() dataMemory is non-0 but has NULL pointer()");
608b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
609b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
610b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
611b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
612df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) {
613df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        return INVALID_OPERATION;
614df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
615b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model = getModel(handle);
616b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model == 0) {
617b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
618b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
6190832b2d7d190f4fbe6f134446b2610df0cccdbbbEric Laurent    if ((dataMemory == 0) ||
6200832b2d7d190f4fbe6f134446b2610df0cccdbbbEric Laurent            (dataMemory->size() < sizeof(struct sound_trigger_recognition_config))) {
6210832b2d7d190f4fbe6f134446b2610df0cccdbbbEric Laurent        return BAD_VALUE;
6220832b2d7d190f4fbe6f134446b2610df0cccdbbbEric Laurent    }
623b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
624b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model->mState == Model::STATE_ACTIVE) {
625b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return INVALID_OPERATION;
626b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
627b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
6280832b2d7d190f4fbe6f134446b2610df0cccdbbbEric Laurent    struct sound_trigger_recognition_config *config =
6290832b2d7d190f4fbe6f134446b2610df0cccdbbbEric Laurent            (struct sound_trigger_recognition_config *)dataMemory->pointer();
630b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
631b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    //TODO: get capture handle and device from audio policy service
632df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    config->capture_handle = model->mCaptureIOHandle;
633df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    config->capture_device = model->mCaptureDevice;
634df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    status_t status = mHwDevice->start_recognition(mHwDevice, handle, config,
635b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                        SoundTriggerHwService::recognitionCallback,
6360832b2d7d190f4fbe6f134446b2610df0cccdbbbEric Laurent                                        this);
637df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
638df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    if (status == NO_ERROR) {
639df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        model->mState = Model::STATE_ACTIVE;
640df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        model->mConfig = *config;
641df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
642df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
643df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    return status;
644b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
645b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
646b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
647b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
648b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("stopRecognition() model handle %d", handle);
6498ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    if (!captureHotwordAllowed()) {
6508ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent        return PERMISSION_DENIED;
6518ba53d87a2d311ff4b3f04e30b2e09309ae7421cEric Laurent    }
652b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
653b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
654b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model = getModel(handle);
655b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model == 0) {
656b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
657b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
658b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
659b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model->mState != Model::STATE_ACTIVE) {
660b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return INVALID_OPERATION;
661b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
662b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mHwDevice->stop_recognition(mHwDevice, handle);
663b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    model->mState = Model::STATE_IDLE;
664b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
665b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
666b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
667b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
668df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
669b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
670df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    ALOGV("onCallbackEvent type %d", event->mType);
671b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
672df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<IMemory> eventMemory = event->mMemory;
673b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
674b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
675b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
676b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
677b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (mClient == 0) {
678b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGI("%s mClient == 0", __func__);
679b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
680b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
681df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
682df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    switch (event->mType) {
683df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case CallbackEvent::TYPE_RECOGNITION: {
684df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        struct sound_trigger_recognition_event *recognitionEvent =
685df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                (struct sound_trigger_recognition_event *)eventMemory->pointer();
686886561f06ddaea86a51def1e918367430240b5acEric Laurent        sp<ISoundTriggerClient> client;
687886561f06ddaea86a51def1e918367430240b5acEric Laurent        {
688886561f06ddaea86a51def1e918367430240b5acEric Laurent            AutoMutex lock(mLock);
689886561f06ddaea86a51def1e918367430240b5acEric Laurent            sp<Model> model = getModel(recognitionEvent->model);
690886561f06ddaea86a51def1e918367430240b5acEric Laurent            if (model == 0) {
691886561f06ddaea86a51def1e918367430240b5acEric Laurent                ALOGW("%s model == 0", __func__);
692886561f06ddaea86a51def1e918367430240b5acEric Laurent                return;
693886561f06ddaea86a51def1e918367430240b5acEric Laurent            }
694886561f06ddaea86a51def1e918367430240b5acEric Laurent            if (model->mState != Model::STATE_ACTIVE) {
695886561f06ddaea86a51def1e918367430240b5acEric Laurent                ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
696886561f06ddaea86a51def1e918367430240b5acEric Laurent                return;
697886561f06ddaea86a51def1e918367430240b5acEric Laurent            }
698df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
699886561f06ddaea86a51def1e918367430240b5acEric Laurent            recognitionEvent->capture_session = model->mCaptureSession;
700886561f06ddaea86a51def1e918367430240b5acEric Laurent            model->mState = Model::STATE_IDLE;
701886561f06ddaea86a51def1e918367430240b5acEric Laurent            client = mClient;
702df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
703886561f06ddaea86a51def1e918367430240b5acEric Laurent        if (client != 0) {
704886561f06ddaea86a51def1e918367430240b5acEric Laurent            client->onRecognitionEvent(eventMemory);
705df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
706df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    } break;
707df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case CallbackEvent::TYPE_SOUNDMODEL: {
708df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        struct sound_trigger_model_event *soundmodelEvent =
709df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                (struct sound_trigger_model_event *)eventMemory->pointer();
710886561f06ddaea86a51def1e918367430240b5acEric Laurent        sp<ISoundTriggerClient> client;
711886561f06ddaea86a51def1e918367430240b5acEric Laurent        {
712886561f06ddaea86a51def1e918367430240b5acEric Laurent            AutoMutex lock(mLock);
713886561f06ddaea86a51def1e918367430240b5acEric Laurent            sp<Model> model = getModel(soundmodelEvent->model);
714886561f06ddaea86a51def1e918367430240b5acEric Laurent            if (model == 0) {
715886561f06ddaea86a51def1e918367430240b5acEric Laurent                ALOGW("%s model == 0", __func__);
716886561f06ddaea86a51def1e918367430240b5acEric Laurent                return;
717886561f06ddaea86a51def1e918367430240b5acEric Laurent            }
718886561f06ddaea86a51def1e918367430240b5acEric Laurent            client = mClient;
719886561f06ddaea86a51def1e918367430240b5acEric Laurent        }
720886561f06ddaea86a51def1e918367430240b5acEric Laurent        if (client != 0) {
721886561f06ddaea86a51def1e918367430240b5acEric Laurent            client->onSoundModelEvent(eventMemory);
722df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
723df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    } break;
724df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    case CallbackEvent::TYPE_SERVICE_STATE: {
725886561f06ddaea86a51def1e918367430240b5acEric Laurent        sp<ISoundTriggerClient> client;
726886561f06ddaea86a51def1e918367430240b5acEric Laurent        {
727886561f06ddaea86a51def1e918367430240b5acEric Laurent            AutoMutex lock(mLock);
728886561f06ddaea86a51def1e918367430240b5acEric Laurent            client = mClient;
729886561f06ddaea86a51def1e918367430240b5acEric Laurent        }
730886561f06ddaea86a51def1e918367430240b5acEric Laurent        if (client != 0) {
731886561f06ddaea86a51def1e918367430240b5acEric Laurent            client->onServiceStateChange(eventMemory);
732886561f06ddaea86a51def1e918367430240b5acEric Laurent        }
733df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    } break;
734df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    default:
735df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType);
736df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
737b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
738b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
739b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentsp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
740b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        sound_model_handle_t handle)
741b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
742b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model;
743b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ssize_t index = mModels.indexOfKey(handle);
744b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (index >= 0) {
745b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        model = mModels.valueAt(index);
746b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
747b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return model;
748b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
749b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
750b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::Module::binderDied(
751b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    const wp<IBinder> &who __unused) {
752b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGW("client binder died for module %d", mDescriptor.handle);
753b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    detach();
754b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
755b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
756df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent// Called with mServiceLock held
757df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentvoid SoundTriggerHwService::Module::setCaptureState_l(bool active)
758b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
759df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    ALOGV("Module::setCaptureState_l %d", active);
760df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sp<SoundTriggerHwService> service;
761df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    sound_trigger_service_state_t state;
762b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
763df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    Vector< sp<IMemory> > events;
764df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    {
765df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        AutoMutex lock(mLock);
766df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        state = (active && !mDescriptor.properties.concurrent_capture) ?
767df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                        SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED;
768b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
769df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (state == mServiceState) {
770df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            return;
771df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
772b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
773df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        mServiceState = state;
774df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
775df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        service = mService.promote();
776df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (service == 0) {
777df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            return;
778df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
779df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
780df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        if (state == SOUND_TRIGGER_STATE_ENABLED) {
781df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            goto exit;
782df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
783df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
784df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        for (size_t i = 0; i < mModels.size(); i++) {
785df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            sp<Model> model = mModels.valueAt(i);
786df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            if (model->mState == Model::STATE_ACTIVE) {
787df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                mHwDevice->stop_recognition(mHwDevice, model->mHandle);
788df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                // keep model in ACTIVE state so that event is processed by onCallbackEvent()
789df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                struct sound_trigger_phrase_recognition_event phraseEvent;
790df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                switch (model->mType) {
791df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                case SOUND_MODEL_TYPE_KEYPHRASE:
792df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    phraseEvent.num_phrases = model->mConfig.num_phrases;
793df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    for (size_t i = 0; i < phraseEvent.num_phrases; i++) {
794df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                        phraseEvent.phrase_extras[i] = model->mConfig.phrases[i];
795df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    }
796df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    break;
797df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                case SOUND_MODEL_TYPE_UNKNOWN:
798df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                default:
799df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    break;
800df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                }
801df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                phraseEvent.common.status = RECOGNITION_STATUS_ABORT;
802df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                phraseEvent.common.type = model->mType;
803df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                phraseEvent.common.model = model->mHandle;
804df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                phraseEvent.common.data_size = 0;
805df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&phraseEvent.common);
806df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                if (eventMemory != 0) {
807df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                    events.add(eventMemory);
808df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                }
809df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent            }
810df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        }
811b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
812df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
813df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    for (size_t i = 0; i < events.size(); i++) {
814df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent        service->sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i],
815df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                                     this));
816df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    }
817df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
818df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurentexit:
819df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    service->sendServiceStateEvent_l(state, this);
820b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
821b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
822df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
823df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric LaurentSoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session,
824df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                    audio_io_handle_t ioHandle, audio_devices_t device,
825df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent                                    sound_trigger_sound_model_type_t type) :
826df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    mHandle(handle), mState(STATE_IDLE), mCaptureSession(session),
827df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent    mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type)
828b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
829df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871Eric Laurent
830b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
831b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
832b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::dump(int fd __unused,
833b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                             const Vector<String16>& args __unused) {
834b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    String8 result;
835b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
836b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
837b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
838b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}; // namespace android
839