Home | History | Annotate | Download | only in default
      1 /*
      2  * Copyright (C) 2018 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 "SoundTriggerHw"
     18 
     19 #include "SoundTriggerHw.h"
     20 
     21 #include <android/hidl/allocator/1.0/IAllocator.h>
     22 #include <android/log.h>
     23 #include <hidlmemory/mapping.h>
     24 #include <utility>
     25 
     26 using android::hardware::hidl_memory;
     27 using android::hidl::allocator::V1_0::IAllocator;
     28 using android::hidl::memory::V1_0::IMemory;
     29 
     30 namespace android {
     31 namespace hardware {
     32 namespace soundtrigger {
     33 namespace V2_2 {
     34 namespace implementation {
     35 
     36 /**
     37  * According to the HIDL C++ Users Guide: client and server implementations
     38  * should never directly refer to anything other than the interface header
     39  * generated from the HIDL definition file (ie. ISoundTriggerHw.hal), so
     40  * this V2_2 implementation copies the V2_0 and V2_1 implementations and
     41  * then adds the new V2_2 implementation.
     42  */
     43 
     44 // Begin V2_0 implementation, copied from
     45 // hardware/interfaces/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
     46 
     47 // static
     48 void soundModelCallback_(struct sound_trigger_model_event* halEvent, void* cookie) {
     49     if (halEvent == NULL) {
     50         ALOGW("soundModelCallback called with NULL event");
     51         return;
     52     }
     53     sp<SoundTriggerHw::SoundModelClient> client =
     54         wp<SoundTriggerHw::SoundModelClient>(static_cast<SoundTriggerHw::SoundModelClient*>(cookie))
     55             .promote();
     56     if (client == 0) {
     57         ALOGW("soundModelCallback called on stale client");
     58         return;
     59     }
     60     if (halEvent->model != client->getHalHandle()) {
     61         ALOGW("soundModelCallback call with wrong handle %d on client with handle %d",
     62               (int)halEvent->model, (int)client->getHalHandle());
     63         return;
     64     }
     65 
     66     client->soundModelCallback(halEvent);
     67 }
     68 
     69 // static
     70 void recognitionCallback_(struct sound_trigger_recognition_event* halEvent, void* cookie) {
     71     if (halEvent == NULL) {
     72         ALOGW("recognitionCallback call NULL event");
     73         return;
     74     }
     75     sp<SoundTriggerHw::SoundModelClient> client =
     76         wp<SoundTriggerHw::SoundModelClient>(static_cast<SoundTriggerHw::SoundModelClient*>(cookie))
     77             .promote();
     78     if (client == 0) {
     79         ALOGW("recognitionCallback called on stale client");
     80         return;
     81     }
     82 
     83     client->recognitionCallback(halEvent);
     84 }
     85 
     86 Return<void> SoundTriggerHw::getProperties(ISoundTriggerHw::getProperties_cb _hidl_cb) {
     87     ALOGV("getProperties() mHwDevice %p", mHwDevice);
     88     int ret;
     89     struct sound_trigger_properties halProperties;
     90     ISoundTriggerHw::Properties properties;
     91 
     92     if (mHwDevice == NULL) {
     93         ret = -ENODEV;
     94         goto exit;
     95     }
     96 
     97     ret = mHwDevice->get_properties(mHwDevice, &halProperties);
     98 
     99     convertPropertiesFromHal(&properties, &halProperties);
    100 
    101     ALOGV("getProperties implementor %s recognitionModes %08x", properties.implementor.c_str(),
    102           properties.recognitionModes);
    103 
    104 exit:
    105     _hidl_cb(ret, properties);
    106     return Void();
    107 }
    108 
    109 int SoundTriggerHw::doLoadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel,
    110                                      sp<SoundTriggerHw::SoundModelClient> client) {
    111     int32_t ret = 0;
    112     struct sound_trigger_sound_model* halSoundModel;
    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     sound_model_handle_t halHandle;
    128     ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, soundModelCallback_, client.get(),
    129                                       &halHandle);
    130 
    131     free(halSoundModel);
    132 
    133     if (ret != 0) {
    134         goto exit;
    135     }
    136 
    137     client->setHalHandle(halHandle);
    138     {
    139         AutoMutex lock(mLock);
    140         mClients.add(client->getId(), client);
    141     }
    142 
    143 exit:
    144     return ret;
    145 }
    146 
    147 Return<void> SoundTriggerHw::loadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel,
    148                                             const sp<V2_0::ISoundTriggerHwCallback>& callback,
    149                                             V2_0::ISoundTriggerHwCallback::CallbackCookie cookie,
    150                                             ISoundTriggerHw::loadSoundModel_cb _hidl_cb) {
    151     sp<SoundTriggerHw::SoundModelClient> client =
    152         new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
    153     _hidl_cb(doLoadSoundModel(soundModel, client), client->getId());
    154     return Void();
    155 }
    156 
    157 Return<void> SoundTriggerHw::loadPhraseSoundModel(
    158     const V2_0::ISoundTriggerHw::PhraseSoundModel& soundModel,
    159     const sp<V2_0::ISoundTriggerHwCallback>& callback,
    160     V2_0::ISoundTriggerHwCallback::CallbackCookie cookie,
    161     ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb) {
    162     sp<SoundTriggerHw::SoundModelClient> client =
    163         new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
    164     _hidl_cb(doLoadSoundModel((const V2_0::ISoundTriggerHw::SoundModel&)soundModel, client),
    165              client->getId());
    166     return Void();
    167 }
    168 
    169 Return<int32_t> SoundTriggerHw::unloadSoundModel(int32_t modelHandle) {
    170     int32_t ret;
    171     sp<SoundTriggerHw::SoundModelClient> client;
    172 
    173     if (mHwDevice == NULL) {
    174         ret = -ENODEV;
    175         goto exit;
    176     }
    177 
    178     {
    179         AutoMutex lock(mLock);
    180         client = mClients.valueFor(modelHandle);
    181         if (client == 0) {
    182             ret = -ENOSYS;
    183             goto exit;
    184         }
    185     }
    186 
    187     ret = mHwDevice->unload_sound_model(mHwDevice, client->getHalHandle());
    188 
    189     mClients.removeItem(modelHandle);
    190 
    191 exit:
    192     return ret;
    193 }
    194 
    195 Return<int32_t> SoundTriggerHw::startRecognition(
    196     int32_t modelHandle, const V2_0::ISoundTriggerHw::RecognitionConfig& config,
    197     const sp<V2_0::ISoundTriggerHwCallback>& /* callback */, int32_t /* cookie */) {
    198     int32_t ret;
    199     sp<SoundTriggerHw::SoundModelClient> client;
    200     struct sound_trigger_recognition_config* halConfig;
    201 
    202     if (mHwDevice == NULL) {
    203         ret = -ENODEV;
    204         goto exit;
    205     }
    206 
    207     {
    208         AutoMutex lock(mLock);
    209         client = mClients.valueFor(modelHandle);
    210         if (client == 0) {
    211             ret = -ENOSYS;
    212             goto exit;
    213         }
    214     }
    215 
    216     halConfig =
    217         convertRecognitionConfigToHal((const V2_0::ISoundTriggerHw::RecognitionConfig*)&config);
    218 
    219     if (halConfig == NULL) {
    220         ret = -EINVAL;
    221         goto exit;
    222     }
    223     ret = mHwDevice->start_recognition(mHwDevice, client->getHalHandle(), halConfig,
    224                                        recognitionCallback_, client.get());
    225 
    226     free(halConfig);
    227 
    228 exit:
    229     return ret;
    230 }
    231 
    232 Return<int32_t> SoundTriggerHw::stopRecognition(int32_t modelHandle) {
    233     int32_t ret;
    234     sp<SoundTriggerHw::SoundModelClient> client;
    235     if (mHwDevice == NULL) {
    236         ret = -ENODEV;
    237         goto exit;
    238     }
    239 
    240     {
    241         AutoMutex lock(mLock);
    242         client = mClients.valueFor(modelHandle);
    243         if (client == 0) {
    244             ret = -ENOSYS;
    245             goto exit;
    246         }
    247     }
    248 
    249     ret = mHwDevice->stop_recognition(mHwDevice, client->getHalHandle());
    250 
    251 exit:
    252     return ret;
    253 }
    254 
    255 Return<int32_t> SoundTriggerHw::stopAllRecognitions() {
    256     int32_t ret;
    257     if (mHwDevice == NULL) {
    258         ret = -ENODEV;
    259         goto exit;
    260     }
    261 
    262     if (mHwDevice->common.version >= SOUND_TRIGGER_DEVICE_API_VERSION_1_1 &&
    263         mHwDevice->stop_all_recognitions) {
    264         ret = mHwDevice->stop_all_recognitions(mHwDevice);
    265     } else {
    266         ret = -ENOSYS;
    267     }
    268 exit:
    269     return ret;
    270 }
    271 
    272 SoundTriggerHw::SoundTriggerHw() : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {}
    273 
    274 void SoundTriggerHw::onFirstRef() {
    275     const hw_module_t* mod;
    276     int rc;
    277 
    278     rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, &mod);
    279     if (rc != 0) {
    280         ALOGE("couldn't load sound trigger module %s.%s (%s)", SOUND_TRIGGER_HARDWARE_MODULE_ID,
    281               mModuleName, strerror(-rc));
    282         return;
    283     }
    284     rc = sound_trigger_hw_device_open(mod, &mHwDevice);
    285     if (rc != 0) {
    286         ALOGE("couldn't open sound trigger hw device in %s.%s (%s)",
    287               SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, strerror(-rc));
    288         mHwDevice = NULL;
    289         return;
    290     }
    291     if (mHwDevice->common.version < SOUND_TRIGGER_DEVICE_API_VERSION_1_0 ||
    292         mHwDevice->common.version > SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
    293         ALOGE("wrong sound trigger hw device version %04x", mHwDevice->common.version);
    294         sound_trigger_hw_device_close(mHwDevice);
    295         mHwDevice = NULL;
    296         return;
    297     }
    298 
    299     ALOGI("onFirstRef() mModuleName %s mHwDevice %p", mModuleName, mHwDevice);
    300 }
    301 
    302 SoundTriggerHw::~SoundTriggerHw() {
    303     if (mHwDevice != NULL) {
    304         sound_trigger_hw_device_close(mHwDevice);
    305     }
    306 }
    307 
    308 uint32_t SoundTriggerHw::nextUniqueModelId() {
    309     uint32_t modelId = 0;
    310     {
    311         AutoMutex lock(mLock);
    312         do {
    313             modelId =
    314                 atomic_fetch_add_explicit(&mNextModelId, (uint_fast32_t)1, memory_order_acq_rel);
    315         } while (mClients.valueFor(modelId) != 0 && modelId != 0);
    316     }
    317     LOG_ALWAYS_FATAL_IF(modelId == 0, "wrap around in sound model IDs, num loaded models %zu",
    318                         mClients.size());
    319     return modelId;
    320 }
    321 
    322 void SoundTriggerHw::convertUuidFromHal(Uuid* uuid, const sound_trigger_uuid_t* halUuid) {
    323     uuid->timeLow = halUuid->timeLow;
    324     uuid->timeMid = halUuid->timeMid;
    325     uuid->versionAndTimeHigh = halUuid->timeHiAndVersion;
    326     uuid->variantAndClockSeqHigh = halUuid->clockSeq;
    327     memcpy(&uuid->node[0], &halUuid->node[0], 6);
    328 }
    329 
    330 void SoundTriggerHw::convertUuidToHal(sound_trigger_uuid_t* halUuid, const Uuid* uuid) {
    331     halUuid->timeLow = uuid->timeLow;
    332     halUuid->timeMid = uuid->timeMid;
    333     halUuid->timeHiAndVersion = uuid->versionAndTimeHigh;
    334     halUuid->clockSeq = uuid->variantAndClockSeqHigh;
    335     memcpy(&halUuid->node[0], &uuid->node[0], 6);
    336 }
    337 
    338 void SoundTriggerHw::convertPropertiesFromHal(
    339     ISoundTriggerHw::Properties* properties, const struct sound_trigger_properties* halProperties) {
    340     properties->implementor = halProperties->implementor;
    341     properties->description = halProperties->description;
    342     properties->version = halProperties->version;
    343     convertUuidFromHal(&properties->uuid, &halProperties->uuid);
    344     properties->maxSoundModels = halProperties->max_sound_models;
    345     properties->maxKeyPhrases = halProperties->max_key_phrases;
    346     properties->maxUsers = halProperties->max_users;
    347     properties->recognitionModes = halProperties->recognition_modes;
    348     properties->captureTransition = halProperties->capture_transition;
    349     properties->maxBufferMs = halProperties->max_buffer_ms;
    350     properties->concurrentCapture = halProperties->concurrent_capture;
    351     properties->triggerInEvent = halProperties->trigger_in_event;
    352     properties->powerConsumptionMw = halProperties->power_consumption_mw;
    353 }
    354 
    355 void SoundTriggerHw::convertTriggerPhraseToHal(struct sound_trigger_phrase* halTriggerPhrase,
    356                                                const ISoundTriggerHw::Phrase* triggerPhrase) {
    357     halTriggerPhrase->id = triggerPhrase->id;
    358     halTriggerPhrase->recognition_mode = triggerPhrase->recognitionModes;
    359     unsigned int i;
    360 
    361     halTriggerPhrase->num_users =
    362         std::min((int)triggerPhrase->users.size(), SOUND_TRIGGER_MAX_USERS);
    363     for (i = 0; i < halTriggerPhrase->num_users; i++) {
    364         halTriggerPhrase->users[i] = triggerPhrase->users[i];
    365     }
    366 
    367     strlcpy(halTriggerPhrase->locale, triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN);
    368     strlcpy(halTriggerPhrase->text, triggerPhrase->text.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
    369 }
    370 
    371 struct sound_trigger_sound_model* SoundTriggerHw::convertSoundModelToHal(
    372     const V2_0::ISoundTriggerHw::SoundModel* soundModel) {
    373     struct sound_trigger_sound_model* halModel = NULL;
    374     if (soundModel->type == V2_0::SoundModelType::KEYPHRASE) {
    375         size_t allocSize =
    376             sizeof(struct sound_trigger_phrase_sound_model) + soundModel->data.size();
    377         struct sound_trigger_phrase_sound_model* halKeyPhraseModel =
    378             static_cast<struct sound_trigger_phrase_sound_model*>(malloc(allocSize));
    379         LOG_ALWAYS_FATAL_IF(halKeyPhraseModel == NULL,
    380                             "malloc failed for size %zu in convertSoundModelToHal PHRASE",
    381                             allocSize);
    382 
    383         const V2_0::ISoundTriggerHw::PhraseSoundModel* keyPhraseModel =
    384             reinterpret_cast<const V2_0::ISoundTriggerHw::PhraseSoundModel*>(soundModel);
    385 
    386         size_t i;
    387         for (i = 0; i < keyPhraseModel->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
    388             convertTriggerPhraseToHal(&halKeyPhraseModel->phrases[i], &keyPhraseModel->phrases[i]);
    389         }
    390         halKeyPhraseModel->num_phrases = (unsigned int)i;
    391         halModel = reinterpret_cast<struct sound_trigger_sound_model*>(halKeyPhraseModel);
    392         halModel->data_offset = sizeof(struct sound_trigger_phrase_sound_model);
    393     } else {
    394         size_t allocSize = sizeof(struct sound_trigger_sound_model) + soundModel->data.size();
    395         halModel = static_cast<struct sound_trigger_sound_model*>(malloc(allocSize));
    396         LOG_ALWAYS_FATAL_IF(halModel == NULL,
    397                             "malloc failed for size %zu in convertSoundModelToHal GENERIC",
    398                             allocSize);
    399 
    400         halModel->data_offset = sizeof(struct sound_trigger_sound_model);
    401     }
    402     halModel->type = (sound_trigger_sound_model_type_t)soundModel->type;
    403     convertUuidToHal(&halModel->uuid, &soundModel->uuid);
    404     convertUuidToHal(&halModel->vendor_uuid, &soundModel->vendorUuid);
    405     halModel->data_size = soundModel->data.size();
    406     uint8_t* dst = reinterpret_cast<uint8_t*>(halModel) + halModel->data_offset;
    407     const uint8_t* src = reinterpret_cast<const uint8_t*>(&soundModel->data[0]);
    408     memcpy(dst, src, soundModel->data.size());
    409 
    410     return halModel;
    411 }
    412 
    413 void SoundTriggerHw::convertPhraseRecognitionExtraToHal(
    414     struct sound_trigger_phrase_recognition_extra* halExtra,
    415     const V2_0::PhraseRecognitionExtra* extra) {
    416     halExtra->id = extra->id;
    417     halExtra->recognition_modes = extra->recognitionModes;
    418     halExtra->confidence_level = extra->confidenceLevel;
    419 
    420     unsigned int i;
    421     for (i = 0; i < extra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) {
    422         halExtra->levels[i].user_id = extra->levels[i].userId;
    423         halExtra->levels[i].level = extra->levels[i].levelPercent;
    424     }
    425     halExtra->num_levels = i;
    426 }
    427 
    428 struct sound_trigger_recognition_config* SoundTriggerHw::convertRecognitionConfigToHal(
    429     const V2_0::ISoundTriggerHw::RecognitionConfig* config) {
    430     size_t allocSize = sizeof(struct sound_trigger_recognition_config) + config->data.size();
    431     struct sound_trigger_recognition_config* halConfig =
    432         static_cast<struct sound_trigger_recognition_config*>(malloc(allocSize));
    433 
    434     LOG_ALWAYS_FATAL_IF(halConfig == NULL,
    435                         "malloc failed for size %zu in convertRecognitionConfigToHal", allocSize);
    436 
    437     halConfig->capture_handle = (audio_io_handle_t)config->captureHandle;
    438     halConfig->capture_device = (audio_devices_t)config->captureDevice;
    439     halConfig->capture_requested = config->captureRequested;
    440 
    441     unsigned int i;
    442     for (i = 0; i < config->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
    443         convertPhraseRecognitionExtraToHal(&halConfig->phrases[i], &config->phrases[i]);
    444     }
    445     halConfig->num_phrases = i;
    446 
    447     halConfig->data_offset = sizeof(struct sound_trigger_recognition_config);
    448     halConfig->data_size = config->data.size();
    449     uint8_t* dst = reinterpret_cast<uint8_t*>(halConfig) + halConfig->data_offset;
    450     const uint8_t* src = reinterpret_cast<const uint8_t*>(&config->data[0]);
    451     memcpy(dst, src, config->data.size());
    452     return halConfig;
    453 }
    454 
    455 // static
    456 void SoundTriggerHw::convertSoundModelEventFromHal(
    457     V2_0::ISoundTriggerHwCallback::ModelEvent* event,
    458     const struct sound_trigger_model_event* halEvent) {
    459     event->status = (V2_0::ISoundTriggerHwCallback::SoundModelStatus)halEvent->status;
    460     // event->model to be remapped by called
    461     event->data.setToExternal(
    462         const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset,
    463         halEvent->data_size);
    464 }
    465 
    466 // static
    467 void SoundTriggerHw::convertPhaseRecognitionEventFromHal(
    468     V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent* event,
    469     const struct sound_trigger_phrase_recognition_event* halEvent) {
    470     event->phraseExtras.resize(halEvent->num_phrases);
    471     for (unsigned int i = 0; i < halEvent->num_phrases; i++) {
    472         convertPhraseRecognitionExtraFromHal(&event->phraseExtras[i], &halEvent->phrase_extras[i]);
    473     }
    474     convertRecognitionEventFromHal(&event->common, &halEvent->common);
    475 }
    476 
    477 // static
    478 void SoundTriggerHw::convertRecognitionEventFromHal(
    479     V2_0::ISoundTriggerHwCallback::RecognitionEvent* event,
    480     const struct sound_trigger_recognition_event* halEvent) {
    481     event->status = static_cast<V2_0::ISoundTriggerHwCallback::RecognitionStatus>(halEvent->status);
    482     event->type = static_cast<V2_0::SoundModelType>(halEvent->type);
    483     // event->model to be remapped by called
    484     event->captureAvailable = halEvent->capture_available;
    485     event->captureSession = halEvent->capture_session;
    486     event->captureDelayMs = halEvent->capture_delay_ms;
    487     event->capturePreambleMs = halEvent->capture_preamble_ms;
    488     event->triggerInData = halEvent->trigger_in_data;
    489     event->audioConfig.sampleRateHz = halEvent->audio_config.sample_rate;
    490     event->audioConfig.channelMask =
    491         (audio::common::V2_0::AudioChannelMask)halEvent->audio_config.channel_mask;
    492     event->audioConfig.format = (audio::common::V2_0::AudioFormat)halEvent->audio_config.format;
    493     event->data.setToExternal(
    494         const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset,
    495         halEvent->data_size);
    496 }
    497 
    498 // static
    499 void SoundTriggerHw::convertPhraseRecognitionExtraFromHal(
    500     V2_0::PhraseRecognitionExtra* extra,
    501     const struct sound_trigger_phrase_recognition_extra* halExtra) {
    502     extra->id = halExtra->id;
    503     extra->recognitionModes = halExtra->recognition_modes;
    504     extra->confidenceLevel = halExtra->confidence_level;
    505 
    506     extra->levels.resize(halExtra->num_levels);
    507     for (unsigned int i = 0; i < halExtra->num_levels; i++) {
    508         extra->levels[i].userId = halExtra->levels[i].user_id;
    509         extra->levels[i].levelPercent = halExtra->levels[i].level;
    510     }
    511 }
    512 
    513 void SoundTriggerHw::SoundModelClient_2_0::recognitionCallback(
    514     struct sound_trigger_recognition_event* halEvent) {
    515     if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
    516         V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent event;
    517         convertPhaseRecognitionEventFromHal(
    518             &event, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent));
    519         event.common.model = mId;
    520         mCallback->phraseRecognitionCallback(event, mCookie);
    521     } else {
    522         V2_0::ISoundTriggerHwCallback::RecognitionEvent event;
    523         convertRecognitionEventFromHal(&event, halEvent);
    524         event.model = mId;
    525         mCallback->recognitionCallback(event, mCookie);
    526     }
    527 }
    528 
    529 void SoundTriggerHw::SoundModelClient_2_0::soundModelCallback(
    530     struct sound_trigger_model_event* halEvent) {
    531     V2_0::ISoundTriggerHwCallback::ModelEvent event;
    532     convertSoundModelEventFromHal(&event, halEvent);
    533     event.model = mId;
    534     mCallback->soundModelCallback(event, mCookie);
    535 }
    536 
    537 // Begin V2_1 implementation, copied from
    538 // hardware/interfaces/soundtrigger/2.1/default/SoundTriggerHw.cpp
    539 
    540 namespace {
    541 
    542 // Backs up by the vector with the contents of shared memory.
    543 // It is assumed that the passed hidl_vector is empty, so it's
    544 // not cleared if the memory is a null object.
    545 // The caller needs to keep the returned sp<IMemory> as long as
    546 // the data is needed.
    547 std::pair<bool, sp<IMemory>> memoryAsVector(const hidl_memory& m, hidl_vec<uint8_t>* vec) {
    548     sp<IMemory> memory;
    549     if (m.size() == 0) {
    550         return std::make_pair(true, memory);
    551     }
    552     memory = mapMemory(m);
    553     if (memory != nullptr) {
    554         memory->read();
    555         vec->setToExternal(static_cast<uint8_t*>(static_cast<void*>(memory->getPointer())),
    556                            memory->getSize());
    557         return std::make_pair(true, memory);
    558     }
    559     ALOGE("%s: Could not map HIDL memory to IMemory", __func__);
    560     return std::make_pair(false, memory);
    561 }
    562 
    563 // Moves the data from the vector into allocated shared memory,
    564 // emptying the vector.
    565 // It is assumed that the passed hidl_memory is a null object, so it's
    566 // not reset if the vector is empty.
    567 // The caller needs to keep the returned sp<IMemory> as long as
    568 // the data is needed.
    569 std::pair<bool, sp<IMemory>> moveVectorToMemory(hidl_vec<uint8_t>* v, hidl_memory* mem) {
    570     sp<IMemory> memory;
    571     if (v->size() == 0) {
    572         return std::make_pair(true, memory);
    573     }
    574     sp<IAllocator> ashmem = IAllocator::getService("ashmem");
    575     if (ashmem == 0) {
    576         ALOGE("Failed to retrieve ashmem allocator service");
    577         return std::make_pair(false, memory);
    578     }
    579     bool success = false;
    580     Return<void> r = ashmem->allocate(v->size(), [&](bool s, const hidl_memory& m) {
    581         success = s;
    582         if (success) *mem = m;
    583     });
    584     if (r.isOk() && success) {
    585         memory = hardware::mapMemory(*mem);
    586         if (memory != 0) {
    587             memory->update();
    588             memcpy(memory->getPointer(), v->data(), v->size());
    589             memory->commit();
    590             v->resize(0);
    591             return std::make_pair(true, memory);
    592         } else {
    593             ALOGE("Failed to map allocated ashmem");
    594         }
    595     } else {
    596         ALOGE("Failed to allocate %llu bytes from ashmem", (unsigned long long)v->size());
    597     }
    598     return std::make_pair(false, memory);
    599 }
    600 
    601 }  // namespace
    602 
    603 Return<void> SoundTriggerHw::loadSoundModel_2_1(
    604     const V2_1::ISoundTriggerHw::SoundModel& soundModel,
    605     const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
    606     V2_1::ISoundTriggerHw::loadSoundModel_2_1_cb _hidl_cb) {
    607     // It is assumed that legacy data vector is empty, thus making copy is cheap.
    608     V2_0::ISoundTriggerHw::SoundModel soundModel_2_0(soundModel.header);
    609     auto result = memoryAsVector(soundModel.data, &soundModel_2_0.data);
    610     if (result.first) {
    611         sp<SoundModelClient> client =
    612             new SoundModelClient_2_1(nextUniqueModelId(), cookie, callback);
    613         _hidl_cb(doLoadSoundModel(soundModel_2_0, client), client->getId());
    614         return Void();
    615     }
    616     _hidl_cb(-ENOMEM, 0);
    617     return Void();
    618 }
    619 
    620 Return<void> SoundTriggerHw::loadPhraseSoundModel_2_1(
    621     const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel,
    622     const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
    623     V2_1::ISoundTriggerHw::loadPhraseSoundModel_2_1_cb _hidl_cb) {
    624     V2_0::ISoundTriggerHw::PhraseSoundModel soundModel_2_0;
    625     // It is assumed that legacy data vector is empty, thus making copy is cheap.
    626     soundModel_2_0.common = soundModel.common.header;
    627     // Avoid copying phrases data.
    628     soundModel_2_0.phrases.setToExternal(
    629         const_cast<V2_0::ISoundTriggerHw::Phrase*>(soundModel.phrases.data()),
    630         soundModel.phrases.size());
    631     auto result = memoryAsVector(soundModel.common.data, &soundModel_2_0.common.data);
    632     if (result.first) {
    633         sp<SoundModelClient> client =
    634             new SoundModelClient_2_1(nextUniqueModelId(), cookie, callback);
    635         _hidl_cb(doLoadSoundModel((const V2_0::ISoundTriggerHw::SoundModel&)soundModel_2_0, client),
    636                  client->getId());
    637         return Void();
    638     }
    639     _hidl_cb(-ENOMEM, 0);
    640     return Void();
    641 }
    642 
    643 Return<int32_t> SoundTriggerHw::startRecognition_2_1(
    644     int32_t modelHandle, const V2_1::ISoundTriggerHw::RecognitionConfig& config,
    645     const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie) {
    646     // It is assumed that legacy data vector is empty, thus making copy is cheap.
    647     V2_0::ISoundTriggerHw::RecognitionConfig config_2_0(config.header);
    648     auto result = memoryAsVector(config.data, &config_2_0.data);
    649     return result.first ? startRecognition(modelHandle, config_2_0, callback, cookie)
    650                         : Return<int32_t>(-ENOMEM);
    651 }
    652 
    653 void SoundTriggerHw::SoundModelClient_2_1::recognitionCallback(
    654     struct sound_trigger_recognition_event* halEvent) {
    655     if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
    656         V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent event_2_0;
    657         convertPhaseRecognitionEventFromHal(
    658             &event_2_0, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent));
    659         event_2_0.common.model = mId;
    660         V2_1::ISoundTriggerHwCallback::PhraseRecognitionEvent event;
    661         event.phraseExtras.setToExternal(event_2_0.phraseExtras.data(),
    662                                          event_2_0.phraseExtras.size());
    663         auto result = moveVectorToMemory(&event_2_0.common.data, &event.common.data);
    664         if (result.first) {
    665             // The data vector is now empty, thus copying is cheap.
    666             event.common.header = event_2_0.common;
    667             mCallback->phraseRecognitionCallback_2_1(event, mCookie);
    668         }
    669     } else {
    670         V2_1::ISoundTriggerHwCallback::RecognitionEvent event;
    671         convertRecognitionEventFromHal(&event.header, halEvent);
    672         event.header.model = mId;
    673         auto result = moveVectorToMemory(&event.header.data, &event.data);
    674         if (result.first) {
    675             mCallback->recognitionCallback_2_1(event, mCookie);
    676         }
    677     }
    678 }
    679 
    680 void SoundTriggerHw::SoundModelClient_2_1::soundModelCallback(
    681     struct sound_trigger_model_event* halEvent) {
    682     V2_1::ISoundTriggerHwCallback::ModelEvent event;
    683     convertSoundModelEventFromHal(&event.header, halEvent);
    684     event.header.model = mId;
    685     auto result = moveVectorToMemory(&event.header.data, &event.data);
    686     if (result.first) {
    687         mCallback->soundModelCallback_2_1(event, mCookie);
    688     }
    689 }
    690 
    691 // Begin V2_2 implementation
    692 
    693 Return<int32_t> SoundTriggerHw::getModelState(int32_t modelHandle) {
    694     sp<SoundModelClient> client;
    695     if (mHwDevice == NULL) {
    696         return -ENODEV;
    697     }
    698 
    699     {
    700         AutoMutex lock(mLock);
    701         client = mClients.valueFor(modelHandle);
    702         if (client == 0) {
    703             return -ENOSYS;
    704         }
    705     }
    706 
    707     if (mHwDevice->common.version < SOUND_TRIGGER_DEVICE_API_VERSION_1_2) {
    708         ALOGE("Get model state not supported");
    709         return -ENODEV;
    710     }
    711 
    712     if (mHwDevice->get_model_state == NULL) {
    713         ALOGE("Failed to get model state from device, no such method");
    714         return -ENODEV;
    715     }
    716 
    717     return mHwDevice->get_model_state(mHwDevice, client->getHalHandle());
    718 }
    719 
    720 // Methods from ::android::hidl::base::V1_0::IBase follow.
    721 
    722 ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* /* name */) {
    723     return new SoundTriggerHw();
    724 }
    725 
    726 }  // namespace implementation
    727 }  // namespace V2_2
    728 }  // namespace soundtrigger
    729 }  // namespace hardware
    730 }  // namespace android
    731