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