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