/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "SoundTriggerHalHidl" //#define LOG_NDEBUG 0 #include #include #include #include "SoundTriggerHalHidl.h" #include #include #include namespace android { using ::android::hardware::ProcessState; using ::android::hardware::Return; using ::android::hardware::Status; using ::android::hardware::Void; using ::android::hardware::audio::common::V2_0::AudioDevice; using ::android::hardware::hidl_memory; using ::android::hidl::allocator::V1_0::IAllocator; using ::android::hidl::memory::V1_0::IMemory; namespace { // Backs up by the vector with the contents of shared memory. // It is assumed that the passed hidl_vector is empty, so it's // not cleared if the memory is a null object. // The caller needs to keep the returned sp as long as // the data is needed. std::pair> memoryAsVector(const hidl_memory& m, hidl_vec* vec) { sp memory; if (m.size() == 0) { return std::make_pair(true, memory); } memory = mapMemory(m); if (memory != nullptr) { memory->read(); vec->setToExternal(static_cast(static_cast(memory->getPointer())), memory->getSize()); return std::make_pair(true, memory); } ALOGE("%s: Could not map HIDL memory to IMemory", __func__); return std::make_pair(false, memory); } // Moves the data from the vector into allocated shared memory, // emptying the vector. // It is assumed that the passed hidl_memory is a null object, so it's // not reset if the vector is empty. // The caller needs to keep the returned sp as long as // the data is needed. std::pair> moveVectorToMemory(hidl_vec* v, hidl_memory* mem) { sp memory; if (v->size() == 0) { return std::make_pair(true, memory); } sp ashmem = IAllocator::getService("ashmem"); if (ashmem == 0) { ALOGE("Failed to retrieve ashmem allocator service"); return std::make_pair(false, memory); } bool success = false; Return r = ashmem->allocate(v->size(), [&](bool s, const hidl_memory& m) { success = s; if (success) *mem = m; }); if (r.isOk() && success) { memory = hardware::mapMemory(*mem); if (memory != 0) { memory->update(); memcpy(memory->getPointer(), v->data(), v->size()); memory->commit(); v->resize(0); return std::make_pair(true, memory); } else { ALOGE("Failed to map allocated ashmem"); } } else { ALOGE("Failed to allocate %llu bytes from ashmem", (unsigned long long)v->size()); } return std::make_pair(false, memory); } } // namespace /* static */ sp SoundTriggerHalInterface::connectModule(const char *moduleName) { return new SoundTriggerHalHidl(moduleName); } int SoundTriggerHalHidl::getProperties(struct sound_trigger_properties *properties) { sp soundtrigger = getService(); if (soundtrigger == 0) { return -ENODEV; } ISoundTriggerHw::Properties halProperties; Return hidlReturn; int ret; { AutoMutex lock(mHalLock); hidlReturn = soundtrigger->getProperties([&](int rc, auto res) { ret = rc; halProperties = res; ALOGI("getProperties res implementor %s", res.implementor.c_str()); }); } if (hidlReturn.isOk()) { if (ret == 0) { convertPropertiesFromHal(properties, &halProperties); } } else { ALOGE("getProperties error %s", hidlReturn.description().c_str()); return FAILED_TRANSACTION; } ALOGI("getProperties ret %d", ret); return ret; } int SoundTriggerHalHidl::loadSoundModel(struct sound_trigger_sound_model *sound_model, sound_model_callback_t callback, void *cookie, sound_model_handle_t *handle) { if (handle == NULL) { return -EINVAL; } sp soundtrigger = getService(); if (soundtrigger == 0) { return -ENODEV; } uint32_t modelId; { AutoMutex lock(mLock); do { modelId = nextUniqueId(); ALOGI("loadSoundModel modelId %u", modelId); sp model = mSoundModels.valueFor(modelId); ALOGI("loadSoundModel model %p", model.get()); } while (mSoundModels.valueFor(modelId) != 0 && modelId != 0); } LOG_ALWAYS_FATAL_IF(modelId == 0, "loadSoundModel(): wrap around in sound model IDs, num loaded models %zd", mSoundModels.size()); Return hidlReturn; int ret; SoundModelHandle halHandle; sp soundtrigger_2_1 = toService2_1(soundtrigger); sp soundtrigger_2_2 = toService2_2(soundtrigger); if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) { if (soundtrigger_2_2) { V2_2_ISoundTriggerHw::PhraseSoundModel halSoundModel; auto result = convertPhraseSoundModelToHal(&halSoundModel, sound_model); if (result.first) { AutoMutex lock(mHalLock); hidlReturn = soundtrigger_2_2->loadPhraseSoundModel_2_1( halSoundModel, this, modelId, [&](int32_t retval, auto res) { ret = retval; halHandle = res; }); } else { return NO_MEMORY; } } else if (soundtrigger_2_1) { V2_1_ISoundTriggerHw::PhraseSoundModel halSoundModel; auto result = convertPhraseSoundModelToHal(&halSoundModel, sound_model); if (result.first) { AutoMutex lock(mHalLock); hidlReturn = soundtrigger_2_1->loadPhraseSoundModel_2_1( halSoundModel, this, modelId, [&](int32_t retval, auto res) { ret = retval; halHandle = res; }); } else { return NO_MEMORY; } } else { ISoundTriggerHw::PhraseSoundModel halSoundModel; convertPhraseSoundModelToHal(&halSoundModel, sound_model); AutoMutex lock(mHalLock); hidlReturn = soundtrigger->loadPhraseSoundModel( halSoundModel, this, modelId, [&](int32_t retval, auto res) { ret = retval; halHandle = res; }); } } else { if (soundtrigger_2_2) { V2_2_ISoundTriggerHw::SoundModel halSoundModel; auto result = convertSoundModelToHal(&halSoundModel, sound_model); if (result.first) { AutoMutex lock(mHalLock); hidlReturn = soundtrigger_2_2->loadSoundModel_2_1(halSoundModel, this, modelId, [&](int32_t retval, auto res) { ret = retval; halHandle = res; }); } else { return NO_MEMORY; } } else if (soundtrigger_2_1) { V2_1_ISoundTriggerHw::SoundModel halSoundModel; auto result = convertSoundModelToHal(&halSoundModel, sound_model); if (result.first) { AutoMutex lock(mHalLock); hidlReturn = soundtrigger_2_1->loadSoundModel_2_1(halSoundModel, this, modelId, [&](int32_t retval, auto res) { ret = retval; halHandle = res; }); } else { return NO_MEMORY; } } else { ISoundTriggerHw::SoundModel halSoundModel; convertSoundModelToHal(&halSoundModel, sound_model); AutoMutex lock(mHalLock); hidlReturn = soundtrigger->loadSoundModel(halSoundModel, this, modelId, [&](int32_t retval, auto res) { ret = retval; halHandle = res; }); } } if (hidlReturn.isOk()) { if (ret == 0) { AutoMutex lock(mLock); *handle = (sound_model_handle_t)modelId; sp model = new SoundModel(*handle, callback, cookie, halHandle); mSoundModels.add(*handle, model); } } else { ALOGE("loadSoundModel error %s", hidlReturn.description().c_str()); return FAILED_TRANSACTION; } return ret; } int SoundTriggerHalHidl::unloadSoundModel(sound_model_handle_t handle) { sp soundtrigger = getService(); if (soundtrigger == 0) { return -ENODEV; } sp model = removeModel(handle); if (model == 0) { ALOGE("unloadSoundModel model not found for handle %u", handle); return -EINVAL; } Return hidlReturn(0); { AutoMutex lock(mHalLock); hidlReturn = soundtrigger->unloadSoundModel(model->mHalHandle); } if (!hidlReturn.isOk()) { ALOGE("unloadSoundModel error %s", hidlReturn.description().c_str()); return FAILED_TRANSACTION; } return hidlReturn; } int SoundTriggerHalHidl::startRecognition(sound_model_handle_t handle, const struct sound_trigger_recognition_config *config, recognition_callback_t callback, void *cookie) { sp soundtrigger = getService(); if (soundtrigger == 0) { return -ENODEV; } sp model = getModel(handle); if (model == 0) { ALOGE("startRecognition model not found for handle %u", handle); return -EINVAL; } model->mRecognitionCallback = callback; model->mRecognitionCookie = cookie; sp soundtrigger_2_1 = toService2_1(soundtrigger); sp soundtrigger_2_2 = toService2_2(soundtrigger); Return hidlReturn(0); if (soundtrigger_2_2) { V2_2_ISoundTriggerHw::RecognitionConfig halConfig; auto result = convertRecognitionConfigToHal(&halConfig, config); if (result.first) { AutoMutex lock(mHalLock); hidlReturn = soundtrigger_2_2->startRecognition_2_1( model->mHalHandle, halConfig, this, handle); } else { return NO_MEMORY; } } else if (soundtrigger_2_1) { V2_1_ISoundTriggerHw::RecognitionConfig halConfig; auto result = convertRecognitionConfigToHal(&halConfig, config); if (result.first) { AutoMutex lock(mHalLock); hidlReturn = soundtrigger_2_1->startRecognition_2_1( model->mHalHandle, halConfig, this, handle); } else { return NO_MEMORY; } } else { ISoundTriggerHw::RecognitionConfig halConfig; convertRecognitionConfigToHal(&halConfig, config); { AutoMutex lock(mHalLock); hidlReturn = soundtrigger->startRecognition(model->mHalHandle, halConfig, this, handle); } } if (!hidlReturn.isOk()) { ALOGE("startRecognition error %s", hidlReturn.description().c_str()); return FAILED_TRANSACTION; } return hidlReturn; } int SoundTriggerHalHidl::stopRecognition(sound_model_handle_t handle) { sp soundtrigger = getService(); if (soundtrigger == 0) { return -ENODEV; } sp model = getModel(handle); if (model == 0) { ALOGE("stopRecognition model not found for handle %u", handle); return -EINVAL; } Return hidlReturn(0); { AutoMutex lock(mHalLock); hidlReturn = soundtrigger->stopRecognition(model->mHalHandle); } if (!hidlReturn.isOk()) { ALOGE("stopRecognition error %s", hidlReturn.description().c_str()); return FAILED_TRANSACTION; } return hidlReturn; } int SoundTriggerHalHidl::stopAllRecognitions() { sp soundtrigger = getService(); if (soundtrigger == 0) { return -ENODEV; } Return hidlReturn(0); { AutoMutex lock(mHalLock); hidlReturn = soundtrigger->stopAllRecognitions(); } if (!hidlReturn.isOk()) { ALOGE("stopAllRecognitions error %s", hidlReturn.description().c_str()); return FAILED_TRANSACTION; } return hidlReturn; } int SoundTriggerHalHidl::getModelState(sound_model_handle_t handle) { sp soundtrigger = getService(); if (soundtrigger == 0) { return -ENODEV; } sp soundtrigger_2_2 = toService2_2(soundtrigger); if (soundtrigger_2_2 == 0) { ALOGE("getModelState not supported"); return -ENODEV; } sp model = getModel(handle); if (model == 0) { ALOGE("getModelState model not found for handle %u", handle); return -EINVAL; } int ret = NO_ERROR; Return hidlReturn(0); { AutoMutex lock(mHalLock); hidlReturn = soundtrigger_2_2->getModelState(model->mHalHandle); } if (!hidlReturn.isOk()) { ALOGE("getModelState error %s", hidlReturn.description().c_str()); ret = FAILED_TRANSACTION; } return ret; } SoundTriggerHalHidl::SoundTriggerHalHidl(const char *moduleName) : mModuleName(moduleName), mNextUniqueId(1) { LOG_ALWAYS_FATAL_IF(strcmp(mModuleName, "primary") != 0, "Treble soundtrigger only supports primary module"); } SoundTriggerHalHidl::~SoundTriggerHalHidl() { } sp SoundTriggerHalHidl::getService() { AutoMutex lock(mLock); if (mISoundTrigger == 0) { if (mModuleName == NULL) { mModuleName = "primary"; } mISoundTrigger = ISoundTriggerHw::getService(); if (mISoundTrigger != 0) { mISoundTrigger->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/); } } return mISoundTrigger; } sp SoundTriggerHalHidl::toService2_1(const sp& s) { auto castResult_2_1 = V2_1_ISoundTriggerHw::castFrom(s); return castResult_2_1.isOk() ? static_cast>(castResult_2_1) : nullptr; } sp SoundTriggerHalHidl::toService2_2(const sp& s) { auto castResult_2_2 = V2_2_ISoundTriggerHw::castFrom(s); return castResult_2_2.isOk() ? static_cast>(castResult_2_2) : nullptr; } sp SoundTriggerHalHidl::getModel(sound_model_handle_t handle) { AutoMutex lock(mLock); return mSoundModels.valueFor(handle); } sp SoundTriggerHalHidl::removeModel(sound_model_handle_t handle) { AutoMutex lock(mLock); sp model = mSoundModels.valueFor(handle); mSoundModels.removeItem(handle); return model; } uint32_t SoundTriggerHalHidl::nextUniqueId() { return (uint32_t) atomic_fetch_add_explicit(&mNextUniqueId, (uint_fast32_t) 1, memory_order_acq_rel); } void SoundTriggerHalHidl::convertUuidToHal(Uuid *halUuid, const sound_trigger_uuid_t *uuid) { halUuid->timeLow = uuid->timeLow; halUuid->timeMid = uuid->timeMid; halUuid->versionAndTimeHigh = uuid->timeHiAndVersion; halUuid->variantAndClockSeqHigh = uuid->clockSeq; memcpy(halUuid->node.data(), &uuid->node[0], sizeof(uuid->node)); } void SoundTriggerHalHidl::convertUuidFromHal(sound_trigger_uuid_t *uuid, const Uuid *halUuid) { uuid->timeLow = halUuid->timeLow; uuid->timeMid = halUuid->timeMid; uuid->timeHiAndVersion = halUuid->versionAndTimeHigh; uuid->clockSeq = halUuid->variantAndClockSeqHigh; memcpy(&uuid->node[0], halUuid->node.data(), sizeof(uuid->node)); } void SoundTriggerHalHidl::convertPropertiesFromHal( struct sound_trigger_properties *properties, const ISoundTriggerHw::Properties *halProperties) { strlcpy(properties->implementor, halProperties->implementor.c_str(), SOUND_TRIGGER_MAX_STRING_LEN); strlcpy(properties->description, halProperties->description.c_str(), SOUND_TRIGGER_MAX_STRING_LEN); properties->version = halProperties->version; convertUuidFromHal(&properties->uuid, &halProperties->uuid); properties->max_sound_models = halProperties->maxSoundModels; properties->max_key_phrases = halProperties->maxKeyPhrases; properties->max_users = halProperties->maxUsers; properties->recognition_modes = halProperties->recognitionModes; properties->capture_transition = (bool)halProperties->captureTransition; properties->max_buffer_ms = halProperties->maxBufferMs; properties->concurrent_capture = (bool)halProperties->concurrentCapture; properties->trigger_in_event = (bool)halProperties->triggerInEvent; properties->power_consumption_mw = halProperties->powerConsumptionMw; } void SoundTriggerHalHidl::convertTriggerPhraseToHal( ISoundTriggerHw::Phrase *halTriggerPhrase, const struct sound_trigger_phrase *triggerPhrase) { halTriggerPhrase->id = triggerPhrase->id; halTriggerPhrase->recognitionModes = triggerPhrase->recognition_mode; halTriggerPhrase->users.setToExternal((uint32_t *)&triggerPhrase->users[0], triggerPhrase->num_users); halTriggerPhrase->locale = triggerPhrase->locale; halTriggerPhrase->text = triggerPhrase->text; } void SoundTriggerHalHidl::convertTriggerPhrasesToHal( hidl_vec *halTriggerPhrases, struct sound_trigger_phrase_sound_model *keyPhraseModel) { halTriggerPhrases->resize(keyPhraseModel->num_phrases); for (unsigned int i = 0; i < keyPhraseModel->num_phrases; i++) { convertTriggerPhraseToHal(&(*halTriggerPhrases)[i], &keyPhraseModel->phrases[i]); } } void SoundTriggerHalHidl::convertSoundModelToHal(ISoundTriggerHw::SoundModel *halModel, const struct sound_trigger_sound_model *soundModel) { halModel->type = (SoundModelType)soundModel->type; convertUuidToHal(&halModel->uuid, &soundModel->uuid); convertUuidToHal(&halModel->vendorUuid, &soundModel->vendor_uuid); halModel->data.setToExternal((uint8_t *)soundModel + soundModel->data_offset, soundModel->data_size); } std::pair> SoundTriggerHalHidl::convertSoundModelToHal( V2_1_ISoundTriggerHw::SoundModel *halModel, const struct sound_trigger_sound_model *soundModel) { convertSoundModelToHal(&halModel->header, soundModel); return moveVectorToMemory(&halModel->header.data, &halModel->data); } void SoundTriggerHalHidl::convertPhraseSoundModelToHal( ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel, const struct sound_trigger_sound_model *soundModel) { struct sound_trigger_phrase_sound_model *keyPhraseModel = (struct sound_trigger_phrase_sound_model *)soundModel; convertTriggerPhrasesToHal(&halKeyPhraseModel->phrases, keyPhraseModel); convertSoundModelToHal(&halKeyPhraseModel->common, soundModel); } std::pair> SoundTriggerHalHidl::convertPhraseSoundModelToHal( V2_1_ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel, const struct sound_trigger_sound_model *soundModel) { struct sound_trigger_phrase_sound_model *keyPhraseModel = (struct sound_trigger_phrase_sound_model *)soundModel; convertTriggerPhrasesToHal(&halKeyPhraseModel->phrases, keyPhraseModel); return convertSoundModelToHal(&halKeyPhraseModel->common, soundModel); } void SoundTriggerHalHidl::convertPhraseRecognitionExtraToHal( PhraseRecognitionExtra *halExtra, const struct sound_trigger_phrase_recognition_extra *extra) { halExtra->id = extra->id; halExtra->recognitionModes = extra->recognition_modes; halExtra->confidenceLevel = extra->confidence_level; halExtra->levels.resize(extra->num_levels); for (unsigned int i = 0; i < extra->num_levels; i++) { halExtra->levels[i].userId = extra->levels[i].user_id; halExtra->levels[i].levelPercent = extra->levels[i].level; } } void SoundTriggerHalHidl::convertRecognitionConfigToHal( ISoundTriggerHw::RecognitionConfig *halConfig, const struct sound_trigger_recognition_config *config) { halConfig->captureHandle = config->capture_handle; halConfig->captureDevice = (AudioDevice)config->capture_device; halConfig->captureRequested = (uint32_t)config->capture_requested; halConfig->phrases.resize(config->num_phrases); for (unsigned int i = 0; i < config->num_phrases; i++) { convertPhraseRecognitionExtraToHal(&halConfig->phrases[i], &config->phrases[i]); } halConfig->data.setToExternal((uint8_t *)config + config->data_offset, config->data_size); } std::pair> SoundTriggerHalHidl::convertRecognitionConfigToHal( V2_1_ISoundTriggerHw::RecognitionConfig *halConfig, const struct sound_trigger_recognition_config *config) { convertRecognitionConfigToHal(&halConfig->header, config); return moveVectorToMemory(&halConfig->header.data, &halConfig->data); } // ISoundTriggerHwCallback ::android::hardware::Return SoundTriggerHalHidl::recognitionCallback( const V2_0_ISoundTriggerHwCallback::RecognitionEvent& halEvent, CallbackCookie cookie) { sp model; { AutoMutex lock(mLock); model = mSoundModels.valueFor((SoundModelHandle)cookie); if (model == 0) { return Return(); } } struct sound_trigger_recognition_event *event = convertRecognitionEventFromHal(&halEvent); if (event == NULL) { return Return(); } event->model = model->mHandle; model->mRecognitionCallback(event, model->mRecognitionCookie); free(event); return Return(); } ::android::hardware::Return SoundTriggerHalHidl::phraseRecognitionCallback( const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent& halEvent, CallbackCookie cookie) { sp model; { AutoMutex lock(mLock); model = mSoundModels.valueFor((SoundModelHandle)cookie); if (model == 0) { return Return(); } } struct sound_trigger_phrase_recognition_event *event = convertPhraseRecognitionEventFromHal(&halEvent); if (event == NULL) { return Return(); } event->common.model = model->mHandle; model->mRecognitionCallback(&event->common, model->mRecognitionCookie); free(event); return Return(); } ::android::hardware::Return SoundTriggerHalHidl::soundModelCallback( const V2_0_ISoundTriggerHwCallback::ModelEvent& halEvent, CallbackCookie cookie) { sp model; { AutoMutex lock(mLock); model = mSoundModels.valueFor((SoundModelHandle)cookie); if (model == 0) { return Return(); } } struct sound_trigger_model_event *event = convertSoundModelEventFromHal(&halEvent); if (event == NULL) { return Return(); } event->model = model->mHandle; model->mSoundModelCallback(event, model->mSoundModelCookie); free(event); return Return(); } ::android::hardware::Return SoundTriggerHalHidl::recognitionCallback_2_1( const ISoundTriggerHwCallback::RecognitionEvent& event, CallbackCookie cookie) { // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap. V2_0_ISoundTriggerHwCallback::RecognitionEvent event_2_0 = event.header; auto result = memoryAsVector(event.data, &event_2_0.data); return result.first ? recognitionCallback(event_2_0, cookie) : Void(); } ::android::hardware::Return SoundTriggerHalHidl::phraseRecognitionCallback_2_1( const ISoundTriggerHwCallback::PhraseRecognitionEvent& event, int32_t cookie) { V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent event_2_0; // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap. event_2_0.common = event.common.header; event_2_0.phraseExtras.setToExternal( const_cast(event.phraseExtras.data()), event.phraseExtras.size()); auto result = memoryAsVector(event.common.data, &event_2_0.common.data); return result.first ? phraseRecognitionCallback(event_2_0, cookie) : Void(); } ::android::hardware::Return SoundTriggerHalHidl::soundModelCallback_2_1( const ISoundTriggerHwCallback::ModelEvent& event, CallbackCookie cookie) { // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap. V2_0_ISoundTriggerHwCallback::ModelEvent event_2_0 = event.header; auto result = memoryAsVector(event.data, &event_2_0.data); return result.first ? soundModelCallback(event_2_0, cookie) : Void(); } struct sound_trigger_model_event *SoundTriggerHalHidl::convertSoundModelEventFromHal( const V2_0_ISoundTriggerHwCallback::ModelEvent *halEvent) { struct sound_trigger_model_event *event = (struct sound_trigger_model_event *)malloc( sizeof(struct sound_trigger_model_event) + halEvent->data.size()); if (event == NULL) { return NULL; } event->status = (int)halEvent->status; // event->model to be set by caller event->data_offset = sizeof(struct sound_trigger_model_event); event->data_size = halEvent->data.size(); uint8_t *dst = (uint8_t *)event + event->data_offset; uint8_t *src = (uint8_t *)&halEvent->data[0]; memcpy(dst, src, halEvent->data.size()); return event; } void SoundTriggerHalHidl::convertPhraseRecognitionExtraFromHal( struct sound_trigger_phrase_recognition_extra *extra, const PhraseRecognitionExtra *halExtra) { extra->id = halExtra->id; extra->recognition_modes = halExtra->recognitionModes; extra->confidence_level = halExtra->confidenceLevel; size_t i; for (i = 0; i < halExtra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) { extra->levels[i].user_id = halExtra->levels[i].userId; extra->levels[i].level = halExtra->levels[i].levelPercent; } extra->num_levels = (unsigned int)i; } struct sound_trigger_phrase_recognition_event* SoundTriggerHalHidl::convertPhraseRecognitionEventFromHal( const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent *halPhraseEvent) { if (halPhraseEvent->common.type != SoundModelType::KEYPHRASE) { ALOGE("Received non-keyphrase event type as PhraseRecognitionEvent"); return NULL; } struct sound_trigger_phrase_recognition_event *phraseEvent = (struct sound_trigger_phrase_recognition_event *)malloc( sizeof(struct sound_trigger_phrase_recognition_event) + halPhraseEvent->common.data.size()); if (phraseEvent == NULL) { return NULL; } phraseEvent->common.data_offset = sizeof(sound_trigger_phrase_recognition_event); for (unsigned int i = 0; i < halPhraseEvent->phraseExtras.size(); i++) { convertPhraseRecognitionExtraFromHal(&phraseEvent->phrase_extras[i], &halPhraseEvent->phraseExtras[i]); } phraseEvent->num_phrases = halPhraseEvent->phraseExtras.size(); fillRecognitionEventFromHal(&phraseEvent->common, &halPhraseEvent->common); return phraseEvent; } struct sound_trigger_recognition_event *SoundTriggerHalHidl::convertRecognitionEventFromHal( const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent) { if (halEvent->type == SoundModelType::KEYPHRASE) { ALOGE("Received keyphrase event type as RecognitionEvent"); return NULL; } struct sound_trigger_recognition_event *event; event = (struct sound_trigger_recognition_event *)malloc( sizeof(struct sound_trigger_recognition_event) + halEvent->data.size()); if (event == NULL) { return NULL; } event->data_offset = sizeof(sound_trigger_recognition_event); fillRecognitionEventFromHal(event, halEvent); return event; } void SoundTriggerHalHidl::fillRecognitionEventFromHal( struct sound_trigger_recognition_event *event, const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent) { event->status = (int)halEvent->status; event->type = (sound_trigger_sound_model_type_t)halEvent->type; // event->model to be set by caller event->capture_available = (bool)halEvent->captureAvailable; event->capture_session = halEvent->captureSession; event->capture_delay_ms = halEvent->captureDelayMs; event->capture_preamble_ms = halEvent->capturePreambleMs; event->trigger_in_data = (bool)halEvent->triggerInData; event->audio_config.sample_rate = halEvent->audioConfig.sampleRateHz; event->audio_config.channel_mask = (audio_channel_mask_t)halEvent->audioConfig.channelMask; event->audio_config.format = (audio_format_t)halEvent->audioConfig.format; event->data_size = halEvent->data.size(); uint8_t *dst = (uint8_t *)event + event->data_offset; uint8_t *src = (uint8_t *)&halEvent->data[0]; memcpy(dst, src, halEvent->data.size()); } } // namespace android