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/include/soundtrigger/ISoundTrigger.h b/include/soundtrigger/ISoundTrigger.h
index c357caa..d628c05 100644
--- a/include/soundtrigger/ISoundTrigger.h
+++ b/include/soundtrigger/ISoundTrigger.h
@@ -41,7 +41,13 @@
                                       const sp<IMemory>& dataMemory) = 0;
     virtual status_t stopRecognition(sound_model_handle_t handle) = 0;
     virtual status_t getModelState(sound_model_handle_t handle) = 0;
-
+    virtual status_t setParameter(sound_model_handle_t handle,
+            sound_trigger_model_parameter_t param, int32_t value) = 0;
+    virtual status_t getParameter(sound_model_handle_t handle,
+            sound_trigger_model_parameter_t param, int32_t* value) = 0;
+    virtual status_t queryParameter(sound_model_handle_t handle,
+            sound_trigger_model_parameter_t param,
+            sound_trigger_model_parameter_range_t* param_range) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/soundtrigger/SoundTrigger.h b/include/soundtrigger/SoundTrigger.h
index ccc61dc..248620a 100644
--- a/include/soundtrigger/SoundTrigger.h
+++ b/include/soundtrigger/SoundTrigger.h
@@ -55,6 +55,13 @@
             status_t startRecognition(sound_model_handle_t handle, const sp<IMemory>& dataMemory);
             status_t stopRecognition(sound_model_handle_t handle);
             status_t getModelState(sound_model_handle_t handle);
+            status_t setParameter(sound_model_handle_t handle,
+                    sound_trigger_model_parameter_t param, int32_t value);
+            status_t getParameter(sound_model_handle_t handle,
+                    sound_trigger_model_parameter_t param, int32_t* value);
+            status_t queryParameter(sound_model_handle_t handle,
+                    sound_trigger_model_parameter_t param,
+                    sound_trigger_model_parameter_range_t* param_range);
 
             // BpSoundTriggerClient
             virtual void onRecognitionEvent(const sp<IMemory>& eventMemory);
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);
 
diff --git a/soundtrigger/ISoundTrigger.cpp b/soundtrigger/ISoundTrigger.cpp
index f5b4b59..9b1da13 100644
--- a/soundtrigger/ISoundTrigger.cpp
+++ b/soundtrigger/ISoundTrigger.cpp
@@ -33,6 +33,9 @@
     START_RECOGNITION,
     STOP_RECOGNITION,
     GET_MODEL_STATE,
+    SET_PARAMETER,
+    GET_PARAMETER,
+    QUERY_PARAMETER,
 };
 
 class BpSoundTrigger: public BpInterface<ISoundTrigger>
@@ -126,6 +129,55 @@
         return status;
     }
 
+    virtual status_t setParameter(sound_model_handle_t handle,
+                                     sound_trigger_model_parameter_t param,
+                                     int32_t value)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
+        data.write(&handle, sizeof(sound_model_handle_t));
+        data.write(&param, sizeof(sound_trigger_model_parameter_t));
+        data.writeInt32(value);
+        status_t status = remote()->transact(SET_PARAMETER, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t getParameter(sound_model_handle_t handle,
+                                     sound_trigger_model_parameter_t param,
+                                     int32_t* value)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
+        data.write(&handle, sizeof(sound_model_handle_t));
+        data.write(&param, sizeof(sound_trigger_model_parameter_t));
+        status_t status = remote()->transact(GET_PARAMETER, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+            *value = reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t queryParameter(sound_model_handle_t handle,
+            sound_trigger_model_parameter_t param,
+            sound_trigger_model_parameter_range_t* param_range)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISoundTrigger::getInterfaceDescriptor());
+        data.write(&handle, sizeof(sound_model_handle_t));
+        data.write(&param, sizeof(sound_trigger_model_parameter_t));
+        status_t status = remote()->transact(QUERY_PARAMETER, data, &reply);
+        if (status == NO_ERROR) {
+            status = (status_t)reply.readInt32();
+            param_range->start = reply.readInt32();
+            param_range->end = reply.readInt32();
+        }
+        return status;
+    }
+
 };
 
 IMPLEMENT_META_INTERFACE(SoundTrigger, "android.hardware.ISoundTrigger");
