Merge "soundtrigger: Add support for HAL V2.1"
diff --git a/services/soundtrigger/Android.mk b/services/soundtrigger/Android.mk
index 10ee141..ca44737 100644
--- a/services/soundtrigger/Android.mk
+++ b/services/soundtrigger/Android.mk
@@ -49,11 +49,15 @@
 LOCAL_SHARED_LIBRARIES += \
     libhwbinder \
     libhidlbase \
+    libhidlmemory \
     libhidltransport \
     libbase \
     libaudiohal \
     android.hardware.soundtrigger@2.0 \
-    android.hardware.audio.common@2.0
+    android.hardware.soundtrigger@2.1 \
+    android.hardware.audio.common@2.0 \
+    android.hidl.allocator@1.0 \
+    android.hidl.memory@1.0
 endif
 
 
diff --git a/services/soundtrigger/SoundTriggerHalHidl.cpp b/services/soundtrigger/SoundTriggerHalHidl.cpp
index 0cd5cf7..adf252e 100644
--- a/services/soundtrigger/SoundTriggerHalHidl.cpp
+++ b/services/soundtrigger/SoundTriggerHalHidl.cpp
@@ -17,17 +17,87 @@
 #define LOG_TAG "SoundTriggerHalHidl"
 //#define LOG_NDEBUG 0
 
+#include <android/hidl/allocator/1.0/IAllocator.h>
 #include <media/audiohal/hidl/HalDeathHandler.h>
 #include <utils/Log.h>
 #include "SoundTriggerHalHidl.h"
+#include <hidlmemory/mapping.h>
 #include <hwbinder/IPCThreadState.h>
 #include <hwbinder/ProcessState.h>
 
 namespace android {
 
-using android::hardware::Return;
-using android::hardware::ProcessState;
-using android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::ProcessState;
+using ::android::hardware::Return;
+using ::android::hardware::Status;
+using ::android::hardware::Void;
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::hidl_memory;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+
+namespace {
+
+// Backs up by the vector with the contents of shared memory.
+// It is assumed that the passed hidl_vector is empty, so it's
+// not cleared if the memory is a null object.
+// The caller needs to keep the returned sp<IMemory> as long as
+// the data is needed.
+std::pair<bool, sp<IMemory>> memoryAsVector(const hidl_memory& m, hidl_vec<uint8_t>* vec) {
+    sp<IMemory> memory;
+    if (m.size() == 0) {
+        return std::make_pair(true, memory);
+    }
+    memory = mapMemory(m);
+    if (memory != nullptr) {
+        memory->read();
+        vec->setToExternal(static_cast<uint8_t*>(static_cast<void*>(memory->getPointer())),
+                memory->getSize());
+        return std::make_pair(true, memory);
+    }
+    ALOGE("%s: Could not map HIDL memory to IMemory", __func__);
+    return std::make_pair(false, memory);
+}
+
+// Moves the data from the vector into allocated shared memory,
+// emptying the vector.
+// It is assumed that the passed hidl_memory is a null object, so it's
+// not reset if the vector is empty.
+// The caller needs to keep the returned sp<IMemory> as long as
+// the data is needed.
+std::pair<bool, sp<IMemory>> moveVectorToMemory(hidl_vec<uint8_t>* v, hidl_memory* mem) {
+    sp<IMemory> memory;
+    if (v->size() == 0) {
+        return std::make_pair(true, memory);
+    }
+    sp<IAllocator> ashmem = IAllocator::getService("ashmem");
+    if (ashmem == 0) {
+        ALOGE("Failed to retrieve ashmem allocator service");
+        return std::make_pair(false, memory);
+    }
+    bool success = false;
+    Return<void> r = ashmem->allocate(v->size(), [&](bool s, const hidl_memory& m) {
+        success = s;
+        if (success) *mem = m;
+    });
+    if (r.isOk() && success) {
+        memory = hardware::mapMemory(*mem);
+        if (memory != 0) {
+            memory->update();
+            memcpy(memory->getPointer(), v->data(), v->size());
+            memory->commit();
+            v->resize(0);
+            return std::make_pair(true, memory);
+        } else {
+            ALOGE("Failed to map allocated ashmem");
+        }
+    } else {
+        ALOGE("Failed to allocate %llu bytes from ashmem", (unsigned long long)v->size());
+    }
+    return std::make_pair(false, memory);
+}
+
+}  // namespace
 
 /* static */
 sp<SoundTriggerHalInterface> SoundTriggerHalInterface::connectModule(const char *moduleName)
@@ -94,36 +164,62 @@
                         "loadSoundModel(): wrap around in sound model IDs, num loaded models %zd",
                         mSoundModels.size());
 
