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
28namespace android {
29
30using ::android::hardware::ProcessState;
31using ::android::hardware::Return;
32using ::android::hardware::Status;
33using ::android::hardware::Void;
34using ::android::hardware::audio::common::V2_0::AudioDevice;
35using ::android::hardware::hidl_memory;
36using ::android::hidl::allocator::V1_0::IAllocator;
37using ::android::hidl::memory::V1_0::IMemory;
38
39namespace {
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.
46std::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.
68std::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 */
103sp<SoundTriggerHalInterface> SoundTriggerHalInterface::connectModule(const char *moduleName)
104{
105    return new SoundTriggerHalHidl(moduleName);
106}
107
108int 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
139int 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
238int 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
265int 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
313int 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
339int 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
359SoundTriggerHalHidl::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
366SoundTriggerHalHidl::~SoundTriggerHalHidl()
367{
368}
369
370sp<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
385sp<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
391sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::getModel(sound_model_handle_t handle)
392{
393    AutoMutex lock(mLock);
394    return mSoundModels.valueFor(handle);
395}
396
397sp<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
405uint32_t SoundTriggerHalHidl::nextUniqueId()
406{
407    return (uint32_t) atomic_fetch_add_explicit(&mNextUniqueId,
408                (uint_fast32_t) 1, memory_order_acq_rel);
409}
410
411void 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
421void 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
431void 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
452void 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
464void 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
474void 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
483std::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
491void 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
501std::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
511void 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
525void 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
542std::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
657struct 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
678void 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
695struct 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
721struct 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
740void 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