SoundTriggerHalHidl.cpp revision 90e2eec58b0db7ee84e4596c723462b9910aa0aa
1/* 2 * Copyright (C) 2016 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 "SoundTriggerHalHidl" 18//#define LOG_NDEBUG 0 19 20#include <utils/Log.h> 21#include "SoundTriggerHalHidl.h" 22#include <hwbinder/IPCThreadState.h> 23#include <hwbinder/ProcessState.h> 24 25namespace android { 26 27using android::hardware::Return; 28using android::hardware::ProcessState; 29using android::hardware::audio::common::V2_0::AudioDevice; 30 31pthread_once_t SoundTriggerHalHidl::sOnceControl = PTHREAD_ONCE_INIT; 32 33void SoundTriggerHalHidl::sOnceInit() 34{ 35 ProcessState::self()->setThreadPoolMaxThreadCount(1); 36 ProcessState::self()->startThreadPool(); 37} 38 39/* static */ 40sp<SoundTriggerHalInterface> SoundTriggerHalInterface::connectModule(const char *moduleName) 41{ 42 return new SoundTriggerHalHidl(moduleName); 43} 44 45int SoundTriggerHalHidl::getProperties(struct sound_trigger_properties *properties) 46{ 47 sp<ISoundTriggerHw> soundtrigger = getService(); 48 if (soundtrigger == 0) { 49 return -ENODEV; 50 } 51 52 ISoundTriggerHw::Properties halProperties; 53 Return<void> hidlReturn; 54 int32_t halReturn; 55 { 56 AutoMutex lock(mHalLock); 57 hidlReturn = soundtrigger->getProperties([&](int rc, auto res) { 58 halReturn = rc; 59 halProperties = res; 60 ALOGI("getProperties res implementor %s", res.implementor.c_str()); 61 }); 62 } 63 64 int ret = 0; 65 if (hidlReturn.getStatus().isOk()) { 66 convertPropertiesFromHal(properties, &halProperties); 67 } else { 68 ret = (int)hidlReturn.getStatus().transactionError(); 69 if (ret == -EPIPE) { 70 clearService(); 71 } 72 } 73 74 return ret; 75} 76 77int SoundTriggerHalHidl::loadSoundModel(struct sound_trigger_sound_model *sound_model, 78 sound_model_callback_t callback, 79 void *cookie, 80 sound_model_handle_t *handle) 81{ 82 if (handle == NULL) { 83 return -EINVAL; 84 } 85 86 sp<ISoundTriggerHw> soundtrigger = getService(); 87 if (soundtrigger == 0) { 88 return -ENODEV; 89 } 90 91 uint32_t modelId; 92 { 93 AutoMutex lock(mLock); 94 do { 95 modelId = nextUniqueId(); 96 ALOGI("loadSoundModel modelId %u", modelId); 97 sp<SoundModel> model = mSoundModels.valueFor(modelId); 98 ALOGI("loadSoundModel model %p", model.get()); 99 } while (mSoundModels.valueFor(modelId) != 0 && modelId != 0); 100 } 101 LOG_ALWAYS_FATAL_IF(modelId == 0, 102 "loadSoundModel(): wrap around in sound model IDs, num loaded models %zd", 103 mSoundModels.size()); 104 105 ISoundTriggerHw::SoundModel *halSoundModel = 106 convertSoundModelToHal(sound_model); 107 if (halSoundModel == NULL) { 108 return -EINVAL; 109 } 110 111 Return<void> hidlReturn; 112 int32_t halReturn; 113 SoundModelHandle halHandle; 114 { 115 AutoMutex lock(mHalLock); 116 if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) { 117 hidlReturn = soundtrigger->loadPhraseSoundModel( 118 *(const ISoundTriggerHw::PhraseSoundModel *)halSoundModel, 119 this, modelId, [&](int32_t retval, auto res) { 120 halReturn = retval; 121 halHandle = res; 122 }); 123 124 } else { 125 hidlReturn = soundtrigger->loadSoundModel(*halSoundModel, 126 this, modelId, [&](int32_t retval, auto res) { 127 halReturn = retval; 128 halHandle = res; 129 }); 130 } 131 } 132 133 delete halSoundModel; 134 135 int ret = 0; 136 if (hidlReturn.getStatus().isOk()) { 137 AutoMutex lock(mLock); 138 *handle = (sound_model_handle_t)modelId; 139 sp<SoundModel> model = new SoundModel(*handle, callback, cookie, halHandle); 140 mSoundModels.add(*handle, model); 141 } else { 142 ret = (int)hidlReturn.getStatus().transactionError(); 143 ALOGE("loadSoundModel error %d", ret); 144 if (ret == -EPIPE) { 145 clearService(); 146 } 147 } 148 149 150 return ret; 151} 152 153int SoundTriggerHalHidl::unloadSoundModel(sound_model_handle_t handle) 154{ 155 sp<ISoundTriggerHw> soundtrigger = getService(); 156 if (soundtrigger == 0) { 157 return -ENODEV; 158 } 159 160 sp<SoundModel> model = removeModel(handle); 161 if (model == 0) { 162 ALOGE("unloadSoundModel model not found for handle %u", handle); 163 return -EINVAL; 164 } 165 166 Return<int32_t> halReturn(0); 167 { 168 AutoMutex lock(mHalLock); 169 halReturn = soundtrigger->unloadSoundModel(model->mHalHandle); 170 } 171 172 int ret = (int)halReturn.getStatus().transactionError(); 173 ALOGE_IF(ret != 0, "unloadSoundModel error %d", ret); 174 if (ret == -EPIPE) { 175 clearService(); 176 } 177 178 return ret; 179} 180 181int SoundTriggerHalHidl::startRecognition(sound_model_handle_t handle, 182 const struct sound_trigger_recognition_config *config, 183 recognition_callback_t callback, 184 void *cookie) 185{ 186 sp<ISoundTriggerHw> soundtrigger = getService(); 187 if (soundtrigger == 0) { 188 return -ENODEV; 189 } 190 191 sp<SoundModel> model = getModel(handle); 192 if (model == 0) { 193 ALOGE("startRecognition model not found for handle %u", handle); 194 return -EINVAL; 195 } 196 197 model->mRecognitionCallback = callback; 198 model->mRecognitionCookie = cookie; 199 200 ISoundTriggerHw::RecognitionConfig *halConfig = 201 convertRecognitionConfigToHal(config); 202 203 Return<int32_t> halReturn(0); 204 { 205 AutoMutex lock(mHalLock); 206 halReturn = soundtrigger->startRecognition(model->mHalHandle, *halConfig, this, handle); 207 } 208 209 delete halConfig; 210 211 int ret = (int)halReturn.getStatus().transactionError(); 212 ALOGE_IF(ret != 0, "startRecognition error %d", ret); 213 if (ret == -EPIPE) { 214 clearService(); 215 } 216 return ret; 217} 218 219int SoundTriggerHalHidl::stopRecognition(sound_model_handle_t handle) 220{ 221 sp<ISoundTriggerHw> soundtrigger = getService(); 222 if (soundtrigger == 0) { 223 return -ENODEV; 224 } 225 226 sp<SoundModel> model = getModel(handle); 227 if (model == 0) { 228 ALOGE("stopRecognition model not found for handle %u", handle); 229 return -EINVAL; 230 } 231 232 Return<int32_t> halReturn(0); 233 { 234 AutoMutex lock(mHalLock); 235 halReturn = soundtrigger->stopRecognition(model->mHalHandle); 236 } 237 238 int ret = (int)halReturn.getStatus().transactionError(); 239 ALOGE_IF(ret != 0, "stopRecognition error %d", ret); 240 if (ret == -EPIPE) { 241 clearService(); 242 } 243 return ret; 244} 245 246int SoundTriggerHalHidl::stopAllRecognitions() 247{ 248 sp<ISoundTriggerHw> soundtrigger = getService(); 249 if (soundtrigger == 0) { 250 return -ENODEV; 251 } 252 253 Return<int32_t> halReturn(0); 254 { 255 AutoMutex lock(mHalLock); 256 Return<int32_t> halReturn = soundtrigger->stopAllRecognitions(); 257 } 258 259 int ret = (int)halReturn.getStatus().transactionError(); 260 ALOGE_IF(ret != 0, "stopAllRecognitions error %d", ret); 261 if (ret == -EPIPE) { 262 clearService(); 263 } 264 return ret; 265} 266 267SoundTriggerHalHidl::SoundTriggerHalHidl(const char *moduleName) 268 : mModuleName(moduleName), mNextUniqueId(1) 269{ 270} 271 272void SoundTriggerHalHidl::onFirstRef() 273{ 274 pthread_once(&sOnceControl, &sOnceInit); 275} 276 277SoundTriggerHalHidl::~SoundTriggerHalHidl() 278{ 279} 280 281sp<ISoundTriggerHw> SoundTriggerHalHidl::getService() 282{ 283 AutoMutex lock(mLock); 284 if (mISoundTrigger == 0) { 285 if (mModuleName == NULL) { 286 mModuleName = "primary"; 287 } 288 std::string serviceName = "sound_trigger."; 289 serviceName.append(mModuleName); 290 mISoundTrigger = ISoundTriggerHw::getService(serviceName); 291 } 292 return mISoundTrigger; 293} 294 295void SoundTriggerHalHidl::clearService() 296{ 297 AutoMutex lock(mLock); 298 mISoundTrigger = 0; 299} 300 301sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::getModel(sound_model_handle_t handle) 302{ 303 AutoMutex lock(mLock); 304 return mSoundModels.valueFor(handle); 305} 306 307sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::removeModel(sound_model_handle_t handle) 308{ 309 AutoMutex lock(mLock); 310 sp<SoundModel> model = mSoundModels.valueFor(handle); 311 mSoundModels.removeItem(handle); 312 return model; 313} 314 315uint32_t SoundTriggerHalHidl::nextUniqueId() 316{ 317 return (uint32_t) atomic_fetch_add_explicit(&mNextUniqueId, 318 (uint_fast32_t) 1, memory_order_acq_rel); 319} 320 321void SoundTriggerHalHidl::convertUuidToHal(Uuid *halUuid, 322 const sound_trigger_uuid_t *uuid) 323{ 324 halUuid->timeLow = uuid->timeLow; 325 halUuid->timeMid = uuid->timeMid; 326 halUuid->versionAndTimeHigh = uuid->timeHiAndVersion; 327 halUuid->variantAndClockSeqHigh = uuid->clockSeq; 328 memcpy(halUuid->node.data(), &uuid->node[0], sizeof(uuid->node)); 329} 330 331void SoundTriggerHalHidl::convertUuidFromHal(sound_trigger_uuid_t *uuid, 332 const Uuid *halUuid) 333{ 334 uuid->timeLow = halUuid->timeLow; 335 uuid->timeMid = halUuid->timeMid; 336 uuid->timeHiAndVersion = halUuid->versionAndTimeHigh; 337 uuid->clockSeq = halUuid->variantAndClockSeqHigh; 338 memcpy(&uuid->node[0], halUuid->node.data(), sizeof(uuid->node)); 339} 340 341void SoundTriggerHalHidl::convertPropertiesFromHal( 342 struct sound_trigger_properties *properties, 343 const ISoundTriggerHw::Properties *halProperties) 344{ 345 strlcpy(properties->implementor, 346 halProperties->implementor.c_str(), SOUND_TRIGGER_MAX_STRING_LEN); 347 strlcpy(properties->description, 348 halProperties->description.c_str(), SOUND_TRIGGER_MAX_STRING_LEN); 349 properties->version = halProperties->version; 350 convertUuidFromHal(&properties->uuid, &halProperties->uuid); 351 properties->max_sound_models = halProperties->maxSoundModels; 352 properties->max_key_phrases = halProperties->maxKeyPhrases; 353 properties->max_users = halProperties->maxUsers; 354 properties->recognition_modes = halProperties->recognitionModes; 355 properties->capture_transition = (bool)halProperties->captureTransition; 356 properties->max_buffer_ms = halProperties->maxBufferMs; 357 properties->concurrent_capture = (bool)halProperties->concurrentCapture; 358 properties->trigger_in_event = (bool)halProperties->triggerInEvent; 359 properties->power_consumption_mw = halProperties->powerConsumptionMw; 360} 361 362void SoundTriggerHalHidl::convertTriggerPhraseToHal( 363 ISoundTriggerHw::Phrase *halTriggerPhrase, 364 const struct sound_trigger_phrase *triggerPhrase) 365{ 366 halTriggerPhrase->id = triggerPhrase->id; 367 halTriggerPhrase->recognitionModes = triggerPhrase->recognition_mode; 368 halTriggerPhrase->users.setToExternal((uint32_t *)&triggerPhrase->users[0], triggerPhrase->num_users); 369 halTriggerPhrase->locale = triggerPhrase->locale; 370 halTriggerPhrase->text = triggerPhrase->text; 371} 372 373ISoundTriggerHw::SoundModel *SoundTriggerHalHidl::convertSoundModelToHal( 374 const struct sound_trigger_sound_model *soundModel) 375{ 376 ISoundTriggerHw::SoundModel *halModel = NULL; 377 if (soundModel->type == SOUND_MODEL_TYPE_KEYPHRASE) { 378 ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel = 379 new ISoundTriggerHw::PhraseSoundModel(); 380 struct sound_trigger_phrase_sound_model *keyPhraseModel = 381 (struct sound_trigger_phrase_sound_model *)soundModel; 382 ISoundTriggerHw::Phrase *halPhrases = 383 new ISoundTriggerHw::Phrase[keyPhraseModel->num_phrases]; 384 385 386 for (unsigned int i = 0; i < keyPhraseModel->num_phrases; i++) { 387 convertTriggerPhraseToHal(&halPhrases[i], 388 &keyPhraseModel->phrases[i]); 389 } 390 halKeyPhraseModel->phrases.setToExternal(halPhrases, keyPhraseModel->num_phrases); 391 // FIXME: transfer buffer ownership. should have a method for that in hidl_vec 392 halKeyPhraseModel->phrases.resize(keyPhraseModel->num_phrases); 393 394 delete[] halPhrases; 395 396 halModel = (ISoundTriggerHw::SoundModel *)halKeyPhraseModel; 397 } else { 398 halModel = new ISoundTriggerHw::SoundModel(); 399 } 400 halModel->type = (SoundModelType)soundModel->type; 401 convertUuidToHal(&halModel->uuid, &soundModel->uuid); 402 convertUuidToHal(&halModel->vendorUuid, &soundModel->vendor_uuid); 403 halModel->data.setToExternal((uint8_t *)soundModel + soundModel->data_offset, soundModel->data_size); 404 halModel->data.resize(soundModel->data_size); 405 406 return halModel; 407} 408 409void SoundTriggerHalHidl::convertPhraseRecognitionExtraToHal( 410 PhraseRecognitionExtra *halExtra, 411 const struct sound_trigger_phrase_recognition_extra *extra) 412{ 413 halExtra->id = extra->id; 414 halExtra->recognitionModes = extra->recognition_modes; 415 halExtra->confidenceLevel = extra->confidence_level; 416 ConfidenceLevel *halLevels = 417 new ConfidenceLevel[extra->num_levels]; 418 for (unsigned int i = 0; i < extra->num_levels; i++) { 419 halLevels[i].userId = extra->levels[i].user_id; 420 halLevels[i].levelPercent = extra->levels[i].level; 421 } 422 halExtra->levels.setToExternal(halLevels, extra->num_levels); 423 // FIXME: transfer buffer ownership. should have a method for that in hidl_vec 424 halExtra->levels.resize(extra->num_levels); 425 426 delete[] halLevels; 427} 428 429 430ISoundTriggerHw::RecognitionConfig *SoundTriggerHalHidl::convertRecognitionConfigToHal( 431 const struct sound_trigger_recognition_config *config) 432{ 433 ISoundTriggerHw::RecognitionConfig *halConfig = 434 new ISoundTriggerHw::RecognitionConfig(); 435 436 halConfig->captureHandle = config->capture_handle; 437 halConfig->captureDevice = (AudioDevice)config->capture_device; 438 halConfig->captureRequested = (uint32_t)config->capture_requested; 439 440 PhraseRecognitionExtra *halExtras = 441 new PhraseRecognitionExtra[config->num_phrases]; 442 443 for (unsigned int i = 0; i < config->num_phrases; i++) { 444 convertPhraseRecognitionExtraToHal(&halExtras[i], 445 &config->phrases[i]); 446 } 447 halConfig->phrases.setToExternal(halExtras, config->num_phrases); 448 // FIXME: transfer buffer ownership. should have a method for that in hidl_vec 449 halConfig->phrases.resize(config->num_phrases); 450 451 delete[] halExtras; 452 453 halConfig->data.setToExternal((uint8_t *)config + config->data_offset, config->data_size); 454 455 return halConfig; 456} 457 458 459// ISoundTriggerHwCallback 460::android::hardware::Return<void> SoundTriggerHalHidl::recognitionCallback( 461 const ISoundTriggerHwCallback::RecognitionEvent& halEvent, 462 CallbackCookie cookie) 463{ 464 sp<SoundModel> model; 465 { 466 AutoMutex lock(mLock); 467 model = mSoundModels.valueFor((SoundModelHandle)cookie); 468 if (model == 0) { 469 return Return<void>(); 470 } 471 } 472 struct sound_trigger_recognition_event *event = convertRecognitionEventFromHal(&halEvent); 473 if (event == NULL) { 474 return Return<void>(); 475 } 476 event->model = model->mHandle; 477 model->mRecognitionCallback(event, model->mRecognitionCookie); 478 479 free(event); 480 481 return Return<void>(); 482} 483 484::android::hardware::Return<void> SoundTriggerHalHidl::phraseRecognitionCallback( 485 const ISoundTriggerHwCallback::PhraseRecognitionEvent& halEvent, 486 CallbackCookie cookie) 487{ 488 sp<SoundModel> model; 489 { 490 AutoMutex lock(mLock); 491 model = mSoundModels.valueFor((SoundModelHandle)cookie); 492 if (model == 0) { 493 return Return<void>(); 494 } 495 } 496 497 struct sound_trigger_recognition_event *event = convertRecognitionEventFromHal( 498 (const ISoundTriggerHwCallback::RecognitionEvent *)&halEvent); 499 if (event == NULL) { 500 return Return<void>(); 501 } 502 503 event->model = model->mHandle; 504 model->mRecognitionCallback(event, model->mRecognitionCookie); 505 506 free(event); 507 508 return Return<void>(); 509} 510 511::android::hardware::Return<void> SoundTriggerHalHidl::soundModelCallback( 512 const ISoundTriggerHwCallback::ModelEvent& halEvent, 513 CallbackCookie cookie) 514{ 515 sp<SoundModel> model; 516 { 517 AutoMutex lock(mLock); 518 model = mSoundModels.valueFor((SoundModelHandle)cookie); 519 if (model == 0) { 520 return Return<void>(); 521 } 522 } 523 524 struct sound_trigger_model_event *event = convertSoundModelEventFromHal(&halEvent); 525 if (event == NULL) { 526 return Return<void>(); 527 } 528 529 event->model = model->mHandle; 530 model->mSoundModelCallback(event, model->mSoundModelCookie); 531 532 free(event); 533 534 return Return<void>(); 535} 536 537 538struct sound_trigger_model_event *SoundTriggerHalHidl::convertSoundModelEventFromHal( 539 const ISoundTriggerHwCallback::ModelEvent *halEvent) 540{ 541 struct sound_trigger_model_event *event = (struct sound_trigger_model_event *)malloc( 542 sizeof(struct sound_trigger_model_event) + 543 halEvent->data.size()); 544 if (event == NULL) { 545 return NULL; 546 } 547 548 event->status = (int)halEvent->status; 549 // event->model to be set by caller 550 event->data_offset = sizeof(struct sound_trigger_model_event); 551 event->data_size = halEvent->data.size(); 552 uint8_t *dst = (uint8_t *)event + event->data_offset; 553 uint8_t *src = (uint8_t *)&halEvent->data[0]; 554 memcpy(dst, src, halEvent->data.size()); 555 556 return event; 557} 558 559void SoundTriggerHalHidl::convertPhraseRecognitionExtraFromHal( 560 struct sound_trigger_phrase_recognition_extra *extra, 561 const PhraseRecognitionExtra *halExtra) 562{ 563 extra->id = halExtra->id; 564 extra->recognition_modes = halExtra->recognitionModes; 565 extra->confidence_level = halExtra->confidenceLevel; 566 567 size_t i; 568 for (i = 0; i < halExtra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) { 569 extra->levels[i].user_id = halExtra->levels[i].userId; 570 extra->levels[i].level = halExtra->levels[i].levelPercent; 571 } 572 extra->num_levels = (unsigned int)i; 573} 574 575 576struct sound_trigger_recognition_event *SoundTriggerHalHidl::convertRecognitionEventFromHal( 577 const ISoundTriggerHwCallback::RecognitionEvent *halEvent) 578{ 579 struct sound_trigger_recognition_event *event; 580 581 if (halEvent->type == SoundModelType::KEYPHRASE) { 582 struct sound_trigger_phrase_recognition_event *phraseEvent = 583 (struct sound_trigger_phrase_recognition_event *)malloc( 584 sizeof(struct sound_trigger_phrase_recognition_event) + 585 halEvent->data.size()); 586 if (phraseEvent == NULL) { 587 return NULL; 588 } 589 const ISoundTriggerHwCallback::PhraseRecognitionEvent *halPhraseEvent = 590 (const ISoundTriggerHwCallback::PhraseRecognitionEvent *)halEvent; 591 592 for (unsigned int i = 0; i < halPhraseEvent->phraseExtras.size(); i++) { 593 convertPhraseRecognitionExtraFromHal(&phraseEvent->phrase_extras[i], 594 &halPhraseEvent->phraseExtras[i]); 595 } 596 phraseEvent->num_phrases = halPhraseEvent->phraseExtras.size(); 597 event = (struct sound_trigger_recognition_event *)phraseEvent; 598 event->data_offset = sizeof(sound_trigger_phrase_recognition_event); 599 } else { 600 event = (struct sound_trigger_recognition_event *)malloc( 601 sizeof(struct sound_trigger_recognition_event) + halEvent->data.size()); 602 if (event == NULL) { 603 return NULL; 604 } 605 event->data_offset = sizeof(sound_trigger_recognition_event); 606 } 607 event->status = (int)halEvent->status; 608 event->type = (sound_trigger_sound_model_type_t)halEvent->type; 609 // event->model to be set by caller 610 event->capture_available = (bool)halEvent->captureAvailable; 611 event->capture_session = halEvent->captureSession; 612 event->capture_delay_ms = halEvent->captureDelayMs; 613 event->capture_preamble_ms = halEvent->capturePreambleMs; 614 event->trigger_in_data = (bool)halEvent->triggerInData; 615 event->audio_config.sample_rate = halEvent->audioConfig.sampleRateHz; 616 event->audio_config.channel_mask = (audio_channel_mask_t)halEvent->audioConfig.channelMask; 617 event->audio_config.format = (audio_format_t)halEvent->audioConfig.format; 618 619 event->data_size = halEvent->data.size(); 620 uint8_t *dst = (uint8_t *)event + event->data_offset; 621 uint8_t *src = (uint8_t *)&halEvent->data[0]; 622 memcpy(dst, src, halEvent->data.size()); 623 624 return event; 625} 626 627} // namespace android 628