1 /* 2 * Copyright (C) 2018 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 "SoundTriggerHw" 18 19 #include "SoundTriggerHw.h" 20 21 #include <android/hidl/allocator/1.0/IAllocator.h> 22 #include <android/log.h> 23 #include <hidlmemory/mapping.h> 24 #include <utility> 25 26 using android::hardware::hidl_memory; 27 using android::hidl::allocator::V1_0::IAllocator; 28 using android::hidl::memory::V1_0::IMemory; 29 30 namespace android { 31 namespace hardware { 32 namespace soundtrigger { 33 namespace V2_2 { 34 namespace implementation { 35 36 /** 37 * According to the HIDL C++ Users Guide: client and server implementations 38 * should never directly refer to anything other than the interface header 39 * generated from the HIDL definition file (ie. ISoundTriggerHw.hal), so 40 * this V2_2 implementation copies the V2_0 and V2_1 implementations and 41 * then adds the new V2_2 implementation. 42 */ 43 44 // Begin V2_0 implementation, copied from 45 // hardware/interfaces/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp 46 47 // static 48 void soundModelCallback_(struct sound_trigger_model_event* halEvent, void* cookie) { 49 if (halEvent == NULL) { 50 ALOGW("soundModelCallback called with NULL event"); 51 return; 52 } 53 sp<SoundTriggerHw::SoundModelClient> client = 54 wp<SoundTriggerHw::SoundModelClient>(static_cast<SoundTriggerHw::SoundModelClient*>(cookie)) 55 .promote(); 56 if (client == 0) { 57 ALOGW("soundModelCallback called on stale client"); 58 return; 59 } 60 if (halEvent->model != client->getHalHandle()) { 61 ALOGW("soundModelCallback call with wrong handle %d on client with handle %d", 62 (int)halEvent->model, (int)client->getHalHandle()); 63 return; 64 } 65 66 client->soundModelCallback(halEvent); 67 } 68 69 // static 70 void recognitionCallback_(struct sound_trigger_recognition_event* halEvent, void* cookie) { 71 if (halEvent == NULL) { 72 ALOGW("recognitionCallback call NULL event"); 73 return; 74 } 75 sp<SoundTriggerHw::SoundModelClient> client = 76 wp<SoundTriggerHw::SoundModelClient>(static_cast<SoundTriggerHw::SoundModelClient*>(cookie)) 77 .promote(); 78 if (client == 0) { 79 ALOGW("recognitionCallback called on stale client"); 80 return; 81 } 82 83 client->recognitionCallback(halEvent); 84 } 85 86 Return<void> SoundTriggerHw::getProperties(ISoundTriggerHw::getProperties_cb _hidl_cb) { 87 ALOGV("getProperties() mHwDevice %p", mHwDevice); 88 int ret; 89 struct sound_trigger_properties halProperties; 90 ISoundTriggerHw::Properties properties; 91 92 if (mHwDevice == NULL) { 93 ret = -ENODEV; 94 goto exit; 95 } 96 97 ret = mHwDevice->get_properties(mHwDevice, &halProperties); 98 99 convertPropertiesFromHal(&properties, &halProperties); 100 101 ALOGV("getProperties implementor %s recognitionModes %08x", properties.implementor.c_str(), 102 properties.recognitionModes); 103 104 exit: 105 _hidl_cb(ret, properties); 106 return Void(); 107 } 108 109 int SoundTriggerHw::doLoadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel, 110 sp<SoundTriggerHw::SoundModelClient> client) { 111 int32_t ret = 0; 112 struct sound_trigger_sound_model* halSoundModel; 113 114 ALOGV("doLoadSoundModel() data size %zu", soundModel.data.size()); 115 116 if (mHwDevice == NULL) { 117 ret = -ENODEV; 118 goto exit; 119 } 120 121 halSoundModel = convertSoundModelToHal(&soundModel); 122 if (halSoundModel == NULL) { 123 ret = -EINVAL; 124 goto exit; 125 } 126 127 sound_model_handle_t halHandle; 128 ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, soundModelCallback_, client.get(), 129 &halHandle); 130 131 free(halSoundModel); 132 133 if (ret != 0) { 134 goto exit; 135 } 136 137 client->setHalHandle(halHandle); 138 { 139 AutoMutex lock(mLock); 140 mClients.add(client->getId(), client); 141 } 142 143 exit: 144 return ret; 145 } 146 147 Return<void> SoundTriggerHw::loadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel, 148 const sp<V2_0::ISoundTriggerHwCallback>& callback, 149 V2_0::ISoundTriggerHwCallback::CallbackCookie cookie, 150 ISoundTriggerHw::loadSoundModel_cb _hidl_cb) { 151 sp<SoundTriggerHw::SoundModelClient> client = 152 new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback); 153 _hidl_cb(doLoadSoundModel(soundModel, client), client->getId()); 154 return Void(); 155 } 156 157 Return<void> SoundTriggerHw::loadPhraseSoundModel( 158 const V2_0::ISoundTriggerHw::PhraseSoundModel& soundModel, 159 const sp<V2_0::ISoundTriggerHwCallback>& callback, 160 V2_0::ISoundTriggerHwCallback::CallbackCookie cookie, 161 ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb) { 162 sp<SoundTriggerHw::SoundModelClient> client = 163 new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback); 164 _hidl_cb(doLoadSoundModel((const V2_0::ISoundTriggerHw::SoundModel&)soundModel, client), 165 client->getId()); 166 return Void(); 167 } 168 169 Return<int32_t> SoundTriggerHw::unloadSoundModel(int32_t modelHandle) { 170 int32_t ret; 171 sp<SoundTriggerHw::SoundModelClient> client; 172 173 if (mHwDevice == NULL) { 174 ret = -ENODEV; 175 goto exit; 176 } 177 178 { 179 AutoMutex lock(mLock); 180 client = mClients.valueFor(modelHandle); 181 if (client == 0) { 182 ret = -ENOSYS; 183 goto exit; 184 } 185 } 186 187 ret = mHwDevice->unload_sound_model(mHwDevice, client->getHalHandle()); 188 189 mClients.removeItem(modelHandle); 190 191 exit: 192 return ret; 193 } 194 195 Return<int32_t> SoundTriggerHw::startRecognition( 196 int32_t modelHandle, const V2_0::ISoundTriggerHw::RecognitionConfig& config, 197 const sp<V2_0::ISoundTriggerHwCallback>& /* callback */, int32_t /* cookie */) { 198 int32_t ret; 199 sp<SoundTriggerHw::SoundModelClient> client; 200 struct sound_trigger_recognition_config* halConfig; 201 202 if (mHwDevice == NULL) { 203 ret = -ENODEV; 204 goto exit; 205 } 206 207 { 208 AutoMutex lock(mLock); 209 client = mClients.valueFor(modelHandle); 210 if (client == 0) { 211 ret = -ENOSYS; 212 goto exit; 213 } 214 } 215 216 halConfig = 217 convertRecognitionConfigToHal((const V2_0::ISoundTriggerHw::RecognitionConfig*)&config); 218 219 if (halConfig == NULL) { 220 ret = -EINVAL; 221 goto exit; 222 } 223 ret = mHwDevice->start_recognition(mHwDevice, client->getHalHandle(), halConfig, 224 recognitionCallback_, client.get()); 225 226 free(halConfig); 227 228 exit: 229 return ret; 230 } 231 232 Return<int32_t> SoundTriggerHw::stopRecognition(int32_t modelHandle) { 233 int32_t ret; 234 sp<SoundTriggerHw::SoundModelClient> client; 235 if (mHwDevice == NULL) { 236 ret = -ENODEV; 237 goto exit; 238 } 239 240 { 241 AutoMutex lock(mLock); 242 client = mClients.valueFor(modelHandle); 243 if (client == 0) { 244 ret = -ENOSYS; 245 goto exit; 246 } 247 } 248 249 ret = mHwDevice->stop_recognition(mHwDevice, client->getHalHandle()); 250 251 exit: 252 return ret; 253 } 254 255 Return<int32_t> SoundTriggerHw::stopAllRecognitions() { 256 int32_t ret; 257 if (mHwDevice == NULL) { 258 ret = -ENODEV; 259 goto exit; 260 } 261 262 if (mHwDevice->common.version >= SOUND_TRIGGER_DEVICE_API_VERSION_1_1 && 263 mHwDevice->stop_all_recognitions) { 264 ret = mHwDevice->stop_all_recognitions(mHwDevice); 265 } else { 266 ret = -ENOSYS; 267 } 268 exit: 269 return ret; 270 } 271 272 SoundTriggerHw::SoundTriggerHw() : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {} 273 274 void SoundTriggerHw::onFirstRef() { 275 const hw_module_t* mod; 276 int rc; 277 278 rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, &mod); 279 if (rc != 0) { 280 ALOGE("couldn't load sound trigger module %s.%s (%s)", SOUND_TRIGGER_HARDWARE_MODULE_ID, 281 mModuleName, strerror(-rc)); 282 return; 283 } 284 rc = sound_trigger_hw_device_open(mod, &mHwDevice); 285 if (rc != 0) { 286 ALOGE("couldn't open sound trigger hw device in %s.%s (%s)", 287 SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, strerror(-rc)); 288 mHwDevice = NULL; 289 return; 290 } 291 if (mHwDevice->common.version < SOUND_TRIGGER_DEVICE_API_VERSION_1_0 || 292 mHwDevice->common.version > SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) { 293 ALOGE("wrong sound trigger hw device version %04x", mHwDevice->common.version); 294 sound_trigger_hw_device_close(mHwDevice); 295 mHwDevice = NULL; 296 return; 297 } 298 299 ALOGI("onFirstRef() mModuleName %s mHwDevice %p", mModuleName, mHwDevice); 300 } 301 302 SoundTriggerHw::~SoundTriggerHw() { 303 if (mHwDevice != NULL) { 304 sound_trigger_hw_device_close(mHwDevice); 305 } 306 } 307 308 uint32_t SoundTriggerHw::nextUniqueModelId() { 309 uint32_t modelId = 0; 310 { 311 AutoMutex lock(mLock); 312 do { 313 modelId = 314 atomic_fetch_add_explicit(&mNextModelId, (uint_fast32_t)1, memory_order_acq_rel); 315 } while (mClients.valueFor(modelId) != 0 && modelId != 0); 316 } 317 LOG_ALWAYS_FATAL_IF(modelId == 0, "wrap around in sound model IDs, num loaded models %zu", 318 mClients.size()); 319 return modelId; 320 } 321 322 void SoundTriggerHw::convertUuidFromHal(Uuid* uuid, const sound_trigger_uuid_t* halUuid) { 323 uuid->timeLow = halUuid->timeLow; 324 uuid->timeMid = halUuid->timeMid; 325 uuid->versionAndTimeHigh = halUuid->timeHiAndVersion; 326 uuid->variantAndClockSeqHigh = halUuid->clockSeq; 327 memcpy(&uuid->node[0], &halUuid->node[0], 6); 328 } 329 330 void SoundTriggerHw::convertUuidToHal(sound_trigger_uuid_t* halUuid, const Uuid* uuid) { 331 halUuid->timeLow = uuid->timeLow; 332 halUuid->timeMid = uuid->timeMid; 333 halUuid->timeHiAndVersion = uuid->versionAndTimeHigh; 334 halUuid->clockSeq = uuid->variantAndClockSeqHigh; 335 memcpy(&halUuid->node[0], &uuid->node[0], 6); 336 } 337 338 void SoundTriggerHw::convertPropertiesFromHal( 339 ISoundTriggerHw::Properties* properties, const struct sound_trigger_properties* halProperties) { 340 properties->implementor = halProperties->implementor; 341 properties->description = halProperties->description; 342 properties->version = halProperties->version; 343 convertUuidFromHal(&properties->uuid, &halProperties->uuid); 344 properties->maxSoundModels = halProperties->max_sound_models; 345 properties->maxKeyPhrases = halProperties->max_key_phrases; 346 properties->maxUsers = halProperties->max_users; 347 properties->recognitionModes = halProperties->recognition_modes; 348 properties->captureTransition = halProperties->capture_transition; 349 properties->maxBufferMs = halProperties->max_buffer_ms; 350 properties->concurrentCapture = halProperties->concurrent_capture; 351 properties->triggerInEvent = halProperties->trigger_in_event; 352 properties->powerConsumptionMw = halProperties->power_consumption_mw; 353 } 354 355 void SoundTriggerHw::convertTriggerPhraseToHal(struct sound_trigger_phrase* halTriggerPhrase, 356 const ISoundTriggerHw::Phrase* triggerPhrase) { 357 halTriggerPhrase->id = triggerPhrase->id; 358 halTriggerPhrase->recognition_mode = triggerPhrase->recognitionModes; 359 unsigned int i; 360 361 halTriggerPhrase->num_users = 362 std::min((int)triggerPhrase->users.size(), SOUND_TRIGGER_MAX_USERS); 363 for (i = 0; i < halTriggerPhrase->num_users; i++) { 364 halTriggerPhrase->users[i] = triggerPhrase->users[i]; 365 } 366 367 strlcpy(halTriggerPhrase->locale, triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN); 368 strlcpy(halTriggerPhrase->text, triggerPhrase->text.c_str(), SOUND_TRIGGER_MAX_STRING_LEN); 369 } 370 371 struct sound_trigger_sound_model* SoundTriggerHw::convertSoundModelToHal( 372 const V2_0::ISoundTriggerHw::SoundModel* soundModel) { 373 struct sound_trigger_sound_model* halModel = NULL; 374 if (soundModel->type == V2_0::SoundModelType::KEYPHRASE) { 375 size_t allocSize = 376 sizeof(struct sound_trigger_phrase_sound_model) + soundModel->data.size(); 377 struct sound_trigger_phrase_sound_model* halKeyPhraseModel = 378 static_cast<struct sound_trigger_phrase_sound_model*>(malloc(allocSize)); 379 LOG_ALWAYS_FATAL_IF(halKeyPhraseModel == NULL, 380 "malloc failed for size %zu in convertSoundModelToHal PHRASE", 381 allocSize); 382 383 const V2_0::ISoundTriggerHw::PhraseSoundModel* keyPhraseModel = 384 reinterpret_cast<const V2_0::ISoundTriggerHw::PhraseSoundModel*>(soundModel); 385 386 size_t i; 387 for (i = 0; i < keyPhraseModel->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) { 388 convertTriggerPhraseToHal(&halKeyPhraseModel->phrases[i], &keyPhraseModel->phrases[i]); 389 } 390 halKeyPhraseModel->num_phrases = (unsigned int)i; 391 halModel = reinterpret_cast<struct sound_trigger_sound_model*>(halKeyPhraseModel); 392 halModel->data_offset = sizeof(struct sound_trigger_phrase_sound_model); 393 } else { 394 size_t allocSize = sizeof(struct sound_trigger_sound_model) + soundModel->data.size(); 395 halModel = static_cast<struct sound_trigger_sound_model*>(malloc(allocSize)); 396 LOG_ALWAYS_FATAL_IF(halModel == NULL, 397 "malloc failed for size %zu in convertSoundModelToHal GENERIC", 398 allocSize); 399 400 halModel->data_offset = sizeof(struct sound_trigger_sound_model); 401 } 402 halModel->type = (sound_trigger_sound_model_type_t)soundModel->type; 403 convertUuidToHal(&halModel->uuid, &soundModel->uuid); 404 convertUuidToHal(&halModel->vendor_uuid, &soundModel->vendorUuid); 405 halModel->data_size = soundModel->data.size(); 406 uint8_t* dst = reinterpret_cast<uint8_t*>(halModel) + halModel->data_offset; 407 const uint8_t* src = reinterpret_cast<const uint8_t*>(&soundModel->data[0]); 408 memcpy(dst, src, soundModel->data.size()); 409 410 return halModel; 411 } 412 413 void SoundTriggerHw::convertPhraseRecognitionExtraToHal( 414 struct sound_trigger_phrase_recognition_extra* halExtra, 415 const V2_0::PhraseRecognitionExtra* extra) { 416 halExtra->id = extra->id; 417 halExtra->recognition_modes = extra->recognitionModes; 418 halExtra->confidence_level = extra->confidenceLevel; 419 420 unsigned int i; 421 for (i = 0; i < extra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) { 422 halExtra->levels[i].user_id = extra->levels[i].userId; 423 halExtra->levels[i].level = extra->levels[i].levelPercent; 424 } 425 halExtra->num_levels = i; 426 } 427 428 struct sound_trigger_recognition_config* SoundTriggerHw::convertRecognitionConfigToHal( 429 const V2_0::ISoundTriggerHw::RecognitionConfig* config) { 430 size_t allocSize = sizeof(struct sound_trigger_recognition_config) + config->data.size(); 431 struct sound_trigger_recognition_config* halConfig = 432 static_cast<struct sound_trigger_recognition_config*>(malloc(allocSize)); 433 434 LOG_ALWAYS_FATAL_IF(halConfig == NULL, 435 "malloc failed for size %zu in convertRecognitionConfigToHal", allocSize); 436 437 halConfig->capture_handle = (audio_io_handle_t)config->captureHandle; 438 halConfig->capture_device = (audio_devices_t)config->captureDevice; 439 halConfig->capture_requested = config->captureRequested; 440 441 unsigned int i; 442 for (i = 0; i < config->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) { 443 convertPhraseRecognitionExtraToHal(&halConfig->phrases[i], &config->phrases[i]); 444 } 445 halConfig->num_phrases = i; 446 447 halConfig->data_offset = sizeof(struct sound_trigger_recognition_config); 448 halConfig->data_size = config->data.size(); 449 uint8_t* dst = reinterpret_cast<uint8_t*>(halConfig) + halConfig->data_offset; 450 const uint8_t* src = reinterpret_cast<const uint8_t*>(&config->data[0]); 451 memcpy(dst, src, config->data.size()); 452 return halConfig; 453 } 454 455 // static 456 void SoundTriggerHw::convertSoundModelEventFromHal( 457 V2_0::ISoundTriggerHwCallback::ModelEvent* event, 458 const struct sound_trigger_model_event* halEvent) { 459 event->status = (V2_0::ISoundTriggerHwCallback::SoundModelStatus)halEvent->status; 460 // event->model to be remapped by called 461 event->data.setToExternal( 462 const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset, 463 halEvent->data_size); 464 } 465 466 // static 467 void SoundTriggerHw::convertPhaseRecognitionEventFromHal( 468 V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent* event, 469 const struct sound_trigger_phrase_recognition_event* halEvent) { 470 event->phraseExtras.resize(halEvent->num_phrases); 471 for (unsigned int i = 0; i < halEvent->num_phrases; i++) { 472 convertPhraseRecognitionExtraFromHal(&event->phraseExtras[i], &halEvent->phrase_extras[i]); 473 } 474 convertRecognitionEventFromHal(&event->common, &halEvent->common); 475 } 476 477 // static 478 void SoundTriggerHw::convertRecognitionEventFromHal( 479 V2_0::ISoundTriggerHwCallback::RecognitionEvent* event, 480 const struct sound_trigger_recognition_event* halEvent) { 481 event->status = static_cast<V2_0::ISoundTriggerHwCallback::RecognitionStatus>(halEvent->status); 482 event->type = static_cast<V2_0::SoundModelType>(halEvent->type); 483 // event->model to be remapped by called 484 event->captureAvailable = halEvent->capture_available; 485 event->captureSession = halEvent->capture_session; 486 event->captureDelayMs = halEvent->capture_delay_ms; 487 event->capturePreambleMs = halEvent->capture_preamble_ms; 488 event->triggerInData = halEvent->trigger_in_data; 489 event->audioConfig.sampleRateHz = halEvent->audio_config.sample_rate; 490 event->audioConfig.channelMask = 491 (audio::common::V2_0::AudioChannelMask)halEvent->audio_config.channel_mask; 492 event->audioConfig.format = (audio::common::V2_0::AudioFormat)halEvent->audio_config.format; 493 event->data.setToExternal( 494 const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset, 495 halEvent->data_size); 496 } 497 498 // static 499 void SoundTriggerHw::convertPhraseRecognitionExtraFromHal( 500 V2_0::PhraseRecognitionExtra* extra, 501 const struct sound_trigger_phrase_recognition_extra* halExtra) { 502 extra->id = halExtra->id; 503 extra->recognitionModes = halExtra->recognition_modes; 504 extra->confidenceLevel = halExtra->confidence_level; 505 506 extra->levels.resize(halExtra->num_levels); 507 for (unsigned int i = 0; i < halExtra->num_levels; i++) { 508 extra->levels[i].userId = halExtra->levels[i].user_id; 509 extra->levels[i].levelPercent = halExtra->levels[i].level; 510 } 511 } 512 513 void SoundTriggerHw::SoundModelClient_2_0::recognitionCallback( 514 struct sound_trigger_recognition_event* halEvent) { 515 if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) { 516 V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent event; 517 convertPhaseRecognitionEventFromHal( 518 &event, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent)); 519 event.common.model = mId; 520 mCallback->phraseRecognitionCallback(event, mCookie); 521 } else { 522 V2_0::ISoundTriggerHwCallback::RecognitionEvent event; 523 convertRecognitionEventFromHal(&event, halEvent); 524 event.model = mId; 525 mCallback->recognitionCallback(event, mCookie); 526 } 527 } 528 529 void SoundTriggerHw::SoundModelClient_2_0::soundModelCallback( 530 struct sound_trigger_model_event* halEvent) { 531 V2_0::ISoundTriggerHwCallback::ModelEvent event; 532 convertSoundModelEventFromHal(&event, halEvent); 533 event.model = mId; 534 mCallback->soundModelCallback(event, mCookie); 535 } 536 537 // Begin V2_1 implementation, copied from 538 // hardware/interfaces/soundtrigger/2.1/default/SoundTriggerHw.cpp 539 540 namespace { 541 542 // Backs up by the vector with the contents of shared memory. 543 // It is assumed that the passed hidl_vector is empty, so it's 544 // not cleared if the memory is a null object. 545 // The caller needs to keep the returned sp<IMemory> as long as 546 // the data is needed. 547 std::pair<bool, sp<IMemory>> memoryAsVector(const hidl_memory& m, hidl_vec<uint8_t>* vec) { 548 sp<IMemory> memory; 549 if (m.size() == 0) { 550 return std::make_pair(true, memory); 551 } 552 memory = mapMemory(m); 553 if (memory != nullptr) { 554 memory->read(); 555 vec->setToExternal(static_cast<uint8_t*>(static_cast<void*>(memory->getPointer())), 556 memory->getSize()); 557 return std::make_pair(true, memory); 558 } 559 ALOGE("%s: Could not map HIDL memory to IMemory", __func__); 560 return std::make_pair(false, memory); 561 } 562 563 // Moves the data from the vector into allocated shared memory, 564 // emptying the vector. 565 // It is assumed that the passed hidl_memory is a null object, so it's 566 // not reset if the vector is empty. 567 // The caller needs to keep the returned sp<IMemory> as long as 568 // the data is needed. 569 std::pair<bool, sp<IMemory>> moveVectorToMemory(hidl_vec<uint8_t>* v, hidl_memory* mem) { 570 sp<IMemory> memory; 571 if (v->size() == 0) { 572 return std::make_pair(true, memory); 573 } 574 sp<IAllocator> ashmem = IAllocator::getService("ashmem"); 575 if (ashmem == 0) { 576 ALOGE("Failed to retrieve ashmem allocator service"); 577 return std::make_pair(false, memory); 578 } 579 bool success = false; 580 Return<void> r = ashmem->allocate(v->size(), [&](bool s, const hidl_memory& m) { 581 success = s; 582 if (success) *mem = m; 583 }); 584 if (r.isOk() && success) { 585 memory = hardware::mapMemory(*mem); 586 if (memory != 0) { 587 memory->update(); 588 memcpy(memory->getPointer(), v->data(), v->size()); 589 memory->commit(); 590 v->resize(0); 591 return std::make_pair(true, memory); 592 } else { 593 ALOGE("Failed to map allocated ashmem"); 594 } 595 } else { 596 ALOGE("Failed to allocate %llu bytes from ashmem", (unsigned long long)v->size()); 597 } 598 return std::make_pair(false, memory); 599 } 600 601 } // namespace 602 603 Return<void> SoundTriggerHw::loadSoundModel_2_1( 604 const V2_1::ISoundTriggerHw::SoundModel& soundModel, 605 const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie, 606 V2_1::ISoundTriggerHw::loadSoundModel_2_1_cb _hidl_cb) { 607 // It is assumed that legacy data vector is empty, thus making copy is cheap. 608 V2_0::ISoundTriggerHw::SoundModel soundModel_2_0(soundModel.header); 609 auto result = memoryAsVector(soundModel.data, &soundModel_2_0.data); 610 if (result.first) { 611 sp<SoundModelClient> client = 612 new SoundModelClient_2_1(nextUniqueModelId(), cookie, callback); 613 _hidl_cb(doLoadSoundModel(soundModel_2_0, client), client->getId()); 614 return Void(); 615 } 616 _hidl_cb(-ENOMEM, 0); 617 return Void(); 618 } 619 620 Return<void> SoundTriggerHw::loadPhraseSoundModel_2_1( 621 const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel, 622 const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie, 623 V2_1::ISoundTriggerHw::loadPhraseSoundModel_2_1_cb _hidl_cb) { 624 V2_0::ISoundTriggerHw::PhraseSoundModel soundModel_2_0; 625 // It is assumed that legacy data vector is empty, thus making copy is cheap. 626 soundModel_2_0.common = soundModel.common.header; 627 // Avoid copying phrases data. 628 soundModel_2_0.phrases.setToExternal( 629 const_cast<V2_0::ISoundTriggerHw::Phrase*>(soundModel.phrases.data()), 630 soundModel.phrases.size()); 631 auto result = memoryAsVector(soundModel.common.data, &soundModel_2_0.common.data); 632 if (result.first) { 633 sp<SoundModelClient> client = 634 new SoundModelClient_2_1(nextUniqueModelId(), cookie, callback); 635 _hidl_cb(doLoadSoundModel((const V2_0::ISoundTriggerHw::SoundModel&)soundModel_2_0, client), 636 client->getId()); 637 return Void(); 638 } 639 _hidl_cb(-ENOMEM, 0); 640 return Void(); 641 } 642 643 Return<int32_t> SoundTriggerHw::startRecognition_2_1( 644 int32_t modelHandle, const V2_1::ISoundTriggerHw::RecognitionConfig& config, 645 const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie) { 646 // It is assumed that legacy data vector is empty, thus making copy is cheap. 647 V2_0::ISoundTriggerHw::RecognitionConfig config_2_0(config.header); 648 auto result = memoryAsVector(config.data, &config_2_0.data); 649 return result.first ? startRecognition(modelHandle, config_2_0, callback, cookie) 650 : Return<int32_t>(-ENOMEM); 651 } 652 653 void SoundTriggerHw::SoundModelClient_2_1::recognitionCallback( 654 struct sound_trigger_recognition_event* halEvent) { 655 if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) { 656 V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent event_2_0; 657 convertPhaseRecognitionEventFromHal( 658 &event_2_0, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent)); 659 event_2_0.common.model = mId; 660 V2_1::ISoundTriggerHwCallback::PhraseRecognitionEvent event; 661 event.phraseExtras.setToExternal(event_2_0.phraseExtras.data(), 662 event_2_0.phraseExtras.size()); 663 auto result = moveVectorToMemory(&event_2_0.common.data, &event.common.data); 664 if (result.first) { 665 // The data vector is now empty, thus copying is cheap. 666 event.common.header = event_2_0.common; 667 mCallback->phraseRecognitionCallback_2_1(event, mCookie); 668 } 669 } else { 670 V2_1::ISoundTriggerHwCallback::RecognitionEvent event; 671 convertRecognitionEventFromHal(&event.header, halEvent); 672 event.header.model = mId; 673 auto result = moveVectorToMemory(&event.header.data, &event.data); 674 if (result.first) { 675 mCallback->recognitionCallback_2_1(event, mCookie); 676 } 677 } 678 } 679 680 void SoundTriggerHw::SoundModelClient_2_1::soundModelCallback( 681 struct sound_trigger_model_event* halEvent) { 682 V2_1::ISoundTriggerHwCallback::ModelEvent event; 683 convertSoundModelEventFromHal(&event.header, halEvent); 684 event.header.model = mId; 685 auto result = moveVectorToMemory(&event.header.data, &event.data); 686 if (result.first) { 687 mCallback->soundModelCallback_2_1(event, mCookie); 688 } 689 } 690 691 // Begin V2_2 implementation 692 693 Return<int32_t> SoundTriggerHw::getModelState(int32_t modelHandle) { 694 sp<SoundModelClient> client; 695 if (mHwDevice == NULL) { 696 return -ENODEV; 697 } 698 699 { 700 AutoMutex lock(mLock); 701 client = mClients.valueFor(modelHandle); 702 if (client == 0) { 703 return -ENOSYS; 704 } 705 } 706 707 if (mHwDevice->common.version < SOUND_TRIGGER_DEVICE_API_VERSION_1_2) { 708 ALOGE("Get model state not supported"); 709 return -ENODEV; 710 } 711 712 if (mHwDevice->get_model_state == NULL) { 713 ALOGE("Failed to get model state from device, no such method"); 714 return -ENODEV; 715 } 716 717 return mHwDevice->get_model_state(mHwDevice, client->getHalHandle()); 718 } 719 720 // Methods from ::android::hidl::base::V1_0::IBase follow. 721 722 ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* /* name */) { 723 return new SoundTriggerHw(); 724 } 725 726 } // namespace implementation 727 } // namespace V2_2 728 } // namespace soundtrigger 729 } // namespace hardware 730 } // namespace android 731