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