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