blob: bbd97f1aa80f275a9bfbfe7d20e564dbdd1e2644 [file] [log] [blame]
Eric Laurent27ef4d82016-10-14 15:46:06 -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 "SoundTriggerHalImpl"
18//#define LOG_NDEBUG 0
19
Eric Laurent27ef4d82016-10-14 15:46:06 -070020#include "SoundTriggerHalImpl.h"
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -080021#include <android/log.h>
Eric Laurent27ef4d82016-10-14 15:46:06 -070022
23namespace android {
24namespace hardware {
25namespace soundtrigger {
26namespace V2_0 {
27namespace implementation {
28
29// static
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -080030void SoundTriggerHalImpl::soundModelCallback(struct sound_trigger_model_event* halEvent,
31 void* cookie) {
Eric Laurent27ef4d82016-10-14 15:46:06 -070032 if (halEvent == NULL) {
33 ALOGW("soundModelCallback called with NULL event");
34 return;
35 }
36 sp<SoundModelClient> client =
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -080037 wp<SoundModelClient>(static_cast<SoundModelClient*>(cookie)).promote();
Eric Laurent27ef4d82016-10-14 15:46:06 -070038 if (client == 0) {
39 ALOGW("soundModelCallback called on stale client");
40 return;
41 }
42 if (halEvent->model != client->mHalHandle) {
43 ALOGW("soundModelCallback call with wrong handle %d on client with handle %d",
44 (int)halEvent->model, (int)client->mHalHandle);
45 return;
46 }
47
48 ISoundTriggerHwCallback::ModelEvent event;
49 convertSoundModelEventFromHal(&event, halEvent);
50 event.model = client->mId;
51
52 client->mCallback->soundModelCallback(event, client->mCookie);
53}
54
55// static
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -080056void SoundTriggerHalImpl::recognitionCallback(struct sound_trigger_recognition_event* halEvent,
57 void* cookie) {
Eric Laurent27ef4d82016-10-14 15:46:06 -070058 if (halEvent == NULL) {
59 ALOGW("recognitionCallback call NULL event");
60 return;
61 }
62 sp<SoundModelClient> client =
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -080063 wp<SoundModelClient>(static_cast<SoundModelClient*>(cookie)).promote();
Eric Laurent27ef4d82016-10-14 15:46:06 -070064 if (client == 0) {
65 ALOGW("soundModelCallback called on stale client");
66 return;
67 }
68
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -080069 ISoundTriggerHwCallback::RecognitionEvent* event = convertRecognitionEventFromHal(halEvent);
Eric Laurent27ef4d82016-10-14 15:46:06 -070070 event->model = client->mId;
71 if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
72 client->mCallback->phraseRecognitionCallback(
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -080073 *(reinterpret_cast<ISoundTriggerHwCallback::PhraseRecognitionEvent*>(event)),
74 client->mCookie);
Eric Laurent27ef4d82016-10-14 15:46:06 -070075 } else {
76 client->mCallback->recognitionCallback(*event, client->mCookie);
77 }
78 delete event;
79}
80
Eric Laurent27ef4d82016-10-14 15:46:06 -070081// Methods from ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw follow.
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -080082Return<void> SoundTriggerHalImpl::getProperties(getProperties_cb _hidl_cb) {
Eric Laurent27ef4d82016-10-14 15:46:06 -070083 ALOGV("getProperties() mHwDevice %p", mHwDevice);
84 int ret;
85 struct sound_trigger_properties halProperties;
86 ISoundTriggerHw::Properties properties;
87
88 if (mHwDevice == NULL) {
89 ret = -ENODEV;
90 goto exit;
91 }
92
93 ret = mHwDevice->get_properties(mHwDevice, &halProperties);
94
95 convertPropertiesFromHal(&properties, &halProperties);
96
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -080097 ALOGV("getProperties implementor %s recognitionModes %08x", properties.implementor.c_str(),
98 properties.recognitionModes);
Eric Laurent27ef4d82016-10-14 15:46:06 -070099
100exit:
101 _hidl_cb(ret, properties);
102 return Void();
103}
104
105int SoundTriggerHalImpl::doLoadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800106 const sp<ISoundTriggerHwCallback>& callback,
107 ISoundTriggerHwCallback::CallbackCookie cookie,
108 uint32_t* modelId) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700109 int32_t ret = 0;
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800110 struct sound_trigger_sound_model* halSoundModel;
Eric Laurent27ef4d82016-10-14 15:46:06 -0700111 *modelId = 0;
112 sp<SoundModelClient> client;
113
114 ALOGV("doLoadSoundModel() data size %zu", soundModel.data.size());
115
116 if (mHwDevice == NULL) {
117 ret = -ENODEV;
118 goto exit;
119 }
120
121 halSoundModel = convertSoundModelToHal(&soundModel);
122 if (halSoundModel == NULL) {
123 ret = -EINVAL;
124 goto exit;
125 }
126
127 {
128 AutoMutex lock(mLock);
129 do {
130 *modelId = nextUniqueId();
131 } while (mClients.valueFor(*modelId) != 0 && *modelId != 0);
132 }
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800133 LOG_ALWAYS_FATAL_IF(*modelId == 0, "wrap around in sound model IDs, num loaded models %zu",
134 mClients.size());
Eric Laurent27ef4d82016-10-14 15:46:06 -0700135
136 client = new SoundModelClient(*modelId, callback, cookie);
137
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800138 ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, soundModelCallback, client.get(),
139 &client->mHalHandle);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700140
141 free(halSoundModel);
142
143 if (ret != 0) {
144 goto exit;
145 }
146
147 {
148 AutoMutex lock(mLock);
149 mClients.add(*modelId, client);
150 }
151
152exit:
153 return ret;
154}
155
156Return<void> SoundTriggerHalImpl::loadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
157 const sp<ISoundTriggerHwCallback>& callback,
158 ISoundTriggerHwCallback::CallbackCookie cookie,
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800159 loadSoundModel_cb _hidl_cb) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700160 uint32_t modelId = 0;
161 int32_t ret = doLoadSoundModel(soundModel, callback, cookie, &modelId);
162
163 _hidl_cb(ret, modelId);
164 return Void();
165}
166
167Return<void> SoundTriggerHalImpl::loadPhraseSoundModel(
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800168 const ISoundTriggerHw::PhraseSoundModel& soundModel,
169 const sp<ISoundTriggerHwCallback>& callback, ISoundTriggerHwCallback::CallbackCookie cookie,
170 ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700171 uint32_t modelId = 0;
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800172 int32_t ret = doLoadSoundModel((const ISoundTriggerHw::SoundModel&)soundModel, callback, cookie,
173 &modelId);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700174
175 _hidl_cb(ret, modelId);
176 return Void();
177}
178
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800179Return<int32_t> SoundTriggerHalImpl::unloadSoundModel(SoundModelHandle modelHandle) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700180 int32_t ret;
181 sp<SoundModelClient> client;
182
183 if (mHwDevice == NULL) {
184 ret = -ENODEV;
185 goto exit;
186 }
187
188 {
189 AutoMutex lock(mLock);
190 client = mClients.valueFor(modelHandle);
191 if (client == 0) {
192 ret = -ENOSYS;
193 goto exit;
194 }
195 }
196
197 ret = mHwDevice->unload_sound_model(mHwDevice, client->mHalHandle);
198
199 mClients.removeItem(modelHandle);
200
201exit:
202 return ret;
203}
204
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800205Return<int32_t> SoundTriggerHalImpl::startRecognition(
206 SoundModelHandle modelHandle, const ISoundTriggerHw::RecognitionConfig& config,
207 const sp<ISoundTriggerHwCallback>& callback __unused,
208 ISoundTriggerHwCallback::CallbackCookie cookie __unused) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700209 int32_t ret;
210 sp<SoundModelClient> client;
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800211 struct sound_trigger_recognition_config* halConfig;
Eric Laurent27ef4d82016-10-14 15:46:06 -0700212
213 if (mHwDevice == NULL) {
214 ret = -ENODEV;
215 goto exit;
216 }
217
218 {
219 AutoMutex lock(mLock);
220 client = mClients.valueFor(modelHandle);
221 if (client == 0) {
222 ret = -ENOSYS;
223 goto exit;
224 }
225 }
226
Eric Laurent27ef4d82016-10-14 15:46:06 -0700227 halConfig = convertRecognitionConfigToHal(&config);
228
229 if (halConfig == NULL) {
230 ret = -EINVAL;
231 goto exit;
232 }
233 ret = mHwDevice->start_recognition(mHwDevice, client->mHalHandle, halConfig,
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800234 recognitionCallback, client.get());
Eric Laurent27ef4d82016-10-14 15:46:06 -0700235
236 free(halConfig);
237
238exit:
239 return ret;
240}
241
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800242Return<int32_t> SoundTriggerHalImpl::stopRecognition(SoundModelHandle modelHandle) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700243 int32_t ret;
244 sp<SoundModelClient> client;
245 if (mHwDevice == NULL) {
246 ret = -ENODEV;
247 goto exit;
248 }
249
250 {
251 AutoMutex lock(mLock);
252 client = mClients.valueFor(modelHandle);
253 if (client == 0) {
254 ret = -ENOSYS;
255 goto exit;
256 }
257 }
258
259 ret = mHwDevice->stop_recognition(mHwDevice, client->mHalHandle);
260
261exit:
262 return ret;
263}
264
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800265Return<int32_t> SoundTriggerHalImpl::stopAllRecognitions() {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700266 int32_t ret;
267 if (mHwDevice == NULL) {
268 ret = -ENODEV;
269 goto exit;
270 }
271
272 if (mHwDevice->common.version >= SOUND_TRIGGER_DEVICE_API_VERSION_1_1 &&
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800273 mHwDevice->stop_all_recognitions) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700274 ret = mHwDevice->stop_all_recognitions(mHwDevice);
275 } else {
276 ret = -ENOSYS;
277 }
278exit:
279 return ret;
280}
281
Mikhail Naganov3acaa662017-04-13 11:00:11 -0700282SoundTriggerHalImpl::SoundTriggerHalImpl()
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800283 : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {}
Eric Laurent27ef4d82016-10-14 15:46:06 -0700284
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800285void SoundTriggerHalImpl::onFirstRef() {
286 const hw_module_t* mod;
Eric Laurent27ef4d82016-10-14 15:46:06 -0700287 int rc;
288
Eric Laurent27ef4d82016-10-14 15:46:06 -0700289 rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, &mod);
290 if (rc != 0) {
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800291 ALOGE("couldn't load sound trigger module %s.%s (%s)", SOUND_TRIGGER_HARDWARE_MODULE_ID,
292 mModuleName, strerror(-rc));
Eric Laurent27ef4d82016-10-14 15:46:06 -0700293 return;
294 }
295 rc = sound_trigger_hw_device_open(mod, &mHwDevice);
296 if (rc != 0) {
297 ALOGE("couldn't open sound trigger hw device in %s.%s (%s)",
298 SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, strerror(-rc));
299 mHwDevice = NULL;
300 return;
301 }
302 if (mHwDevice->common.version < SOUND_TRIGGER_DEVICE_API_VERSION_1_0 ||
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800303 mHwDevice->common.version > SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700304 ALOGE("wrong sound trigger hw device version %04x", mHwDevice->common.version);
305 sound_trigger_hw_device_close(mHwDevice);
306 mHwDevice = NULL;
307 return;
308 }
309
310 ALOGI("onFirstRef() mModuleName %s mHwDevice %p", mModuleName, mHwDevice);
311}
312
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800313SoundTriggerHalImpl::~SoundTriggerHalImpl() {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700314 if (mHwDevice != NULL) {
315 sound_trigger_hw_device_close(mHwDevice);
316 }
317}
318
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800319uint32_t SoundTriggerHalImpl::nextUniqueId() {
320 return (uint32_t)atomic_fetch_add_explicit(&mNextModelId, (uint_fast32_t)1,
321 memory_order_acq_rel);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700322}
323
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800324void SoundTriggerHalImpl::convertUuidFromHal(Uuid* uuid, const sound_trigger_uuid_t* halUuid) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700325 uuid->timeLow = halUuid->timeLow;
326 uuid->timeMid = halUuid->timeMid;
327 uuid->versionAndTimeHigh = halUuid->timeHiAndVersion;
328 uuid->variantAndClockSeqHigh = halUuid->clockSeq;
329 memcpy(&uuid->node[0], &halUuid->node[0], 6);
330}
331
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800332void SoundTriggerHalImpl::convertUuidToHal(sound_trigger_uuid_t* halUuid, const Uuid* uuid) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700333 halUuid->timeLow = uuid->timeLow;
334 halUuid->timeMid = uuid->timeMid;
335 halUuid->timeHiAndVersion = uuid->versionAndTimeHigh;
336 halUuid->clockSeq = uuid->variantAndClockSeqHigh;
337 memcpy(&halUuid->node[0], &uuid->node[0], 6);
338}
339
340void SoundTriggerHalImpl::convertPropertiesFromHal(
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800341 ISoundTriggerHw::Properties* properties, const struct sound_trigger_properties* halProperties) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700342 properties->implementor = halProperties->implementor;
343 properties->description = halProperties->description;
344 properties->version = halProperties->version;
345 convertUuidFromHal(&properties->uuid, &halProperties->uuid);
346 properties->maxSoundModels = halProperties->max_sound_models;
347 properties->maxKeyPhrases = halProperties->max_key_phrases;
348 properties->maxUsers = halProperties->max_users;
349 properties->recognitionModes = halProperties->recognition_modes;
350 properties->captureTransition = halProperties->capture_transition;
351 properties->maxBufferMs = halProperties->max_buffer_ms;
352 properties->concurrentCapture = halProperties->concurrent_capture;
353 properties->triggerInEvent = halProperties->trigger_in_event;
354 properties->powerConsumptionMw = halProperties->power_consumption_mw;
Eric Laurent27ef4d82016-10-14 15:46:06 -0700355}
356
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800357void SoundTriggerHalImpl::convertTriggerPhraseToHal(struct sound_trigger_phrase* halTriggerPhrase,
358 const ISoundTriggerHw::Phrase* triggerPhrase) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700359 halTriggerPhrase->id = triggerPhrase->id;
360 halTriggerPhrase->recognition_mode = triggerPhrase->recognitionModes;
361 unsigned int i;
Eric Laurenta6920302017-09-07 12:35:29 -0700362
363 halTriggerPhrase->num_users =
364 std::min((int)triggerPhrase->users.size(), SOUND_TRIGGER_MAX_USERS);
365 for (i = 0; i < halTriggerPhrase->num_users; i++) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700366 halTriggerPhrase->users[i] = triggerPhrase->users[i];
367 }
Eric Laurent27ef4d82016-10-14 15:46:06 -0700368
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800369 strlcpy(halTriggerPhrase->locale, triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN);
370 strlcpy(halTriggerPhrase->text, triggerPhrase->text.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700371}
372
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800373struct sound_trigger_sound_model* SoundTriggerHalImpl::convertSoundModelToHal(
374 const ISoundTriggerHw::SoundModel* soundModel) {
375 struct sound_trigger_sound_model* halModel = NULL;
Eric Laurent27ef4d82016-10-14 15:46:06 -0700376 if (soundModel->type == SoundModelType::KEYPHRASE) {
377 size_t allocSize =
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800378 sizeof(struct sound_trigger_phrase_sound_model) + soundModel->data.size();
379 struct sound_trigger_phrase_sound_model* halKeyPhraseModel =
380 static_cast<struct sound_trigger_phrase_sound_model*>(malloc(allocSize));
Eric Laurent27ef4d82016-10-14 15:46:06 -0700381 LOG_ALWAYS_FATAL_IF(halKeyPhraseModel == NULL,
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800382 "malloc failed for size %zu in convertSoundModelToHal PHRASE",
383 allocSize);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700384
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800385 const ISoundTriggerHw::PhraseSoundModel* keyPhraseModel =
386 reinterpret_cast<const ISoundTriggerHw::PhraseSoundModel*>(soundModel);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700387
388 size_t i;
389 for (i = 0; i < keyPhraseModel->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800390 convertTriggerPhraseToHal(&halKeyPhraseModel->phrases[i], &keyPhraseModel->phrases[i]);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700391 }
392 halKeyPhraseModel->num_phrases = (unsigned int)i;
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800393 halModel = reinterpret_cast<struct sound_trigger_sound_model*>(halKeyPhraseModel);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700394 halModel->data_offset = sizeof(struct sound_trigger_phrase_sound_model);
395 } else {
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800396 size_t allocSize = sizeof(struct sound_trigger_sound_model) + soundModel->data.size();
397 halModel = static_cast<struct sound_trigger_sound_model*>(malloc(allocSize));
Eric Laurent27ef4d82016-10-14 15:46:06 -0700398 LOG_ALWAYS_FATAL_IF(halModel == NULL,
399 "malloc failed for size %zu in convertSoundModelToHal GENERIC",
400 allocSize);
401
402 halModel->data_offset = sizeof(struct sound_trigger_sound_model);
403 }
404 halModel->type = (sound_trigger_sound_model_type_t)soundModel->type;
405 convertUuidToHal(&halModel->uuid, &soundModel->uuid);
406 convertUuidToHal(&halModel->vendor_uuid, &soundModel->vendorUuid);
407 halModel->data_size = soundModel->data.size();
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800408 uint8_t* dst = reinterpret_cast<uint8_t*>(halModel) + halModel->data_offset;
409 const uint8_t* src = reinterpret_cast<const uint8_t*>(&soundModel->data[0]);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700410 memcpy(dst, src, soundModel->data.size());
411
412 return halModel;
413}
414
415void SoundTriggerHalImpl::convertPhraseRecognitionExtraToHal(
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800416 struct sound_trigger_phrase_recognition_extra* halExtra, const PhraseRecognitionExtra* extra) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700417 halExtra->id = extra->id;
418 halExtra->recognition_modes = extra->recognitionModes;
419 halExtra->confidence_level = extra->confidenceLevel;
420
421 unsigned int i;
422 for (i = 0; i < extra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) {
423 halExtra->levels[i].user_id = extra->levels[i].userId;
424 halExtra->levels[i].level = extra->levels[i].levelPercent;
425 }
426 halExtra->num_levels = i;
427}
428
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800429struct sound_trigger_recognition_config* SoundTriggerHalImpl::convertRecognitionConfigToHal(
430 const ISoundTriggerHw::RecognitionConfig* config) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700431 size_t allocSize = sizeof(struct sound_trigger_recognition_config) + config->data.size();
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800432 struct sound_trigger_recognition_config* halConfig =
433 static_cast<struct sound_trigger_recognition_config*>(malloc(allocSize));
Eric Laurent27ef4d82016-10-14 15:46:06 -0700434
435 LOG_ALWAYS_FATAL_IF(halConfig == NULL,
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800436 "malloc failed for size %zu in convertRecognitionConfigToHal", allocSize);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700437
438 halConfig->capture_handle = (audio_io_handle_t)config->captureHandle;
439 halConfig->capture_device = (audio_devices_t)config->captureDevice;
440 halConfig->capture_requested = config->captureRequested;
441
442 unsigned int i;
443 for (i = 0; i < config->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800444 convertPhraseRecognitionExtraToHal(&halConfig->phrases[i], &config->phrases[i]);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700445 }
446 halConfig->num_phrases = i;
447
448 halConfig->data_offset = sizeof(struct sound_trigger_recognition_config);
449 halConfig->data_size = config->data.size();
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800450 uint8_t* dst = reinterpret_cast<uint8_t*>(halConfig) + halConfig->data_offset;
451 const uint8_t* src = reinterpret_cast<const uint8_t*>(&config->data[0]);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700452 memcpy(dst, src, config->data.size());
453 return halConfig;
454}
455
456// static
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800457void SoundTriggerHalImpl::convertSoundModelEventFromHal(
458 ISoundTriggerHwCallback::ModelEvent* event, const struct sound_trigger_model_event* halEvent) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700459 event->status = (ISoundTriggerHwCallback::SoundModelStatus)halEvent->status;
460 // event->model to be remapped by called
461 event->data.setToExternal(
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800462 const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset,
463 halEvent->data_size);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700464}
465
466// static
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800467ISoundTriggerHwCallback::RecognitionEvent* SoundTriggerHalImpl::convertRecognitionEventFromHal(
468 const struct sound_trigger_recognition_event* halEvent) {
469 ISoundTriggerHwCallback::RecognitionEvent* event;
Eric Laurent27ef4d82016-10-14 15:46:06 -0700470
471 if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800472 const struct sound_trigger_phrase_recognition_event* halPhraseEvent =
473 reinterpret_cast<const struct sound_trigger_phrase_recognition_event*>(halEvent);
474 ISoundTriggerHwCallback::PhraseRecognitionEvent* phraseEvent =
475 new ISoundTriggerHwCallback::PhraseRecognitionEvent();
Eric Laurent27ef4d82016-10-14 15:46:06 -0700476
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800477 PhraseRecognitionExtra* phraseExtras =
478 new PhraseRecognitionExtra[halPhraseEvent->num_phrases];
Eric Laurent27ef4d82016-10-14 15:46:06 -0700479 for (unsigned int i = 0; i < halPhraseEvent->num_phrases; i++) {
480 convertPhraseRecognitionExtraFromHal(&phraseExtras[i],
481 &halPhraseEvent->phrase_extras[i]);
482 }
483 phraseEvent->phraseExtras.setToExternal(phraseExtras, halPhraseEvent->num_phrases);
484 // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
485 phraseEvent->phraseExtras.resize(halPhraseEvent->num_phrases);
486 delete[] phraseExtras;
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800487 event = reinterpret_cast<ISoundTriggerHwCallback::RecognitionEvent*>(phraseEvent);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700488 } else {
489 event = new ISoundTriggerHwCallback::RecognitionEvent();
490 }
491
492 event->status = static_cast<ISoundTriggerHwCallback::RecognitionStatus>(halEvent->status);
493 event->type = static_cast<SoundModelType>(halEvent->type);
494 // event->model to be remapped by called
495 event->captureAvailable = halEvent->capture_available;
496 event->captureSession = halEvent->capture_session;
497 event->captureDelayMs = halEvent->capture_delay_ms;
498 event->capturePreambleMs = halEvent->capture_preamble_ms;
499 event->triggerInData = halEvent->trigger_in_data;
500 event->audioConfig.sampleRateHz = halEvent->audio_config.sample_rate;
501 event->audioConfig.channelMask =
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800502 (audio::common::V2_0::AudioChannelMask)halEvent->audio_config.channel_mask;
Eric Laurent27ef4d82016-10-14 15:46:06 -0700503 event->audioConfig.format = (audio::common::V2_0::AudioFormat)halEvent->audio_config.format;
504 event->data.setToExternal(
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800505 const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset,
506 halEvent->data_size);
Eric Laurent27ef4d82016-10-14 15:46:06 -0700507
508 return event;
509}
510
511// static
512void SoundTriggerHalImpl::convertPhraseRecognitionExtraFromHal(
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800513 PhraseRecognitionExtra* extra, const struct sound_trigger_phrase_recognition_extra* halExtra) {
Eric Laurent27ef4d82016-10-14 15:46:06 -0700514 extra->id = halExtra->id;
515 extra->recognitionModes = halExtra->recognition_modes;
516 extra->confidenceLevel = halExtra->confidence_level;
517
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800518 ConfidenceLevel* levels = new ConfidenceLevel[halExtra->num_levels];
Eric Laurent27ef4d82016-10-14 15:46:06 -0700519 for (unsigned int i = 0; i < halExtra->num_levels; i++) {
520 levels[i].userId = halExtra->levels[i].user_id;
521 levels[i].levelPercent = halExtra->levels[i].level;
522 }
523 extra->levels.setToExternal(levels, halExtra->num_levels);
524 // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
525 extra->levels.resize(halExtra->num_levels);
526 delete[] levels;
527}
528
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800529ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* /* name */) {
Mikhail Naganov3acaa662017-04-13 11:00:11 -0700530 return new SoundTriggerHalImpl();
Eric Laurent27ef4d82016-10-14 15:46:06 -0700531}
Mikhail Naganov0bbc4aa2017-12-22 13:23:08 -0800532} // namespace implementation
Eric Laurent27ef4d82016-10-14 15:46:06 -0700533} // namespace V2_0
534} // namespace soundtrigger
535} // namespace hardware
536} // namespace android