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