soundtrigger: Add support for HAL V2.1

Use HAL V2.1 methods if this version is deployed on the device.
Initially the middleware layer requests for HAL V2.0, but if
the interface can be cast to V2.1, then new methods are used.

Made changes to avoid C-style type coercion as it was leading
to erroneous results when using V2.1 and V2.0 data structures
simultaneously.

Bug: 68823037
Test: use "ok google" and music IQ with HAL V2.0 and V2.1
Change-Id: I34924afe3cd4fb45a75fa34888e6e5c72727dbce
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);