add SoundTrigger HAL V2.3 support

add support for model parameter control APIs with THRESHOLD_FACTOR
as the first supported parameter

Bug: 141929369
Test: Tested manually with test app and confirmed with GTS test
gts-tradefed run gts-dev -m GtsAssistIntentTestCases
Change-Id: I613dfe7486b4b4b695c79bda515b9f07fe750a70
diff --git a/services/soundtrigger/Android.bp b/services/soundtrigger/Android.bp
index 1bbd591..600f4a3 100644
--- a/services/soundtrigger/Android.bp
+++ b/services/soundtrigger/Android.bp
@@ -39,6 +39,7 @@
         "android.hardware.soundtrigger@2.0",
         "android.hardware.soundtrigger@2.1",
         "android.hardware.soundtrigger@2.2",
+        "android.hardware.soundtrigger@2.3",
         "android.hardware.audio.common@2.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
diff --git a/services/soundtrigger/SoundTriggerHalHidl.cpp b/services/soundtrigger/SoundTriggerHalHidl.cpp
index 68d54c7..b1d34df 100644
--- a/services/soundtrigger/SoundTriggerHalHidl.cpp
+++ b/services/soundtrigger/SoundTriggerHalHidl.cpp
@@ -427,6 +427,146 @@
     return ret;
 }
 
+int SoundTriggerHalHidl::setParameter(sound_model_handle_t handle,
+                                sound_trigger_model_parameter_t model_param, int32_t value)
+{
+    sp<ISoundTriggerHw> soundtrigger = getService();
+    if (!soundtrigger) {
+        return -ENODEV;
+    }
+
+    sp<V2_3_ISoundTriggerHw> soundtrigger_2_3 = toService2_3(soundtrigger);
+    if (!soundtrigger_2_3) {
+        ALOGE("setParameter not supported");
+        return -ENOSYS;
+    }
+
+    sp<SoundModel> model = getModel(handle);
+    if (!model) {
+        ALOGE("setParameter model not found for handle %u", handle);
+        return -EINVAL;
+    }
+
+    V2_3_ModelParameter halParam;
+    convertModelParameterToHal(&halParam, model_param);
+
+    Return<int32_t> hidlReturn(0);
+    {
+        AutoMutex lock(mHalLock);
+        hidlReturn = soundtrigger_2_3->setParameter(model->mHalHandle, halParam, value);
+    }
+    if (!hidlReturn.isOk()) {
+        ALOGE("getModelState error %s", hidlReturn.description().c_str());
+        return FAILED_TRANSACTION;
+    }
+
+    return hidlReturn;
+}
+
+int SoundTriggerHalHidl::getParameter(sound_model_handle_t handle,
+                                sound_trigger_model_parameter_t model_param, int32_t* value)
+{
+    sp<ISoundTriggerHw> soundtrigger = getService();
+    if (!soundtrigger) {
+        return -ENODEV;
+    }
+
+    sp<V2_3_ISoundTriggerHw> soundtrigger_2_3 = toService2_3(soundtrigger);
+    if (!soundtrigger_2_3) {
+        ALOGE("getParameter not supported");
+        return -ENOSYS;
+    }
+
+    if (value == NULL) {
+        ALOGE("getParameter invalid value pointer");
+        return -EINVAL;
+    }
+
+    sp<SoundModel> model = getModel(handle);
+    if (!model) {
+        ALOGE("getParameter model not found for handle %u", handle);
+        return -EINVAL;
+    }
+
+    V2_3_ModelParameter halParam;
+    convertModelParameterToHal(&halParam, model_param);
+
+    Return<void> hidlReturn;
+    int32_t hidlStatus;
+    int32_t hidlValue;
+    {
+        AutoMutex lock(mHalLock);
+        hidlReturn = soundtrigger_2_3->getParameter(model->mHalHandle, halParam,
+            [&](int32_t retStatus, int32_t retValue) {
+                hidlStatus = retStatus;
+                hidlValue = retValue;
+            });
+    }
+    if (!hidlReturn.isOk()) {
+        ALOGE("getModelState error %s", hidlReturn.description().c_str());
+        return FAILED_TRANSACTION;
+    }
+
+    *value = hidlValue;
+    return hidlStatus;
+}
+
+int SoundTriggerHalHidl::queryParameter(sound_model_handle_t handle,
+                    sound_trigger_model_parameter_t model_param,
+                    sound_trigger_model_parameter_range_t* param_range)
+{
+    sp<ISoundTriggerHw> soundtrigger = getService();
+    if (!soundtrigger) {
+        return -ENODEV;
+    }
+
+    sp<V2_3_ISoundTriggerHw> soundtrigger_2_3 = toService2_3(soundtrigger);
+    if (!soundtrigger_2_3) {
+        ALOGE("queryParameter not supported");
+        return -ENOSYS;
+    }
+
+    sp<SoundModel> model = getModel(handle);
+    if (!model) {
+        ALOGE("queryParameter model not found for handle %u", handle);
+        return -EINVAL;
+    }
+
+    V2_3_ModelParameter halParam;
+    convertModelParameterToHal(&halParam, model_param);
+
+    Return<void> hidlReturn;
+    int32_t hidlStatus;
+    V2_3_OptionalModelParameterRange hidlValue;
+    {
+        AutoMutex lock(mHalLock);
+        hidlReturn = soundtrigger_2_3->queryParameter(model->mHalHandle, halParam,
+            [&](int32_t retStatus, V2_3_OptionalModelParameterRange retValue) {
+                hidlStatus = retStatus;
+                hidlValue = retValue;
+            });
+    }
+    if (!hidlReturn.isOk()) {
+        ALOGE("queryParameter error %s", hidlReturn.description().c_str());
+        return FAILED_TRANSACTION;
+    }
+
+    if (hidlStatus != 0) {
+        ALOGE("queryParameter error code: %d", hidlStatus);
+        return hidlStatus;
+    }
+
+    if (hidlValue.getDiscriminator() ==
+            V2_3_OptionalModelParameterRange::hidl_discriminator::noinit) {
+        return -1;
+    }
+
+    param_range->start = hidlValue.range().start;
+    param_range->end = hidlValue.range().end;
+
+    return 0;
+}
+
 SoundTriggerHalHidl::SoundTriggerHalHidl(const char *moduleName)
     : mModuleName(moduleName), mNextUniqueId(1)
 {
@@ -465,6 +605,12 @@
     return castResult_2_2.isOk() ? static_cast<sp<V2_2_ISoundTriggerHw>>(castResult_2_2) : nullptr;
 }
 
