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