SoundTriggerHwService.cpp revision 1a1cba8f9a93db188b09d9754987354029129113
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    }
3701a1cba8f9a93db188b09d9754987354029129113Eric Laurent    sp<Model> model = mModels.valueAt(index);
371b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mModels.removeItem(handle);
3721a1cba8f9a93db188b09d9754987354029129113Eric Laurent    if (model->mState == Model::STATE_ACTIVE) {
3731a1cba8f9a93db188b09d9754987354029129113Eric Laurent        mHwDevice->stop_recognition(mHwDevice, model->mHandle);
3741a1cba8f9a93db188b09d9754987354029129113Eric Laurent        model->deallocateMemory();
3751a1cba8f9a93db188b09d9754987354029129113Eric Laurent    }
376b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return mHwDevice->unload_sound_model(mHwDevice, handle);
377b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
378b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
379b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle,
380b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                  const sp<IMemory>& dataMemory)
381b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
382b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("startRecognition() model handle %d", handle);
383b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
384b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (dataMemory != 0 && dataMemory->pointer() == NULL) {
385b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGE("startRecognition() dataMemory is non-0 but has NULL pointer()");
386b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
387b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
388b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
389b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
390b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model = getModel(handle);
391b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model == 0) {
392b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
393b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
394b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
395b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model->mState == Model::STATE_ACTIVE) {
396b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return INVALID_OPERATION;
397b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
398b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    model->mState = Model::STATE_ACTIVE;
399b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
400b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    char *data = NULL;
401b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    unsigned int data_size = 0;
402b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (dataMemory != 0 && dataMemory->size() != 0) {
403b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        data_size = (unsigned int)dataMemory->size();
404b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        data = (char *)dataMemory->pointer();
405b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGV("startRecognition() data size %d data %d - %d",
406b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                      data_size, data[0], data[data_size - 1]);
407b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
408b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
409b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    //TODO: get capture handle and device from audio policy service
410b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    audio_io_handle_t capture_handle = 0;
411b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return mHwDevice->start_recognition(mHwDevice, handle, capture_handle, AUDIO_DEVICE_NONE,
412b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                        SoundTriggerHwService::recognitionCallback,
413b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                        this,
414b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                        data_size,
415b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                        data);
416b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
417b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
418b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle)
419b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
420b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("stopRecognition() model handle %d", handle);
421b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
422b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
423b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model = getModel(handle);
424b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model == 0) {
425b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return BAD_VALUE;
426b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
427b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
428b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model->mState != Model::STATE_ACTIVE) {
429b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return INVALID_OPERATION;
430b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
431b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mHwDevice->stop_recognition(mHwDevice, handle);
432b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    model->deallocateMemory();
433b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    model->mState = Model::STATE_IDLE;
434b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
435b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
436b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
437b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::Module::sendRecognitionEvent(
438b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                                    struct sound_trigger_recognition_event *event)
439b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
440b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<SoundTriggerHwService> service;
441b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<IMemory> eventMemory;
442b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("sendRecognitionEvent for model %d", event->model);
443b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    {
444b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        AutoMutex lock(mLock);
445b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        sp<Model> model = getModel(event->model);
446b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (model == 0) {
447b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            return;
448b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
449b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (model->mState != Model::STATE_ACTIVE) {
450b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            ALOGV("sendRecognitionEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
451b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            return;
452b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
453b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (mClient == 0) {
454b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            return;
455b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
456b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        service = mService.promote();
457b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (service == 0) {
458b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            return;
459b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
460b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
461b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        //sanitize event
462b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        switch (event->type) {
463b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        case SOUND_MODEL_TYPE_KEYPHRASE:
464b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            ALOGW_IF(event->data_offset !=
465b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        sizeof(struct sound_trigger_phrase_recognition_event),
466b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        "sendRecognitionEvent(): invalid data offset %u for keyphrase event type",
467b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        event->data_offset);
468b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event);
469b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            break;
470b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        case SOUND_MODEL_TYPE_UNKNOWN:
471b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            ALOGW_IF(event->data_offset !=
472b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        sizeof(struct sound_trigger_recognition_event),
473b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        "sendRecognitionEvent(): invalid data offset %u for unknown event type",
474b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                        event->data_offset);
475b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            event->data_offset = sizeof(struct sound_trigger_recognition_event);
476b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            break;
477b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        default:
478b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                return;
479b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
480b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
481b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        size_t size = event->data_offset + event->data_size;
482b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        eventMemory = model->allocateMemory(size);
483b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        if (eventMemory == 0 || eventMemory->pointer() == NULL) {
484b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            return;
485b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        }
486b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        memcpy(eventMemory->pointer(), event, size);
487b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
488b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    service->sendRecognitionEvent(new RecognitionEvent(eventMemory, this));
489b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
490b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
491b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::Module::onRecognitionEvent(sp<IMemory> eventMemory)
492b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
493b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGV("Module::onRecognitionEvent");
494b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
495b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    AutoMutex lock(mLock);
496b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
497b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
498b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
499b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
500b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    struct sound_trigger_recognition_event *event =
501b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent            (struct sound_trigger_recognition_event *)eventMemory->pointer();
502b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
503b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model = getModel(event->model);
504b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model == 0) {
505b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGI("%s model == 0", __func__);
506b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
507b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
508b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (model->mState != Model::STATE_ACTIVE) {
509b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGV("onRecognitionEvent model->mState %d != Model::STATE_ACTIVE", model->mState);
510b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
511b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
512b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (mClient == 0) {
513b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        ALOGI("%s mClient == 0", __func__);
514b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        return;
515b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
516b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mClient->onRecognitionEvent(eventMemory);
517b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    model->mState = Model::STATE_IDLE;
518b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    model->deallocateMemory();
519b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
520b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
521b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentsp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel(
522b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        sound_model_handle_t handle)
523b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
524b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<Model> model;
525b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ssize_t index = mModels.indexOfKey(handle);
526b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (index >= 0) {
527b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        model = mModels.valueAt(index);
528b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
529b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return model;
530b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
531b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
532b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::Module::binderDied(
533b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    const wp<IBinder> &who __unused) {
534b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    ALOGW("client binder died for module %d", mDescriptor.handle);
535b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    detach();
536b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
537b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
538b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
539b7a11d83f749ad0200778c4815e907d011d4b5d3Eric LaurentSoundTriggerHwService::Model::Model(sound_model_handle_t handle) :
540b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mHandle(handle), mState(STATE_IDLE), mInputHandle(AUDIO_IO_HANDLE_NONE),
541b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mCaptureSession(AUDIO_SESSION_ALLOCATE),
542b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mMemoryDealer(new MemoryDealer(sizeof(struct sound_trigger_recognition_event),
543b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                   "SoundTriggerHwService::Event"))
544b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
545b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
546b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
547b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
548b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
549b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentsp<IMemory> SoundTriggerHwService::Model::allocateMemory(size_t size)
550b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
551b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    sp<IMemory> memory;
552b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    if (mMemoryDealer->getMemoryHeap()->getSize() < size) {
553b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent        mMemoryDealer = new MemoryDealer(size, "SoundTriggerHwService::Event");
554b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    }
555b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    memory = mMemoryDealer->allocate(size);
556b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return memory;
557b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
558b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
559b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentvoid SoundTriggerHwService::Model::deallocateMemory()
560b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent{
561b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    mMemoryDealer->deallocate(0);
562b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
563b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
564b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurentstatus_t SoundTriggerHwService::Module::dump(int fd __unused,
565b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent                                             const Vector<String16>& args __unused) {
566b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    String8 result;
567b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent    return NO_ERROR;
568b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}
569b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent
570b7a11d83f749ad0200778c4815e907d011d4b5d3Eric Laurent}; // namespace android
571