+sp<V2_3_ISoundTriggerHw> SoundTriggerHalHidl::toService2_3(const sp<ISoundTriggerHw>& s)
+{
+    auto castResult_3_0 = V2_3_ISoundTriggerHw::castFrom(s);
+    return castResult_3_0.isOk() ? static_cast<sp<V2_3_ISoundTriggerHw>>(castResult_3_0) : nullptr;
+}
+
 sp<SoundTriggerHalHidl::SoundModel> SoundTriggerHalHidl::getModel(sound_model_handle_t handle)
 {
     AutoMutex lock(mLock);
@@ -526,6 +672,20 @@
     properties->power_consumption_mw = halProperties->powerConsumptionMw;
 }
 
+// static
+void SoundTriggerHalHidl::convertModelParameterToHal(V2_3_ModelParameter* halParam,
+    sound_trigger_model_parameter_t param)
+{
+    switch (param) {
+        case MODEL_PARAMETER_THRESHOLD_FACTOR:
+            *halParam = V2_3_ModelParameter::THRESHOLD_FACTOR;
+            return;
+        case MODEL_PARAMETER_INVALID:
+        default:
+            *halParam = V2_3_ModelParameter::INVALID;
+    }
+}
+
 void SoundTriggerHalHidl::convertTriggerPhraseToHal(
         ISoundTriggerHw::Phrase *halTriggerPhrase,
         const struct sound_trigger_phrase *triggerPhrase)
