SoundTriggerHwService.cpp revision df3dc7e2fe6c639529b70e3f3a7d2bf0f4c6e871
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, "primary", 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, "primary", 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 client->asBinder()->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_UNKNOWN: 245 ALOGW_IF(event->data_size != 0 && event->data_offset != 246 sizeof(struct sound_trigger_recognition_event), 247 "prepareRecognitionEvent_l(): invalid data offset %u for unknown event type", 248 event->data_offset); 249 event->data_offset = sizeof(struct sound_trigger_recognition_event); 250 break; 251 default: 252 return eventMemory; 253 } 254 255 size_t size = event->data_offset + event->data_size; 256 eventMemory = mMemoryDealer->allocate(size); 257 if (eventMemory == 0 || eventMemory->pointer() == NULL) { 258 eventMemory.clear(); 259 return eventMemory; 260 } 261 memcpy(eventMemory->pointer(), event, size); 262 263 return eventMemory; 264} 265 266void SoundTriggerHwService::sendRecognitionEvent(struct sound_trigger_recognition_event *event, 267 Module *module) 268 { 269 AutoMutex lock(mServiceLock); 270 if (module == NULL) { 271 return; 272 } 273 sp<IMemory> eventMemory = prepareRecognitionEvent_l(event); 274 if (eventMemory == 0) { 275 return; 276 } 277 sp<Module> strongModule; 278 for (size_t i = 0; i < mModules.size(); i++) { 279 if (mModules.valueAt(i).get() == module) { 280 strongModule = mModules.valueAt(i); 281 break; 282 } 283 } 284 if (strongModule == 0) { 285 return; 286 } 287 288 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, 289 eventMemory, strongModule)); 290} 291 292// static 293void SoundTriggerHwService::soundModelCallback(struct sound_trigger_model_event *event, 294 void *cookie) 295{ 296 Module *module = (Module *)cookie; 297 if (module == NULL) { 298 return; 299 } 300 sp<SoundTriggerHwService> service = module->service().promote(); 301 if (service == 0) { 302 return; 303 } 304 305 service->sendSoundModelEvent(event, module); 306} 307 308sp<IMemory> SoundTriggerHwService::prepareSoundModelEvent_l(struct sound_trigger_model_event *event) 309{ 310 sp<IMemory> eventMemory; 311 312 size_t size = event->data_offset + event->data_size; 313 eventMemory = mMemoryDealer->allocate(size); 314 if (eventMemory == 0 || eventMemory->pointer() == NULL) { 315 eventMemory.clear(); 316 return eventMemory; 317 } 318 memcpy(eventMemory->pointer(), event, size); 319 320 return eventMemory; 321} 322 323void SoundTriggerHwService::sendSoundModelEvent(struct sound_trigger_model_event *event, 324 Module *module) 325{ 326 AutoMutex lock(mServiceLock); 327 sp<IMemory> eventMemory = prepareSoundModelEvent_l(event); 328 if (eventMemory == 0) { 329 return; 330 } 331 sp<Module> strongModule; 332 for (size_t i = 0; i < mModules.size(); i++) { 333 if (mModules.valueAt(i).get() == module) { 334 strongModule = mModules.valueAt(i); 335 break; 336 } 337 } 338 if (strongModule == 0) { 339 return; 340 } 341 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SOUNDMODEL, 342 eventMemory, strongModule)); 343} 344 345 346sp<IMemory> SoundTriggerHwService::prepareServiceStateEvent_l(sound_trigger_service_state_t state) 347{ 348 sp<IMemory> eventMemory; 349 350 size_t size = sizeof(sound_trigger_service_state_t); 351 eventMemory = mMemoryDealer->allocate(size); 352 if (eventMemory == 0 || eventMemory->pointer() == NULL) { 353 eventMemory.clear(); 354 return eventMemory; 355 } 356 *((sound_trigger_service_state_t *)eventMemory->pointer()) = state; 357 return eventMemory; 358} 359 360// call with mServiceLock held 361void SoundTriggerHwService::sendServiceStateEvent_l(sound_trigger_service_state_t state, 362 Module *module) 363{ 364 sp<IMemory> eventMemory = prepareServiceStateEvent_l(state); 365 if (eventMemory == 0) { 366 return; 367 } 368 sp<Module> strongModule; 369 for (size_t i = 0; i < mModules.size(); i++) { 370 if (mModules.valueAt(i).get() == module) { 371 strongModule = mModules.valueAt(i); 372 break; 373 } 374 } 375 if (strongModule == 0) { 376 return; 377 } 378 sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_SERVICE_STATE, 379 eventMemory, strongModule)); 380} 381 382// call with mServiceLock held 383void SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event) 384{ 385 mCallbackThread->sendCallbackEvent(event); 386} 387 388void SoundTriggerHwService::onCallbackEvent(const sp<CallbackEvent>& event) 389{ 390 ALOGV("onCallbackEvent"); 391 sp<Module> module; 392 { 393 AutoMutex lock(mServiceLock); 394 module = event->mModule.promote(); 395 if (module == 0) { 396 return; 397 } 398 } 399 module->onCallbackEvent(event); 400 { 401 AutoMutex lock(mServiceLock); 402 // clear now to execute with mServiceLock locked 403 event->mMemory.clear(); 404 } 405} 406 407#undef LOG_TAG 408#define LOG_TAG "SoundTriggerHwService::CallbackThread" 409 410SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service) 411 : mService(service) 412{ 413} 414 415SoundTriggerHwService::CallbackThread::~CallbackThread() 416{ 417 while (!mEventQueue.isEmpty()) { 418 mEventQueue[0]->mMemory.clear(); 419 mEventQueue.removeAt(0); 420 } 421} 422 423void SoundTriggerHwService::CallbackThread::onFirstRef() 424{ 425 run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO); 426} 427 428bool SoundTriggerHwService::CallbackThread::threadLoop() 429{ 430 while (!exitPending()) { 431 sp<CallbackEvent> event; 432 sp<SoundTriggerHwService> service; 433 { 434 Mutex::Autolock _l(mCallbackLock); 435 while (mEventQueue.isEmpty() && !exitPending()) { 436 ALOGV("CallbackThread::threadLoop() sleep"); 437 mCallbackCond.wait(mCallbackLock); 438 ALOGV("CallbackThread::threadLoop() wake up"); 439 } 440 if (exitPending()) { 441 break; 442 } 443 event = mEventQueue[0]; 444 mEventQueue.removeAt(0); 445 service = mService.promote(); 446 } 447 if (service != 0) { 448 service->onCallbackEvent(event); 449 } 450 } 451 return false; 452} 453 454void SoundTriggerHwService::CallbackThread::exit() 455{ 456 Mutex::Autolock _l(mCallbackLock); 457 requestExit(); 458 mCallbackCond.broadcast(); 459} 460 461void SoundTriggerHwService::CallbackThread::sendCallbackEvent( 462 const sp<SoundTriggerHwService::CallbackEvent>& event) 463{ 464 AutoMutex lock(mCallbackLock); 465 mEventQueue.add(event); 466 mCallbackCond.signal(); 467} 468 469SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory, 470 wp<Module> module) 471 : mType(type), mMemory(memory), mModule(module) 472{ 473} 474 475SoundTriggerHwService::CallbackEvent::~CallbackEvent() 476{ 477} 478 479 480#undef LOG_TAG 481#define LOG_TAG "SoundTriggerHwService::Module" 482 483SoundTriggerHwService::Module::Module(const sp<SoundTriggerHwService>& service, 484 sound_trigger_hw_device* hwDevice, 485 sound_trigger_module_descriptor descriptor, 486 const sp<ISoundTriggerClient>& client) 487 : mService(service), mHwDevice(hwDevice), mDescriptor(descriptor), 488 mClient(client), mServiceState(SOUND_TRIGGER_STATE_NO_INIT) 489{ 490} 491 492SoundTriggerHwService::Module::~Module() { 493} 494 495void SoundTriggerHwService::Module::detach() { 496 ALOGV("detach()"); 497 if (!captureHotwordAllowed()) { 498 return; 499 } 500 { 501 AutoMutex lock(mLock); 502 for (size_t i = 0; i < mModels.size(); i++) { 503 sp<Model> model = mModels.valueAt(i); 504 ALOGV("detach() unloading model %d", model->mHandle); 505 if (model->mState == Model::STATE_ACTIVE) { 506 mHwDevice->stop_recognition(mHwDevice, model->mHandle); 507 } 508 mHwDevice->unload_sound_model(mHwDevice, model->mHandle); 509 } 510 mModels.clear(); 511 } 512 if (mClient != 0) { 513 mClient->asBinder()->unlinkToDeath(this); 514 } 515 sp<SoundTriggerHwService> service = mService.promote(); 516 if (service == 0) { 517 return; 518 } 519 service->detachModule(this); 520} 521 522status_t SoundTriggerHwService::Module::loadSoundModel(const sp<IMemory>& modelMemory, 523 sound_model_handle_t *handle) 524{ 525 ALOGV("loadSoundModel() handle"); 526 if (!captureHotwordAllowed()) { 527 return PERMISSION_DENIED; 528 } 529 530 if (modelMemory == 0 || modelMemory->pointer() == NULL) { 531 ALOGE("loadSoundModel() modelMemory is 0 or has NULL pointer()"); 532 return BAD_VALUE; 533 } 534 struct sound_trigger_sound_model *sound_model = 535 (struct sound_trigger_sound_model *)modelMemory->pointer(); 536 537 AutoMutex lock(mLock); 538 status_t status = mHwDevice->load_sound_model(mHwDevice, 539 sound_model, 540 SoundTriggerHwService::soundModelCallback, 541 this, 542 handle); 543 if (status != NO_ERROR) { 544 return status; 545 } 546 audio_session_t session; 547 audio_io_handle_t ioHandle; 548 audio_devices_t device; 549 550 status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device); 551 if (status != NO_ERROR) { 552 return status; 553 } 554 555 sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type); 556 mModels.replaceValueFor(*handle, model); 557 558 return status; 559} 560 561status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle) 562{ 563 ALOGV("unloadSoundModel() model handle %d", handle); 564 if (!captureHotwordAllowed()) { 565 return PERMISSION_DENIED; 566 } 567 568 AutoMutex lock(mLock); 569 ssize_t index = mModels.indexOfKey(handle); 570 if (index < 0) { 571 return BAD_VALUE; 572 } 573 sp<Model> model = mModels.valueAt(index); 574 mModels.removeItem(handle); 575 if (model->mState == Model::STATE_ACTIVE) { 576 mHwDevice->stop_recognition(mHwDevice, model->mHandle); 577 } 578 AudioSystem::releaseSoundTriggerSession(model->mCaptureSession); 579 return mHwDevice->unload_sound_model(mHwDevice, handle); 580} 581 582status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle, 583 const sp<IMemory>& dataMemory) 584{ 585 ALOGV("startRecognition() model handle %d", handle); 586 if (!captureHotwordAllowed()) { 587 return PERMISSION_DENIED; 588 } 589 590 if (dataMemory != 0 && dataMemory->pointer() == NULL) { 591 ALOGE("startRecognition() dataMemory is non-0 but has NULL pointer()"); 592 return BAD_VALUE; 593 594 } 595 AutoMutex lock(mLock); 596 if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) { 597 return INVALID_OPERATION; 598 } 599 sp<Model> model = getModel(handle); 600 if (model == 0) { 601 return BAD_VALUE; 602 } 603 if ((dataMemory == 0) || 604 (dataMemory->size() < sizeof(struct sound_trigger_recognition_config))) { 605 return BAD_VALUE; 606 } 607 608 if (model->mState == Model::STATE_ACTIVE) { 609 return INVALID_OPERATION; 610 } 611 612 struct sound_trigger_recognition_config *config = 613 (struct sound_trigger_recognition_config *)dataMemory->pointer(); 614 615 //TODO: get capture handle and device from audio policy service 616 config->capture_handle = model->mCaptureIOHandle; 617 config->capture_device = model->mCaptureDevice; 618 status_t status = mHwDevice->start_recognition(mHwDevice, handle, config, 619 SoundTriggerHwService::recognitionCallback, 620 this); 621 622 if (status == NO_ERROR) { 623 model->mState = Model::STATE_ACTIVE; 624 model->mConfig = *config; 625 } 626 627 return status; 628} 629 630status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle) 631{ 632 ALOGV("stopRecognition() model handle %d", handle); 633 if (!captureHotwordAllowed()) { 634 return PERMISSION_DENIED; 635 } 636 637 AutoMutex lock(mLock); 638 sp<Model> model = getModel(handle); 639 if (model == 0) { 640 return BAD_VALUE; 641 } 642 643 if (model->mState != Model::STATE_ACTIVE) { 644 return INVALID_OPERATION; 645 } 646 mHwDevice->stop_recognition(mHwDevice, handle); 647 model->mState = Model::STATE_IDLE; 648 return NO_ERROR; 649} 650 651 652void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event) 653{ 654 ALOGV("onCallbackEvent type %d", event->mType); 655 656 AutoMutex lock(mLock); 657 sp<IMemory> eventMemory = event->mMemory; 658 659 if (eventMemory == 0 || eventMemory->pointer() == NULL) { 660 return; 661 } 662 if (mClient == 0) { 663 ALOGI("%s mClient == 0", __func__); 664 return; 665 } 666 667 switch (event->mType) { 668 case CallbackEvent::TYPE_RECOGNITION: { 669 struct sound_trigger_recognition_event *recognitionEvent = 670 (struct sound_trigger_recognition_event *)eventMemory->pointer(); 671 672 sp<Model> model = getModel(recognitionEvent->model); 673 if (model == 0) { 674 ALOGW("%s model == 0", __func__); 675 return; 676 } 677 if (model->mState != Model::STATE_ACTIVE) { 678 ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState); 679 return; 680 } 681 682 recognitionEvent->capture_session = model->mCaptureSession; 683 mClient->onRecognitionEvent(eventMemory); 684 model->mState = Model::STATE_IDLE; 685 } break; 686 case CallbackEvent::TYPE_SOUNDMODEL: { 687 struct sound_trigger_model_event *soundmodelEvent = 688 (struct sound_trigger_model_event *)eventMemory->pointer(); 689 690 sp<Model> model = getModel(soundmodelEvent->model); 691 if (model == 0) { 692 ALOGW("%s model == 0", __func__); 693 return; 694 } 695 mClient->onSoundModelEvent(eventMemory); 696 } break; 697 case CallbackEvent::TYPE_SERVICE_STATE: { 698 mClient->onServiceStateChange(eventMemory); 699 } break; 700 default: 701 LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType); 702 } 703} 704 705sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel( 706 sound_model_handle_t handle) 707{ 708 sp<Model> model; 709 ssize_t index = mModels.indexOfKey(handle); 710 if (index >= 0) { 711 model = mModels.valueAt(index); 712 } 713 return model; 714} 715 716void SoundTriggerHwService::Module::binderDied( 717 const wp<IBinder> &who __unused) { 718 ALOGW("client binder died for module %d", mDescriptor.handle); 719 detach(); 720} 721 722// Called with mServiceLock held 723void SoundTriggerHwService::Module::setCaptureState_l(bool active) 724{ 725 ALOGV("Module::setCaptureState_l %d", active); 726 sp<SoundTriggerHwService> service; 727 sound_trigger_service_state_t state; 728 729 Vector< sp<IMemory> > events; 730 { 731 AutoMutex lock(mLock); 732 state = (active && !mDescriptor.properties.concurrent_capture) ? 733 SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED; 734 735 if (state == mServiceState) { 736 return; 737 } 738 739 mServiceState = state; 740 741 service = mService.promote(); 742 if (service == 0) { 743 return; 744 } 745 746 if (state == SOUND_TRIGGER_STATE_ENABLED) { 747 goto exit; 748 } 749 750 for (size_t i = 0; i < mModels.size(); i++) { 751 sp<Model> model = mModels.valueAt(i); 752 if (model->mState == Model::STATE_ACTIVE) { 753 mHwDevice->stop_recognition(mHwDevice, model->mHandle); 754 // keep model in ACTIVE state so that event is processed by onCallbackEvent() 755 struct sound_trigger_phrase_recognition_event phraseEvent; 756 switch (model->mType) { 757 case SOUND_MODEL_TYPE_KEYPHRASE: 758 phraseEvent.num_phrases = model->mConfig.num_phrases; 759 for (size_t i = 0; i < phraseEvent.num_phrases; i++) { 760 phraseEvent.phrase_extras[i] = model->mConfig.phrases[i]; 761 } 762 break; 763 case SOUND_MODEL_TYPE_UNKNOWN: 764 default: 765 break; 766 } 767 phraseEvent.common.status = RECOGNITION_STATUS_ABORT; 768 phraseEvent.common.type = model->mType; 769 phraseEvent.common.model = model->mHandle; 770 phraseEvent.common.data_size = 0; 771 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&phraseEvent.common); 772 if (eventMemory != 0) { 773 events.add(eventMemory); 774 } 775 } 776 } 777 } 778 779 for (size_t i = 0; i < events.size(); i++) { 780 service->sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i], 781 this)); 782 } 783 784exit: 785 service->sendServiceStateEvent_l(state, this); 786} 787 788 789SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session, 790 audio_io_handle_t ioHandle, audio_devices_t device, 791 sound_trigger_sound_model_type_t type) : 792 mHandle(handle), mState(STATE_IDLE), mCaptureSession(session), 793 mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type) 794{ 795 796} 797 798status_t SoundTriggerHwService::Module::dump(int fd __unused, 799 const Vector<String16>& args __unused) { 800 String8 result; 801 return NO_ERROR; 802} 803 804}; // namespace android 805