-    ISoundTriggerHw::SoundModel *halSoundModel =
-            convertSoundModelToHal(sound_model);
-    if (halSoundModel == NULL) {
-        return -EINVAL;
-    }
-
     Return<void> hidlReturn;
     int ret;
     SoundModelHandle halHandle;
-    {
-        AutoMutex lock(mHalLock);
-        if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
+    sp<V2_1_ISoundTriggerHw> soundtrigger_2_1 = toService2_1(soundtrigger);
+    if (sound_model->type == SOUND_MODEL_TYPE_KEYPHRASE) {
+        if (!soundtrigger_2_1) {
+            ISoundTriggerHw::PhraseSoundModel halSoundModel;
+            convertPhraseSoundModelToHal(&halSoundModel, sound_model);
+            AutoMutex lock(mHalLock);
             hidlReturn = soundtrigger->loadPhraseSoundModel(
-                    *(const ISoundTriggerHw::PhraseSoundModel *)halSoundModel,
+                    halSoundModel,
                     this, modelId, [&](int32_t retval, auto res) {
-                ret = retval;
-                halHandle = res;
-            });
-
+                        ret = retval;
+                        halHandle = res;
+                    });
         } else {
-            hidlReturn = soundtrigger->loadSoundModel(*halSoundModel,
+            V2_1_ISoundTriggerHw::PhraseSoundModel halSoundModel;
+            auto result = convertPhraseSoundModelToHal(&halSoundModel, sound_model);
+            if (result.first) {
+                AutoMutex lock(mHalLock);
+                hidlReturn = soundtrigger_2_1->loadPhraseSoundModel_2_1(
+                        halSoundModel,
+                        this, modelId, [&](int32_t retval, auto res) {
+                            ret = retval;
+                            halHandle = res;
+                        });
+            } else {
+                return NO_MEMORY;
+            }
+        }
+    } else {
+        if (!soundtrigger_2_1) {
+            ISoundTriggerHw::SoundModel halSoundModel;
+            convertSoundModelToHal(&halSoundModel, sound_model);
+            AutoMutex lock(mHalLock);
+            hidlReturn = soundtrigger->loadSoundModel(halSoundModel,
                     this, modelId, [&](int32_t retval, auto res) {
-                ret = retval;
-                halHandle = res;
-            });
+                        ret = retval;
+                        halHandle = res;
+                    });
+        } else {
+            V2_1_ISoundTriggerHw::SoundModel halSoundModel;
+            auto result = convertSoundModelToHal(&halSoundModel, sound_model);
+            if (result.first) {
+                AutoMutex lock(mHalLock);
+                hidlReturn = soundtrigger_2_1->loadSoundModel_2_1(halSoundModel,
+                        this, modelId, [&](int32_t retval, auto res) {
+                            ret = retval;
+                            halHandle = res;
+                        });
+            } else {
+                return NO_MEMORY;
+            }
         }
     }
 