diff --git a/services/soundtrigger/SoundTriggerHalHidl.h b/services/soundtrigger/SoundTriggerHalHidl.h
index fb9e39e..25878d0 100644
--- a/services/soundtrigger/SoundTriggerHalHidl.h
+++ b/services/soundtrigger/SoundTriggerHalHidl.h
@@ -26,8 +26,10 @@
 #include <utils/threads.h>
 #include "SoundTriggerHalInterface.h"
 #include <android/hardware/soundtrigger/2.0/types.h>
+#include <android/hardware/soundtrigger/2.3/types.h>
 #include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
 #include <android/hardware/soundtrigger/2.2/ISoundTriggerHw.h>
+#include <android/hardware/soundtrigger/2.3/ISoundTriggerHw.h>
 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHwCallback.h>
 #include <android/hardware/soundtrigger/2.1/ISoundTriggerHwCallback.h>
 
@@ -49,6 +51,12 @@
 using ::android::hidl::memory::V1_0::IMemory;
 using V2_2_ISoundTriggerHw =
         ::android::hardware::soundtrigger::V2_2::ISoundTriggerHw;
+using V2_3_ISoundTriggerHw =
+        ::android::hardware::soundtrigger::V2_3::ISoundTriggerHw;
+using V2_3_ModelParameter =
+        ::android::hardware::soundtrigger::V2_3::ModelParameter;
+using V2_3_OptionalModelParameterRange =
+        ::android::hardware::soundtrigger::V2_3::OptionalModelParameterRange;
 
 class SoundTriggerHalHidl : public SoundTriggerHalInterface,
                             public virtual V2_1_ISoundTriggerHwCallback
@@ -103,6 +111,34 @@
          */
         virtual int getModelState(sound_model_handle_t handle);
 
+        /* Set a model specific ModelParameter with the given value. This parameter
+         * will keep its value for the duration the model is loaded regardless of starting and
+         * stopping recognition. Once the model is unloaded, the value will be lost.
+         * Returns 0 or an error code.
+         * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_3 or above.
+         */
+        int setParameter(sound_model_handle_t handle,
+                         sound_trigger_model_parameter_t model_param, int32_t value);
+
+        /* Get a model specific ModelParameter. This parameter will keep its value
+         * for the duration the model is loaded regardless of starting and stopping recognition.
+         * Once the model is unloaded, the value will be lost. If the value is not set, a default
+         * value is returned. See sound_trigger_model_parameter_t for parameter default values.
+         * Returns 0 or an error code.  On return 0, value pointer will be set.
+         * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_3 or above.
+         */
+        int getParameter(sound_model_handle_t handle,
+                         sound_trigger_model_parameter_t model_param, int32_t* value);
+
+        /* Get supported parameter attributes with respect to the provided model
+         * handle. Along with determining the valid range, this API is also used
+         * to determine if a given parameter ID is supported at all by the
+         * modelHandle for use with getParameter and setParameter APIs.
+         */
+        int queryParameter(sound_model_handle_t handle,
+                            sound_trigger_model_parameter_t model_param,
+                            sound_trigger_model_parameter_range_t* param_range);
+
         // ISoundTriggerHwCallback
         virtual ::android::hardware::Return<void> recognitionCallback(
                 const V2_0_ISoundTriggerHwCallback::RecognitionEvent& event, CallbackCookie cookie);
@@ -147,6 +183,8 @@
         void convertPropertiesFromHal(
                 struct sound_trigger_properties *properties,
                 const ISoundTriggerHw::Properties *halProperties);
