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 "SoundTriggerHalImpl"
18 //#define LOG_NDEBUG 0
19 
20 #include "SoundTriggerHalImpl.h"
21 #include <android/log.h>
22 
23 namespace android {
24 namespace hardware {
25 namespace soundtrigger {
26 namespace V2_0 {
27 namespace implementation {
28 
29 // static
soundModelCallback(struct sound_trigger_model_event * halEvent,void * cookie)30 void SoundTriggerHalImpl::soundModelCallback(struct sound_trigger_model_event* halEvent,
31                                              void* cookie) {
32     if (halEvent == NULL) {
33         ALOGW("soundModelCallback called with NULL event");
34         return;
35     }
36     sp<SoundModelClient> client =
37         wp<SoundModelClient>(static_cast<SoundModelClient*>(cookie)).promote();
38     if (client == 0) {
39         ALOGW("soundModelCallback called on stale client");
40         return;
41     }
42     if (halEvent->model != client->getHalHandle()) {
43         ALOGW("soundModelCallback call with wrong handle %d on client with handle %d",
44               (int)halEvent->model, (int)client->getHalHandle());
45         return;
46     }
47 
48     client->soundModelCallback(halEvent);
49 }
50 
51 // static
recognitionCallback(struct sound_trigger_recognition_event * halEvent,void * cookie)52 void SoundTriggerHalImpl::recognitionCallback(struct sound_trigger_recognition_event* halEvent,
53                                               void* cookie) {
54     if (halEvent == NULL) {
55         ALOGW("recognitionCallback call NULL event");
56         return;
57     }
58     sp<SoundModelClient> client =
59         wp<SoundModelClient>(static_cast<SoundModelClient*>(cookie)).promote();
60     if (client == 0) {
61         ALOGW("soundModelCallback called on stale client");
62         return;
63     }
64 
65     client->recognitionCallback(halEvent);
66 }
67 
getProperties(ISoundTriggerHw::getProperties_cb _hidl_cb)68 Return<void> SoundTriggerHalImpl::getProperties(ISoundTriggerHw::getProperties_cb _hidl_cb) {
69     ALOGV("getProperties() mHwDevice %p", mHwDevice);
70     int ret;
71     struct sound_trigger_properties halProperties;
72     ISoundTriggerHw::Properties properties;
73 
74     if (mHwDevice == NULL) {
75         ret = -ENODEV;
76         goto exit;
77     }
78 
79     ret = mHwDevice->get_properties(mHwDevice, &halProperties);
80 
81     convertPropertiesFromHal(&properties, &halProperties);
82 
83     ALOGV("getProperties implementor %s recognitionModes %08x", properties.implementor.c_str(),
84           properties.recognitionModes);
85 
86 exit:
87     _hidl_cb(ret, properties);
88     return Void();
89 }
90 
doLoadSoundModel(const ISoundTriggerHw::SoundModel & soundModel,sp<SoundModelClient> client)91 int SoundTriggerHalImpl::doLoadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
92                                           sp<SoundModelClient> client) {
93     int32_t ret = 0;
94     struct sound_trigger_sound_model* halSoundModel;
95 
96     ALOGV("doLoadSoundModel() data size %zu", soundModel.data.size());
97 
98     if (mHwDevice == NULL) {
99         ret = -ENODEV;
100         goto exit;
101     }
102 
103     halSoundModel = convertSoundModelToHal(&soundModel);
104     if (halSoundModel == NULL) {
105         ret = -EINVAL;
106         goto exit;
107     }
108 
109     sound_model_handle_t halHandle;
110     ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, soundModelCallback, client.get(),
111                                       &halHandle);
112 
113     free(halSoundModel);
114 
115     if (ret != 0) {
116         goto exit;
117     }
118 
119     client->setHalHandle(halHandle);
120     {
121         AutoMutex lock(mLock);
122         mClients.add(client->getId(), client);
123     }
124 
125 exit:
126     return ret;
127 }
128 
loadSoundModel(const ISoundTriggerHw::SoundModel & soundModel,const sp<ISoundTriggerHwCallback> & callback,ISoundTriggerHwCallback::CallbackCookie cookie,ISoundTriggerHw::loadSoundModel_cb _hidl_cb)129 Return<void> SoundTriggerHalImpl::loadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
130                                                  const sp<ISoundTriggerHwCallback>& callback,
131                                                  ISoundTriggerHwCallback::CallbackCookie cookie,
132                                                  ISoundTriggerHw::loadSoundModel_cb _hidl_cb) {
133     sp<SoundModelClient> client = new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
134     _hidl_cb(doLoadSoundModel(soundModel, client), client->getId());
135     return Void();
136 }
137 
loadPhraseSoundModel(const ISoundTriggerHw::PhraseSoundModel & soundModel,const sp<ISoundTriggerHwCallback> & callback,ISoundTriggerHwCallback::CallbackCookie cookie,ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb)138 Return<void> SoundTriggerHalImpl::loadPhraseSoundModel(
139     const ISoundTriggerHw::PhraseSoundModel& soundModel,
140     const sp<ISoundTriggerHwCallback>& callback, ISoundTriggerHwCallback::CallbackCookie cookie,
141     ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb) {
142     sp<SoundModelClient> client = new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
143     _hidl_cb(doLoadSoundModel((const ISoundTriggerHw::SoundModel&)soundModel, client),
144              client->getId());
145     return Void();
146 }
147 
unloadSoundModel(SoundModelHandle modelHandle)148 Return<int32_t> SoundTriggerHalImpl::unloadSoundModel(SoundModelHandle modelHandle) {
149     int32_t ret;
150     sp<SoundModelClient> client;
151 
152     if (mHwDevice == NULL) {
153         ret = -ENODEV;
154         goto exit;
155     }
156 
157     {
158         AutoMutex lock(mLock);
159         client = mClients.valueFor(modelHandle);
160         if (client == 0) {
161             ret = -ENOSYS;
162             goto exit;
163         }
164     }
165 
166     ret = mHwDevice->unload_sound_model(mHwDevice, client->getHalHandle());
167 
168     mClients.removeItem(modelHandle);
169 
170 exit:
171     return ret;
172 }
173 
startRecognition(SoundModelHandle modelHandle,const ISoundTriggerHw::RecognitionConfig & config)174 Return<int32_t> SoundTriggerHalImpl::startRecognition(
175     SoundModelHandle modelHandle, const ISoundTriggerHw::RecognitionConfig& config) {
176     int32_t ret;
177     sp<SoundModelClient> client;
178     struct sound_trigger_recognition_config* halConfig;
179 
180     if (mHwDevice == NULL) {
181         ret = -ENODEV;
182         goto exit;
183     }
184 
185     {
186         AutoMutex lock(mLock);
187         client = mClients.valueFor(modelHandle);
188         if (client == 0) {
189             ret = -ENOSYS;
190             goto exit;
191         }
192     }
193 
194     halConfig = convertRecognitionConfigToHal(&config);
195 
196     if (halConfig == NULL) {
197         ret = -EINVAL;
198         goto exit;
199     }
200     ret = mHwDevice->start_recognition(mHwDevice, client->getHalHandle(), halConfig,
201                                        recognitionCallback, client.get());
202 
203     free(halConfig);
204 
205 exit:
206     return ret;
207 }
208 
stopRecognition(SoundModelHandle modelHandle)209 Return<int32_t> SoundTriggerHalImpl::stopRecognition(SoundModelHandle modelHandle) {
210     int32_t ret;
211     sp<SoundModelClient> client;
212     if (mHwDevice == NULL) {
213         ret = -ENODEV;
214         goto exit;
215     }
216 
217     {
218         AutoMutex lock(mLock);
219         client = mClients.valueFor(modelHandle);
220         if (client == 0) {
221             ret = -ENOSYS;
222             goto exit;
223         }
224     }
225 
226     ret = mHwDevice->stop_recognition(mHwDevice, client->getHalHandle());
227 
228 exit:
229     return ret;
230 }
231 
stopAllRecognitions()232 Return<int32_t> SoundTriggerHalImpl::stopAllRecognitions() {
233     int32_t ret;
234     if (mHwDevice == NULL) {
235         ret = -ENODEV;
236         goto exit;
237     }
238 
239     if (mHwDevice->common.version >= SOUND_TRIGGER_DEVICE_API_VERSION_1_1 &&
240         mHwDevice->stop_all_recognitions) {
241         ret = mHwDevice->stop_all_recognitions(mHwDevice);
242     } else {
243         ret = -ENOSYS;
244     }
245 exit:
246     return ret;
247 }
248 
SoundTriggerHalImpl()249 SoundTriggerHalImpl::SoundTriggerHalImpl()
250     : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {}
251 
onFirstRef()252 void SoundTriggerHalImpl::onFirstRef() {
253     const hw_module_t* mod;
254     int rc;
255 
256     rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, &mod);
257     if (rc != 0) {
258         ALOGE("couldn't load sound trigger module %s.%s (%s)", SOUND_TRIGGER_HARDWARE_MODULE_ID,
259               mModuleName, strerror(-rc));
260         return;
261     }
262     rc = sound_trigger_hw_device_open(mod, &mHwDevice);
263     if (rc != 0) {
264         ALOGE("couldn't open sound trigger hw device in %s.%s (%s)",
265               SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, strerror(-rc));
266         mHwDevice = NULL;
267         return;
268     }
269     if (mHwDevice->common.version < SOUND_TRIGGER_DEVICE_API_VERSION_1_0 ||
270         mHwDevice->common.version > SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
271         ALOGE("wrong sound trigger hw device version %04x", mHwDevice->common.version);
272         sound_trigger_hw_device_close(mHwDevice);
273         mHwDevice = NULL;
274         return;
275     }
276 
277     ALOGI("onFirstRef() mModuleName %s mHwDevice %p", mModuleName, mHwDevice);
278 }
279 
~SoundTriggerHalImpl()280 SoundTriggerHalImpl::~SoundTriggerHalImpl() {
281     if (mHwDevice != NULL) {
282         sound_trigger_hw_device_close(mHwDevice);
283     }
284 }
285 
nextUniqueModelId()286 uint32_t SoundTriggerHalImpl::nextUniqueModelId() {
287     uint32_t modelId = 0;
288     {
289         AutoMutex lock(mLock);
290         do {
291             modelId =
292                 atomic_fetch_add_explicit(&mNextModelId, (uint_fast32_t)1, memory_order_acq_rel);
293         } while (mClients.valueFor(modelId) != 0 && modelId != 0);
294     }
295     LOG_ALWAYS_FATAL_IF(modelId == 0, "wrap around in sound model IDs, num loaded models %zu",
296                         mClients.size());
297     return modelId;
298 }
299 
convertUuidFromHal(Uuid * uuid,const sound_trigger_uuid_t * halUuid)300 void SoundTriggerHalImpl::convertUuidFromHal(Uuid* uuid, const sound_trigger_uuid_t* halUuid) {
301     uuid->timeLow = halUuid->timeLow;
302     uuid->timeMid = halUuid->timeMid;
303     uuid->versionAndTimeHigh = halUuid->timeHiAndVersion;
304     uuid->variantAndClockSeqHigh = halUuid->clockSeq;
305     memcpy(&uuid->node[0], &halUuid->node[0], 6);
306 }
307 
convertUuidToHal(sound_trigger_uuid_t * halUuid,const Uuid * uuid)308 void SoundTriggerHalImpl::convertUuidToHal(sound_trigger_uuid_t* halUuid, const Uuid* uuid) {
309     halUuid->timeLow = uuid->timeLow;
310     halUuid->timeMid = uuid->timeMid;
311     halUuid->timeHiAndVersion = uuid->versionAndTimeHigh;
312     halUuid->clockSeq = uuid->variantAndClockSeqHigh;
313     memcpy(&halUuid->node[0], &uuid->node[0], 6);
314 }
315 
convertPropertiesFromHal(ISoundTriggerHw::Properties * properties,const struct sound_trigger_properties * halProperties)316 void SoundTriggerHalImpl::convertPropertiesFromHal(
317     ISoundTriggerHw::Properties* properties, const struct sound_trigger_properties* halProperties) {
318     properties->implementor = halProperties->implementor;
319     properties->description = halProperties->description;
320     properties->version = halProperties->version;
321     convertUuidFromHal(&properties->uuid, &halProperties->uuid);
322     properties->maxSoundModels = halProperties->max_sound_models;
323     properties->maxKeyPhrases = halProperties->max_key_phrases;
324     properties->maxUsers = halProperties->max_users;
325     properties->recognitionModes = halProperties->recognition_modes;
326     properties->captureTransition = halProperties->capture_transition;
327     properties->maxBufferMs = halProperties->max_buffer_ms;
328     properties->concurrentCapture = halProperties->concurrent_capture;
329     properties->triggerInEvent = halProperties->trigger_in_event;
330     properties->powerConsumptionMw = halProperties->power_consumption_mw;
331 }
332 
convertTriggerPhraseToHal(struct sound_trigger_phrase * halTriggerPhrase,const ISoundTriggerHw::Phrase * triggerPhrase)333 void SoundTriggerHalImpl::convertTriggerPhraseToHal(struct sound_trigger_phrase* halTriggerPhrase,
334                                                     const ISoundTriggerHw::Phrase* triggerPhrase) {
335     halTriggerPhrase->id = triggerPhrase->id;
336     halTriggerPhrase->recognition_mode = triggerPhrase->recognitionModes;
337     unsigned int i;
338 
339     halTriggerPhrase->num_users =
340         std::min((int)triggerPhrase->users.size(), SOUND_TRIGGER_MAX_USERS);
341     for (i = 0; i < halTriggerPhrase->num_users; i++) {
342         halTriggerPhrase->users[i] = triggerPhrase->users[i];
343     }
344 
345     strlcpy(halTriggerPhrase->locale, triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN);
346     strlcpy(halTriggerPhrase->text, triggerPhrase->text.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
347 }
348 
convertSoundModelToHal(const ISoundTriggerHw::SoundModel * soundModel)349 struct sound_trigger_sound_model* SoundTriggerHalImpl::convertSoundModelToHal(
350     const ISoundTriggerHw::SoundModel* soundModel) {
351     struct sound_trigger_sound_model* halModel = NULL;
352     if (soundModel->type == SoundModelType::KEYPHRASE) {
353         size_t allocSize =
354             sizeof(struct sound_trigger_phrase_sound_model) + soundModel->data.size();
355         struct sound_trigger_phrase_sound_model* halKeyPhraseModel =
356             static_cast<struct sound_trigger_phrase_sound_model*>(malloc(allocSize));
357         LOG_ALWAYS_FATAL_IF(halKeyPhraseModel == NULL,
358                             "malloc failed for size %zu in convertSoundModelToHal PHRASE",
359                             allocSize);
360 
361         const ISoundTriggerHw::PhraseSoundModel* keyPhraseModel =
362             reinterpret_cast<const ISoundTriggerHw::PhraseSoundModel*>(soundModel);
363 
364         size_t i;
365         for (i = 0; i < keyPhraseModel->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
366             convertTriggerPhraseToHal(&halKeyPhraseModel->phrases[i], &keyPhraseModel->phrases[i]);
367         }
368         halKeyPhraseModel->num_phrases = (unsigned int)i;
369         halModel = reinterpret_cast<struct sound_trigger_sound_model*>(halKeyPhraseModel);
370         halModel->data_offset = sizeof(struct sound_trigger_phrase_sound_model);
371     } else {
372         size_t allocSize = sizeof(struct sound_trigger_sound_model) + soundModel->data.size();
373         halModel = static_cast<struct sound_trigger_sound_model*>(malloc(allocSize));
374         LOG_ALWAYS_FATAL_IF(halModel == NULL,
375                             "malloc failed for size %zu in convertSoundModelToHal GENERIC",
376                             allocSize);
377 
378         halModel->data_offset = sizeof(struct sound_trigger_sound_model);
379     }
380     halModel->type = (sound_trigger_sound_model_type_t)soundModel->type;
381     convertUuidToHal(&halModel->uuid, &soundModel->uuid);
382     convertUuidToHal(&halModel->vendor_uuid, &soundModel->vendorUuid);
383     halModel->data_size = soundModel->data.size();
384     uint8_t* dst = reinterpret_cast<uint8_t*>(halModel) + halModel->data_offset;
385     const uint8_t* src = reinterpret_cast<const uint8_t*>(&soundModel->data[0]);
386     memcpy(dst, src, soundModel->data.size());
387 
388     return halModel;
389 }
390 
convertPhraseRecognitionExtraToHal(struct sound_trigger_phrase_recognition_extra * halExtra,const PhraseRecognitionExtra * extra)391 void SoundTriggerHalImpl::convertPhraseRecognitionExtraToHal(
392     struct sound_trigger_phrase_recognition_extra* halExtra, const PhraseRecognitionExtra* extra) {
393     halExtra->id = extra->id;
394     halExtra->recognition_modes = extra->recognitionModes;
395     halExtra->confidence_level = extra->confidenceLevel;
396 
397     unsigned int i;
398     for (i = 0; i < extra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) {
399         halExtra->levels[i].user_id = extra->levels[i].userId;
400         halExtra->levels[i].level = extra->levels[i].levelPercent;
401     }
402     halExtra->num_levels = i;
403 }
404 
convertRecognitionConfigToHal(const ISoundTriggerHw::RecognitionConfig * config)405 struct sound_trigger_recognition_config* SoundTriggerHalImpl::convertRecognitionConfigToHal(
406     const ISoundTriggerHw::RecognitionConfig* config) {
407     size_t allocSize = sizeof(struct sound_trigger_recognition_config) + config->data.size();
408     struct sound_trigger_recognition_config* halConfig =
409         static_cast<struct sound_trigger_recognition_config*>(malloc(allocSize));
410 
411     LOG_ALWAYS_FATAL_IF(halConfig == NULL,
412                         "malloc failed for size %zu in convertRecognitionConfigToHal", allocSize);
413 
414     halConfig->capture_handle = (audio_io_handle_t)config->captureHandle;
415     halConfig->capture_device = (audio_devices_t)config->captureDevice;
416     halConfig->capture_requested = config->captureRequested;
417 
418     unsigned int i;
419     for (i = 0; i < config->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
420         convertPhraseRecognitionExtraToHal(&halConfig->phrases[i], &config->phrases[i]);
421     }
422     halConfig->num_phrases = i;
423 
424     halConfig->data_offset = sizeof(struct sound_trigger_recognition_config);
425     halConfig->data_size = config->data.size();
426     uint8_t* dst = reinterpret_cast<uint8_t*>(halConfig) + halConfig->data_offset;
427     const uint8_t* src = reinterpret_cast<const uint8_t*>(&config->data[0]);
428     memcpy(dst, src, config->data.size());
429     return halConfig;
430 }
431 
432 // static
convertSoundModelEventFromHal(ISoundTriggerHwCallback::ModelEvent * event,const struct sound_trigger_model_event * halEvent)433 void SoundTriggerHalImpl::convertSoundModelEventFromHal(
434     ISoundTriggerHwCallback::ModelEvent* event, const struct sound_trigger_model_event* halEvent) {
435     event->status = (ISoundTriggerHwCallback::SoundModelStatus)halEvent->status;
436     // event->model to be remapped by called
437     event->data.setToExternal(
438         const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset,
439         halEvent->data_size);
440 }
441 
442 // static
convertPhaseRecognitionEventFromHal(ISoundTriggerHwCallback::PhraseRecognitionEvent * event,const struct sound_trigger_phrase_recognition_event * halEvent)443 void SoundTriggerHalImpl::convertPhaseRecognitionEventFromHal(
444     ISoundTriggerHwCallback::PhraseRecognitionEvent* event,
445     const struct sound_trigger_phrase_recognition_event* halEvent) {
446     event->phraseExtras.resize(halEvent->num_phrases);
447     for (unsigned int i = 0; i < halEvent->num_phrases; i++) {
448         convertPhraseRecognitionExtraFromHal(&event->phraseExtras[i], &halEvent->phrase_extras[i]);
449     }
450     convertRecognitionEventFromHal(&event->common, &halEvent->common);
451 }
452 
453 // static
convertRecognitionEventFromHal(ISoundTriggerHwCallback::RecognitionEvent * event,const struct sound_trigger_recognition_event * halEvent)454 void SoundTriggerHalImpl::convertRecognitionEventFromHal(
455     ISoundTriggerHwCallback::RecognitionEvent* event,
456     const struct sound_trigger_recognition_event* halEvent) {
457     event->status = static_cast<ISoundTriggerHwCallback::RecognitionStatus>(halEvent->status);
458     event->type = static_cast<SoundModelType>(halEvent->type);
459     // event->model to be remapped by called
460     event->captureAvailable = halEvent->capture_available;
461     event->captureSession = halEvent->capture_session;
462     event->captureDelayMs = halEvent->capture_delay_ms;
463     event->capturePreambleMs = halEvent->capture_preamble_ms;
464     event->triggerInData = halEvent->trigger_in_data;
465     event->audioConfig.sampleRateHz = halEvent->audio_config.sample_rate;
466     event->audioConfig.channelMask =
467         (audio::common::V2_0::AudioChannelMask)halEvent->audio_config.channel_mask;
468     event->audioConfig.format = (audio::common::V2_0::AudioFormat)halEvent->audio_config.format;
469     event->data.setToExternal(
470         const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset,
471         halEvent->data_size);
472 }
473 
474 // static
convertPhraseRecognitionExtraFromHal(PhraseRecognitionExtra * extra,const struct sound_trigger_phrase_recognition_extra * halExtra)475 void SoundTriggerHalImpl::convertPhraseRecognitionExtraFromHal(
476     PhraseRecognitionExtra* extra, const struct sound_trigger_phrase_recognition_extra* halExtra) {
477     extra->id = halExtra->id;
478     extra->recognitionModes = halExtra->recognition_modes;
479     extra->confidenceLevel = halExtra->confidence_level;
480 
481     extra->levels.resize(halExtra->num_levels);
482     for (unsigned int i = 0; i < halExtra->num_levels; i++) {
483         extra->levels[i].userId = halExtra->levels[i].user_id;
484         extra->levels[i].levelPercent = halExtra->levels[i].level;
485     }
486 }
487 
recognitionCallback(struct sound_trigger_recognition_event * halEvent)488 void SoundTriggerHalImpl::SoundModelClient_2_0::recognitionCallback(
489     struct sound_trigger_recognition_event* halEvent) {
490     if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
491         ISoundTriggerHwCallback::PhraseRecognitionEvent event;
492         convertPhaseRecognitionEventFromHal(
493             &event, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent));
494         event.common.model = mId;
495         mCallback->phraseRecognitionCallback(event, mCookie);
496     } else {
497         ISoundTriggerHwCallback::RecognitionEvent event;
498         convertRecognitionEventFromHal(&event, halEvent);
499         event.model = mId;
500         mCallback->recognitionCallback(event, mCookie);
501     }
502 }
503 
soundModelCallback(struct sound_trigger_model_event * halEvent)504 void SoundTriggerHalImpl::SoundModelClient_2_0::soundModelCallback(
505     struct sound_trigger_model_event* halEvent) {
506     ISoundTriggerHwCallback::ModelEvent event;
507     convertSoundModelEventFromHal(&event, halEvent);
508     event.model = mId;
509     mCallback->soundModelCallback(event, mCookie);
510 }
511 
512 }  // namespace implementation
513 }  // namespace V2_0
514 }  // namespace soundtrigger
515 }  // namespace hardware
516 }  // namespace android
517