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     sp<V2_2_ISoundTriggerHw> soundtrigger_2_2 = toService2_2(soundtrigger);
    172     if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
    173         if (soundtrigger_2_2) {
    174             V2_2_ISoundTriggerHw::PhraseSoundModel halSoundModel;
    175             auto result = convertPhraseSoundModelToHal(&halSoundModel, sound_model);
    176             if (result.first) {
    177                 AutoMutex lock(mHalLock);
    178                 hidlReturn = soundtrigger_2_2->loadPhraseSoundModel_2_1(
    179                         halSoundModel,
    180                         this, modelId, [&](int32_t retval, auto res) {
    181                             ret = retval;
    182                             halHandle = res;
    183                         });
    184             } else {
    185                 return NO_MEMORY;
    186             }
    187         } else if (soundtrigger_2_1) {
    188             V2_1_ISoundTriggerHw::PhraseSoundModel halSoundModel;
    189             auto result = convertPhraseSoundModelToHal(&halSoundModel, sound_model);
    190             if (result.first) {
    191                 AutoMutex lock(mHalLock);
    192                 hidlReturn = soundtrigger_2_1->loadPhraseSoundModel_2_1(
    193                         halSoundModel,
    194                         this, modelId, [&](int32_t retval, auto res) {
    195                             ret = retval;
    196                             halHandle = res;
    197                         });
    198             } else {
    199                 return NO_MEMORY;
    200             }
    201         } else {
    202             ISoundTriggerHw::PhraseSoundModel halSoundModel;
    203             convertPhraseSoundModelToHal(&halSoundModel, sound_model);
    204             AutoMutex lock(mHalLock);
    205             hidlReturn = soundtrigger->loadPhraseSoundModel(
    206                     halSoundModel,
    207                     this, modelId, [&](int32_t retval, auto res) {
    208                         ret = retval;
    209                         halHandle = res;
    210                     });
    211         }
    212     } else {
    213         if (soundtrigger_2_2) {
    214             V2_2_ISoundTriggerHw::SoundModel halSoundModel;
    215             auto result = convertSoundModelToHal(&halSoundModel, sound_model);
    216             if (result.first) {
    217                 AutoMutex lock(mHalLock);
    218                 hidlReturn = soundtrigger_2_2->loadSoundModel_2_1(halSoundModel,
    219                         this, modelId, [&](int32_t retval, auto res) {
    220                             ret = retval;
    221                             halHandle = res;
    222                         });
    223             } else {
    224                 return NO_MEMORY;
    225             }
    226         } else if (soundtrigger_2_1) {
    227             V2_1_ISoundTriggerHw::SoundModel halSoundModel;
    228             auto result = convertSoundModelToHal(&halSoundModel, sound_model);
    229             if (result.first) {
    230                 AutoMutex lock(mHalLock);
    231                 hidlReturn = soundtrigger_2_1->loadSoundModel_2_1(halSoundModel,
    232                         this, modelId, [&](int32_t retval, auto res) {
    233                             ret = retval;
    234                             halHandle = res;
    235                         });
    236             } else {
    237                 return NO_MEMORY;
    238             }
    239         } else {
    240             ISoundTriggerHw::SoundModel halSoundModel;
    241             convertSoundModelToHal(&halSoundModel, sound_model);
    242             AutoMutex lock(mHalLock);
    243             hidlReturn = soundtrigger->loadSoundModel(halSoundModel,
    244                     this, modelId, [&](int32_t retval, auto res) {
    245                         ret = retval;
    246                         halHandle = res;
    247                     });
    248         }
    249     }
    250 
    251     if (hidlReturn.isOk()) {
    252         if (ret == 0) {
    253             AutoMutex lock(mLock);
    254             *handle = (sound_model_handle_t)modelId;
    255             sp<SoundModel> model = new SoundModel(*handle, callback, cookie, halHandle);
    256             mSoundModels.add(*handle, model);
    257         }
    258     } else {
    259         ALOGE("loadSoundModel error %s", hidlReturn.description().c_str());
    260         return FAILED_TRANSACTION;
    261     }
    262 
    263     return ret;
    264 }
    265 
    266 int SoundTriggerHalHidl::unloadSoundModel(sound_model_handle_t handle)
    267 {
    268     sp<ISoundTriggerHw> soundtrigger = getService();
    269     if (soundtrigger == 0) {
    270         return -ENODEV;
    271     }
    272 
    273     sp<SoundModel> model = removeModel(handle);
    274     if (model == 0) {
    275         ALOGE("unloadSoundModel model not found for handle %u", handle);
    276         return -EINVAL;
    277     }
    278 
    279     Return<int32_t> hidlReturn(0);
    280     {
    281         AutoMutex lock(mHalLock);
    282         hidlReturn = soundtrigger->unloadSoundModel(model->mHalHandle);
    283     }
    284 
    285     if (!hidlReturn.isOk()) {
    286         ALOGE("unloadSoundModel error %s", hidlReturn.description().c_str());
    287         return FAILED_TRANSACTION;
    288     }
    289 
    290     return hidlReturn;
    291 }
    292 
    293 int SoundTriggerHalHidl::startRecognition(sound_model_handle_t handle,
    294                          const struct sound_trigger_recognition_config *config,
    295                          recognition_callback_t callback,
    296                          void *cookie)
    297 {
    298     sp<ISoundTriggerHw> soundtrigger = getService();
    299     if (soundtrigger == 0) {
    300         return -ENODEV;
    301     }
    302 
    303     sp<SoundModel> model = getModel(handle);
    304     if (model == 0) {
    305         ALOGE("startRecognition model not found for handle %u", handle);
    306         return -EINVAL;
    307     }
    308 
    309     model->mRecognitionCallback = callback;
    310     model->mRecognitionCookie = cookie;
    311 
    312     sp<V2_1_ISoundTriggerHw> soundtrigger_2_1 = toService2_1(soundtrigger);
    313     sp<V2_2_ISoundTriggerHw> soundtrigger_2_2 = toService2_2(soundtrigger);
    314     Return<int32_t> hidlReturn(0);
    315 
    316     if (soundtrigger_2_2) {
    317         V2_2_ISoundTriggerHw::RecognitionConfig halConfig;
    318         auto result = convertRecognitionConfigToHal(&halConfig, config);
    319         if (result.first) {
    320             AutoMutex lock(mHalLock);
    321             hidlReturn = soundtrigger_2_2->startRecognition_2_1(
    322                     model->mHalHandle, halConfig, this, handle);
    323         } else {
    324             return NO_MEMORY;
    325         }
    326     } else if (soundtrigger_2_1) {
    327         V2_1_ISoundTriggerHw::RecognitionConfig halConfig;
    328         auto result = convertRecognitionConfigToHal(&halConfig, config);
    329         if (result.first) {
    330             AutoMutex lock(mHalLock);
    331             hidlReturn = soundtrigger_2_1->startRecognition_2_1(
    332                     model->mHalHandle, halConfig, this, handle);
    333         } else {
    334             return NO_MEMORY;
    335         }
    336     } else {
    337         ISoundTriggerHw::RecognitionConfig halConfig;
    338         convertRecognitionConfigToHal(&halConfig, config);
    339         {
    340             AutoMutex lock(mHalLock);
    341             hidlReturn = soundtrigger->startRecognition(model->mHalHandle, halConfig, this, handle);
    342         }
    343     }
    344 
    345     if (!hidlReturn.isOk()) {
    346         ALOGE("startRecognition error %s", hidlReturn.description().c_str());
    347         return FAILED_TRANSACTION;
    348     }
    349     return hidlReturn;
    350 }
    351 
    352 int SoundTriggerHalHidl::stopRecognition(sound_model_handle_t handle)
    353 {
    354     sp<ISoundTriggerHw> soundtrigger = getService();
    355     if (soundtrigger == 0) {
    356         return -ENODEV;
    357     }
    358 
    359     sp<SoundModel> model = getModel(handle);
    360     if (model == 0) {
    361         ALOGE("stopRecognition model not found for handle %u", handle);
    362         return -EINVAL;
    363     }
    364 
    365     Return<int32_t> hidlReturn(0);
    366     {
    367         AutoMutex lock(mHalLock);
    368         hidlReturn = soundtrigger->stopRecognition(model->mHalHandle);
    369     }
    370 
    371     if (!hidlReturn.isOk()) {
    372         ALOGE("stopRecognition error %s", hidlReturn.description().c_str());
    373         return FAILED_TRANSACTION;
    374     }
    375     return hidlReturn;
    376 }
    377 
    378 int SoundTriggerHalHidl::stopAllRecognitions()
    379 {
    380     sp<ISoundTriggerHw> soundtrigger = getService();
    381     if (soundtrigger == 0) {
    382         return -ENODEV;
    383     }
    384 
    385     Return<int32_t> hidlReturn(0);
    386     {
    387         AutoMutex lock(mHalLock);
    388         hidlReturn = soundtrigger->stopAllRecognitions();
    389     }
    390 
    391     if (!hidlReturn.isOk()) {
    392         ALOGE("stopAllRecognitions error %s", hidlReturn.description().c_str());
    393         return FAILED_TRANSACTION;
    394     }
    395     return hidlReturn;
    396 }
    397 
    398 int SoundTriggerHalHidl::getModelState(sound_model_handle_t handle)
    399 {
    400     sp<ISoundTriggerHw> soundtrigger = getService();
    401     if (soundtrigger == 0) {
    402         return -ENODEV;
    403     }
    404 
    405     sp<V2_2_ISoundTriggerHw> soundtrigger_2_2 = toService2_2(soundtrigger);
    406     if (soundtrigger_2_2 == 0) {
    407         ALOGE("getModelState not supported");
    408         return -ENODEV;
    409     }
    410 
    411     sp<SoundModel> model = getModel(handle);
    412     if (model == 0) {
    413         ALOGE("getModelState model not found for handle %u", handle);
    414         return -EINVAL;
    415     }
    416 
    417     int ret = NO_ERROR;
    418     Return<int32_t> hidlReturn(0);
    419     {
    420         AutoMutex lock(mHalLock);
    421         hidlReturn = soundtrigger_2_2->getModelState(model->mHalHandle);
    422     }
    423     if (!hidlReturn.isOk()) {
    424         ALOGE("getModelState error %s", hidlReturn.description().c_str());
    425         ret = FAILED_TRANSACTION;
    426     }
    427     return ret;
    428 }
    429 
    430 SoundTriggerHalHidl::SoundTriggerHalHidl(const char *moduleName)
    431     : mModuleName(moduleName), mNextUniqueId(1)
    432 {
    433     LOG_ALWAYS_FATAL_IF(strcmp(mModuleName, "primary") != 0,
    434             "Treble soundtrigger only supports primary module");
    435 }
    436 
    437 SoundTriggerHalHidl::~SoundTriggerHalHidl()
    438 {
    439 }
    440 
    441 sp<ISoundTriggerHw> SoundTriggerHalHidl::getService()
    442 {
    443     AutoMutex lock(mLock);
    444     if (mISoundTrigger == 0) {
    445         if (mModuleName == NULL) {
    446             mModuleName = "primary";
    447         }
    448         mISoundTrigger = ISoundTriggerHw::getService();
    449         if (mISoundTrigger != 0) {
    450             mISoundTrigger->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
    451         }
    452     }
    453     return mISoundTrigger;
    454 }
    455 
    456 sp<V2_1_ISoundTriggerHw> SoundTriggerHalHidl::toService2_1(const sp<ISoundTriggerHw>& s)
    457 {
    458     auto castResult_2_1 = V2_1_ISoundTriggerHw::castFrom(s);
    459     return castResult_2_1.isOk() ? static_cast<sp<V2_1_ISoundTriggerHw>>(castResult_2_1) : nullptr;
    460 }
    461 
    462 sp<V2_2_ISoundTriggerHw> SoundTriggerHalHidl::toService2_2(const sp<ISoundTriggerHw>& s)
    463 {
    464     auto castResult_2_2 = V2_2_ISoundTriggerHw::castFrom(s);
    465     return castResult_2_2.isOk() ? static_cast<sp<V2_2_ISoundTriggerHw>>(castResult_2_2) : nullptr;
    466 }
    467 
    468 sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::getModel(sound_model_handle_t handle)
    469 {
    470     AutoMutex lock(mLock);
    471     return mSoundModels.valueFor(handle);
    472 }
    473 
    474 sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::removeModel(sound_model_handle_t handle)
    475 {
    476     AutoMutex lock(mLock);
    477     sp<SoundModel> model = mSoundModels.valueFor(handle);
    478     mSoundModels.removeItem(handle);
    479     return model;
    480 }
    481 
    482 uint32_t SoundTriggerHalHidl::nextUniqueId()
    483 {
    484     return (uint32_t) atomic_fetch_add_explicit(&mNextUniqueId,
    485                 (uint_fast32_t) 1, memory_order_acq_rel);
    486 }
    487 
    488 void SoundTriggerHalHidl::convertUuidToHal(Uuid *halUuid,
    489                                            const sound_trigger_uuid_t *uuid)
    490 {
    491     halUuid->timeLow = uuid->timeLow;
    492     halUuid->timeMid = uuid->timeMid;
    493     halUuid->versionAndTimeHigh = uuid->timeHiAndVersion;
    494     halUuid->variantAndClockSeqHigh = uuid->clockSeq;
    495     memcpy(halUuid->node.data(), &uuid->node[0], sizeof(uuid->node));
    496 }
    497 
    498 void SoundTriggerHalHidl::convertUuidFromHal(sound_trigger_uuid_t *uuid,
    499                                              const Uuid *halUuid)
    500 {
    501     uuid->timeLow = halUuid->timeLow;
    502     uuid->timeMid = halUuid->timeMid;
    503     uuid->timeHiAndVersion = halUuid->versionAndTimeHigh;
    504     uuid->clockSeq = halUuid->variantAndClockSeqHigh;
    505     memcpy(&uuid->node[0], halUuid->node.data(), sizeof(uuid->node));
    506 }
    507 
    508 void SoundTriggerHalHidl::convertPropertiesFromHal(
    509         struct sound_trigger_properties *properties,
    510         const ISoundTriggerHw::Properties *halProperties)
    511 {
    512     strlcpy(properties->implementor,
    513             halProperties->implementor.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
    514     strlcpy(properties->description,
    515             halProperties->description.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
    516     properties->version = halProperties->version;
    517     convertUuidFromHal(&properties->uuid, &halProperties->uuid);
    518     properties->max_sound_models = halProperties->maxSoundModels;
    519     properties->max_key_phrases = halProperties->maxKeyPhrases;
    520     properties->max_users = halProperties->maxUsers;
    521     properties->recognition_modes = halProperties->recognitionModes;
    522     properties->capture_transition = (bool)halProperties->captureTransition;
    523     properties->max_buffer_ms = halProperties->maxBufferMs;
    524     properties->concurrent_capture = (bool)halProperties->concurrentCapture;
    525     properties->trigger_in_event = (bool)halProperties->triggerInEvent;
    526     properties->power_consumption_mw = halProperties->powerConsumptionMw;
    527 }
    528 
    529 void SoundTriggerHalHidl::convertTriggerPhraseToHal(
    530         ISoundTriggerHw::Phrase *halTriggerPhrase,
    531         const struct sound_trigger_phrase *triggerPhrase)
    532 {
    533     halTriggerPhrase->id = triggerPhrase->id;
    534     halTriggerPhrase->recognitionModes = triggerPhrase->recognition_mode;
    535     halTriggerPhrase->users.setToExternal((uint32_t *)&triggerPhrase->users[0], triggerPhrase->num_users);
    536     halTriggerPhrase->locale = triggerPhrase->locale;
    537     halTriggerPhrase->text = triggerPhrase->text;
    538 }
    539 
    540 
    541 void SoundTriggerHalHidl::convertTriggerPhrasesToHal(
    542         hidl_vec<ISoundTriggerHw::Phrase> *halTriggerPhrases,
    543         struct sound_trigger_phrase_sound_model *keyPhraseModel)
    544 {
    545     halTriggerPhrases->resize(keyPhraseModel->num_phrases);
    546     for (unsigned int i = 0; i < keyPhraseModel->num_phrases; i++) {
    547         convertTriggerPhraseToHal(&(*halTriggerPhrases)[i], &keyPhraseModel->phrases[i]);
    548     }
    549 }
    550 
    551 void SoundTriggerHalHidl::convertSoundModelToHal(ISoundTriggerHw::SoundModel *halModel,
    552         const struct sound_trigger_sound_model *soundModel)
    553 {
    554     halModel->type = (SoundModelType)soundModel->type;
    555     convertUuidToHal(&halModel->uuid, &soundModel->uuid);
    556     convertUuidToHal(&halModel->vendorUuid, &soundModel->vendor_uuid);
    557     halModel->data.setToExternal((uint8_t *)soundModel + soundModel->data_offset, soundModel->data_size);
    558 }
    559 
    560 std::pair<bool, sp<IMemory>> SoundTriggerHalHidl::convertSoundModelToHal(
    561         V2_1_ISoundTriggerHw::SoundModel *halModel,
    562         const struct sound_trigger_sound_model *soundModel)
    563 {
    564     convertSoundModelToHal(&halModel->header, soundModel);
    565     return moveVectorToMemory(&halModel->header.data, &halModel->data);
    566 }
    567 
    568 void SoundTriggerHalHidl::convertPhraseSoundModelToHal(
    569         ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel,
    570         const struct sound_trigger_sound_model *soundModel)
    571 {
    572     struct sound_trigger_phrase_sound_model *keyPhraseModel =
    573             (struct sound_trigger_phrase_sound_model *)soundModel;
    574     convertTriggerPhrasesToHal(&halKeyPhraseModel->phrases, keyPhraseModel);
    575     convertSoundModelToHal(&halKeyPhraseModel->common, soundModel);
    576 }
    577 
    578 std::pair<bool, sp<IMemory>> SoundTriggerHalHidl::convertPhraseSoundModelToHal(
    579         V2_1_ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel,
    580         const struct sound_trigger_sound_model *soundModel)
    581 {
    582     struct sound_trigger_phrase_sound_model *keyPhraseModel =
    583             (struct sound_trigger_phrase_sound_model *)soundModel;
    584     convertTriggerPhrasesToHal(&halKeyPhraseModel->phrases, keyPhraseModel);
    585     return convertSoundModelToHal(&halKeyPhraseModel->common, soundModel);
    586 }
    587 
    588 void SoundTriggerHalHidl::convertPhraseRecognitionExtraToHal(
    589         PhraseRecognitionExtra *halExtra,
    590         const struct sound_trigger_phrase_recognition_extra *extra)
    591 {
    592     halExtra->id = extra->id;
    593     halExtra->recognitionModes = extra->recognition_modes;
    594     halExtra->confidenceLevel = extra->confidence_level;
    595     halExtra->levels.resize(extra->num_levels);
    596     for (unsigned int i = 0; i < extra->num_levels; i++) {
    597         halExtra->levels[i].userId = extra->levels[i].user_id;
    598         halExtra->levels[i].levelPercent = extra->levels[i].level;
    599     }
    600 }
    601 
    602 void SoundTriggerHalHidl::convertRecognitionConfigToHal(
    603         ISoundTriggerHw::RecognitionConfig *halConfig,
    604         const struct sound_trigger_recognition_config *config)
    605 {
    606     halConfig->captureHandle = config->capture_handle;
    607     halConfig->captureDevice = (AudioDevice)config->capture_device;
    608     halConfig->captureRequested = (uint32_t)config->capture_requested;
    609 
    610     halConfig->phrases.resize(config->num_phrases);
    611     for (unsigned int i = 0; i < config->num_phrases; i++) {
    612         convertPhraseRecognitionExtraToHal(&halConfig->phrases[i],
    613                                   &config->phrases[i]);
    614     }
    615 
    616     halConfig->data.setToExternal((uint8_t *)config + config->data_offset, config->data_size);
    617 }
    618 
    619 std::pair<bool, sp<IMemory>> SoundTriggerHalHidl::convertRecognitionConfigToHal(
    620         V2_1_ISoundTriggerHw::RecognitionConfig *halConfig,
    621         const struct sound_trigger_recognition_config *config)
    622 {
    623     convertRecognitionConfigToHal(&halConfig->header, config);
    624     return moveVectorToMemory(&halConfig->header.data, &halConfig->data);
    625 }
    626 
    627 
    628 // ISoundTriggerHwCallback
    629 ::android::hardware::Return<void> SoundTriggerHalHidl::recognitionCallback(
    630         const V2_0_ISoundTriggerHwCallback::RecognitionEvent& halEvent,
    631         CallbackCookie cookie)
    632 {
    633     sp<SoundModel> model;
    634     {
    635         AutoMutex lock(mLock);
    636         model = mSoundModels.valueFor((SoundModelHandle)cookie);
    637         if (model == 0) {
    638             return Return<void>();
    639         }
    640     }
    641     struct sound_trigger_recognition_event *event = convertRecognitionEventFromHal(&halEvent);
    642     if (event == NULL) {
    643         return Return<void>();
    644     }
    645     event->model = model->mHandle;
    646     model->mRecognitionCallback(event, model->mRecognitionCookie);
    647 
    648     free(event);
    649 
    650     return Return<void>();
    651 }
    652 
    653 ::android::hardware::Return<void> SoundTriggerHalHidl::phraseRecognitionCallback(
    654         const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent& halEvent,
    655         CallbackCookie cookie)
    656 {
    657     sp<SoundModel> model;
    658     {
    659         AutoMutex lock(mLock);
    660         model = mSoundModels.valueFor((SoundModelHandle)cookie);
    661         if (model == 0) {
    662             return Return<void>();
    663         }
    664     }
    665 
    666     struct sound_trigger_phrase_recognition_event *event =
    667             convertPhraseRecognitionEventFromHal(&halEvent);
    668     if (event == NULL) {
    669         return Return<void>();
    670     }
    671     event->common.model = model->mHandle;
    672     model->mRecognitionCallback(&event->common, model->mRecognitionCookie);
    673 
    674     free(event);
    675 
    676     return Return<void>();
    677 }
    678 
    679 ::android::hardware::Return<void> SoundTriggerHalHidl::soundModelCallback(
    680         const V2_0_ISoundTriggerHwCallback::ModelEvent& halEvent,
    681         CallbackCookie cookie)
    682 {
    683     sp<SoundModel> model;
    684     {
    685         AutoMutex lock(mLock);
    686         model = mSoundModels.valueFor((SoundModelHandle)cookie);
    687         if (model == 0) {
    688             return Return<void>();
    689         }
    690     }
    691 
    692     struct sound_trigger_model_event *event = convertSoundModelEventFromHal(&halEvent);
    693     if (event == NULL) {
    694         return Return<void>();
    695     }
    696 
    697     event->model = model->mHandle;
    698     model->mSoundModelCallback(event, model->mSoundModelCookie);
    699 
    700     free(event);
    701 
    702     return Return<void>();
    703 }
    704 
    705 ::android::hardware::Return<void> SoundTriggerHalHidl::recognitionCallback_2_1(
    706         const ISoundTriggerHwCallback::RecognitionEvent& event, CallbackCookie cookie) {
    707     // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap.
    708     V2_0_ISoundTriggerHwCallback::RecognitionEvent event_2_0 = event.header;
    709     auto result = memoryAsVector(event.data, &event_2_0.data);
    710     return result.first ? recognitionCallback(event_2_0, cookie) : Void();
    711 }
    712 
    713 ::android::hardware::Return<void> SoundTriggerHalHidl::phraseRecognitionCallback_2_1(
    714         const ISoundTriggerHwCallback::PhraseRecognitionEvent& event, int32_t cookie) {
    715     V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent event_2_0;
    716     // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap.
    717     event_2_0.common = event.common.header;
    718     event_2_0.phraseExtras.setToExternal(
    719             const_cast<PhraseRecognitionExtra*>(event.phraseExtras.data()),
    720             event.phraseExtras.size());
    721     auto result = memoryAsVector(event.common.data, &event_2_0.common.data);
    722     return result.first ? phraseRecognitionCallback(event_2_0, cookie) : Void();
    723 }
    724 
    725 ::android::hardware::Return<void> SoundTriggerHalHidl::soundModelCallback_2_1(
    726         const ISoundTriggerHwCallback::ModelEvent& event, CallbackCookie cookie) {
    727     // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap.
    728     V2_0_ISoundTriggerHwCallback::ModelEvent event_2_0 = event.header;
    729     auto result = memoryAsVector(event.data, &event_2_0.data);
    730     return result.first ? soundModelCallback(event_2_0, cookie) : Void();
    731 }
    732 
    733 
    734 struct sound_trigger_model_event *SoundTriggerHalHidl::convertSoundModelEventFromHal(
    735                                               const V2_0_ISoundTriggerHwCallback::ModelEvent *halEvent)
    736 {
    737     struct sound_trigger_model_event *event = (struct sound_trigger_model_event *)malloc(
    738             sizeof(struct sound_trigger_model_event) +
    739             halEvent->data.size());
    740     if (event == NULL) {
    741         return NULL;
    742     }
    743 
    744     event->status = (int)halEvent->status;
    745     // event->model to be set by caller
    746     event->data_offset = sizeof(struct sound_trigger_model_event);
    747     event->data_size = halEvent->data.size();
    748     uint8_t *dst = (uint8_t *)event + event->data_offset;
    749     uint8_t *src = (uint8_t *)&halEvent->data[0];
    750     memcpy(dst, src, halEvent->data.size());
    751 
    752     return event;
    753 }
    754 
    755 void SoundTriggerHalHidl::convertPhraseRecognitionExtraFromHal(
    756         struct sound_trigger_phrase_recognition_extra *extra,
    757         const PhraseRecognitionExtra *halExtra)
    758 {
    759     extra->id = halExtra->id;
    760     extra->recognition_modes = halExtra->recognitionModes;
    761     extra->confidence_level = halExtra->confidenceLevel;
    762 
    763     size_t i;
    764     for (i = 0; i < halExtra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) {
    765         extra->levels[i].user_id = halExtra->levels[i].userId;
    766         extra->levels[i].level = halExtra->levels[i].levelPercent;
    767     }
    768     extra->num_levels = (unsigned int)i;
    769 }
    770 
    771 
    772 struct sound_trigger_phrase_recognition_event* SoundTriggerHalHidl::convertPhraseRecognitionEventFromHal(
    773         const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent *halPhraseEvent)
    774 {
    775     if (halPhraseEvent->common.type != SoundModelType::KEYPHRASE) {
    776         ALOGE("Received non-keyphrase event type as PhraseRecognitionEvent");
    777         return NULL;
    778     }
    779     struct sound_trigger_phrase_recognition_event *phraseEvent =
    780             (struct sound_trigger_phrase_recognition_event *)malloc(
    781                     sizeof(struct sound_trigger_phrase_recognition_event) +
    782                     halPhraseEvent->common.data.size());
    783     if (phraseEvent == NULL) {
    784         return NULL;
    785     }
    786     phraseEvent->common.data_offset = sizeof(sound_trigger_phrase_recognition_event);
    787 
    788     for (unsigned int i = 0; i < halPhraseEvent->phraseExtras.size(); i++) {
    789         convertPhraseRecognitionExtraFromHal(&phraseEvent->phrase_extras[i],
    790                                              &halPhraseEvent->phraseExtras[i]);
    791     }
    792     phraseEvent->num_phrases = halPhraseEvent->phraseExtras.size();
    793 
    794     fillRecognitionEventFromHal(&phraseEvent->common, &halPhraseEvent->common);
    795     return phraseEvent;
    796 }
    797 
    798 struct sound_trigger_recognition_event *SoundTriggerHalHidl::convertRecognitionEventFromHal(
    799         const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent)
    800 {
    801     if (halEvent->type == SoundModelType::KEYPHRASE) {
    802         ALOGE("Received keyphrase event type as RecognitionEvent");
    803         return NULL;
    804     }
    805     struct sound_trigger_recognition_event *event;
    806     event = (struct sound_trigger_recognition_event *)malloc(
    807             sizeof(struct sound_trigger_recognition_event) + halEvent->data.size());
    808     if (event == NULL) {
    809         return NULL;
    810     }
    811     event->data_offset = sizeof(sound_trigger_recognition_event);
    812 
    813     fillRecognitionEventFromHal(event, halEvent);
    814     return event;
    815 }
    816 
    817 void SoundTriggerHalHidl::fillRecognitionEventFromHal(
    818         struct sound_trigger_recognition_event *event,
    819         const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent)
    820 {
    821     event->status = (int)halEvent->status;
    822     event->type = (sound_trigger_sound_model_type_t)halEvent->type;
    823     // event->model to be set by caller
    824     event->capture_available = (bool)halEvent->captureAvailable;
    825     event->capture_session = halEvent->captureSession;
    826     event->capture_delay_ms = halEvent->captureDelayMs;
    827     event->capture_preamble_ms = halEvent->capturePreambleMs;
    828     event->trigger_in_data = (bool)halEvent->triggerInData;
    829     event->audio_config.sample_rate = halEvent->audioConfig.sampleRateHz;
    830     event->audio_config.channel_mask = (audio_channel_mask_t)halEvent->audioConfig.channelMask;
    831     event->audio_config.format = (audio_format_t)halEvent->audioConfig.format;
    832 
    833     event->data_size = halEvent->data.size();
    834     uint8_t *dst = (uint8_t *)event + event->data_offset;
    835     uint8_t *src = (uint8_t *)&halEvent->data[0];
    836     memcpy(dst, src, halEvent->data.size());
    837 }
    838 
    839 } // namespace android
    840