SoundTriggerHwService.cpp revision 2c561209f00320f7ca2b75998bbe72ecec527210
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "SoundTriggerHwService" 18//#define LOG_NDEBUG 0 19 20#include <stdio.h> 21#include <string.h> 22#include <sys/types.h> 23#include <pthread.h> 24 25#include <system/sound_trigger.h> 26#include <cutils/atomic.h> 27#include <cutils/properties.h> 28#include <hardware/hardware.h> 29#include <media/AudioSystem.h> 30#include <utils/Errors.h> 31#include <utils/Log.h> 32#include <binder/IServiceManager.h> 33#include <binder/MemoryBase.h> 34#include <binder/MemoryHeapBase.h> 35#include <hardware/sound_trigger.h> 36#include <ServiceUtilities.h> 37#include "SoundTriggerHwService.h" 38 39namespace android { 40 41#ifdef SOUND_TRIGGER_USE_STUB_MODULE 42#define HW_MODULE_PREFIX "stub" 43#else 44#define HW_MODULE_PREFIX "primary" 45#endif 46 47SoundTriggerHwService::SoundTriggerHwService() 48 : BnSoundTriggerHwService(), 49 mNextUniqueId(1), 50 mMemoryDealer(new MemoryDealer(1024 * 1024, "SoundTriggerHwService")), 51 mCaptureState(false) 52{ 53} 54 55void SoundTriggerHwService::onFirstRef() 56{ 57 const hw_module_t *mod; 58 int rc; 59 sound_trigger_hw_device *dev; 60 61 rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, HW_MODULE_PREFIX, &mod); 62 if (rc != 0) { 63 ALOGE("couldn't load sound trigger module %s.%s (%s)", 64 SOUND_TRIGGER_HARDWARE_MODULE_ID, HW_MODULE_PREFIX, strerror(-rc)); 65 return; 66 } 67 rc = sound_trigger_hw_device_open(mod, &dev); 68 if (rc != 0) { 69 ALOGE("couldn't open sound trigger hw device in %s.%s (%s)", 70 SOUND_TRIGGER_HARDWARE_MODULE_ID, HW_MODULE_PREFIX, strerror(-rc)); 71 return; 72 } 73 if (dev->common.version != SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) { 74 ALOGE("wrong sound trigger hw device version %04x", dev->common.version); 75 return; 76 } 77 78 sound_trigger_module_descriptor descriptor; 79 rc = dev->get_properties(dev, &descriptor.properties); 80 if (rc != 0) { 81 ALOGE("could not read implementation properties"); 82 return; 83 } 84 descriptor.handle = 85 (sound_trigger_module_handle_t)android_atomic_inc(&mNextUniqueId); 86 ALOGI("loaded default module %s, handle %d", descriptor.properties.description, 87 descriptor.handle); 88 89 sp<ISoundTriggerClient> client; 90 sp<Module> module = new Module(this, dev, descriptor, client); 91 mModules.add(descriptor.handle, module); 92 mCallbackThread = new CallbackThread(this); 93} 94 95SoundTriggerHwService::~SoundTriggerHwService() 96{ 97 if (mCallbackThread != 0) { 98 mCallbackThread->exit(); 99 } 100 for (size_t i = 0; i < mModules.size(); i++) { 101 sound_trigger_hw_device_close(mModules.valueAt(i)->hwDevice()); 102 } 103} 104 105status_t SoundTriggerHwService::listModules(struct sound_trigger_module_descriptor *modules, 106 uint32_t *numModules) 107{ 108 ALOGV("listModules"); 109 if (!captureHotwordAllowed()) { 110 return PERMISSION_DENIED; 111 } 112 113 AutoMutex lock(mServiceLock); 114 if (numModules == NULL || (*numModules != 0 && modules == NULL)) { 115 return BAD_VALUE; 116 } 117 size_t maxModules = *numModules; 118 *numModules = mModules.size(); 119 for (size_t i = 0; i < mModules.size() && i < maxModules; i++) { 120 modules[i] = mModules.valueAt(i)->descriptor(); 121 } 122 return NO_ERROR; 123} 124 125status_t SoundTriggerHwService::attach(const sound_trigger_module_handle_t handle, 126 const sp<ISoundTriggerClient>& client, 127 sp<ISoundTrigger>& moduleInterface) 128{ 129 ALOGV("attach module %d", handle); 130 if (!captureHotwordAllowed()) { 131 return PERMISSION_DENIED; 132 } 133 134 AutoMutex lock(mServiceLock); 135 moduleInterface.clear(); 136 if (client == 0) { 137 return BAD_VALUE; 138 } 139 ssize_t index = mModules.indexOfKey(handle); 140 if (index < 0) { 141 return BAD_VALUE; 142 } 143 sp<Module> module = mModules.valueAt(index); 144 145 module->setClient(client); 146 IInterface::asBinder(client)->linkToDeath(module); 147 moduleInterface = module; 148 149 module->setCaptureState_l(mCaptureState); 150 151 return NO_ERROR; 152} 153 154status_t SoundTriggerHwService::setCaptureState(bool active) 155{ 156 ALOGV("setCaptureState %d", active); 157 AutoMutex lock(mServiceLock); 158 mCaptureState = active; 159 for (size_t i = 0; i < mModules.size(); i++) { 160 mModules.valueAt(i)->setCaptureState_l(active); 161 } 162 return NO_ERROR; 163} 164 165 166void SoundTriggerHwService::detachModule(sp<Module> module) 167{ 168 ALOGV("detachModule"); 169 AutoMutex lock(mServiceLock); 170 module->clearClient(); 171} 172 173 174static const int kDumpLockRetries = 50; 175static const int kDumpLockSleep = 60000; 176 177static bool tryLock(Mutex& mutex) 178{ 179 bool locked = false; 180 for (int i = 0; i < kDumpLockRetries; ++i) { 181 if (mutex.tryLock() == NO_ERROR) { 182 locked = true; 183 break; 184 } 185 usleep(kDumpLockSleep); 186 } 187 return locked; 188} 189 190status_t SoundTriggerHwService::dump(int fd, const Vector<String16>& args __unused) { 191 String8 result; 192 if (checkCallingPermission(String16("android.permission.DUMP")) == false) { 193 result.appendFormat("Permission Denial: can't dump SoundTriggerHwService"); 194 write(fd, result.string(), result.size()); 195 } else { 196 bool locked = tryLock(mServiceLock); 197 // failed to lock - SoundTriggerHwService is probably deadlocked 198 if (!locked) { 199 result.append("SoundTriggerHwService may be deadlocked\n"); 200 write(fd, result.string(), result.size()); 201 } 202 203 if (locked) mServiceLock.unlock(); 204 } 205 return NO_ERROR; 206} 207 208status_t SoundTriggerHwService::onTransact( 209 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { 210 return BnSoundTriggerHwService::onTransact(code, data, reply, flags); 211} 212 213 214// static 215void SoundTriggerHwService::recognitionCallback(struct sound_trigger_recognition_event *event, 216 void *cookie) 217{ 218 Module *module = (Module *)cookie; 219 if (module == NULL) { 220 return; 221 } 222 sp<SoundTriggerHwService> service = module->service().promote(); 223 if (service == 0) { 224 return; 225 } 226 227 service->sendRecognitionEvent(event, module); 228} 229 230sp<IMemory> SoundTriggerHwService::prepareRecognitionEvent_l( 231 struct sound_trigger_recognition_event *event) 232{ 233 sp<IMemory> eventMemory; 234 235 //sanitize event 236 switch (event->type) { 237 case SOUND_MODEL_TYPE_KEYPHRASE: 238 ALOGW_IF(event->data_size != 0 && event->data_offset != 239 sizeof(struct sound_trigger_phrase_recognition_event), 240 "prepareRecognitionEvent_l(): invalid data offset %u for keyphrase event type", 241 event->data_offset); 242 event->data_offset = sizeof(struct sound_trigger_phrase_recognition_event); 243 break; 244 case SOUND_MODEL_TYPE_GENERIC: 245 ALOGW_IF(event->data_size != 0 && event->data_offset != 246 sizeof(struct sound_trigger_generic_recognition_event), 247 "prepareRecognitionEvent_l(): invalid data offset %u for generic event type", 248 event->data_offset); 249 event->data_offset = sizeof(struct sound_trigger_generic_recognition_event); 250 break; 251 case SOUND_MODEL_TYPE_UNKNOWN: 252 ALOGW_IF(event->data_size != 0 && event->data_offset != 253 sizeof(struct sound_trigger_recognition_event), 254 "prepareRecognitionEvent_l(): invalid data offset %u for unknown event type", 255 event->data_offset); 256 event->data_offset = sizeof(struct sound_trigger_recognition_event); 257 break; 258 default: 259 return eventMemory; 260 } 261 262 size_t size = event->data_offset + event->data_size; 263 eventMemory = mMemoryDealer->allocate(size); 264 if (eventMemory == 0 || eventMemory->pointer() == NULL) { 265 eventMemory.clear(); 266 return eventMemory; 267 } 268 memcpy(eventMemory->pointer(), event, size); 269 270 return eventMemory; 271} 272 273void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event, 274 Module *module) 275 { 276 AutoMutex lock(mServiceLock); 277 if (module == NULL) { 278 return; 279 } 280 sp<IMemory> eventMemory = prepareRecognitionEvent_l(event); 281 if (eventMemory == 0) { 282 return; 283 } 284 sp<Module> strongModule; 285 for (size_t i = 0; i < mModules.size(); i++) { 286 if (mModules.valueAt(i).get() == module) { 287 strongModule = mModules.valueAt(i); 288 break; 289 } 290 } 291 if (strongModule == 0) { 292 return; 293 } 294 295 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, 296 eventMemory, strongModule)); 297} 298 299// static 300void SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event, 301 void *cookie) 302{ 303 Module *module = (Module *)cookie; 304 if (module == NULL) { 305 return; 306 } 307 sp<SoundTriggerHwService> service = module->service().promote(); 308 if (service == 0) { 309 return; 310 } 311 312 service->sendSoundModelEvent(event, module); 313} 314 315sp<IMemory> SoundTriggerHwService::prepareSoundModelEvent_l(struct sound_trigger_model_event *event) 316{ 317 sp<IMemory> eventMemory; 318 319 size_t size = event->data_offset + event->data_size; 320 eventMemory = mMemoryDealer->allocate(size); 321 if (eventMemory == 0 || eventMemory->pointer() == NULL) { 322 eventMemory.clear(); 323 return eventMemory; 324 } 325 memcpy(eventMemory->pointer(), event, size); 326 327 return eventMemory; 328} 329 330void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event, 331 Module *module) 332{ 333 AutoMutex lock(mServiceLock); 334 sp<IMemory> eventMemory = prepareSoundModelEvent_l(event); 335 if (eventMemory == 0) { 336 return; 337 } 338 sp<Module> strongModule; 339 for (size_t i = 0; i < mModules.size(); i++) { 340 if (mModules.valueAt(i).get() == module) { 341 strongModule = mModules.valueAt(i); 342 break; 343 } 344 } 345 if (strongModule == 0) { 346 return; 347 } 348 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL, 349 eventMemory, strongModule)); 350} 351 352 353sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state) 354{ 355 sp<IMemory> eventMemory; 356 357 size_t size = sizeof(sound_trigger_service_state_t); 358 eventMemory = mMemoryDealer->allocate(size); 359 if (eventMemory == 0 || eventMemory->pointer() == NULL) { 360 eventMemory.clear(); 361 return eventMemory; 362 } 363 *((sound_trigger_service_state_t *)eventMemory->pointer()) = state; 364 return eventMemory; 365} 366 367// call with mServiceLock held 368void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state, 369 Module *module) 370{ 371 sp<IMemory> eventMemory = prepareServiceStateEvent_l(state); 372 if (eventMemory == 0) { 373 return; 374 } 375 sp<Module> strongModule; 376 for (size_t i = 0; i < mModules.size(); i++) { 377 if (mModules.valueAt(i).get() == module) { 378 strongModule = mModules.valueAt(i); 379 break; 380 } 381 } 382 if (strongModule == 0) { 383 return; 384 } 385 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE, 386 eventMemory, strongModule)); 387} 388 389// call with mServiceLock held 390void SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event) 391{ 392 mCallbackThread->sendCallbackEvent(event); 393} 394 395void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event) 396{ 397 ALOGV("onCallbackEvent"); 398 sp<Module> module; 399 { 400 AutoMutex lock(mServiceLock); 401 module = event->mModule.promote(); 402 if (module == 0) { 403 return; 404 } 405 } 406 module->onCallbackEvent(event); 407 { 408 AutoMutex lock(mServiceLock); 409 // clear now to execute with mServiceLock locked 410 event->mMemory.clear(); 411 } 412} 413 414#undef LOG_TAG 415#define LOG_TAG "SoundTriggerHwService::CallbackThread" 416 417SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service) 418 : mService(service) 419{ 420} 421 422SoundTriggerHwService::CallbackThread::~CallbackThread() 423{ 424 while (!mEventQueue.isEmpty()) { 425 mEventQueue[0]->mMemory.clear(); 426 mEventQueue.removeAt(0); 427 } 428} 429 430void SoundTriggerHwService::CallbackThread::onFirstRef() 431{ 432 run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO); 433} 434 435bool SoundTriggerHwService::CallbackThread::threadLoop() 436{ 437 while (!exitPending()) { 438 sp<CallbackEvent> event; 439 sp<SoundTriggerHwService> service; 440 { 441 Mutex::Autolock _l(mCallbackLock); 442 while (mEventQueue.isEmpty() && !exitPending()) { 443 ALOGV("CallbackThread::threadLoop() sleep"); 444 mCallbackCond.wait(mCallbackLock); 445 ALOGV("CallbackThread::threadLoop() wake up"); 446 } 447 if (exitPending()) { 448 break; 449 } 450 event = mEventQueue[0]; 451 mEventQueue.removeAt(0); 452 service = mService.promote(); 453 } 454 if (service != 0) { 455 service->onCallbackEvent(event); 456 } 457 } 458 return false; 459} 460 461void SoundTriggerHwService::CallbackThread::exit() 462{ 463 Mutex::Autolock _l(mCallbackLock); 464 requestExit(); 465 mCallbackCond.broadcast(); 466} 467 468void SoundTriggerHwService::CallbackThread::sendCallbackEvent( 469 const sp<SoundTriggerHwService::CallbackEvent>& event) 470{ 471 AutoMutex lock(mCallbackLock); 472 mEventQueue.add(event); 473 mCallbackCond.signal(); 474} 475 476SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory, 477 wp<Module> module) 478 : mType(type), mMemory(memory), mModule(module) 479{ 480} 481 482SoundTriggerHwService::CallbackEvent::~CallbackEvent() 483{ 484} 485 486 487#undef LOG_TAG 488#define LOG_TAG "SoundTriggerHwService::Module" 489 490SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service, 491 sound_trigger_hw_device* hwDevice, 492 sound_trigger_module_descriptor descriptor, 493 const sp<ISoundTriggerClient>& client) 494 : mService(service), mHwDevice(hwDevice), mDescriptor(descriptor), 495 mClient(client), mServiceState(SOUND_TRIGGER_STATE_NO_INIT) 496{ 497} 498 499SoundTriggerHwService::Module::~Module() { 500} 501 502void SoundTriggerHwService::Module::detach() { 503 ALOGV("detach()"); 504 if (!captureHotwordAllowed()) { 505 return; 506 } 507 { 508 AutoMutex lock(mLock); 509 for (size_t i = 0; i < mModels.size(); i++) { 510 sp<Model> model = mModels.valueAt(i); 511 ALOGV("detach() unloading model %d", model->mHandle); 512 if (model->mState == Model::STATE_ACTIVE) { 513 mHwDevice->stop_recognition(mHwDevice, model->mHandle); 514 } 515 mHwDevice->unload_sound_model(mHwDevice, model->mHandle); 516 } 517 mModels.clear(); 518 } 519 if (mClient != 0) { 520 IInterface::asBinder(mClient)->unlinkToDeath(this); 521 } 522 sp<SoundTriggerHwService> service = mService.promote(); 523 if (service == 0) { 524 return; 525 } 526 service->detachModule(this); 527} 528 529status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory, 530 sound_model_handle_t *handle) 531{ 532 ALOGV("loadSoundModel() handle"); 533 if (!captureHotwordAllowed()) { 534 return PERMISSION_DENIED; 535 } 536 537 if (modelMemory == 0 || modelMemory->pointer() == NULL) { 538 ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()"); 539 return BAD_VALUE; 540 } 541 struct sound_trigger_sound_model *sound_model = 542 (struct sound_trigger_sound_model *)modelMemory->pointer(); 543 544 AutoMutex lock(mLock); 545 546 if (mModels.size() >= mDescriptor.properties.max_sound_models) { 547 /* Make space for a keyphrase sound model by first trying to swap out a previously loaded 548 * keyphrase sound model, or if needed, another sound model. This decision would optimally 549 * happen in SoundTriggerHelper, but is happening here because state tracking isn't good 550 * enough in SoundTriggerHelper to ensure that state is consistent between it and the HAL, 551 * nor does sufficient error handling exist to recover from inconsistencies. 552 * Once that exists: 553 * TODO: we should return an error instead of unloading a previous sound model here. 554 */ 555 if (mModels.size() == 0) { 556 return INVALID_OPERATION; 557 } 558 if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) { 559 ALOGW("loadSoundModel() max number of models exceeded %d making room for a new one", 560 mDescriptor.properties.max_sound_models); 561 sound_model_handle_t unload_handle = mModels.valueAt(0)->mHandle; 562 for (size_t i = 0; i < mModels.size(); i++) { 563 if (mModels.valueAt(i)->mType == SOUND_MODEL_TYPE_KEYPHRASE) { 564 unload_handle = mModels.keyAt(i); 565 break; 566 } 567 } 568 unloadSoundModel_l(unload_handle); 569 } else { 570 ALOGW("loadSoundModel(): Not loading, max number of models (%d) would be exceeded", 571 mDescriptor.properties.max_sound_models); 572 return INVALID_OPERATION; 573 } 574 } 575 576 status_t status = mHwDevice->load_sound_model(mHwDevice, sound_model, 577 SoundTriggerHwService::soundModelCallback, 578 this, handle); 579 580 if (status != NO_ERROR) { 581 return status; 582 } 583 audio_session_t session; 584 audio_io_handle_t ioHandle; 585 audio_devices_t device; 586 587 status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device); 588 if (status != NO_ERROR) { 589 return status; 590 } 591 592 sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type); 593 mModels.replaceValueFor(*handle, model); 594 595 return status; 596} 597 598status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle) 599{ 600 ALOGV("unloadSoundModel() model handle %d", handle); 601 if (!captureHotwordAllowed()) { 602 return PERMISSION_DENIED; 603 } 604 605 AutoMutex lock(mLock); 606 return unloadSoundModel_l(handle); 607} 608 609status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle) 610{ 611 ssize_t index = mModels.indexOfKey(handle); 612 if (index < 0) { 613 return BAD_VALUE; 614 } 615 sp<Model> model = mModels.valueAt(index); 616 mModels.removeItem(handle); 617 if (model->mState == Model::STATE_ACTIVE) { 618 mHwDevice->stop_recognition(mHwDevice, model->mHandle); 619 model->mState = Model::STATE_IDLE; 620 } 621 AudioSystem::releaseSoundTriggerSession(model->mCaptureSession); 622 return mHwDevice->unload_sound_model(mHwDevice, handle); 623} 624 625status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle, 626 const sp<IMemory>& dataMemory) 627{ 628 ALOGV("startRecognition() model handle %d", handle); 629 if (!captureHotwordAllowed()) { 630 return PERMISSION_DENIED; 631 } 632 633 if (dataMemory != 0 && dataMemory->pointer() == NULL) { 634 ALOGE("startRecognition() dataMemory is non-0 but has NULL pointer()"); 635 return BAD_VALUE; 636 637 } 638 AutoMutex lock(mLock); 639 if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) { 640 return INVALID_OPERATION; 641 } 642 sp<Model> model = getModel(handle); 643 if (model == 0) { 644 return BAD_VALUE; 645 } 646 if ((dataMemory == 0) || 647 (dataMemory->size() < sizeof(struct sound_trigger_recognition_config))) { 648 return BAD_VALUE; 649 } 650 651 if (model->mState == Model::STATE_ACTIVE) { 652 return INVALID_OPERATION; 653 } 654 655 struct sound_trigger_recognition_config *config = 656 (struct sound_trigger_recognition_config *)dataMemory->pointer(); 657 658 //TODO: get capture handle and device from audio policy service 659 config->capture_handle = model->mCaptureIOHandle; 660 config->capture_device = model->mCaptureDevice; 661 status_t status = mHwDevice->start_recognition(mHwDevice, handle, config, 662 SoundTriggerHwService::recognitionCallback, 663 this); 664 665 if (status == NO_ERROR) { 666 model->mState = Model::STATE_ACTIVE; 667 model->mConfig = *config; 668 } 669 670 return status; 671} 672 673status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle) 674{ 675 ALOGV("stopRecognition() model handle %d", handle); 676 if (!captureHotwordAllowed()) { 677 return PERMISSION_DENIED; 678 } 679 680 AutoMutex lock(mLock); 681 sp<Model> model = getModel(handle); 682 if (model == 0) { 683 return BAD_VALUE; 684 } 685 686 if (model->mState != Model::STATE_ACTIVE) { 687 return INVALID_OPERATION; 688 } 689 mHwDevice->stop_recognition(mHwDevice, handle); 690 model->mState = Model::STATE_IDLE; 691 return NO_ERROR; 692} 693 694 695void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event) 696{ 697 ALOGV("onCallbackEvent type %d", event->mType); 698 699 sp<IMemory> eventMemory = event->mMemory; 700 701 if (eventMemory == 0 || eventMemory->pointer() == NULL) { 702 return; 703 } 704 if (mClient == 0) { 705 ALOGI("%s mClient == 0", __func__); 706 return; 707 } 708 709 switch (event->mType) { 710 case CallbackEvent::TYPE_RECOGNITION: { 711 struct sound_trigger_recognition_event *recognitionEvent = 712 (struct sound_trigger_recognition_event *)eventMemory->pointer(); 713 sp<ISoundTriggerClient> client; 714 { 715 AutoMutex lock(mLock); 716 sp<Model> model = getModel(recognitionEvent->model); 717 if (model == 0) { 718 ALOGW("%s model == 0", __func__); 719 return; 720 } 721 if (model->mState != Model::STATE_ACTIVE) { 722 ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState); 723 return; 724 } 725 726 recognitionEvent->capture_session = model->mCaptureSession; 727 model->mState = Model::STATE_IDLE; 728 client = mClient; 729 } 730 if (client != 0) { 731 client->onRecognitionEvent(eventMemory); 732 } 733 } break; 734 case CallbackEvent::TYPE_SOUNDMODEL: { 735 struct sound_trigger_model_event *soundmodelEvent = 736 (struct sound_trigger_model_event *)eventMemory->pointer(); 737 sp<ISoundTriggerClient> client; 738 { 739 AutoMutex lock(mLock); 740 sp<Model> model = getModel(soundmodelEvent->model); 741 if (model == 0) { 742 ALOGW("%s model == 0", __func__); 743 return; 744 } 745 client = mClient; 746 } 747 if (client != 0) { 748 client->onSoundModelEvent(eventMemory); 749 } 750 } break; 751 case CallbackEvent::TYPE_SERVICE_STATE: { 752 sp<ISoundTriggerClient> client; 753 { 754 AutoMutex lock(mLock); 755 client = mClient; 756 } 757 if (client != 0) { 758 client->onServiceStateChange(eventMemory); 759 } 760 } break; 761 default: 762 LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType); 763 } 764} 765 766sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel( 767 sound_model_handle_t handle) 768{ 769 sp<Model> model; 770 ssize_t index = mModels.indexOfKey(handle); 771 if (index >= 0) { 772 model = mModels.valueAt(index); 773 } 774 return model; 775} 776 777void SoundTriggerHwService::Module::binderDied( 778 const wp<IBinder> &who __unused) { 779 ALOGW("client binder died for module %d", mDescriptor.handle); 780 detach(); 781} 782 783// Called with mServiceLock held 784void SoundTriggerHwService::Module::setCaptureState_l(bool active) 785{ 786 ALOGV("Module::setCaptureState_l %d", active); 787 sp<SoundTriggerHwService> service; 788 sound_trigger_service_state_t state; 789 790 Vector< sp<IMemory> > events; 791 { 792 AutoMutex lock(mLock); 793 state = (active && !mDescriptor.properties.concurrent_capture) ? 794 SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED; 795 796 if (state == mServiceState) { 797 return; 798 } 799 800 mServiceState = state; 801 802 service = mService.promote(); 803 if (service == 0) { 804 return; 805 } 806 807 if (state == SOUND_TRIGGER_STATE_ENABLED) { 808 goto exit; 809 } 810 811 for (size_t i = 0; i < mModels.size(); i++) { 812 sp<Model> model = mModels.valueAt(i); 813 if (model->mState == Model::STATE_ACTIVE) { 814 mHwDevice->stop_recognition(mHwDevice, model->mHandle); 815 // keep model in ACTIVE state so that event is processed by onCallbackEvent() 816 if (model->mType == SOUND_MODEL_TYPE_KEYPHRASE) { 817 struct sound_trigger_phrase_recognition_event event; 818 memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event)); 819 event.num_phrases = model->mConfig.num_phrases; 820 for (size_t i = 0; i < event.num_phrases; i++) { 821 event.phrase_extras[i] = model->mConfig.phrases[i]; 822 } 823 event.common.status = RECOGNITION_STATUS_ABORT; 824 event.common.type = model->mType; 825 event.common.model = model->mHandle; 826 event.common.data_size = 0; 827 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common); 828 if (eventMemory != 0) { 829 events.add(eventMemory); 830 } 831 } else if (model->mType == SOUND_MODEL_TYPE_GENERIC) { 832 struct sound_trigger_generic_recognition_event event; 833 memset(&event, 0, sizeof(struct sound_trigger_generic_recognition_event)); 834 event.common.status = RECOGNITION_STATUS_ABORT; 835 event.common.type = model->mType; 836 event.common.model = model->mHandle; 837 event.common.data_size = 0; 838 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common); 839 if (eventMemory != 0) { 840 events.add(eventMemory); 841 } 842 } else if (model->mType == SOUND_MODEL_TYPE_UNKNOWN) { 843 struct sound_trigger_phrase_recognition_event event; 844 memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event)); 845 event.common.status = RECOGNITION_STATUS_ABORT; 846 event.common.type = model->mType; 847 event.common.model = model->mHandle; 848 event.common.data_size = 0; 849 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common); 850 if (eventMemory != 0) { 851 events.add(eventMemory); 852 } 853 } else { 854 goto exit; 855 } 856 } 857 } 858 } 859 860 for (size_t i = 0; i < events.size(); i++) { 861 service->sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i], 862 this)); 863 } 864 865exit: 866 service->sendServiceStateEvent_l(state, this); 867} 868 869 870SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session, 871 audio_io_handle_t ioHandle, audio_devices_t device, 872 sound_trigger_sound_model_type_t type) : 873 mHandle(handle), mState(STATE_IDLE), mCaptureSession(session), 874 mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type) 875{ 876 877} 878 879status_t SoundTriggerHwService::Module::dump(int fd __unused, 880 const Vector<String16>& args __unused) { 881 String8 result; 882 return NO_ERROR; 883} 884 885}; // namespace android 886