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