SoundTriggerHwService.cpp revision b7a11d83f749ad0200778c4815e907d011d4b5d3
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
25b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include <binder/IServiceManager.h>
26b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include <binder/MemoryBase.h>
27b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include <binder/MemoryHeapBase.h>
28b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include <cutils/atomic.h>
29b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include <cutils/properties.h>
30b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include <hardware/hardware.h>
31b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include <utils/Errors.h>
32b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include <utils/Log.h>
33b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
34b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include "SoundTriggerHwService.h"
35b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include <system/sound_trigger.h>
36b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#include <hardware/sound_trigger.h>
37b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
38b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentnamespace android {
39b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
40b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#ifdef SOUND_TRIGGER_USE_STUB_MODULE
41b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define HW_MODULE_PREFIX "stub"
42b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#else
43b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define HW_MODULE_PREFIX "primary"
44b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#endif
45b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
46b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::SoundTriggerHwService()
47b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    : BnSoundTriggerHwService(),
48b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent      mNextUniqueId(1)
49b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
50b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
51b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
52b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::onFirstRef()
53b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
54b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    const hw_module_t *mod;
55b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    int rc;
56b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sound_trigger_hw_device *dev;
57b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
58b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, HW_MODULE_PREFIX, &mod);
59b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (rc != 0) {
60b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("couldn't load sound trigger module %s.%s (%s)",
61b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent              SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", strerror(-rc));
62b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
63b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
64b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    rc = sound_trigger_hw_device_open(mod, &dev);
65b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (rc != 0) {
66b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("couldn't open sound trigger hw device in %s.%s (%s)",
67b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent              SOUND_TRIGGER_HARDWARE_MODULE_ID, "primary", strerror(-rc));
68b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
69b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
70b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (dev->common.version != SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
71b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("wrong sound trigger hw device version %04x", dev->common.version);
72b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
73b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
74b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
75b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sound_trigger_module_descriptor descriptor;
76b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    rc = dev->get_properties(dev, &descriptor.properties);
77b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (rc != 0) {
78b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("could not read implementation properties");
79b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
80b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
81b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    descriptor.handle =
82b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            (sound_trigger_module_handle_t)android_atomic_inc(&mNextUniqueId);
83b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGI("loaded default module %s, handle %d", descriptor.properties.description,
84b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                 descriptor.handle);
85b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
86b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<ISoundTriggerClient> client;
87b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Module> module = new Module(this, dev, descriptor, client);
88b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mModules.add(descriptor.handle, module);
89b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mCallbackThread = new CallbackThread(this);
90b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
91b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
92b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::~SoundTriggerHwService()
93b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
94b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (mCallbackThread != 0) {
95b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        mCallbackThread->exit();
96b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
97b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    for (size_t i = 0; i < mModules.size(); i++) {
98b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        sound_trigger_hw_device_close(mModules.valueAt(i)->hwDevice());
99b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
100b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
101b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
102b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::listModules(struct sound_trigger_module_descriptor *modules,
103b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                             uint32_t *numModules)
104b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
105b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("listModules");
106b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mServiceLock);
107b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (numModules == NULL || (*numModules != 0 && modules == NULL)) {
108b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
109b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
110b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    size_t maxModules = *numModules;
111b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    *numModules = mModules.size();
112b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    for (size_t i = 0; i < mModules.size() && i < maxModules; i++) {
113b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        modules[i] = mModules.valueAt(i)->descriptor();
114b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
115b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
116b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
117b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
118b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::attach(const sound_trigger_module_handle_t handle,
119b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        const sp<ISoundTriggerClient>& client,
120b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        sp<ISoundTrigger>& moduleInterface)
121b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
122b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("attach module %d", handle);
123b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mServiceLock);
124b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    moduleInterface.clear();
125b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (client == 0) {
126b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
127b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
128b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ssize_t index = mModules.indexOfKey(handle);
129b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (index < 0) {
130b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
131b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
132b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Module> module = mModules.valueAt(index);
133b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
134b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    module->setClient(client);
135b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    client->asBinder()->linkToDeath(module);
136b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    moduleInterface = module;
137b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
138b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
139b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
140b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
141b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::detachModule(sp<Module> module) {
142b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mServiceLock);
143b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("detachModule");
144b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    module->clearClient();
145b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
146b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
147b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatic const int kDumpLockRetries = 50;
148b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatic const int kDumpLockSleep = 60000;
149b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
150b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatic bool tryLock(Mutex& mutex)
151b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
152b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    bool locked = false;
153b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    for (int i = 0; i < kDumpLockRetries; ++i) {
154b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (mutex.tryLock() == NO_ERROR) {
155b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            locked = true;
156b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            break;
157b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
158b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        usleep(kDumpLockSleep);
159b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
160b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return locked;
161b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
162b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
163b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::dump(int fd, const Vector<String16>& args __unused) {
164b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    String8 result;
165b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
166b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        result.appendFormat("Permission Denial: can't dump SoundTriggerHwService");
167b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        write(fd, result.string(), result.size());
168b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    } else {
169b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        bool locked = tryLock(mServiceLock);
170b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        // failed to lock - SoundTriggerHwService is probably deadlocked
171b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (!locked) {
172b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            result.append("SoundTriggerHwService may be deadlocked\n");
173b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            write(fd, result.string(), result.size());
174b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
175b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
176b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (locked) mServiceLock.unlock();
177b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
178b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
179b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
180b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
181b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::onTransact(
182b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
183b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return BnSoundTriggerHwService::onTransact(code, data, reply, flags);
184b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
185b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
186b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
187b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent// static
188b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition_event *event,
189b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                void *cookie)
190b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
191b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    Module *module = (Module *)cookie;
192b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (module == NULL) {
193b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
194b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
195b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    module->sendRecognitionEvent(event);
196b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
197b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
198b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
199b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::sendRecognitionEvent(const sp<RecognitionEvent>& event)
200b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
201b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mCallbackThread->sendRecognitionEvent(event);
202b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
203b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
204b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::onRecognitionEvent(const sp<RecognitionEvent>& event)
205b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
206b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("onRecognitionEvent");
207b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Module> module;
208b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    {
209b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        AutoMutex lock(mServiceLock);
210b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        module = event->mModule.promote();
211b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (module == 0) {
212b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            return;
213b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
214b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
215b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    module->onRecognitionEvent(event->mEventMemory);
216b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
217b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
218b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent// static
219b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event __unused,
220b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                               void *cookie)
221b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
222b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    Module *module = (Module *)cookie;
223b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
224b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
225b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
226b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#undef LOG_TAG
227b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define LOG_TAG "SoundTriggerHwService::CallbackThread"
228b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
229b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service)
230b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    : mService(service)
231b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
232b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
233b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
234b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::CallbackThread::~CallbackThread()
235b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
236b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mEventQueue.clear();
237b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
238b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
239b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::CallbackThread::onFirstRef()
240b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
241b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO);
242b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
243b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
244b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentbool SoundTriggerHwService::CallbackThread::threadLoop()
245b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
246b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    while (!exitPending()) {
247b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        sp<RecognitionEvent> event;
248b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        sp<SoundTriggerHwService> service;
249b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        {
250b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            Mutex::Autolock _l(mCallbackLock);
251b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            while (mEventQueue.isEmpty() && !exitPending()) {
252b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                ALOGV("CallbackThread::threadLoop() sleep");
253b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                mCallbackCond.wait(mCallbackLock);
254b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                ALOGV("CallbackThread::threadLoop() wake up");
255b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            }
256b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            if (exitPending()) {
257b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                break;
258b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            }
259b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            event = mEventQueue[0];
260b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            mEventQueue.removeAt(0);
261b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            service = mService.promote();
262b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
263b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (service != 0) {
264b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            service->onRecognitionEvent(event);
265b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
266b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
267b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return false;
268b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
269b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
270b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::CallbackThread::exit()
271b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
272b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    Mutex::Autolock _l(mCallbackLock);
273b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    requestExit();
274b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mCallbackCond.broadcast();
275b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
276b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
277b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::CallbackThread::sendRecognitionEvent(
278b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        const sp<SoundTriggerHwService::RecognitionEvent>& event)
279b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
280b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mCallbackLock);
281b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mEventQueue.add(event);
282b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mCallbackCond.signal();
283b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
284b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
285b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::RecognitionEvent::RecognitionEvent(
286b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                            sp<IMemory> eventMemory,
287b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                            wp<Module> module)
288b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    : mEventMemory(eventMemory), mModule(module)
289b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
290b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
291b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
292b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::RecognitionEvent::~RecognitionEvent()
293b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
294b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
295b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
296b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#undef LOG_TAG
297b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent#define LOG_TAG "SoundTriggerHwService::Module"
298b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
299b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service,
300b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                      sound_trigger_hw_device* hwDevice,
301b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                      sound_trigger_module_descriptor descriptor,
302b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                      const sp<ISoundTriggerClient>& client)
303b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent : mService(service), mHwDevice(hwDevice), mDescriptor(descriptor),
304b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent   mClient(client)
305b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
306b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
307b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
308b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::Module::~Module() {
309b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
310b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
311b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::Module::detach() {
312b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("detach()");
313b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    {
314b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        AutoMutex lock(mLock);
315b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        for (size_t i = 0; i < mModels.size(); i++) {
316b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            sp<Model> model = mModels.valueAt(i);
317b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            ALOGV("detach() unloading model %d", model->mHandle);
318b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            if (model->mState == Model::STATE_ACTIVE) {
319b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                mHwDevice->stop_recognition(mHwDevice, model->mHandle);
320b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                model->deallocateMemory();
321b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            }
322b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            mHwDevice->unload_sound_model(mHwDevice, model->mHandle);
323b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
324b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        mModels.clear();
325b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
326b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (mClient != 0) {
327b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        mClient->asBinder()->unlinkToDeath(this);
328b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
329b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<SoundTriggerHwService> service = mService.promote();
330b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (service == 0) {
331b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
332b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
333b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    service->detachModule(this);
334b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
335b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
336b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory,
337b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                sound_model_handle_t *handle)
338b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
339b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("loadSoundModel() handle");
340b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
341b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (modelMemory == 0 || modelMemory->pointer() == NULL) {
342b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()");
343b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
344b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
345b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    struct sound_trigger_sound_model *sound_model =
346b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            (struct sound_trigger_sound_model *)modelMemory->pointer();
347b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
348b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
349b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    status_t status = mHwDevice->load_sound_model(mHwDevice,
350b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                  sound_model,
351b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                  SoundTriggerHwService::soundModelCallback,
352b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                  this,
353b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                  handle);
354b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (status == NO_ERROR) {
355b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        mModels.replaceValueFor(*handle, new Model(*handle));
356b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
357b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
358b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return status;
359b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
360b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
361b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle)
362b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
363b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("unloadSoundModel() model handle %d", handle);
364b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
365b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
366b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ssize_t index = mModels.indexOfKey(handle);
367b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (index < 0) {
368b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
369b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
370b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mModels.removeItem(handle);
371b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
372b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return mHwDevice->unload_sound_model(mHwDevice, handle);
373b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
374b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
375b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
376b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                  const sp<IMemory>& dataMemory)
377b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
378b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("startRecognition() model handle %d", handle);
379b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
380b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (dataMemory != 0 && dataMemory->pointer() == NULL) {
381b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("startRecognition() dataMemory is non-0 but has NULL pointer()");
382b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
383b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
384b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
385b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
386b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model = getModel(handle);
387b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model == 0) {
388b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
389b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
390b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
391b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model->mState == Model::STATE_ACTIVE) {
392b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return INVALID_OPERATION;
393b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
394b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    model->mState = Model::STATE_ACTIVE;
395b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
396b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    char *data = NULL;
397b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    unsigned int data_size = 0;
398b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (dataMemory != 0 && dataMemory->size() != 0) {
399b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        data_size = (unsigned int)dataMemory->size();
400b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        data = (char *)dataMemory->pointer();
401b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGV("startRecognition() data size %d data %d - %d",
402b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                      data_size, data[0], data[data_size - 1]);
403b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
404b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
405b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    //TODO: get capture handle and device from audio policy service
406b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    audio_io_handle_t capture_handle = 0;
407b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return mHwDevice->start_recognition(mHwDevice, handle, capture_handle, AUDIO_DEVICE_NONE,
408b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                        SoundTriggerHwService::recognitionCallback,
409b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                        this,
410b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                        data_size,
411b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                        data);
412b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
413b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
414b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
415b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
416b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("stopRecognition() model handle %d", handle);
417b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
418b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
419b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model = getModel(handle);
420b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model == 0) {
421b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
422b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
423b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
424b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model->mState != Model::STATE_ACTIVE) {
425b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return INVALID_OPERATION;
426b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
427b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mHwDevice->stop_recognition(mHwDevice, handle);
428b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    model->deallocateMemory();
429b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    model->mState = Model::STATE_IDLE;
430b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
431b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
432b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
433b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::Module::sendRecognitionEvent(
434b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                    struct sound_trigger_recognition_event *event)
435b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
436b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<SoundTriggerHwService> service;
437b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<IMemory> eventMemory;
438b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("sendRecognitionEvent for model %d", event->model);
439b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    {
440b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        AutoMutex lock(mLock);
441b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        sp<Model> model = getModel(event->model);
442b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (model == 0) {
443b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            return;
444b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
445b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (model->mState != Model::STATE_ACTIVE) {
446b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            ALOGV("sendRecognitionEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
447b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            return;
448b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
449b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (mClient == 0) {
450b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            return;
451b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
452b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        service = mService.promote();
453b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (service == 0) {
454b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            return;
455b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
456b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
457b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        //sanitize event
458b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        switch (event->type) {
459b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        case SOUND_MODEL_TYPE_KEYPHRASE:
460b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            ALOGW_IF(event->data_offset !=
461b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        sizeof(struct sound_trigger_phrase_recognition_event),
462b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        "sendRecognitionEvent(): invalid data offset %u for keyphrase event type",
463b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        event->data_offset);
464b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
465b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            break;
466b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        case SOUND_MODEL_TYPE_UNKNOWN:
467b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            ALOGW_IF(event->data_offset !=
468b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        sizeof(struct sound_trigger_recognition_event),
469b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        "sendRecognitionEvent(): invalid data offset %u for unknown event type",
470b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        event->data_offset);
471b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            event->data_offset = sizeof(struct sound_trigger_recognition_event);
472b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            break;
473b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        default:
474b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                return;
475b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
476b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
477b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        size_t size = event->data_offset + event->data_size;
478b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        eventMemory = model->allocateMemory(size);
479b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (eventMemory == 0 || eventMemory->pointer() == NULL) {
480b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            return;
481b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
482b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        memcpy(eventMemory->pointer(), event, size);
483b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
484b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    service->sendRecognitionEvent(new RecognitionEvent(eventMemory, this));
485b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
486b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
487b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::Module::onRecognitionEvent(sp<IMemory> eventMemory)
488b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
489b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("Module::onRecognitionEvent");
490b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
491b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
492b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
493b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
494b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
495b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
496b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    struct sound_trigger_recognition_event *event =
497b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            (struct sound_trigger_recognition_event *)eventMemory->pointer();
498b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
499b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model = getModel(event->model);
500b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model == 0) {
501b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGI("%s model == 0", __func__);
502b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
503b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
504b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model->mState != Model::STATE_ACTIVE) {
505b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGV("onRecognitionEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
506b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
507b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
508b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (mClient == 0) {
509b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGI("%s mClient == 0", __func__);
510b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
511b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
512b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mClient->onRecognitionEvent(eventMemory);
513b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    model->mState = Model::STATE_IDLE;
514b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    model->deallocateMemory();
515b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
516b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
517b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentsp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
518b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        sound_model_handle_t handle)
519b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
520b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model;
521b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ssize_t index = mModels.indexOfKey(handle);
522b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (index >= 0) {
523b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        model = mModels.valueAt(index);
524b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
525b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return model;
526b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
527b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
528b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::Module::binderDied(
529b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    const wp<IBinder> &who __unused) {
530b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGW("client binder died for module %d", mDescriptor.handle);
531b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    detach();
532b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
533b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
534b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
535b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::Model::Model(sound_model_handle_t handle) :
536b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mHandle(handle), mState(STATE_IDLE), mInputHandle(AUDIO_IO_HANDLE_NONE),
537b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mCaptureSession(AUDIO_SESSION_ALLOCATE),
538b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mMemoryDealer(new MemoryDealer(sizeof(struct sound_trigger_recognition_event),
539b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                   "SoundTriggerHwService::Event"))
540b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
541b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
542b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
543b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
544b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
545b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentsp<IMemory> SoundTriggerHwService::Model::allocateMemory(size_t size)
546b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
547b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<IMemory> memory;
548b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (mMemoryDealer->getMemoryHeap()->getSize() < size) {
549b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        mMemoryDealer = new MemoryDealer(size, "SoundTriggerHwService::Event");
550b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
551b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    memory = mMemoryDealer->allocate(size);
552b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return memory;
553b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
554b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
555b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::Model::deallocateMemory()
556b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
557b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mMemoryDealer->deallocate(0);
558b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
559b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
560b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::dump(int fd __unused,
561b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                             const Vector<String16>& args __unused) {
562b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    String8 result;
563b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
564b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
565b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
566b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}; // namespace android
567