@@ -193,6 +245,70 @@
             reply->writeInt32(status);
             return ret;
         }
+        case SET_PARAMETER: {
+            CHECK_INTERFACE(ISoundTrigger, data, reply);
+            sound_model_handle_t handle;
+            sound_trigger_model_parameter_t param;
+            int32_t value;
+            status_t status = UNKNOWN_ERROR;
+            status_t ret;
+            ret = data.read(&handle, sizeof(sound_model_handle_t));
+            if (ret != NO_ERROR) {
+                return ret;
+            }
+            ret = data.read(&param, sizeof(sound_trigger_model_parameter_t));
+            if (ret != NO_ERROR) {
+                return ret;
+            }
+            ret = data.read(&value, sizeof(int32_t));
+            if (ret != NO_ERROR) {
+                return ret;
+            }
+            status = setParameter(handle, param, value);
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+        case GET_PARAMETER: {
+            CHECK_INTERFACE(ISoundTrigger, data, reply);
+            sound_model_handle_t handle;
+            sound_trigger_model_parameter_t param;
+            int32_t value;
+            status_t status = UNKNOWN_ERROR;
+            status_t ret;
+            ret = data.read(&handle, sizeof(sound_model_handle_t));
+            if (ret != NO_ERROR) {
+                return ret;
+            }
+            ret = data.read(&param, sizeof(sound_trigger_model_parameter_t));
+            if (ret != NO_ERROR) {
+                return ret;
+            }
+            status = getParameter(handle, param, &value);
+            reply->writeInt32(status);
+            reply->writeInt32(value);
+            return NO_ERROR;
+        }
+        case QUERY_PARAMETER: {
+            CHECK_INTERFACE(ISoundTrigger, data, reply);
+            sound_model_handle_t handle;
+            sound_trigger_model_parameter_t param;
+            status_t ret;
+            status_t status = UNKNOWN_ERROR;
+            sound_trigger_model_parameter_range_t retValue;
+            ret = data.read(&handle, sizeof(sound_model_handle_t));
+            if (ret != NO_ERROR) {
+                return ret;
+            }
+            ret = data.read(&param, sizeof(sound_trigger_model_parameter_t));
+            if (ret != NO_ERROR) {
+                return ret;
+            }
+            status = queryParameter(handle, param, &retValue);
+            reply->writeInt32(status);
+            reply->writeInt32(retValue.start);
+            reply->writeInt32(retValue.end);
+            return NO_ERROR;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/soundtrigger/SoundTrigger.cpp b/soundtrigger/SoundTrigger.cpp
index e297ee7..021697b 100644
--- a/soundtrigger/SoundTrigger.cpp
+++ b/soundtrigger/SoundTrigger.cpp
@@ -200,6 +200,37 @@
     return mISoundTrigger->getModelState(handle);
 }
 
+status_t SoundTrigger::setParameter(sound_model_handle_t handle,
+        sound_trigger_model_parameter_t param, int32_t value)
+{
+    Mutex::Autolock _l(mLock);
+    if (mISoundTrigger == 0) {
+        return NO_INIT;
+    }
+    return mISoundTrigger->setParameter(handle, param, value);
+}
+
+status_t SoundTrigger::getParameter(sound_model_handle_t handle,
+        sound_trigger_model_parameter_t param, int32_t* value)
+{
+    Mutex::Autolock _l(mLock);
+    if (mISoundTrigger == 0) {
+        return NO_INIT;
+    }
+    return mISoundTrigger->getParameter(handle, param, value);
+}
+
+status_t SoundTrigger::queryParameter(sound_model_handle_t handle,
+        sound_trigger_model_parameter_t param,
+        sound_trigger_model_parameter_range_t* param_range)
+{
+    Mutex::Autolock _l(mLock);
+    if (mISoundTrigger == 0) {
+        return NO_INIT;
+    }
+    return mISoundTrigger->queryParameter(handle, param, param_range);
+}
+
 // BpSoundTriggerClient
 void SoundTrigger::onRecognitionEvent(const sp<IMemory>& eventMemory)
 {