Home | History | Annotate | Download | only in default
      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 "SoundTriggerHalImpl"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include "SoundTriggerHalImpl.h"
     21 #include <android/log.h>
     22 
     23 namespace android {
     24 namespace hardware {
     25 namespace soundtrigger {
     26 namespace V2_0 {
     27 namespace implementation {
     28 
     29 // static
     30 void SoundTriggerHalImpl::soundModelCallback(struct sound_trigger_model_event* halEvent,
     31                                              void* cookie) {
     32     if (halEvent == NULL) {
     33         ALOGW("soundModelCallback called with NULL event");
     34         return;
     35     }
     36     sp<SoundModelClient> client =
     37         wp<SoundModelClient>(static_cast<SoundModelClient*>(cookie)).promote();
     38     if (client == 0) {
     39         ALOGW("soundModelCallback called on stale client");
     40         return;
     41     }
     42     if (halEvent->model != client->getHalHandle()) {
     43         ALOGW("soundModelCallback call with wrong handle %d on client with handle %d",
     44               (int)halEvent->model, (int)client->getHalHandle());
     45         return;
     46     }
     47 
     48     client->soundModelCallback(halEvent);
     49 }
     50 
     51 // static
     52 void SoundTriggerHalImpl::recognitionCallback(struct sound_trigger_recognition_event* halEvent,
     53                                               void* cookie) {
     54     if (halEvent == NULL) {
     55         ALOGW("recognitionCallback call NULL event");
     56         return;
     57     }
     58     sp<SoundModelClient> client =
     59         wp<SoundModelClient>(static_cast<SoundModelClient*>(cookie)).promote();
     60     if (client == 0) {
     61         ALOGW("soundModelCallback called on stale client");
     62         return;
     63     }
     64 
     65     client->recognitionCallback(halEvent);
     66 }
     67 
     68 Return<void> SoundTriggerHalImpl::getProperties(ISoundTriggerHw::getProperties_cb _hidl_cb) {
     69     ALOGV("getProperties() mHwDevice %p", mHwDevice);
     70     int ret;
     71     struct sound_trigger_properties halProperties;
     72     ISoundTriggerHw::Properties properties;
     73 
     74     if (mHwDevice == NULL) {
     75         ret = -ENODEV;
     76         goto exit;
     77     }
     78 
     79     ret = mHwDevice->get_properties(mHwDevice, &halProperties);
     80 
     81     convertPropertiesFromHal(&properties, &halProperties);
     82 
     83     ALOGV("getProperties implementor %s recognitionModes %08x", properties.implementor.c_str(),
     84           properties.recognitionModes);
     85 
     86 exit:
     87     _hidl_cb(ret, properties);
     88     return Void();
     89 }
     90 
     91 int SoundTriggerHalImpl::doLoadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
     92                                           sp<SoundModelClient> client) {
     93     int32_t ret = 0;
     94     struct sound_trigger_sound_model* halSoundModel;
     95 
     96     ALOGV("doLoadSoundModel() data size %zu", soundModel.data.size());
     97 
     98     if (mHwDevice == NULL) {
     99         ret = -ENODEV;
    100         goto exit;
    101     }
    102 
    103     halSoundModel = convertSoundModelToHal(&soundModel);
    104     if (halSoundModel == NULL) {
    105         ret = -EINVAL;
    106         goto exit;
    107     }
    108 
    109     sound_model_handle_t halHandle;
    110     ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, soundModelCallback, client.get(),
    111                                       &halHandle);
    112 
    113     free(halSoundModel);
    114 
    115     if (ret != 0) {
    116         goto exit;
    117     }
    118 
    119     client->setHalHandle(halHandle);
    120     {
    121         AutoMutex lock(mLock);
    122         mClients.add(client->getId(), client);
    123     }
    124 
    125 exit:
    126     return ret;
    127 }
    128 
    129 Return<void> SoundTriggerHalImpl::loadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
    130                                                  const sp<ISoundTriggerHwCallback>& callback,
    131                                                  ISoundTriggerHwCallback::CallbackCookie cookie,
    132                                                  ISoundTriggerHw::loadSoundModel_cb _hidl_cb) {
    133     sp<SoundModelClient> client = new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
    134     _hidl_cb(doLoadSoundModel(soundModel, client), client->getId());
    135     return Void();
    136 }
    137 
    138 Return<void> SoundTriggerHalImpl::loadPhraseSoundModel(
    139     const ISoundTriggerHw::PhraseSoundModel& soundModel,
    140     const sp<ISoundTriggerHwCallback>& callback, ISoundTriggerHwCallback::CallbackCookie cookie,
    141     ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb) {
    142     sp<SoundModelClient> client = new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
    143     _hidl_cb(doLoadSoundModel((const ISoundTriggerHw::SoundModel&)soundModel, client),
    144              client->getId());
    145     return Void();
    146 }
    147 
    148 Return<int32_t> SoundTriggerHalImpl::unloadSoundModel(SoundModelHandle modelHandle) {
    149     int32_t ret;
    150     sp<SoundModelClient> client;
    151 
    152     if (mHwDevice == NULL) {
    153         ret = -ENODEV;
    154         goto exit;
    155     }
    156 
    157     {
    158         AutoMutex lock(mLock);
    159         client = mClients.valueFor(modelHandle);
    160         if (client == 0) {
    161             ret = -ENOSYS;
    162             goto exit;
    163         }
    164     }
    165 
    166     ret = mHwDevice->unload_sound_model(mHwDevice, client->getHalHandle());
    167 
    168     mClients.removeItem(modelHandle);
    169 
    170 exit:
    171     return ret;
    172 }
    173 
    174 Return<int32_t> SoundTriggerHalImpl::startRecognition(
    175     SoundModelHandle modelHandle, const ISoundTriggerHw::RecognitionConfig& config) {
    176     int32_t ret;
    177     sp<SoundModelClient> client;
    178     struct sound_trigger_recognition_config* halConfig;
    179 
    180     if (mHwDevice == NULL) {
    181         ret = -ENODEV;
    182         goto exit;
    183     }
    184 
    185     {
    186         AutoMutex lock(mLock);
    187         client = mClients.valueFor(modelHandle);
    188         if (client == 0) {
    189             ret = -ENOSYS;
    190             goto exit;
    191         }
    192     }
    193 
    194     halConfig = convertRecognitionConfigToHal(&config);
    195 
    196     if (halConfig == NULL) {
    197         ret = -EINVAL;
    198         goto exit;
    199     }
    200     ret = mHwDevice->start_recognition(mHwDevice, client->getHalHandle(), halConfig,
    201                                        recognitionCallback, client.get());
    202 
    203     free(halConfig);
    204 
    205 exit:
    206     return ret;
    207 }
    208 
    209 Return<int32_t> SoundTriggerHalImpl::stopRecognition(SoundModelHandle modelHandle) {
    210     int32_t ret;
    211     sp<SoundModelClient> client;
    212     if (mHwDevice == NULL) {
    213         ret = -ENODEV;
    214         goto exit;
    215     }
    216 
    217     {
    218         AutoMutex lock(mLock);
    219         client = mClients.valueFor(modelHandle);
    220         if (client == 0) {
    221             ret = -ENOSYS;
    222             goto exit;
    223         }
    224     }
    225 
    226     ret = mHwDevice->stop_recognition(mHwDevice, client->getHalHandle());
    227 
    228 exit:
    229     return ret;
    230 }
    231 
    232 Return<int32_t> SoundTriggerHalImpl::stopAllRecognitions() {
    233     int32_t ret;
    234     if (mHwDevice == NULL) {
    235         ret = -ENODEV;
    236         goto exit;
    237     }
    238 
    239     if (mHwDevice->common.version >= SOUND_TRIGGER_DEVICE_API_VERSION_1_1 &&
    240         mHwDevice->stop_all_recognitions) {
    241         ret = mHwDevice->stop_all_recognitions(mHwDevice);
    242     } else {
    243         ret = -ENOSYS;
    244     }
    245 exit:
    246     return ret;
    247 }
    248 
    249 SoundTriggerHalImpl::SoundTriggerHalImpl()
    250     : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {}
    251 
    252 void SoundTriggerHalImpl::onFirstRef() {
    253     const hw_module_t* mod;
    254     int rc;
    255 
    256     rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, &mod);
    257     if (rc != 0) {
    258         ALOGE("couldn't load sound trigger module %s.%s (%s)", SOUND_TRIGGER_HARDWARE_MODULE_ID,
    259               mModuleName, strerror(-rc));
    260         return;
    261     }
    262     rc = sound_trigger_hw_device_open(mod, &mHwDevice);
    263     if (rc != 0) {
    264         ALOGE("couldn't open sound trigger hw device in %s.%s (%s)",
    265               SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, strerror(-rc));
    266         mHwDevice = NULL;
    267         return;
    268     }
    269     if (mHwDevice->common.version < SOUND_TRIGGER_DEVICE_API_VERSION_1_0 ||
    270         mHwDevice->common.version > SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
    271         ALOGE("wrong sound trigger hw device version %04x", mHwDevice->common.version);
    272         sound_trigger_hw_device_close(mHwDevice);
    273         mHwDevice = NULL;
    274         return;
    275     }
    276 
    277     ALOGI("onFirstRef() mModuleName %s mHwDevice %p", mModuleName, mHwDevice);
    278 }
    279 
    280 SoundTriggerHalImpl::~SoundTriggerHalImpl() {
    281     if (mHwDevice != NULL) {
    282         sound_trigger_hw_device_close(mHwDevice);
    283     }
    284 }
    285 
    286 uint32_t SoundTriggerHalImpl::nextUniqueModelId() {
    287     uint32_t modelId = 0;
    288     {
    289         AutoMutex lock(mLock);
    290         do {
    291             modelId =
    292                 atomic_fetch_add_explicit(&mNextModelId, (uint_fast32_t)1, memory_order_acq_rel);
    293         } while (mClients.valueFor(modelId) != 0 && modelId != 0);
    294     }
    295     LOG_ALWAYS_FATAL_IF(modelId == 0, "wrap around in sound model IDs, num loaded models %zu",
    296                         mClients.size());
    297     return modelId;
    298 }
    299 
    300 void SoundTriggerHalImpl::convertUuidFromHal(Uuid* uuid, const sound_trigger_uuid_t* halUuid) {
    301     uuid->timeLow = halUuid->timeLow;
    302     uuid->timeMid = halUuid->timeMid;
    303     uuid->versionAndTimeHigh = halUuid->timeHiAndVersion;
    304     uuid->variantAndClockSeqHigh = halUuid->clockSeq;
    305     memcpy(&uuid->node[0], &halUuid->node[0], 6);
    306 }
    307 
    308 void SoundTriggerHalImpl::convertUuidToHal(sound_trigger_uuid_t* halUuid, const Uuid* uuid) {
    309     halUuid->timeLow = uuid->timeLow;
    310     halUuid->timeMid = uuid->timeMid;
    311     halUuid->timeHiAndVersion = uuid->versionAndTimeHigh;
    312     halUuid->clockSeq = uuid->variantAndClockSeqHigh;
    313     memcpy(&halUuid->node[0], &uuid->node[0], 6);
    314 }
    315 
    316 void SoundTriggerHalImpl::convertPropertiesFromHal(
    317     ISoundTriggerHw::Properties* properties, const struct sound_trigger_properties* halProperties) {
    318     properties->implementor = halProperties->implementor;
    319     properties->description = halProperties->description;
    320     properties->version = halProperties->version;
    321     convertUuidFromHal(&properties->uuid, &halProperties->uuid);
    322     properties->maxSoundModels = halProperties->max_sound_models;
    323     properties->maxKeyPhrases = halProperties->max_key_phrases;
    324     properties->maxUsers = halProperties->max_users;
    325     properties->recognitionModes = halProperties->recognition_modes;
    326     properties->captureTransition = halProperties->capture_transition;
    327     properties->maxBufferMs = halProperties->max_buffer_ms;
    328     properties->concurrentCapture = halProperties->concurrent_capture;
    329     properties->triggerInEvent = halProperties->trigger_in_event;
    330     properties->powerConsumptionMw = halProperties->power_consumption_mw;
    331 }
    332 
    333 void SoundTriggerHalImpl::convertTriggerPhraseToHal(struct sound_trigger_phrase* halTriggerPhrase,
    334                                                     const ISoundTriggerHw::Phrase* triggerPhrase) {
    335     halTriggerPhrase->id = triggerPhrase->id;
    336     halTriggerPhrase->recognition_mode = triggerPhrase->recognitionModes;
    337     unsigned int i;
    338 
    339     halTriggerPhrase->num_users =
    340         std::min((int)triggerPhrase->users.size(), SOUND_TRIGGER_MAX_USERS);
    341     for (i = 0; i < halTriggerPhrase->num_users; i++) {
    342         halTriggerPhrase->users[i] = triggerPhrase->users[i];
    343     }
    344 
    345     strlcpy(halTriggerPhrase->locale, triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN);
    346     strlcpy(halTriggerPhrase->text, triggerPhrase->text.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
    347 }
    348 
    349 struct sound_trigger_sound_model* SoundTriggerHalImpl::convertSoundModelToHal(
    350     const ISoundTriggerHw::SoundModel* soundModel) {
    351     struct sound_trigger_sound_model* halModel = NULL;
    352     if (soundModel->type == SoundModelType::KEYPHRASE) {
    353         size_t allocSize =
    354             sizeof(struct sound_trigger_phrase_sound_model) + soundModel->data.size();
    355         struct sound_trigger_phrase_sound_model* halKeyPhraseModel =
    356             static_cast<struct sound_trigger_phrase_sound_model*>(malloc(allocSize));
    357         LOG_ALWAYS_FATAL_IF(halKeyPhraseModel == NULL,
    358                             "malloc failed for size %zu in convertSoundModelToHal PHRASE",
    359                             allocSize);
    360 
    361         const ISoundTriggerHw::PhraseSoundModel* keyPhraseModel =
    362             reinterpret_cast<const ISoundTriggerHw::PhraseSoundModel*>(soundModel);
    363 
    364         size_t i;
    365         for (i = 0; i < keyPhraseModel->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
    366             convertTriggerPhraseToHal(&halKeyPhraseModel->phrases[i], &keyPhraseModel->phrases[i]);
    367         }
    368         halKeyPhraseModel->num_phrases = (unsigned int)i;
    369         halModel = reinterpret_cast<struct sound_trigger_sound_model*>(halKeyPhraseModel);
    370         halModel->data_offset = sizeof(struct sound_trigger_phrase_sound_model);
    371     } else {
    372         size_t allocSize = sizeof(struct sound_trigger_sound_model) + soundModel->data.size();
    373         halModel = static_cast<struct sound_trigger_sound_model*>(malloc(allocSize));
    374         LOG_ALWAYS_FATAL_IF(halModel == NULL,
    375                             "malloc failed for size %zu in convertSoundModelToHal GENERIC",
    376                             allocSize);
    377 
    378         halModel->data_offset = sizeof(struct sound_trigger_sound_model);
    379     }
    380     halModel->type = (sound_trigger_sound_model_type_t)soundModel->type;
    381     convertUuidToHal(&halModel->uuid, &soundModel->uuid);
    382     convertUuidToHal(&halModel->vendor_uuid, &soundModel->vendorUuid);
    383     halModel->data_size = soundModel->data.size();
    384     uint8_t* dst = reinterpret_cast<uint8_t*>(halModel) + halModel->data_offset;
    385     const uint8_t* src = reinterpret_cast<const uint8_t*>(&soundModel->data[0]);
    386     memcpy(dst, src, soundModel->data.size());
    387 
    388     return halModel;
    389 }
    390 
    391 void SoundTriggerHalImpl::convertPhraseRecognitionExtraToHal(
    392     struct sound_trigger_phrase_recognition_extra* halExtra, const PhraseRecognitionExtra* extra) {
    393     halExtra->id = extra->id;
    394     halExtra->recognition_modes = extra->recognitionModes;
    395     halExtra->confidence_level = extra->confidenceLevel;
    396 
    397     unsigned int i;
    398     for (i = 0; i < extra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) {
    399         halExtra->levels[i].user_id = extra->levels[i].userId;
    400         halExtra->levels[i].level = extra->levels[i].levelPercent;
    401     }
    402     halExtra->num_levels = i;
    403 }
    404 
    405 struct sound_trigger_recognition_config* SoundTriggerHalImpl::convertRecognitionConfigToHal(
    406     const ISoundTriggerHw::RecognitionConfig* config) {
    407     size_t allocSize = sizeof(struct sound_trigger_recognition_config) + config->data.size();
    408     struct sound_trigger_recognition_config* halConfig =
    409         static_cast<struct sound_trigger_recognition_config*>(malloc(allocSize));
    410 
    411     LOG_ALWAYS_FATAL_IF(halConfig == NULL,
    412                         "malloc failed for size %zu in convertRecognitionConfigToHal", allocSize);
    413 
    414     halConfig->capture_handle = (audio_io_handle_t)config->captureHandle;
    415     halConfig->capture_device = (audio_devices_t)config->captureDevice;
    416     halConfig->capture_requested = config->captureRequested;
    417 
    418     unsigned int i;
    419     for (i = 0; i < config->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
    420         convertPhraseRecognitionExtraToHal(&halConfig->phrases[i], &config->phrases[i]);
    421     }
    422     halConfig->num_phrases = i;
    423 
    424     halConfig->data_offset = sizeof(struct sound_trigger_recognition_config);
    425     halConfig->data_size = config->data.size();
    426     uint8_t* dst = reinterpret_cast<uint8_t*>(halConfig) + halConfig->data_offset;
    427     const uint8_t* src = reinterpret_cast<const uint8_t*>(&config->data[0]);
    428     memcpy(dst, src, config->data.size());
    429     return halConfig;
    430 }
    431 
    432 // static
    433 void SoundTriggerHalImpl::convertSoundModelEventFromHal(
    434     ISoundTriggerHwCallback::ModelEvent* event, const struct sound_trigger_model_event* halEvent) {
    435     event->status = (ISoundTriggerHwCallback::SoundModelStatus)halEvent->status;
    436     // event->model to be remapped by called
    437     event->data.setToExternal(
    438         const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset,
    439         halEvent->data_size);
    440 }
    441 
    442 // static
    443 void SoundTriggerHalImpl::convertPhaseRecognitionEventFromHal(
    444     ISoundTriggerHwCallback::PhraseRecognitionEvent* event,
    445     const struct sound_trigger_phrase_recognition_event* halEvent) {
    446     event->phraseExtras.resize(halEvent->num_phrases);
    447     for (unsigned int i = 0; i < halEvent->num_phrases; i++) {
    448         convertPhraseRecognitionExtraFromHal(&event->phraseExtras[i], &halEvent->phrase_extras[i]);
    449     }
    450     convertRecognitionEventFromHal(&event->common, &halEvent->common);
    451 }
    452 
    453 // static
    454 void SoundTriggerHalImpl::convertRecognitionEventFromHal(
    455     ISoundTriggerHwCallback::RecognitionEvent* event,
    456     const struct sound_trigger_recognition_event* halEvent) {
    457     event->status = static_cast<ISoundTriggerHwCallback::RecognitionStatus>(halEvent->status);
    458     event->type = static_cast<SoundModelType>(halEvent->type);
    459     // event->model to be remapped by called
    460     event->captureAvailable = halEvent->capture_available;
    461     event->captureSession = halEvent->capture_session;
    462     event->captureDelayMs = halEvent->capture_delay_ms;
    463     event->capturePreambleMs = halEvent->capture_preamble_ms;
    464     event->triggerInData = halEvent->trigger_in_data;
    465     event->audioConfig.sampleRateHz = halEvent->audio_config.sample_rate;
    466     event->audioConfig.channelMask =
    467         (audio::common::V2_0::AudioChannelMask)halEvent->audio_config.channel_mask;
    468     event->audioConfig.format = (audio::common::V2_0::AudioFormat)halEvent->audio_config.format;
    469     event->data.setToExternal(
    470         const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset,
    471         halEvent->data_size);
    472 }
    473 
    474 // static
    475 void SoundTriggerHalImpl::convertPhraseRecognitionExtraFromHal(
    476     PhraseRecognitionExtra* extra, const struct sound_trigger_phrase_recognition_extra* halExtra) {
    477     extra->id = halExtra->id;
    478     extra->recognitionModes = halExtra->recognition_modes;
    479     extra->confidenceLevel = halExtra->confidence_level;
    480 
    481     extra->levels.resize(halExtra->num_levels);
    482     for (unsigned int i = 0; i < halExtra->num_levels; i++) {
    483         extra->levels[i].userId = halExtra->levels[i].user_id;
    484         extra->levels[i].levelPercent = halExtra->levels[i].level;
    485     }
    486 }
    487 
    488 void SoundTriggerHalImpl::SoundModelClient_2_0::recognitionCallback(
    489     struct sound_trigger_recognition_event* halEvent) {
    490     if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
    491         ISoundTriggerHwCallback::PhraseRecognitionEvent event;
    492         convertPhaseRecognitionEventFromHal(
    493             &event, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent));
    494         event.common.model = mId;
    495         mCallback->phraseRecognitionCallback(event, mCookie);
    496     } else {
    497         ISoundTriggerHwCallback::RecognitionEvent event;
    498         convertRecognitionEventFromHal(&event, halEvent);
    499         event.model = mId;
    500         mCallback->recognitionCallback(event, mCookie);
    501     }
    502 }
    503 
    504 void SoundTriggerHalImpl::SoundModelClient_2_0::soundModelCallback(
    505     struct sound_trigger_model_event* halEvent) {
    506     ISoundTriggerHwCallback::ModelEvent event;
    507     convertSoundModelEventFromHal(&event, halEvent);
    508     event.model = mId;
    509     mCallback->soundModelCallback(event, mCookie);
    510 }
    511 
    512 }  // namespace implementation
    513 }  // namespace V2_0
    514 }  // namespace soundtrigger
    515 }  // namespace hardware
    516 }  // namespace android
    517