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 39 namespace 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 47 SoundTriggerHwService::SoundTriggerHwService() 48 : BnSoundTriggerHwService(), 49 mNextUniqueId(1), 50 mMemoryDealer(new MemoryDealer(1024 * 1024, "SoundTriggerHwService")), 51 mCaptureState(false) 52 { 53 } 54 55 void 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 95 SoundTriggerHwService::~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 105 status_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 125 status_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 154 status_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 166 void SoundTriggerHwService::detachModule(sp<Module> module) 167 { 168 ALOGV("detachModule"); 169 AutoMutex lock(mServiceLock); 170 module->clearClient(); 171 } 172 173 174 static const int kDumpLockRetries = 50; 175 static const int kDumpLockSleep = 60000; 176 177 static 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 190 status_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 208 status_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 215 void 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 230 sp<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 266 void 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 293 void 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 308 sp<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 323 void 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 346 sp<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 361 void 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 383 void SoundTriggerHwService::sendCallbackEvent_l(const sp<CallbackEvent>& event) 384 { 385 mCallbackThread->sendCallbackEvent(event); 386 } 387 388 void 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 410 SoundTriggerHwService::CallbackThread::CallbackThread(const wp<SoundTriggerHwService>& service) 411 : mService(service) 412 { 413 } 414 415 SoundTriggerHwService::CallbackThread::~CallbackThread() 416 { 417 while (!mEventQueue.isEmpty()) { 418 mEventQueue[0]->mMemory.clear(); 419 mEventQueue.removeAt(0); 420 } 421 } 422 423 void SoundTriggerHwService::CallbackThread::onFirstRef() 424 { 425 run("soundTrigger cbk", ANDROID_PRIORITY_URGENT_AUDIO); 426 } 427 428 bool 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 454 void SoundTriggerHwService::CallbackThread::exit() 455 { 456 Mutex::Autolock _l(mCallbackLock); 457 requestExit(); 458 mCallbackCond.broadcast(); 459 } 460 461 void SoundTriggerHwService::CallbackThread::sendCallbackEvent( 462 const sp<SoundTriggerHwService::CallbackEvent>& event) 463 { 464 AutoMutex lock(mCallbackLock); 465 mEventQueue.add(event); 466 mCallbackCond.signal(); 467 } 468 469 SoundTriggerHwService::CallbackEvent::CallbackEvent(event_type type, sp<IMemory> memory, 470 wp<Module> module) 471 : mType(type), mMemory(memory), mModule(module) 472 { 473 } 474 475 SoundTriggerHwService::CallbackEvent::~CallbackEvent() 476 { 477 } 478 479 480 #undef LOG_TAG 481 #define LOG_TAG "SoundTriggerHwService::Module" 482 483 SoundTriggerHwService::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 492 SoundTriggerHwService::Module::~Module() { 493 } 494 495 void 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 522 status_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 539 if (mModels.size() >= mDescriptor.properties.max_sound_models) { 540 if (mModels.size() == 0) { 541 return INVALID_OPERATION; 542 } 543 ALOGW("loadSoundModel() max number of models exceeded %d making room for a new one", 544 mDescriptor.properties.max_sound_models); 545 unloadSoundModel_l(mModels.valueAt(0)->mHandle); 546 } 547 548 status_t status = mHwDevice->load_sound_model(mHwDevice, 549 sound_model, 550 SoundTriggerHwService::soundModelCallback, 551 this, 552 handle); 553 if (status != NO_ERROR) { 554 return status; 555 } 556 audio_session_t session; 557 audio_io_handle_t ioHandle; 558 audio_devices_t device; 559 560 status = AudioSystem::acquireSoundTriggerSession(&session, &ioHandle, &device); 561 if (status != NO_ERROR) { 562 return status; 563 } 564 565 sp<Model> model = new Model(*handle, session, ioHandle, device, sound_model->type); 566 mModels.replaceValueFor(*handle, model); 567 568 return status; 569 } 570 571 status_t SoundTriggerHwService::Module::unloadSoundModel(sound_model_handle_t handle) 572 { 573 ALOGV("unloadSoundModel() model handle %d", handle); 574 if (!captureHotwordAllowed()) { 575 return PERMISSION_DENIED; 576 } 577 578 AutoMutex lock(mLock); 579 return unloadSoundModel_l(handle); 580 } 581 582 status_t SoundTriggerHwService::Module::unloadSoundModel_l(sound_model_handle_t handle) 583 { 584 ssize_t index = mModels.indexOfKey(handle); 585 if (index < 0) { 586 return BAD_VALUE; 587 } 588 sp<Model> model = mModels.valueAt(index); 589 mModels.removeItem(handle); 590 if (model->mState == Model::STATE_ACTIVE) { 591 mHwDevice->stop_recognition(mHwDevice, model->mHandle); 592 model->mState = Model::STATE_IDLE; 593 } 594 AudioSystem::releaseSoundTriggerSession(model->mCaptureSession); 595 return mHwDevice->unload_sound_model(mHwDevice, handle); 596 } 597 598 status_t SoundTriggerHwService::Module::startRecognition(sound_model_handle_t handle, 599 const sp<IMemory>& dataMemory) 600 { 601 ALOGV("startRecognition() model handle %d", handle); 602 if (!captureHotwordAllowed()) { 603 return PERMISSION_DENIED; 604 } 605 606 if (dataMemory != 0 && dataMemory->pointer() == NULL) { 607 ALOGE("startRecognition() dataMemory is non-0 but has NULL pointer()"); 608 return BAD_VALUE; 609 610 } 611 AutoMutex lock(mLock); 612 if (mServiceState == SOUND_TRIGGER_STATE_DISABLED) { 613 return INVALID_OPERATION; 614 } 615 sp<Model> model = getModel(handle); 616 if (model == 0) { 617 return BAD_VALUE; 618 } 619 if ((dataMemory == 0) || 620 (dataMemory->size() < sizeof(struct sound_trigger_recognition_config))) { 621 return BAD_VALUE; 622 } 623 624 if (model->mState == Model::STATE_ACTIVE) { 625 return INVALID_OPERATION; 626 } 627 628 struct sound_trigger_recognition_config *config = 629 (struct sound_trigger_recognition_config *)dataMemory->pointer(); 630 631 //TODO: get capture handle and device from audio policy service 632 config->capture_handle = model->mCaptureIOHandle; 633 config->capture_device = model->mCaptureDevice; 634 status_t status = mHwDevice->start_recognition(mHwDevice, handle, config, 635 SoundTriggerHwService::recognitionCallback, 636 this); 637 638 if (status == NO_ERROR) { 639 model->mState = Model::STATE_ACTIVE; 640 model->mConfig = *config; 641 } 642 643 return status; 644 } 645 646 status_t SoundTriggerHwService::Module::stopRecognition(sound_model_handle_t handle) 647 { 648 ALOGV("stopRecognition() model handle %d", handle); 649 if (!captureHotwordAllowed()) { 650 return PERMISSION_DENIED; 651 } 652 653 AutoMutex lock(mLock); 654 sp<Model> model = getModel(handle); 655 if (model == 0) { 656 return BAD_VALUE; 657 } 658 659 if (model->mState != Model::STATE_ACTIVE) { 660 return INVALID_OPERATION; 661 } 662 mHwDevice->stop_recognition(mHwDevice, handle); 663 model->mState = Model::STATE_IDLE; 664 return NO_ERROR; 665 } 666 667 668 void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event) 669 { 670 ALOGV("onCallbackEvent type %d", event->mType); 671 672 sp<IMemory> eventMemory = event->mMemory; 673 674 if (eventMemory == 0 || eventMemory->pointer() == NULL) { 675 return; 676 } 677 if (mClient == 0) { 678 ALOGI("%s mClient == 0", __func__); 679 return; 680 } 681 682 switch (event->mType) { 683 case CallbackEvent::TYPE_RECOGNITION: { 684 struct sound_trigger_recognition_event *recognitionEvent = 685 (struct sound_trigger_recognition_event *)eventMemory->pointer(); 686 sp<ISoundTriggerClient> client; 687 { 688 AutoMutex lock(mLock); 689 sp<Model> model = getModel(recognitionEvent->model); 690 if (model == 0) { 691 ALOGW("%s model == 0", __func__); 692 return; 693 } 694 if (model->mState != Model::STATE_ACTIVE) { 695 ALOGV("onCallbackEvent model->mState %d != Model::STATE_ACTIVE", model->mState); 696 return; 697 } 698 699 recognitionEvent->capture_session = model->mCaptureSession; 700 model->mState = Model::STATE_IDLE; 701 client = mClient; 702 } 703 if (client != 0) { 704 client->onRecognitionEvent(eventMemory); 705 } 706 } break; 707 case CallbackEvent::TYPE_SOUNDMODEL: { 708 struct sound_trigger_model_event *soundmodelEvent = 709 (struct sound_trigger_model_event *)eventMemory->pointer(); 710 sp<ISoundTriggerClient> client; 711 { 712 AutoMutex lock(mLock); 713 sp<Model> model = getModel(soundmodelEvent->model); 714 if (model == 0) { 715 ALOGW("%s model == 0", __func__); 716 return; 717 } 718 client = mClient; 719 } 720 if (client != 0) { 721 client->onSoundModelEvent(eventMemory); 722 } 723 } break; 724 case CallbackEvent::TYPE_SERVICE_STATE: { 725 sp<ISoundTriggerClient> client; 726 { 727 AutoMutex lock(mLock); 728 client = mClient; 729 } 730 if (client != 0) { 731 client->onServiceStateChange(eventMemory); 732 } 733 } break; 734 default: 735 LOG_ALWAYS_FATAL("onCallbackEvent unknown event type %d", event->mType); 736 } 737 } 738 739 sp<SoundTriggerHwService::Model> SoundTriggerHwService::Module::getModel( 740 sound_model_handle_t handle) 741 { 742 sp<Model> model; 743 ssize_t index = mModels.indexOfKey(handle); 744 if (index >= 0) { 745 model = mModels.valueAt(index); 746 } 747 return model; 748 } 749 750 void SoundTriggerHwService::Module::binderDied( 751 const wp<IBinder> &who __unused) { 752 ALOGW("client binder died for module %d", mDescriptor.handle); 753 detach(); 754 } 755 756 // Called with mServiceLock held 757 void SoundTriggerHwService::Module::setCaptureState_l(bool active) 758 { 759 ALOGV("Module::setCaptureState_l %d", active); 760 sp<SoundTriggerHwService> service; 761 sound_trigger_service_state_t state; 762 763 Vector< sp<IMemory> > events; 764 { 765 AutoMutex lock(mLock); 766 state = (active && !mDescriptor.properties.concurrent_capture) ? 767 SOUND_TRIGGER_STATE_DISABLED : SOUND_TRIGGER_STATE_ENABLED; 768 769 if (state == mServiceState) { 770 return; 771 } 772 773 mServiceState = state; 774 775 service = mService.promote(); 776 if (service == 0) { 777 return; 778 } 779 780 if (state == SOUND_TRIGGER_STATE_ENABLED) { 781 goto exit; 782 } 783 784 for (size_t i = 0; i < mModels.size(); i++) { 785 sp<Model> model = mModels.valueAt(i); 786 if (model->mState == Model::STATE_ACTIVE) { 787 mHwDevice->stop_recognition(mHwDevice, model->mHandle); 788 // keep model in ACTIVE state so that event is processed by onCallbackEvent() 789 struct sound_trigger_phrase_recognition_event phraseEvent; 790 switch (model->mType) { 791 case SOUND_MODEL_TYPE_KEYPHRASE: 792 phraseEvent.num_phrases = model->mConfig.num_phrases; 793 for (size_t i = 0; i < phraseEvent.num_phrases; i++) { 794 phraseEvent.phrase_extras[i] = model->mConfig.phrases[i]; 795 } 796 break; 797 case SOUND_MODEL_TYPE_UNKNOWN: 798 default: 799 break; 800 } 801 phraseEvent.common.status = RECOGNITION_STATUS_ABORT; 802 phraseEvent.common.type = model->mType; 803 phraseEvent.common.model = model->mHandle; 804 phraseEvent.common.data_size = 0; 805 sp<IMemory> eventMemory = service->prepareRecognitionEvent_l(&phraseEvent.common); 806 if (eventMemory != 0) { 807 events.add(eventMemory); 808 } 809 } 810 } 811 } 812 813 for (size_t i = 0; i < events.size(); i++) { 814 service->sendCallbackEvent_l(new CallbackEvent(CallbackEvent::TYPE_RECOGNITION, events[i], 815 this)); 816 } 817 818 exit: 819 service->sendServiceStateEvent_l(state, this); 820 } 821 822 823 SoundTriggerHwService::Model::Model(sound_model_handle_t handle, audio_session_t session, 824 audio_io_handle_t ioHandle, audio_devices_t device, 825 sound_trigger_sound_model_type_t type) : 826 mHandle(handle), mState(STATE_IDLE), mCaptureSession(session), 827 mCaptureIOHandle(ioHandle), mCaptureDevice(device), mType(type) 828 { 829 830 } 831 832 status_t SoundTriggerHwService::Module::dump(int fd __unused, 833 const Vector<String16>& args __unused) { 834 String8 result; 835 return NO_ERROR; 836 } 837 838 }; // namespace android 839