-    delete halSoundModel;
-
     if (hidlReturn.isOk()) {
         if (ret == 0) {
             AutoMutex lock(mLock);
@@ -185,16 +281,27 @@
     model->mRecognitionCallback = callback;
     model->mRecognitionCookie = cookie;
 
-    ISoundTriggerHw::RecognitionConfig *halConfig =
-            convertRecognitionConfigToHal(config);
-
+    sp<V2_1_ISoundTriggerHw> soundtrigger_2_1 = toService2_1(soundtrigger);
     Return<int32_t> hidlReturn(0);
-    {
-        AutoMutex lock(mHalLock);
-        hidlReturn = soundtrigger->startRecognition(model->mHalHandle, *halConfig, this, handle);
-    }
 
-    delete halConfig;
+    if (!soundtrigger_2_1) {
+        ISoundTriggerHw::RecognitionConfig halConfig;
+        convertRecognitionConfigToHal(&halConfig, config);
+        {
+            AutoMutex lock(mHalLock);
+            hidlReturn = soundtrigger->startRecognition(model->mHalHandle, halConfig, this, handle);
+        }
+    } else {
+        V2_1_ISoundTriggerHw::RecognitionConfig halConfig;
+        auto result = convertRecognitionConfigToHal(&halConfig, config);
+        if (result.first) {
+            AutoMutex lock(mHalLock);
+            hidlReturn = soundtrigger_2_1->startRecognition_2_1(
+                    model->mHalHandle, halConfig, this, handle);
+        } else {
+            return NO_MEMORY;
+        }
+    }
 
     if (!hidlReturn.isOk()) {
         ALOGE("startRecognition error %s", hidlReturn.description().c_str());
@@ -275,6 +382,12 @@
     return mISoundTrigger;
 }
 
+sp<V2_1_ISoundTriggerHw> SoundTriggerHalHidl::toService2_1(const sp<ISoundTriggerHw>& s)
+{
+    auto castResult_2_1 = V2_1_ISoundTriggerHw::castFrom(s);
+    return castResult_2_1.isOk() ? static_cast<sp<V2_1_ISoundTriggerHw>>(castResult_2_1) : nullptr;
+}
+
 sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::getModel(sound_model_handle_t handle)
 {
     AutoMutex lock(mLock);
@@ -347,40 +460,52 @@
     halTriggerPhrase->text = triggerPhrase->text;
 }
 
-ISoundTriggerHw::SoundModel *SoundTriggerHalHidl::convertSoundModelToHal(
+
+void SoundTriggerHalHidl::convertTriggerPhrasesToHal(
+        hidl_vec<ISoundTriggerHw::Phrase> *halTriggerPhrases,
+        struct sound_trigger_phrase_sound_model *keyPhraseModel)
+{
+    halTriggerPhrases->resize(keyPhraseModel->num_phrases);
+    for (unsigned int i = 0; i < keyPhraseModel->num_phrases; i++) {
+        convertTriggerPhraseToHal(&(*halTriggerPhrases)[i], &keyPhraseModel->phrases[i]);
+    }
+}
+
+void SoundTriggerHalHidl::convertSoundModelToHal(ISoundTriggerHw::SoundModel *halModel,
         const struct sound_trigger_sound_model *soundModel)
 {
-    ISoundTriggerHw::SoundModel *halModel = NULL;
-    if (soundModel->type == SOUND_MODEL_TYPE_KEYPHRASE) {
-        ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel =
-                new ISoundTriggerHw::PhraseSoundModel();
-        struct sound_trigger_phrase_sound_model *keyPhraseModel =
-                (struct sound_trigger_phrase_sound_model *)soundModel;
-        ISoundTriggerHw::Phrase *halPhrases =
-                new ISoundTriggerHw::Phrase[keyPhraseModel->num_phrases];
-
-
-        for (unsigned int i = 0; i < keyPhraseModel->num_phrases; i++) {
-            convertTriggerPhraseToHal(&halPhrases[i],
-                                      &keyPhraseModel->phrases[i]);
-        }
-        halKeyPhraseModel->phrases.setToExternal(halPhrases, keyPhraseModel->num_phrases);
-        // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
-        halKeyPhraseModel->phrases.resize(keyPhraseModel->num_phrases);
-
-        delete[] halPhrases;
-
-        halModel = (ISoundTriggerHw::SoundModel *)halKeyPhraseModel;
-    } else {
-        halModel = new ISoundTriggerHw::SoundModel();
-    }
     halModel->type = (SoundModelType)soundModel->type;
     convertUuidToHal(&halModel->uuid, &soundModel->uuid);
     convertUuidToHal(&halModel->vendorUuid, &soundModel->vendor_uuid);
     halModel->data.setToExternal((uint8_t *)soundModel + soundModel->data_offset, soundModel->data_size);
-    halModel->data.resize(soundModel->data_size);
+}
 
-    return halModel;
+std::pair<bool, sp<IMemory>> SoundTriggerHalHidl::convertSoundModelToHal(
+        V2_1_ISoundTriggerHw::SoundModel *halModel,
+        const struct sound_trigger_sound_model *soundModel)
+{
+    convertSoundModelToHal(&halModel->header, soundModel);
+    return moveVectorToMemory(&halModel->header.data, &halModel->data);
+}
+
+void SoundTriggerHalHidl::convertPhraseSoundModelToHal(
+        ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel,
+        const struct sound_trigger_sound_model *soundModel)
+{
+    struct sound_trigger_phrase_sound_model *keyPhraseModel =
+            (struct sound_trigger_phrase_sound_model *)soundModel;
+    convertTriggerPhrasesToHal(&halKeyPhraseModel->phrases, keyPhraseModel);
+    convertSoundModelToHal(&halKeyPhraseModel->common, soundModel);
+}
+
+std::pair<bool, sp<IMemory>> SoundTriggerHalHidl::convertPhraseSoundModelToHal(
+        V2_1_ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel,
+        const struct sound_trigger_sound_model *soundModel)
+{
+    struct sound_trigger_phrase_sound_model *keyPhraseModel =
+            (struct sound_trigger_phrase_sound_model *)soundModel;
+    convertTriggerPhrasesToHal(&halKeyPhraseModel->phrases, keyPhraseModel);
+    return convertSoundModelToHal(&halKeyPhraseModel->common, soundModel);
 }
 
 void SoundTriggerHalHidl::convertPhraseRecognitionExtraToHal(
@@ -390,52 +515,42 @@
     halExtra->id = extra->id;
     halExtra->recognitionModes = extra->recognition_modes;
     halExtra->confidenceLevel = extra->confidence_level;
-    ConfidenceLevel *halLevels =
-            new ConfidenceLevel[extra->num_levels];
-    for (unsigned int i = 0; i < extra->num_levels; i++) {
-        halLevels[i].userId = extra->levels[i].user_id;
-        halLevels[i].levelPercent = extra->levels[i].level;
-    }
-    halExtra->levels.setToExternal(halLevels, extra->num_levels);
-    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
     halExtra->levels.resize(extra->num_levels);
-
-    delete[] halLevels;
+    for (unsigned int i = 0; i < extra->num_levels; i++) {
+        halExtra->levels[i].userId = extra->levels[i].user_id;
+        halExtra->levels[i].levelPercent = extra->levels[i].level;
+    }
 }
 
-
-ISoundTriggerHw::RecognitionConfig *SoundTriggerHalHidl::convertRecognitionConfigToHal(
+void SoundTriggerHalHidl::convertRecognitionConfigToHal(
+        ISoundTriggerHw::RecognitionConfig *halConfig,
         const struct sound_trigger_recognition_config *config)
 {
-    ISoundTriggerHw::RecognitionConfig *halConfig =
-            new ISoundTriggerHw::RecognitionConfig();
-
     halConfig->captureHandle = config->capture_handle;
     halConfig->captureDevice = (AudioDevice)config->capture_device;
     halConfig->captureRequested = (uint32_t)config->capture_requested;
 
-    PhraseRecognitionExtra *halExtras =
-            new PhraseRecognitionExtra[config->num_phrases];
-
+    halConfig->phrases.resize(config->num_phrases);
     for (unsigned int i = 0; i < config->num_phrases; i++) {
-        convertPhraseRecognitionExtraToHal(&halExtras[i],
+        convertPhraseRecognitionExtraToHal(&halConfig->phrases[i],
                                   &config->phrases[i]);
     }
-    halConfig->phrases.setToExternal(halExtras, config->num_phrases);
-    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
-    halConfig->phrases.resize(config->num_phrases);
-
-    delete[] halExtras;
 
     halConfig->data.setToExternal((uint8_t *)config + config->data_offset, config->data_size);
+}
 
-    return halConfig;
+std::pair<bool, sp<IMemory>> SoundTriggerHalHidl::convertRecognitionConfigToHal(
+        V2_1_ISoundTriggerHw::RecognitionConfig *halConfig,
+        const struct sound_trigger_recognition_config *config)
+{
+    convertRecognitionConfigToHal(&halConfig->header, config);
+    return moveVectorToMemory(&halConfig->header.data, &halConfig->data);
 }
 
 
 // ISoundTriggerHwCallback
 ::android::hardware::Return<void> SoundTriggerHalHidl::recognitionCallback(
-        const ISoundTriggerHwCallback::RecognitionEvent& halEvent,
+        const V2_0_ISoundTriggerHwCallback::RecognitionEvent& halEvent,
         CallbackCookie cookie)
 {
     sp<SoundModel> model;
@@ -459,7 +574,7 @@
 }
 
 ::android::hardware::Return<void> SoundTriggerHalHidl::phraseRecognitionCallback(
-        const ISoundTriggerHwCallback::PhraseRecognitionEvent& halEvent,
+        const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent& halEvent,
         CallbackCookie cookie)
 {
     sp<SoundModel> model;
@@ -471,14 +586,13 @@
         }
     }
 
-    struct sound_trigger_recognition_event *event = convertRecognitionEventFromHal(
-                                   (const ISoundTriggerHwCallback::RecognitionEvent *)&halEvent);
+    struct sound_trigger_phrase_recognition_event *event =
+            convertPhraseRecognitionEventFromHal(&halEvent);
     if (event == NULL) {
         return Return<void>();
     }
-
-    event->model = model->mHandle;
-    model->mRecognitionCallback(event, model->mRecognitionCookie);
+    event->common.model = model->mHandle;
+    model->mRecognitionCallback(&event->common, model->mRecognitionCookie);
 
     free(event);
 
@@ -486,7 +600,7 @@
 }
 
 ::android::hardware::Return<void> SoundTriggerHalHidl::soundModelCallback(
-        const ISoundTriggerHwCallback::ModelEvent& halEvent,
+        const V2_0_ISoundTriggerHwCallback::ModelEvent& halEvent,
         CallbackCookie cookie)
 {
     sp<SoundModel> model;
@@ -511,9 +625,37 @@
     return Return<void>();
 }
 
+::android::hardware::Return<void> SoundTriggerHalHidl::recognitionCallback_2_1(
+        const ISoundTriggerHwCallback::RecognitionEvent& event, CallbackCookie cookie) {
+    // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap.
+    V2_0_ISoundTriggerHwCallback::RecognitionEvent event_2_0 = event.header;
+    auto result = memoryAsVector(event.data, &event_2_0.data);
+    return result.first ? recognitionCallback(event_2_0, cookie) : Void();
+}
+
+::android::hardware::Return<void> SoundTriggerHalHidl::phraseRecognitionCallback_2_1(
+        const ISoundTriggerHwCallback::PhraseRecognitionEvent& event, int32_t cookie) {
+    V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent event_2_0;
+    // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap.
+    event_2_0.common = event.common.header;
+    event_2_0.phraseExtras.setToExternal(
+            const_cast<PhraseRecognitionExtra*>(event.phraseExtras.data()),
+            event.phraseExtras.size());
+    auto result = memoryAsVector(event.common.data, &event_2_0.common.data);
+    return result.first ? phraseRecognitionCallback(event_2_0, cookie) : Void();
+}
+
+::android::hardware::Return<void> SoundTriggerHalHidl::soundModelCallback_2_1(
+        const ISoundTriggerHwCallback::ModelEvent& event, CallbackCookie cookie) {
+    // The data vector in the 'header' part of V2.1 structure is empty, thus copying is cheap.
+    V2_0_ISoundTriggerHwCallback::ModelEvent event_2_0 = event.header;
+    auto result = memoryAsVector(event.data, &event_2_0.data);
+    return result.first ? soundModelCallback(event_2_0, cookie) : Void();
+}
+
 
 struct sound_trigger_model_event *SoundTriggerHalHidl::convertSoundModelEventFromHal(
-                                              const ISoundTriggerHwCallback::ModelEvent *halEvent)
+                                              const V2_0_ISoundTriggerHwCallback::ModelEvent *halEvent)
 {
     struct sound_trigger_model_event *event = (struct sound_trigger_model_event *)malloc(
             sizeof(struct sound_trigger_model_event) +
@@ -550,37 +692,55 @@
 }
 
 
-struct sound_trigger_recognition_event *SoundTriggerHalHidl::convertRecognitionEventFromHal(
-        const ISoundTriggerHwCallback::RecognitionEvent *halEvent)
+struct sound_trigger_phrase_recognition_event* SoundTriggerHalHidl::convertPhraseRecognitionEventFromHal(
+        const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent *halPhraseEvent)
 {
-    struct sound_trigger_recognition_event *event;
-
-    if (halEvent->type == SoundModelType::KEYPHRASE) {
-        struct sound_trigger_phrase_recognition_event *phraseEvent =
-                (struct sound_trigger_phrase_recognition_event *)malloc(
-                        sizeof(struct sound_trigger_phrase_recognition_event) +
-                        halEvent->data.size());
-        if (phraseEvent == NULL) {
-            return NULL;
-        }
-        const ISoundTriggerHwCallback::PhraseRecognitionEvent *halPhraseEvent =
-                (const ISoundTriggerHwCallback::PhraseRecognitionEvent *)halEvent;
-
-        for (unsigned int i = 0; i < halPhraseEvent->phraseExtras.size(); i++) {
-            convertPhraseRecognitionExtraFromHal(&phraseEvent->phrase_extras[i],
-                                                 &halPhraseEvent->phraseExtras[i]);
-        }
-        phraseEvent->num_phrases = halPhraseEvent->phraseExtras.size();
-        event = (struct sound_trigger_recognition_event *)phraseEvent;
-        event->data_offset = sizeof(sound_trigger_phrase_recognition_event);
-    } else {
-        event = (struct sound_trigger_recognition_event *)malloc(
-                sizeof(struct sound_trigger_recognition_event) + halEvent->data.size());
-        if (event == NULL) {
-            return NULL;
-        }
-        event->data_offset = sizeof(sound_trigger_recognition_event);
+    if (halPhraseEvent->common.type != SoundModelType::KEYPHRASE) {
+        ALOGE("Received non-keyphrase event type as PhraseRecognitionEvent");
+        return NULL;
     }
+    struct sound_trigger_phrase_recognition_event *phraseEvent =
+            (struct sound_trigger_phrase_recognition_event *)malloc(
+                    sizeof(struct sound_trigger_phrase_recognition_event) +
+                    halPhraseEvent->common.data.size());
+    if (phraseEvent == NULL) {
+        return NULL;
+    }
+    phraseEvent->common.data_offset = sizeof(sound_trigger_phrase_recognition_event);
+
+    for (unsigned int i = 0; i < halPhraseEvent->phraseExtras.size(); i++) {
+        convertPhraseRecognitionExtraFromHal(&phraseEvent->phrase_extras[i],
+                                             &halPhraseEvent->phraseExtras[i]);
+    }
+    phraseEvent->num_phrases = halPhraseEvent->phraseExtras.size();
+
+    fillRecognitionEventFromHal(&phraseEvent->common, &halPhraseEvent->common);
+    return phraseEvent;
+}
+
+struct sound_trigger_recognition_event *SoundTriggerHalHidl::convertRecognitionEventFromHal(
+        const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent)
+{
+    if (halEvent->type == SoundModelType::KEYPHRASE) {
+        ALOGE("Received keyphrase event type as RecognitionEvent");
+        return NULL;
+    }
+    struct sound_trigger_recognition_event *event;
+    event = (struct sound_trigger_recognition_event *)malloc(
+            sizeof(struct sound_trigger_recognition_event) + halEvent->data.size());
+    if (event == NULL) {
+        return NULL;
+    }
+    event->data_offset = sizeof(sound_trigger_recognition_event);
+
+    fillRecognitionEventFromHal(event, halEvent);
+    return event;
+}
+
+void SoundTriggerHalHidl::fillRecognitionEventFromHal(
+        struct sound_trigger_recognition_event *event,
+        const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent)
+{
     event->status = (int)halEvent->status;
     event->type = (sound_trigger_sound_model_type_t)halEvent->type;
     // event->model to be set by caller
@@ -597,8 +757,6 @@
     uint8_t *dst = (uint8_t *)event + event->data_offset;
     uint8_t *src = (uint8_t *)&halEvent->data[0];
     memcpy(dst, src, halEvent->data.size());
-
-    return event;
 }
 
 } // namespace android
diff --git a/services/soundtrigger/SoundTriggerHalHidl.h b/services/soundtrigger/SoundTriggerHalHidl.h
index 0c68cf1..0b44ae0 100644
--- a/services/soundtrigger/SoundTriggerHalHidl.h
+++ b/services/soundtrigger/SoundTriggerHalHidl.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_HARDWARE_SOUNDTRIGGER_HAL_HIDL_H
 #define ANDROID_HARDWARE_SOUNDTRIGGER_HAL_HIDL_H
 
+#include <utility>
+
 #include <stdatomic.h>
 #include <utils/RefBase.h>
 #include <utils/KeyedVector.h>
@@ -24,21 +26,29 @@
 #include <utils/threads.h>
 #include "SoundTriggerHalInterface.h"
 #include <android/hardware/soundtrigger/2.0/types.h>
-#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
+#include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHwCallback.h>
+#include <android/hardware/soundtrigger/2.1/ISoundTriggerHwCallback.h>
 
 namespace android {
 
-using android::hardware::audio::common::V2_0::Uuid;
-using android::hardware::soundtrigger::V2_0::ConfidenceLevel;
-using android::hardware::soundtrigger::V2_0::PhraseRecognitionExtra;
-using android::hardware::soundtrigger::V2_0::SoundModelType;
-using android::hardware::soundtrigger::V2_0::SoundModelHandle;
-using android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
-using android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback;
+using ::android::hardware::audio::common::V2_0::Uuid;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::soundtrigger::V2_0::ConfidenceLevel;
+using ::android::hardware::soundtrigger::V2_0::PhraseRecognitionExtra;
+using ::android::hardware::soundtrigger::V2_0::SoundModelType;
+using ::android::hardware::soundtrigger::V2_0::SoundModelHandle;
+using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
+using V2_0_ISoundTriggerHwCallback =
+        ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback;
+using V2_1_ISoundTriggerHw =
+        ::android::hardware::soundtrigger::V2_1::ISoundTriggerHw;
+using V2_1_ISoundTriggerHwCallback =
+        ::android::hardware::soundtrigger::V2_1::ISoundTriggerHwCallback;
+using ::android::hidl::memory::V1_0::IMemory;
 
 class SoundTriggerHalHidl : public SoundTriggerHalInterface,
-                            public virtual ISoundTriggerHwCallback
+                            public virtual V2_1_ISoundTriggerHwCallback
 
 {
 public:
@@ -84,11 +94,17 @@
 
         // ISoundTriggerHwCallback
         virtual ::android::hardware::Return<void> recognitionCallback(
-                const ISoundTriggerHwCallback::RecognitionEvent& event, CallbackCookie cookie);
+                const V2_0_ISoundTriggerHwCallback::RecognitionEvent& event, CallbackCookie cookie);
         virtual ::android::hardware::Return<void> phraseRecognitionCallback(
-                const ISoundTriggerHwCallback::PhraseRecognitionEvent& event, int32_t cookie);
+                const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent& event, int32_t cookie);
         virtual ::android::hardware::Return<void> soundModelCallback(
-                const ISoundTriggerHwCallback::ModelEvent& event, CallbackCookie cookie);
+                const V2_0_ISoundTriggerHwCallback::ModelEvent& event, CallbackCookie cookie);
+        virtual ::android::hardware::Return<void> recognitionCallback_2_1(
+                const RecognitionEvent& event, CallbackCookie cookie);
+        virtual ::android::hardware::Return<void> phraseRecognitionCallback_2_1(
+                const PhraseRecognitionEvent& event, int32_t cookie);
+        virtual ::android::hardware::Return<void> soundModelCallback_2_1(
+                const ModelEvent& event, CallbackCookie cookie);
 private:
         class SoundModel : public RefBase {
         public:
@@ -124,25 +140,48 @@
         void convertTriggerPhraseToHal(
                 ISoundTriggerHw::Phrase *halTriggerPhrase,
                 const struct sound_trigger_phrase *triggerPhrase);
-        ISoundTriggerHw::SoundModel *convertSoundModelToHal(
+        void convertTriggerPhrasesToHal(
+                hidl_vec<ISoundTriggerHw::Phrase> *halTriggerPhrases,
+                struct sound_trigger_phrase_sound_model *keyPhraseModel);
+        void convertSoundModelToHal(ISoundTriggerHw::SoundModel *halModel,
                 const struct sound_trigger_sound_model *soundModel);
+        std::pair<bool, sp<IMemory>> convertSoundModelToHal(
+                V2_1_ISoundTriggerHw::SoundModel *halModel,
+                const struct sound_trigger_sound_model *soundModel)
+                __attribute__((warn_unused_result));
+        void convertPhraseSoundModelToHal(ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel,
+                const struct sound_trigger_sound_model *soundModel);
+        std::pair<bool, sp<IMemory>> convertPhraseSoundModelToHal(
+                V2_1_ISoundTriggerHw::PhraseSoundModel *halKeyPhraseModel,
+                const struct sound_trigger_sound_model *soundModel)
+                __attribute__((warn_unused_result));
 
         void convertPhraseRecognitionExtraToHal(
                 PhraseRecognitionExtra *halExtra,
                 const struct sound_trigger_phrase_recognition_extra *extra);
-        ISoundTriggerHw::RecognitionConfig *convertRecognitionConfigToHal(
+        void convertRecognitionConfigToHal(ISoundTriggerHw::RecognitionConfig *halConfig,
                 const struct sound_trigger_recognition_config *config);
+        std::pair<bool, sp<IMemory>> convertRecognitionConfigToHal(
+                V2_1_ISoundTriggerHw::RecognitionConfig *halConfig,
+                const struct sound_trigger_recognition_config *config)
+                __attribute__((warn_unused_result));
 
         struct sound_trigger_model_event *convertSoundModelEventFromHal(
-                                              const ISoundTriggerHwCallback::ModelEvent *halEvent);
+                                              const V2_0_ISoundTriggerHwCallback::ModelEvent *halEvent);
         void convertPhraseRecognitionExtraFromHal(
                 struct sound_trigger_phrase_recognition_extra *extra,
                 const PhraseRecognitionExtra *halExtra);
+        struct sound_trigger_phrase_recognition_event* convertPhraseRecognitionEventFromHal(
+                const V2_0_ISoundTriggerHwCallback::PhraseRecognitionEvent *halPhraseEvent);
         struct sound_trigger_recognition_event *convertRecognitionEventFromHal(
-                const ISoundTriggerHwCallback::RecognitionEvent *halEvent);
+                const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent);
+        void fillRecognitionEventFromHal(
+                struct sound_trigger_recognition_event *event,
+                const V2_0_ISoundTriggerHwCallback::RecognitionEvent *halEvent);
 
         uint32_t nextUniqueId();
         sp<ISoundTriggerHw> getService();
+        sp<V2_1_ISoundTriggerHw> toService2_1(const sp<ISoundTriggerHw>& s);
         sp<SoundModel> getModel(sound_model_handle_t handle);
         sp<SoundModel> removeModel(sound_model_handle_t handle);