SoundTriggerHwService.cpp revision 00a727c430c474f77f8835675a9d773f0314fb68
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 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 if (mModels.size() == 0) { 548 return INVALID_OPERATION; 549 } 550 ALOGW("loadSoundModel() max number of models exceeded %d making room for a new one", 551 mDescriptor.properties.max_sound_models); 552 unloadSoundModel_l(mModels.valueAt(0)->mHandle); 553 } 554 555 status_t status = mHwDevice->load_sound_model(mHwDevice, 556 sound_model, 557 SoundTriggerHwService::soundModelCallback, 558 this, 559 handle); 560 if (status != NO_ERROR) { 561 return status; 562 } 563 audio_session_t session; 564 audio_io_handle_t ioHandle; 565 audio_devices_t device; 566 567 status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device); 568 if (status != NO_ERROR) { 569 return status; 570 } 571 572 sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type); 573 mModels.replaceValueFor(*handle, model); 574 575 return status; 576} 577 578status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle) 579{ 580 ALOGV("unloadSoundModel() model handle %d", handle); 581 if (!captureHotwordAllowed()) { 582 return PERMISSION_DENIED; 583 } 584 585 AutoMutex lock(mLock); 586 return unloadSoundModel_l(handle); 587} 588 589status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle) 590{ 591 ssize_t index = mModels.indexOfKey(handle); 592 if (index < 0) { 593 return BAD_VALUE; 594 } 595 sp<Model> model = mModels.valueAt(index); 596 mModels.removeItem(handle); 597 if (model->mState == Model::STATE_ACTIVE) { 598 mHwDevice->stop_recognition(mHwDevice, model->mHandle); 599 model->mState = Model::STATE_IDLE; 600 } 601 AudioSystem::releaseSoundTriggerSession(model->mCaptureSession); 602 return mHwDevice->unload_sound_model(mHwDevice, handle); 603} 604 605status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle, 606 const sp<IMemory>& dataMemory) 607{ 608 ALOGV("startRecognition() model handle %d", handle); 609 if (!captureHotwordAllowed()) { 610 return PERMISSION_DENIED; 611 } 612 613 if (dataMemory != 0 && dataMemory->pointer() == NULL) { 614 ALOGE("startRecognition() dataMemory is non-0 but has NULL pointer()"); 615 return BAD_VALUE; 616 617 } 618 AutoMutex lock(mLock); 619 if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) { 620 return INVALID_OPERATION; 621 } 622 sp<Model> model = getModel(handle); 623 if (model == 0) { 624 return BAD_VALUE; 625 } 626 if ((dataMemory == 0) || 627 (dataMemory->size() < sizeof(struct sound_trigger_recognition_config))) { 628 return BAD_VALUE; 629 } 630 631 if (model->mState == Model::STATE_ACTIVE) { 632 return INVALID_OPERATION; 633 } 634 635 struct sound_trigger_recognition_config *config = 636 (struct sound_trigger_recognition_config *)dataMemory->pointer(); 637 638 //TODO: get capture handle and device from audio policy service 639 config->capture_handle = model->mCaptureIOHandle; 640 config->capture_device = model->mCaptureDevice; 641 status_t status = mHwDevice->start_recognition(mHwDevice, handle, config, 642 SoundTriggerHwService::recognitionCallback, 643 this); 644 645 if (status == NO_ERROR) { 646 model->mState = Model::STATE_ACTIVE; 647 model->mConfig = *config; 648 } 649 650 return status; 651} 652 653status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle) 654{ 655 ALOGV("stopRecognition() model handle %d", handle); 656 if (!captureHotwordAllowed()) { 657 return PERMISSION_DENIED; 658 } 659 660 AutoMutex lock(mLock); 661 sp<Model> model = getModel(handle); 662 if (model == 0) { 663 return BAD_VALUE; 664 } 665 666 if (model->mState != Model::STATE_ACTIVE) { 667 return INVALID_OPERATION; 668 } 669 mHwDevice->stop_recognition(mHwDevice, handle); 670 model->mState = Model::STATE_IDLE; 671 return NO_ERROR; 672} 673 674 675void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event) 676{ 677 ALOGV("onCallbackEvent type %d", event->mType); 678 679 sp<IMemory> eventMemory = event->mMemory; 680 681 if (eventMemory == 0 || eventMemory->pointer() == NULL) { 682 return; 683 } 684 if (mClient == 0) { 685 ALOGI("%s mClient == 0", __func__); 686 return; 687 } 688 689 switch (event->mType) { 690 case CallbackEvent::TYPE_RECOGNITION: { 691 struct sound_trigger_recognition_event *recognitionEvent = 692 (struct sound_trigger_recognition_event *)eventMemory->pointer(); 693 sp<ISoundTriggerClient> client; 694 { 695 AutoMutex lock(mLock); 696 sp<Model> model = getModel(recognitionEvent->model); 697 if (model == 0) { 698 ALOGW("%s model == 0", __func__); 699 return; 700 } 701 if (model->mState != Model::STATE_ACTIVE) { 702 ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState); 703 return; 704 } 705 706 recognitionEvent->capture_session = model->mCaptureSession; 707 model->mState = Model::STATE_IDLE; 708 client = mClient; 709 } 710 if (client != 0) { 711 client->onRecognitionEvent(eventMemory); 712 } 713 } break; 714 case CallbackEvent::TYPE_SOUNDMODEL: { 715 struct sound_trigger_model_event *soundmodelEvent = 716 (struct sound_trigger_model_event *)eventMemory->pointer(); 717 sp<ISoundTriggerClient> client; 718 { 719 AutoMutex lock(mLock); 720 sp<Model> model = getModel(soundmodelEvent->model); 721 if (model == 0) { 722 ALOGW("%s model == 0", __func__); 723 return; 724 } 725 client = mClient; 726 } 727 if (client != 0) { 728 client->onSoundModelEvent(eventMemory); 729 } 730 } break; 731 case CallbackEvent::TYPE_SERVICE_STATE: { 732 sp<ISoundTriggerClient> client; 733 { 734 AutoMutex lock(mLock); 735 client = mClient; 736 } 737 if (client != 0) { 738 client->onServiceStateChange(eventMemory); 739 } 740 } break; 741 default: 742 LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType); 743 } 744} 745 746sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel( 747 sound_model_handle_t handle) 748{ 749 sp<Model> model; 750 ssize_t index = mModels.indexOfKey(handle); 751 if (index >= 0) { 752 model = mModels.valueAt(index); 753 } 754 return model; 755} 756 757void SoundTriggerHwService::Module::binderDied( 758 const wp<IBinder> &who __unused) { 759 ALOGW("client binder died for module %d", mDescriptor.handle); 760 detach(); 761} 762 763// Called with mServiceLock held 764void SoundTriggerHwService::Module::setCaptureState_l(bool active) 765{ 766 ALOGV("Module::setCaptureState_l %d", active); 767 sp<SoundTriggerHwService> service; 768 sound_trigger_service_state_t state; 769 770 Vector< sp<IMemory> > events; 771 { 772 AutoMutex lock(mLock); 773 state = (active && !mDescriptor.properties.concurrent_capture) ? 774 SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED; 775 776 if (state == mServiceState) { 777 return; 778 } 779 780 mServiceState = state; 781 782 service = mService.promote(); 783 if (service == 0) { 784 return; 785 } 786 787 if (state == SOUND_TRIGGER_STATE_ENABLED) { 788 goto exit; 789 } 790 791 for (size_t i = 0; i < mModels.size(); i++) { 792 sp<Model> model = mModels.valueAt(i); 793 if (model->mState == Model::STATE_ACTIVE) { 794 mHwDevice->stop_recognition(mHwDevice, model->mHandle); 795 // keep model in ACTIVE state so that event is processed by onCallbackEvent() 796 if (model->mType == SOUND_MODEL_TYPE_KEYPHRASE) { 797 struct sound_trigger_phrase_recognition_event event; 798 memset(&event, 0, sizeof(struct sound_trigger_phrase_recognition_event)); 799 event.num_phrases = model->mConfig.num_phrases; 800 for (size_t i = 0; i < event.num_phrases; i++) { 801 event.phrase_extras[i] = model->mConfig.phrases[i]; 802 } 803 event.common.status = RECOGNITION_STATUS_ABORT; 804 event.common.type = model->mType; 805 event.common.model = model->mHandle; 806 event.common.data_size = 0; 807 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common); 808 if (eventMemory != 0) { 809 events.add(eventMemory); 810 } 811 } else if (model->mType == SOUND_MODEL_TYPE_GENERIC) { 812 struct sound_trigger_generic_recognition_event event; 813 memset(&event, 0, sizeof(struct sound_trigger_generic_recognition_event)); 814 event.common.status = RECOGNITION_STATUS_ABORT; 815 event.common.type = model->mType; 816 event.common.model = model->mHandle; 817 event.common.data_size = 0; 818 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&event.common); 819 if (eventMemory != 0) { 820 events.add(eventMemory); 821 } 822 } else { 823 goto exit; 824 } 825 } 826 } 827 } 828 829 for (size_t i = 0; i < events.size(); i++) { 830 service->sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i], 831 this)); 832 } 833 834exit: 835 service->sendServiceStateEvent_l(state, this); 836} 837 838 839SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session, 840 audio_io_handle_t ioHandle, audio_devices_t device, 841 sound_trigger_sound_model_type_t type) : 842 mHandle(handle), mState(STATE_IDLE), mCaptureSession(session), 843 mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type) 844{ 845 846} 847 848status_t SoundTriggerHwService::Module::dump(int fd __unused, 849 const Vector<String16>& args __unused) { 850 String8 result; 851 return NO_ERROR; 852} 853 854}; // namespace android 855