• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <media/audiohal/hidl/HalDeathHandler.h>
21 #include <utils/Log.h>
22 #include "SoundTriggerHalHidl.h"
23 #include <hwbinder/IPCThreadState.h>
24 #include <hwbinder/ProcessState.h>
25 
26 namespace android {
27 
28 using android::hardware::Return;
29 using android::hardware::ProcessState;
30 using android::hardware::audio::common::V2_0::AudioDevice;
31 
32 /* static */
connectModule(const char * moduleName)33 sp<SoundTriggerHalInterface> SoundTriggerHalInterface::connectModule(const char *moduleName)
34 {
35     return new SoundTriggerHalHidl(moduleName);
36 }
37 
getProperties(struct sound_trigger_properties * properties)38 int SoundTriggerHalHidl::getProperties(struct sound_trigger_properties *properties)
39 {
40     sp<ISoundTriggerHw> soundtrigger = getService();
41     if (soundtrigger == 0) {
42         return -ENODEV;
43     }
44 
45     ISoundTriggerHw::Properties halProperties;
46     Return<void> hidlReturn;
47     int ret;
48     {
49         AutoMutex lock(mHalLock);
50         hidlReturn = soundtrigger->getProperties([&](int rc, auto res) {
51             ret = rc;
52             halProperties = res;
53             ALOGI("getProperties res implementor %s", res.implementor.c_str());
54         });
55     }
56 
57     if (hidlReturn.isOk()) {
58         if (ret == 0) {
59             convertPropertiesFromHal(properties, &halProperties);
60         }
61     } else {
62         ALOGE("getProperties error %s", hidlReturn.description().c_str());
63         return FAILED_TRANSACTION;
64     }
65     ALOGI("getProperties ret %d", ret);
66     return ret;
67 }
68 
loadSoundModel(struct sound_trigger_sound_model * sound_model,sound_model_callback_t callback,void * cookie,sound_model_handle_t * handle)69 int SoundTriggerHalHidl::loadSoundModel(struct sound_trigger_sound_model *sound_model,
70                         sound_model_callback_t callback,
71                         void *cookie,
72                         sound_model_handle_t *handle)
73 {
74     if (handle == NULL) {
75         return -EINVAL;
76     }
77 
78     sp<ISoundTriggerHw> soundtrigger = getService();
79     if (soundtrigger == 0) {
80         return -ENODEV;
81     }
82 
83     uint32_t modelId;
84     {
85         AutoMutex lock(mLock);
86         do {
87             modelId = nextUniqueId();
88             ALOGI("loadSoundModel modelId %u", modelId);
89             sp<SoundModel> model = mSoundModels.valueFor(modelId);
90             ALOGI("loadSoundModel model %p", model.get());
91         } while (mSoundModels.valueFor(modelId) != 0 && modelId != 0);
92     }
93     LOG_ALWAYS_FATAL_IF(modelId == 0,
94                         "loadSoundModel(): wrap around in sound model IDs, num loaded models %zd",
95                         mSoundModels.size());
96 
97     ISoundTriggerHw::SoundModel *halSoundModel =
98             convertSoundModelToHal(sound_model);
99     if (halSoundModel == NULL) {
100         return -EINVAL;
101     }
102 
103     Return<void> hidlReturn;
104     int ret;
105     SoundModelHandle halHandle;
106     {
107         AutoMutex lock(mHalLock);
108         if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
109             hidlReturn = soundtrigger->loadPhraseSoundModel(
110                     *(const ISoundTriggerHw::PhraseSoundModel *)halSoundModel,
111                     this, modelId, [&](int32_t retval, auto res) {
112                 ret = retval;
113                 halHandle = res;
114             });
115 
116         } else {
117             hidlReturn = soundtrigger->loadSoundModel(*halSoundModel,
118                     this, modelId, [&](int32_t retval, auto res) {
119                 ret = retval;
120                 halHandle = res;
121             });
122         }
123     }
124 
125     delete halSoundModel;
126 
127     if (hidlReturn.isOk()) {
128         if (ret == 0) {
129             AutoMutex lock(mLock);
130             *handle = (sound_model_handle_t)modelId;
131             sp<SoundModel> model = new SoundModel(*handle, callback, cookie, halHandle);
132             mSoundModels.add(*handle, model);
133         }
134     } else {
135         ALOGE("loadSoundModel error %s", hidlReturn.description().c_str());
136         return FAILED_TRANSACTION;
137     }
138 
139     return ret;
140 }
141 
unloadSoundModel(sound_model_handle_t handle)142 int SoundTriggerHalHidl::unloadSoundModel(sound_model_handle_t handle)
143 {
144     sp<ISoundTriggerHw> soundtrigger = getService();
145     if (soundtrigger == 0) {
146         return -ENODEV;
147     }
148 
149     sp<SoundModel> model = removeModel(handle);
150     if (model == 0) {
151         ALOGE("unloadSoundModel model not found for handle %u", handle);
152         return -EINVAL;
153     }
154 
155     Return<int32_t> hidlReturn(0);
156     {
157         AutoMutex lock(mHalLock);
158         hidlReturn = soundtrigger->unloadSoundModel(model->mHalHandle);
159     }
160 
161     if (!hidlReturn.isOk()) {
162         ALOGE("unloadSoundModel error %s", hidlReturn.description().c_str());
163         return FAILED_TRANSACTION;
164     }
165 
166     return hidlReturn;
167 }
168 
startRecognition(sound_model_handle_t handle,const struct sound_trigger_recognition_config * config,recognition_callback_t callback,void * cookie)169 int SoundTriggerHalHidl::startRecognition(sound_model_handle_t handle,
170                          const struct sound_trigger_recognition_config *config,
171                          recognition_callback_t callback,
172                          void *cookie)
173 {
174     sp<ISoundTriggerHw> soundtrigger = getService();
175     if (soundtrigger == 0) {
176         return -ENODEV;
177     }
178 
179     sp<SoundModel> model = getModel(handle);
180     if (model == 0) {
181         ALOGE("startRecognition model not found for handle %u", handle);
182         return -EINVAL;
183     }
184 
185     model->mRecognitionCallback = callback;
186     model->mRecognitionCookie = cookie;
187 
188     ISoundTriggerHw::RecognitionConfig *halConfig =
189             convertRecognitionConfigToHal(config);
190 
191     Return<int32_t> hidlReturn(0);
192     {
193         AutoMutex lock(mHalLock);
194         hidlReturn = soundtrigger->startRecognition(model->mHalHandle, *halConfig, this, handle);
195     }
196 
197     delete halConfig;
198 
199     if (!hidlReturn.isOk()) {
200         ALOGE("startRecognition error %s", hidlReturn.description().c_str());
201         return FAILED_TRANSACTION;
202     }
203     return hidlReturn;
204 }
205 
stopRecognition(sound_model_handle_t handle)206 int SoundTriggerHalHidl::stopRecognition(sound_model_handle_t handle)
207 {
208     sp<ISoundTriggerHw> soundtrigger = getService();
209     if (soundtrigger == 0) {
210         return -ENODEV;
211     }
212 
213     sp<SoundModel> model = getModel(handle);
214     if (model == 0) {
215         ALOGE("stopRecognition model not found for handle %u", handle);
216         return -EINVAL;
217     }
218 
219     Return<int32_t> hidlReturn(0);
220     {
221         AutoMutex lock(mHalLock);
222         hidlReturn = soundtrigger->stopRecognition(model->mHalHandle);
223     }
224 
225     if (!hidlReturn.isOk()) {
226         ALOGE("stopRecognition error %s", hidlReturn.description().c_str());
227         return FAILED_TRANSACTION;
228     }
229     return hidlReturn;
230 }
231 
stopAllRecognitions()232 int SoundTriggerHalHidl::stopAllRecognitions()
233 {
234     sp<ISoundTriggerHw> soundtrigger = getService();
235     if (soundtrigger == 0) {
236         return -ENODEV;
237     }
238 
239     Return<int32_t> hidlReturn(0);
240     {
241         AutoMutex lock(mHalLock);
242         hidlReturn = soundtrigger->stopAllRecognitions();
243     }
244 
245     if (!hidlReturn.isOk()) {
246         ALOGE("stopAllRecognitions error %s", hidlReturn.description().c_str());
247         return FAILED_TRANSACTION;
248     }
249     return hidlReturn;
250 }
251 
SoundTriggerHalHidl(const char * moduleName)252 SoundTriggerHalHidl::SoundTriggerHalHidl(const char *moduleName)
253     : mModuleName(moduleName), mNextUniqueId(1)
254 {
255     LOG_ALWAYS_FATAL_IF(strcmp(mModuleName, "primary") != 0,
256             "Treble soundtrigger only supports primary module");
257 }
258 
~SoundTriggerHalHidl()259 SoundTriggerHalHidl::~SoundTriggerHalHidl()
260 {
261 }
262 
getService()263 sp<ISoundTriggerHw> SoundTriggerHalHidl::getService()
264 {
265     AutoMutex lock(mLock);
266     if (mISoundTrigger == 0) {
267         if (mModuleName == NULL) {
268             mModuleName = "primary";
269         }
270         mISoundTrigger = ISoundTriggerHw::getService();
271         if (mISoundTrigger != 0) {
272             mISoundTrigger->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
273         }
274     }
275     return mISoundTrigger;
276 }
277 
getModel(sound_model_handle_t handle)278 sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::getModel(sound_model_handle_t handle)
279 {
280     AutoMutex lock(mLock);
281     return mSoundModels.valueFor(handle);
282 }
283 
removeModel(sound_model_handle_t handle)284 sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::removeModel(sound_model_handle_t handle)
285 {
286     AutoMutex lock(mLock);
287     sp<SoundModel> model = mSoundModels.valueFor(handle);
288     mSoundModels.removeItem(handle);
289     return model;
290 }
291 
nextUniqueId()292 uint32_t SoundTriggerHalHidl::nextUniqueId()
293 {
294     return (uint32_t) atomic_fetch_add_explicit(&mNextUniqueId,
295                 (uint_fast32_t) 1, memory_order_acq_rel);
296 }
297 
convertUuidToHal(Uuid * halUuid,const sound_trigger_uuid_t * uuid)298 void SoundTriggerHalHidl::convertUuidToHal(Uuid *halUuid,
299                                            const sound_trigger_uuid_t *uuid)
300 {
301     halUuid->timeLow = uuid->timeLow;
302     halUuid->timeMid = uuid->timeMid;
303     halUuid->versionAndTimeHigh = uuid->timeHiAndVersion;
304     halUuid->variantAndClockSeqHigh = uuid->clockSeq;
305     memcpy(halUuid->node.data(), &uuid->node[0], sizeof(uuid->node));
306 }
307 
convertUuidFromHal(sound_trigger_uuid_t * uuid,const Uuid * halUuid)308 void SoundTriggerHalHidl::convertUuidFromHal(sound_trigger_uuid_t *uuid,
309                                              const Uuid *halUuid)
310 {
311     uuid->timeLow = halUuid->timeLow;
312     uuid->timeMid = halUuid->timeMid;
313     uuid->timeHiAndVersion = halUuid->versionAndTimeHigh;
314     uuid->clockSeq = halUuid->variantAndClockSeqHigh;
315     memcpy(&uuid->node[0], halUuid->node.data(), sizeof(uuid->node));
316 }
317 
convertPropertiesFromHal(struct sound_trigger_properties * properties,const ISoundTriggerHw::Properties * halProperties)318 void SoundTriggerHalHidl::convertPropertiesFromHal(
319         struct sound_trigger_properties *properties,
320         const ISoundTriggerHw::Properties *halProperties)
321 {
322     strlcpy(properties->implementor,
323             halProperties->implementor.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
324     strlcpy(properties->description,
325             halProperties->description.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
326     properties->version = halProperties->version;
327     convertUuidFromHal(&properties->uuid, &halProperties->uuid);
328     properties->max_sound_models = halProperties->maxSoundModels;
329     properties->max_key_phrases = halProperties->maxKeyPhrases;
330     properties->max_users = halProperties->maxUsers;
331     properties->recognition_modes = halProperties->recognitionModes;
332     properties->capture_transition = (bool)halProperties->captureTransition;
333     properties->max_buffer_ms = halProperties->maxBufferMs;
334     properties->concurrent_capture = (bool)halProperties->concurrentCapture;
335     properties->trigger_in_event = (bool)halProperties->triggerInEvent;
336     properties->power_consumption_mw = halProperties->powerConsumptionMw;
337 }
338 
convertTriggerPhraseToHal(ISoundTriggerHw::Phrase * halTriggerPhrase,const struct sound_trigger_phrase * triggerPhrase)339 void SoundTriggerHalHidl::convertTriggerPhraseToHal(
340         ISoundTriggerHw::Phrase *halTriggerPhrase,
341         const struct sound_trigger_phrase *triggerPhrase)
342 {
343     halTriggerPhrase->id = triggerPhrase->id;
344     halTriggerPhrase->recognitionModes = triggerPhrase->recognition_mode;
345     halTriggerPhrase->users.setToExternal((uint32_t *)&triggerPhrase->users[0], triggerPhrase->num_users);
346     halTriggerPhrase->locale = triggerPhrase->locale;
347     halTriggerPhrase->text = triggerPhrase->text;
348 }
349 
convertSoundModelToHal(const struct sound_trigger_sound_model * soundModel)350 ISoundTriggerHw::SoundModel *SoundTriggerHalHidl::convertSoundModelToHal(
351         const struct sound_trigger_sound_model *soundModel)
352 {
353     ISoundTriggerHw::SoundModel *halModel = NULL;
354     if (soundModel->type == SOUND_MODEL_TYPE_KEYPHRASE) {
355         ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel =
356                 new ISoundTriggerHw::PhraseSoundModel();
357         struct sound_trigger_phrase_sound_model *keyPhraseModel =
358                 (struct sound_trigger_phrase_sound_model *)soundModel;
359         ISoundTriggerHw::Phrase *halPhrases =
360                 new ISoundTriggerHw::Phrase[keyPhraseModel->num_phrases];
361 
362 
363         for (unsigned int i = 0; i < keyPhraseModel->num_phrases; i++) {
364             convertTriggerPhraseToHal(&halPhrases[i],
365                                       &keyPhraseModel->phrases[i]);
366         }
367         halKeyPhraseModel->phrases.setToExternal(halPhrases, keyPhraseModel->num_phrases);
368         // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
369         halKeyPhraseModel->phrases.resize(keyPhraseModel->num_phrases);
370 
371         delete[] halPhrases;
372 
373         halModel = (ISoundTriggerHw::SoundModel *)halKeyPhraseModel;
374     } else {
375         halModel = new ISoundTriggerHw::SoundModel();
376     }
377     halModel->type = (SoundModelType)soundModel->type;
378     convertUuidToHal(&halModel->uuid, &soundModel->uuid);
379     convertUuidToHal(&halModel->vendorUuid, &soundModel->vendor_uuid);
380     halModel->data.setToExternal((uint8_t *)soundModel + soundModel->data_offset, soundModel->data_size);
381     halModel->data.resize(soundModel->data_size);
382 
383     return halModel;
384 }
385 
convertPhraseRecognitionExtraToHal(PhraseRecognitionExtra * halExtra,const struct sound_trigger_phrase_recognition_extra * extra)386 void SoundTriggerHalHidl::convertPhraseRecognitionExtraToHal(
387         PhraseRecognitionExtra *halExtra,
388         const struct sound_trigger_phrase_recognition_extra *extra)
389 {
390     halExtra->id = extra->id;
391     halExtra->recognitionModes = extra->recognition_modes;
392     halExtra->confidenceLevel = extra->confidence_level;
393     ConfidenceLevel *halLevels =
394             new ConfidenceLevel[extra->num_levels];
395     for (unsigned int i = 0; i < extra->num_levels; i++) {
396         halLevels[i].userId = extra->levels[i].user_id;
397         halLevels[i].levelPercent = extra->levels[i].level;
398     }
399     halExtra->levels.setToExternal(halLevels, extra->num_levels);
400     // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
401     halExtra->levels.resize(extra->num_levels);
402 
403     delete[] halLevels;
404 }
405 
406 
convertRecognitionConfigToHal(const struct sound_trigger_recognition_config * config)407 ISoundTriggerHw::RecognitionConfig *SoundTriggerHalHidl::convertRecognitionConfigToHal(
408         const struct sound_trigger_recognition_config *config)
409 {
410     ISoundTriggerHw::RecognitionConfig *halConfig =
411             new ISoundTriggerHw::RecognitionConfig();
412 
413     halConfig->captureHandle = config->capture_handle;
414     halConfig->captureDevice = (AudioDevice)config->capture_device;
415     halConfig->captureRequested = (uint32_t)config->capture_requested;
416 
417     PhraseRecognitionExtra *halExtras =
418             new PhraseRecognitionExtra[config->num_phrases];
419 
420     for (unsigned int i = 0; i < config->num_phrases; i++) {
421         convertPhraseRecognitionExtraToHal(&halExtras[i],
422                                   &config->phrases[i]);
423     }
424     halConfig->phrases.setToExternal(halExtras, config->num_phrases);
425     // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
426     halConfig->phrases.resize(config->num_phrases);
427 
428     delete[] halExtras;
429 
430     halConfig->data.setToExternal((uint8_t *)config + config->data_offset, config->data_size);
431 
432     return halConfig;
433 }
434 
435 
436 // ISoundTriggerHwCallback
recognitionCallback(const ISoundTriggerHwCallback::RecognitionEvent & halEvent,CallbackCookie cookie)437 ::android::hardware::Return<void> SoundTriggerHalHidl::recognitionCallback(
438         const ISoundTriggerHwCallback::RecognitionEvent& halEvent,
439         CallbackCookie cookie)
440 {
441     sp<SoundModel> model;
442     {
443         AutoMutex lock(mLock);
444         model = mSoundModels.valueFor((SoundModelHandle)cookie);
445         if (model == 0) {
446             return Return<void>();
447         }
448     }
449     struct sound_trigger_recognition_event *event = convertRecognitionEventFromHal(&halEvent);
450     if (event == NULL) {
451         return Return<void>();
452     }
453     event->model = model->mHandle;
454     model->mRecognitionCallback(event, model->mRecognitionCookie);
455 
456     free(event);
457 
458     return Return<void>();
459 }
460 
phraseRecognitionCallback(const ISoundTriggerHwCallback::PhraseRecognitionEvent & halEvent,CallbackCookie cookie)461 ::android::hardware::Return<void> SoundTriggerHalHidl::phraseRecognitionCallback(
462         const ISoundTriggerHwCallback::PhraseRecognitionEvent& halEvent,
463         CallbackCookie cookie)
464 {
465     sp<SoundModel> model;
466     {
467         AutoMutex lock(mLock);
468         model = mSoundModels.valueFor((SoundModelHandle)cookie);
469         if (model == 0) {
470             return Return<void>();
471         }
472     }
473 
474     struct sound_trigger_recognition_event *event = convertRecognitionEventFromHal(
475                                    (const ISoundTriggerHwCallback::RecognitionEvent *)&halEvent);
476     if (event == NULL) {
477         return Return<void>();
478     }
479 
480     event->model = model->mHandle;
481     model->mRecognitionCallback(event, model->mRecognitionCookie);
482 
483     free(event);
484 
485     return Return<void>();
486 }
487 
soundModelCallback(const ISoundTriggerHwCallback::ModelEvent & halEvent,CallbackCookie cookie)488 ::android::hardware::Return<void> SoundTriggerHalHidl::soundModelCallback(
489         const ISoundTriggerHwCallback::ModelEvent& halEvent,
490         CallbackCookie cookie)
491 {
492     sp<SoundModel> model;
493     {
494         AutoMutex lock(mLock);
495         model = mSoundModels.valueFor((SoundModelHandle)cookie);
496         if (model == 0) {
497             return Return<void>();
498         }
499     }
500 
501     struct sound_trigger_model_event *event = convertSoundModelEventFromHal(&halEvent);
502     if (event == NULL) {
503         return Return<void>();
504     }
505 
506     event->model = model->mHandle;
507     model->mSoundModelCallback(event, model->mSoundModelCookie);
508 
509     free(event);
510 
511     return Return<void>();
512 }
513 
514 
convertSoundModelEventFromHal(const ISoundTriggerHwCallback::ModelEvent * halEvent)515 struct sound_trigger_model_event *SoundTriggerHalHidl::convertSoundModelEventFromHal(
516                                               const ISoundTriggerHwCallback::ModelEvent *halEvent)
517 {
518     struct sound_trigger_model_event *event = (struct sound_trigger_model_event *)malloc(
519             sizeof(struct sound_trigger_model_event) +
520             halEvent->data.size());
521     if (event == NULL) {
522         return NULL;
523     }
524 
525     event->status = (int)halEvent->status;
526     // event->model to be set by caller
527     event->data_offset = sizeof(struct sound_trigger_model_event);
528     event->data_size = halEvent->data.size();
529     uint8_t *dst = (uint8_t *)event + event->data_offset;
530     uint8_t *src = (uint8_t *)&halEvent->data[0];
531     memcpy(dst, src, halEvent->data.size());
532 
533     return event;
534 }
535 
convertPhraseRecognitionExtraFromHal(struct sound_trigger_phrase_recognition_extra * extra,const PhraseRecognitionExtra * halExtra)536 void SoundTriggerHalHidl::convertPhraseRecognitionExtraFromHal(
537         struct sound_trigger_phrase_recognition_extra *extra,
538         const PhraseRecognitionExtra *halExtra)
539 {
540     extra->id = halExtra->id;
541     extra->recognition_modes = halExtra->recognitionModes;
542     extra->confidence_level = halExtra->confidenceLevel;
543 
544     size_t i;
545     for (i = 0; i < halExtra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) {
546         extra->levels[i].user_id = halExtra->levels[i].userId;
547         extra->levels[i].level = halExtra->levels[i].levelPercent;
548     }
549     extra->num_levels = (unsigned int)i;
550 }
551 
552 
convertRecognitionEventFromHal(const ISoundTriggerHwCallback::RecognitionEvent * halEvent)553 struct sound_trigger_recognition_event *SoundTriggerHalHidl::convertRecognitionEventFromHal(
554         const ISoundTriggerHwCallback::RecognitionEvent *halEvent)
555 {
556     struct sound_trigger_recognition_event *event;
557 
558     if (halEvent->type == SoundModelType::KEYPHRASE) {
559         struct sound_trigger_phrase_recognition_event *phraseEvent =
560                 (struct sound_trigger_phrase_recognition_event *)malloc(
561                         sizeof(struct sound_trigger_phrase_recognition_event) +
562                         halEvent->data.size());
563         if (phraseEvent == NULL) {
564             return NULL;
565         }
566         const ISoundTriggerHwCallback::PhraseRecognitionEvent *halPhraseEvent =
567                 (const ISoundTriggerHwCallback::PhraseRecognitionEvent *)halEvent;
568 
569         for (unsigned int i = 0; i < halPhraseEvent->phraseExtras.size(); i++) {
570             convertPhraseRecognitionExtraFromHal(&phraseEvent->phrase_extras[i],
571                                                  &halPhraseEvent->phraseExtras[i]);
572         }
573         phraseEvent->num_phrases = halPhraseEvent->phraseExtras.size();
574         event = (struct sound_trigger_recognition_event *)phraseEvent;
575         event->data_offset = sizeof(sound_trigger_phrase_recognition_event);
576     } else {
577         event = (struct sound_trigger_recognition_event *)malloc(
578                 sizeof(struct sound_trigger_recognition_event) + halEvent->data.size());
579         if (event == NULL) {
580             return NULL;
581         }
582         event->data_offset = sizeof(sound_trigger_recognition_event);
583     }
584     event->status = (int)halEvent->status;
585     event->type = (sound_trigger_sound_model_type_t)halEvent->type;
586     // event->model to be set by caller
587     event->capture_available = (bool)halEvent->captureAvailable;
588     event->capture_session = halEvent->captureSession;
589     event->capture_delay_ms = halEvent->captureDelayMs;
590     event->capture_preamble_ms = halEvent->capturePreambleMs;
591     event->trigger_in_data = (bool)halEvent->triggerInData;
592     event->audio_config.sample_rate = halEvent->audioConfig.sampleRateHz;
593     event->audio_config.channel_mask = (audio_channel_mask_t)halEvent->audioConfig.channelMask;
594     event->audio_config.format = (audio_format_t)halEvent->audioConfig.format;
595 
596     event->data_size = halEvent->data.size();
597     uint8_t *dst = (uint8_t *)event + event->data_offset;
598     uint8_t *src = (uint8_t *)&halEvent->data[0];
599     memcpy(dst, src, halEvent->data.size());
600 
601     return event;
602 }
603 
604 } // namespace android
605