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