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