+        static void convertModelParameterToHal(V2_3_ModelParameter* halParam,
+                sound_trigger_model_parameter_t param);
 
         void convertTriggerPhraseToHal(
                 ISoundTriggerHw::Phrase *halTriggerPhrase,
@@ -194,6 +232,7 @@
         sp<ISoundTriggerHw> getService();
         sp<V2_1_ISoundTriggerHw> toService2_1(const sp<ISoundTriggerHw>& s);
         sp<V2_2_ISoundTriggerHw> toService2_2(const sp<ISoundTriggerHw>& s);
+        sp<V2_3_ISoundTriggerHw> toService2_3(const sp<ISoundTriggerHw>& s);
         sp<SoundModel> getModel(sound_model_handle_t handle);
         sp<SoundModel> removeModel(sound_model_handle_t handle);
 
diff --git a/services/soundtrigger/SoundTriggerHalInterface.h b/services/soundtrigger/SoundTriggerHalInterface.h
index 0183ece..e1fffff 100644
--- a/services/soundtrigger/SoundTriggerHalInterface.h
+++ b/services/soundtrigger/SoundTriggerHalInterface.h
@@ -79,6 +79,34 @@
          */
         virtual int getModelState(sound_model_handle_t handle) = 0;
 
+        /* Set a model specific ModelParameter with the given value. This parameter
+         * will keep its value for the duration the model is loaded regardless of starting and stopping
+         * recognition. Once the model is unloaded, the value will be lost.
+         * Returns 0 or an error code.
+         * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_3 or above.
+         */
+        virtual int setParameter(sound_model_handle_t handle,
+                                 sound_trigger_model_parameter_t model_param, int32_t value) = 0;
+
+        /* Get a model specific ModelParameter. This parameter will keep its value
+         * for the duration the model is loaded regardless of starting and stopping recognition.
+         * Once the model is unloaded, the value will be lost. If the value is not set, a default
+         * value is returned. See sound_trigger_model_parameter_t for parameter default values.
+         * Returns 0 or an error code. On return 0, value pointer will be set.
+         * Only supported for device api versions SOUND_TRIGGER_DEVICE_API_VERSION_1_3 or above.
+         */
+        virtual int getParameter(sound_model_handle_t sound_model_handle,
+                                 sound_trigger_model_parameter_t model_param, int32_t* value) = 0;
+
+        /* Get supported parameter attributes with respect to the provided model
+         * handle. Along with determining the valid range, this API is also used
+         * to determine if a given parameter ID is supported at all by the
+         * modelHandle for use with getParameter and setParameter APIs.
+         */
+        virtual int queryParameter(sound_model_handle_t sound_model_handle,
+                                 sound_trigger_model_parameter_t model_param,
+                                 sound_trigger_model_parameter_range_t* param_range) = 0;
+
 protected:
         SoundTriggerHalInterface() {}
 };
diff --git a/services/soundtrigger/SoundTriggerHwService.cpp b/services/soundtrigger/SoundTriggerHwService.cpp
index ccbeb77..4d8b0da 100644
--- a/services/soundtrigger/SoundTriggerHwService.cpp
+++ b/services/soundtrigger/SoundTriggerHwService.cpp
@@ -768,6 +768,45 @@
     return mHalInterface->getModelState(handle);
 }
 
+status_t SoundTriggerHwService::Module::setParameter(sound_model_handle_t handle,
+                                sound_trigger_model_parameter_t param,
+                                int32_t value)
+{
+    ALOGV("setParameter() handle=%d, param=%d, value=%d", handle, param, value);
+    if (mHalInterface == 0) {
+        return NO_INIT;
+    }
+
+    AutoMutex lock(mLock);
+    return mHalInterface->setParameter(handle, param, value);
+}
+
+status_t SoundTriggerHwService::Module::getParameter(sound_model_handle_t handle,
+                                sound_trigger_model_parameter_t param,
+                                int32_t* value)
+{
+    ALOGV("getParameter() handle=%d, param=%d", handle, param);
+    if (mHalInterface == 0) {
+        return NO_INIT;
+    }
+
+    AutoMutex lock(mLock);
+    return mHalInterface->getParameter(handle, param, value);
+}
+
+status_t SoundTriggerHwService::Module::queryParameter(sound_model_handle_t handle,
+                                sound_trigger_model_parameter_t param,
+                                sound_trigger_model_parameter_range_t* param_range)
+{
+    ALOGV("queryParameter() handle=%d, param=%d", handle, param);
+    if (mHalInterface == 0) {
+        return NO_INIT;
+    }
+
+    AutoMutex lock(mLock);
+    return mHalInterface->queryParameter(handle, param, param_range);
+}
+
 void SoundTriggerHwService::Module::onCallbackEvent(const sp<CallbackEvent>& event)
 {
     ALOGV("onCallbackEvent type %d", event->mType);
@@ -1092,6 +1131,58 @@
     return module->getModelState(handle);
 }
 
