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