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