+status_t SoundTriggerHwService::ModuleClient::setParameter(sound_model_handle_t handle,
+        sound_trigger_model_parameter_t param, int32_t value)
+{
+    ALOGV("setParameter() handle=%d, param=%d, value=%d", handle, param, value);
+    if (!captureHotwordAllowed(mOpPackageName,
+                               IPCThreadState::self()->getCallingPid(),
+                               IPCThreadState::self()->getCallingUid())) {
+        return PERMISSION_DENIED;
+    }
+
+    sp<Module> module = mModule.promote();
+    if (module == 0) {
+        return NO_INIT;
+    }
+    return module->setParameter(handle, param, value);
+}
+
+status_t SoundTriggerHwService::ModuleClient::getParameter(sound_model_handle_t handle,
+        sound_trigger_model_parameter_t param, int32_t* value)
+{
+    ALOGV("getParameter() handle=%d, param=%d", handle, param);
+    if (!captureHotwordAllowed(mOpPackageName,
+                               IPCThreadState::self()->getCallingPid(),
+                               IPCThreadState::self()->getCallingUid())) {
+        return PERMISSION_DENIED;
+    }
+
+    sp<Module> module = mModule.promote();
+    if (module == 0) {
+        return NO_INIT;
+    }
+    return module->getParameter(handle, param, value);
+}
+
+status_t SoundTriggerHwService::ModuleClient::queryParameter(sound_model_handle_t handle,
+        sound_trigger_model_parameter_t param,
+        sound_trigger_model_parameter_range_t* param_range)
+{
+    ALOGV("isParameterSupported() handle=%d, param=%d", handle, param);
+    if (!captureHotwordAllowed(mOpPackageName,
+                               IPCThreadState::self()->getCallingPid(),
+                               IPCThreadState::self()->getCallingUid())) {
+        return PERMISSION_DENIED;
+    }
+
+    sp<Module> module = mModule.promote();
+    if (module == 0) {
+        return NO_INIT;
+    }
+    return module->queryParameter(handle, param, param_range);
+}
+
 void SoundTriggerHwService::ModuleClient::setCaptureState_l(bool active)
 {
     ALOGV("ModuleClient::setCaptureState_l %d", active);
diff --git a/services/soundtrigger/SoundTriggerHwService.h b/services/soundtrigger/SoundTriggerHwService.h
index 43ad611..4057e14 100644
--- a/services/soundtrigger/SoundTriggerHwService.h
+++ b/services/soundtrigger/SoundTriggerHwService.h
@@ -125,6 +125,15 @@
                                          const sp<IMemory>& dataMemory);
        virtual status_t stopRecognition(sound_model_handle_t handle);
        virtual status_t getModelState(sound_model_handle_t handle);
+       virtual status_t setParameter(sound_model_handle_t handle,
+                                     sound_trigger_model_parameter_t param,
+                                     int32_t value);
+       virtual status_t getParameter(sound_model_handle_t handle,
+                                     sound_trigger_model_parameter_t param,
+                                     int32_t* value);
+       virtual status_t queryParameter(sound_model_handle_t handle,
+                                       sound_trigger_model_parameter_t param,
+                                       sound_trigger_model_parameter_range_t* param_range);
 
        sp<SoundTriggerHalInterface> halInterface() const { return mHalInterface; }
        struct sound_trigger_module_descriptor descriptor() { return mDescriptor; }
@@ -175,6 +184,15 @@
                                          const sp<IMemory>& dataMemory);
        virtual status_t stopRecognition(sound_model_handle_t handle);
        virtual status_t getModelState(sound_model_handle_t handle);
+       virtual status_t setParameter(sound_model_handle_t handle,
+                                     sound_trigger_model_parameter_t param,
+                                     int32_t value);
+       virtual status_t getParameter(sound_model_handle_t handle,
+                                     sound_trigger_model_parameter_t param,
+                                     int32_t* value);
+       virtual status_t queryParameter(sound_model_handle_t handle,
+                                sound_trigger_model_parameter_t param,
+                                sound_trigger_model_parameter_range_t* param_range);
 
        virtual status_t dump(int fd, const Vector<String16>& args);