blob: 0cd5cf702fab9968f772cee8cbd042879c2158e3 [file] [log] [blame]
Eric Laurent7a544b42016-08-05 19:01:13 -07001/*
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
Mikhail Naganovd621ac82017-01-12 17:17:45 -080020#include <media/audiohal/hidl/HalDeathHandler.h>
Eric Laurent7a544b42016-08-05 19:01:13 -070021#include <utils/Log.h>
22#include "SoundTriggerHalHidl.h"
Eric Laurent7a544b42016-08-05 19:01:13 -070023#include <hwbinder/IPCThreadState.h>
24#include <hwbinder/ProcessState.h>
25
26namespace android {
27
28using android::hardware::Return;
29using android::hardware::ProcessState;
30using android::hardware::audio::common::V2_0::AudioDevice;
31
Eric Laurent7a544b42016-08-05 19:01:13 -070032/* static */
33sp<SoundTriggerHalInterface> SoundTriggerHalInterface::connectModule(const char *moduleName)
34{
35 return new SoundTriggerHalHidl(moduleName);
36}
37
38int 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;
Eric Laurent4b38e7a2016-11-11 13:28:53 -080047 int ret;
Eric Laurent7a544b42016-08-05 19:01:13 -070048 {
49 AutoMutex lock(mHalLock);
50 hidlReturn = soundtrigger->getProperties([&](int rc, auto res) {
Eric Laurent4b38e7a2016-11-11 13:28:53 -080051 ret = rc;
Eric Laurent7a544b42016-08-05 19:01:13 -070052 halProperties = res;
53 ALOGI("getProperties res implementor %s", res.implementor.c_str());
54 });
55 }
56
Steven Morelande83be8a2017-01-06 11:06:33 -080057 if (hidlReturn.isOk()) {
Eric Laurent4b38e7a2016-11-11 13:28:53 -080058 if (ret == 0) {
59 convertPropertiesFromHal(properties, &halProperties);
60 }
Eric Laurent7a544b42016-08-05 19:01:13 -070061 } else {
Steven Morelande83be8a2017-01-06 11:06:33 -080062 ALOGE("getProperties error %s", hidlReturn.description().c_str());
Mikhail Naganovd621ac82017-01-12 17:17:45 -080063 return FAILED_TRANSACTION;
Eric Laurent7a544b42016-08-05 19:01:13 -070064 }
Eric Laurent4b38e7a2016-11-11 13:28:53 -080065 ALOGI("getProperties ret %d", ret);
Eric Laurent7a544b42016-08-05 19:01:13 -070066 return ret;
67}
68
69int 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;
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800104 int ret;
Eric Laurent7a544b42016-08-05 19:01:13 -0700105 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) {
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800112 ret = retval;
Eric Laurent7a544b42016-08-05 19:01:13 -0700113 halHandle = res;
114 });
115
116 } else {
117 hidlReturn = soundtrigger->loadSoundModel(*halSoundModel,
118 this, modelId, [&](int32_t retval, auto res) {
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800119 ret = retval;
Eric Laurent7a544b42016-08-05 19:01:13 -0700120 halHandle = res;
121 });
122 }
123 }
124
125 delete halSoundModel;
126
Steven Morelande83be8a2017-01-06 11:06:33 -0800127 if (hidlReturn.isOk()) {
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800128 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 }
Eric Laurent7a544b42016-08-05 19:01:13 -0700134 } else {
Steven Morelande83be8a2017-01-06 11:06:33 -0800135 ALOGE("loadSoundModel error %s", hidlReturn.description().c_str());
Mikhail Naganovd621ac82017-01-12 17:17:45 -0800136 return FAILED_TRANSACTION;
Eric Laurent7a544b42016-08-05 19:01:13 -0700137 }
138
Eric Laurent7a544b42016-08-05 19:01:13 -0700139 return ret;
140}
141
142int 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
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800155 Return<int32_t> hidlReturn(0);
Eric Laurent7a544b42016-08-05 19:01:13 -0700156 {
157 AutoMutex lock(mHalLock);
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800158 hidlReturn = soundtrigger->unloadSoundModel(model->mHalHandle);
Eric Laurent7a544b42016-08-05 19:01:13 -0700159 }
Steven Morelande83be8a2017-01-06 11:06:33 -0800160
161 if (!hidlReturn.isOk()) {
162 ALOGE("unloadSoundModel error %s", hidlReturn.description().c_str());
Mikhail Naganovd621ac82017-01-12 17:17:45 -0800163 return FAILED_TRANSACTION;
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800164 }
Steven Morelande83be8a2017-01-06 11:06:33 -0800165
166 return hidlReturn;
Eric Laurent7a544b42016-08-05 19:01:13 -0700167}
168
169int 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
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800191 Return<int32_t> hidlReturn(0);
Eric Laurent7a544b42016-08-05 19:01:13 -0700192 {
193 AutoMutex lock(mHalLock);
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800194 hidlReturn = soundtrigger->startRecognition(model->mHalHandle, *halConfig, this, handle);
Eric Laurent7a544b42016-08-05 19:01:13 -0700195 }
196
197 delete halConfig;
198
Steven Morelande83be8a2017-01-06 11:06:33 -0800199 if (!hidlReturn.isOk()) {
200 ALOGE("startRecognition error %s", hidlReturn.description().c_str());
Mikhail Naganovd621ac82017-01-12 17:17:45 -0800201 return FAILED_TRANSACTION;
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800202 }
Steven Morelande83be8a2017-01-06 11:06:33 -0800203 return hidlReturn;
Eric Laurent7a544b42016-08-05 19:01:13 -0700204}
205
206int 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
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800219 Return<int32_t> hidlReturn(0);
Eric Laurent7a544b42016-08-05 19:01:13 -0700220 {
221 AutoMutex lock(mHalLock);
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800222 hidlReturn = soundtrigger->stopRecognition(model->mHalHandle);
Eric Laurent7a544b42016-08-05 19:01:13 -0700223 }
224
Steven Morelande83be8a2017-01-06 11:06:33 -0800225 if (!hidlReturn.isOk()) {
226 ALOGE("stopRecognition error %s", hidlReturn.description().c_str());
Mikhail Naganovd621ac82017-01-12 17:17:45 -0800227 return FAILED_TRANSACTION;
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800228 }
Steven Morelande83be8a2017-01-06 11:06:33 -0800229 return hidlReturn;
Eric Laurent7a544b42016-08-05 19:01:13 -0700230}
231
232int SoundTriggerHalHidl::stopAllRecognitions()
233{
234 sp<ISoundTriggerHw> soundtrigger = getService();
235 if (soundtrigger == 0) {
236 return -ENODEV;
237 }
238
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800239 Return<int32_t> hidlReturn(0);
Eric Laurent7a544b42016-08-05 19:01:13 -0700240 {
241 AutoMutex lock(mHalLock);
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800242 hidlReturn = soundtrigger->stopAllRecognitions();
Eric Laurent7a544b42016-08-05 19:01:13 -0700243 }
244
Steven Morelande83be8a2017-01-06 11:06:33 -0800245 if (!hidlReturn.isOk()) {
246 ALOGE("stopAllRecognitions error %s", hidlReturn.description().c_str());
Mikhail Naganovd621ac82017-01-12 17:17:45 -0800247 return FAILED_TRANSACTION;
Eric Laurent4b38e7a2016-11-11 13:28:53 -0800248 }
Steven Morelande83be8a2017-01-06 11:06:33 -0800249 return hidlReturn;
Eric Laurent7a544b42016-08-05 19:01:13 -0700250}
251
252SoundTriggerHalHidl::SoundTriggerHalHidl(const char *moduleName)
253 : mModuleName(moduleName), mNextUniqueId(1)
254{
Mikhail Naganov49ad5522017-04-13 11:00:06 -0700255 LOG_ALWAYS_FATAL_IF(strcmp(mModuleName, "primary") != 0,
256 "Treble soundtrigger only supports primary module");
Eric Laurent7a544b42016-08-05 19:01:13 -0700257}
258
Eric Laurent7a544b42016-08-05 19:01:13 -0700259SoundTriggerHalHidl::~SoundTriggerHalHidl()
260{
261}
262
263sp<ISoundTriggerHw> SoundTriggerHalHidl::getService()
264{
265 AutoMutex lock(mLock);
266 if (mISoundTrigger == 0) {
267 if (mModuleName == NULL) {
268 mModuleName = "primary";
269 }
Mikhail Naganov49ad5522017-04-13 11:00:06 -0700270 mISoundTrigger = ISoundTriggerHw::getService();
Mikhail Naganovd621ac82017-01-12 17:17:45 -0800271 if (mISoundTrigger != 0) {
272 mISoundTrigger->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
273 }
Eric Laurent7a544b42016-08-05 19:01:13 -0700274 }
275 return mISoundTrigger;
276}
277
Eric Laurent7a544b42016-08-05 19:01:13 -0700278sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::getModel(sound_model_handle_t handle)
279{
280 AutoMutex lock(mLock);
281 return mSoundModels.valueFor(handle);
282}
283
284sp<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
292uint32_t SoundTriggerHalHidl::nextUniqueId()
293{
294 return (uint32_t) atomic_fetch_add_explicit(&mNextUniqueId,
295 (uint_fast32_t) 1, memory_order_acq_rel);
296}
297
298void SoundTriggerHalHidl::convertUuidToHal(Uuid *halUuid,
Eric Laurentf7854d42016-10-14 15:57:18 -0700299 const sound_trigger_uuid_t *uuid)
Eric Laurent7a544b42016-08-05 19:01:13 -0700300{
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
Eric Laurentf7854d42016-10-14 15:57:18 -0700308void SoundTriggerHalHidl::convertUuidFromHal(sound_trigger_uuid_t *uuid,
Eric Laurent7a544b42016-08-05 19:01:13 -0700309 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
318void 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
339void 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
350ISoundTriggerHw::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
386void 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
407ISoundTriggerHw::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
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
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
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
515struct 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
536void 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
553struct 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