Merge "Audio effects: define interface between EffectModule and audio framework"
diff --git a/apex/ld.config.txt b/apex/ld.config.txt
index ec8f049..1c44e65 100644
--- a/apex/ld.config.txt
+++ b/apex/ld.config.txt
@@ -27,7 +27,7 @@
 # TODO: replace the following when apex has a way to auto-generate this list
 # namespace.default.link.platform.shared_libs  = %LLNDK_LIBRARIES%
 # namespace.default.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so
+namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so:libbinder_ndk.so
 
 ###############################################################################
 # "platform" namespace
@@ -132,7 +132,7 @@
 # TODO: replace the following when apex has a way to auto-generate this list
 # namespace.sphal.link.platform.shared_libs  = %LLNDK_LIBRARIES%
 # namespace.sphal.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so
+namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so:libbinder_ndk.so
 
 # Add a link for libz.so which is llndk on devices where VNDK is not enforced.
 namespace.sphal.link.platform.shared_libs += libz.so
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/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index d928222..1560e0c 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -475,7 +475,7 @@
 
 void AudioStream::MyPlayerBase::registerWithAudioManager() {
     if (!mRegistered) {
-        init(android::PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA);
+        init(android::PLAYER_TYPE_AAUDIO, AAudioConvert_usageToInternal(mParent->getUsage()));
         mRegistered = true;
     }
 }
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index d52416c..cd3ac1f 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -289,6 +289,10 @@
         sinkMetadata.tracks[0].destination.device(std::move(hidlOutputDevice));
     }
 #endif
+#if MAJOR_VERSION <= 5
+    // Some flags were specific to framework and must not leak to the HAL.
+    flags = static_cast<audio_input_flags_t>(flags & ~AUDIO_INPUT_FLAG_DIRECT);
+#endif
     Return<void> ret = mDevice->openInputStream(
             handle,
             hidlDevice,
diff --git a/media/libmediahelper/TypeConverter.cpp b/media/libmediahelper/TypeConverter.cpp
index 6ea6172..aa54b82 100644
--- a/media/libmediahelper/TypeConverter.cpp
+++ b/media/libmediahelper/TypeConverter.cpp
@@ -358,6 +358,7 @@
     MAKE_STRING_FROM_ENUM(AUDIO_USAGE_GAME),
     MAKE_STRING_FROM_ENUM(AUDIO_USAGE_VIRTUAL_SOURCE),
     MAKE_STRING_FROM_ENUM(AUDIO_USAGE_ASSISTANT),
+    MAKE_STRING_FROM_ENUM(AUDIO_USAGE_CALL_ASSISTANT),
     TERMINATOR
 };
 
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index e8edd91..e953c8e 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2674,9 +2674,6 @@
         return 0;
     }
 
-    // Some flags are specific to framework and must not leak to the HAL.
-    flags = static_cast<audio_input_flags_t>(flags & ~AUDIO_INPUT_FRAMEWORK_FLAGS);
-
     // Audio Policy can request a specific handle for hardware hotword.
     // The goal here is not to re-open an already opened input.
     // It is to use a pre-assigned I/O handle.
diff --git a/services/audiopolicy/config/msd_audio_policy_configuration.xml b/services/audiopolicy/config/msd_audio_policy_configuration.xml
index db17bc6..305cbe6 100644
--- a/services/audiopolicy/config/msd_audio_policy_configuration.xml
+++ b/services/audiopolicy/config/msd_audio_policy_configuration.xml
@@ -40,7 +40,7 @@
                      channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
         </mixPort>
         <!-- The HW AV Sync flag is not required, but is recommended -->
-        <mixPort name="ms12 output" role="sink" flags="AUDIO_INPUT_FLAG_HW_AV_SYNC">
+        <mixPort name="ms12 output" role="sink" flags="AUDIO_INPUT_FLAG_HW_AV_SYNC|AUDIO_INPUT_FLAG_DIRECT">
             <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                      samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
             <profile name="" format="AUDIO_FORMAT_AC3"
diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
index fede0d9..20c57ee 100644
--- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
+++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
@@ -107,6 +107,13 @@
          }
      },
     },
+    {"STRATEGY_CALL_ASSISTANT",
+     {
+         {"", AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
+          {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_CALL_ASSISTANT, AUDIO_SOURCE_DEFAULT, 0, ""}}
+         }
+     },
+    },
     {"STRATEGY_TRANSMITTED_THROUGH_SPEAKER",
      {
          {"", AUDIO_STREAM_TTS, "AUDIO_STREAM_TTS",
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index b34928d..a3fa974 100755
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -53,6 +53,7 @@
     { "STRATEGY_ACCESSIBILITY", STRATEGY_ACCESSIBILITY },
     { "STRATEGY_REROUTING", STRATEGY_REROUTING },
     { "STRATEGY_PATCH", STRATEGY_REROUTING }, // boiler to manage stream patch volume
+    { "STRATEGY_CALL_ASSISTANT", STRATEGY_CALL_ASSISTANT },
 };
 
 Engine::Engine()
@@ -443,6 +444,10 @@
         }
         } break;
 
+    case STRATEGY_CALL_ASSISTANT:
+        devices = availableOutputDevices.getDevicesFromType(AUDIO_DEVICE_OUT_TELEPHONY_TX);
+        break;
+
     default:
         ALOGW("getDevicesForStrategy() unknown strategy: %d", strategy);
         break;
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 4360c6f..bb9e2df 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -39,6 +39,7 @@
     STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
     STRATEGY_ACCESSIBILITY,
     STRATEGY_REROUTING,
+    STRATEGY_CALL_ASSISTANT,
 };
 
 class Engine : public EngineBase
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 2e3f2d8..9d80a16 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -6113,6 +6113,7 @@
     case AUDIO_USAGE_GAME:
     case AUDIO_USAGE_VIRTUAL_SOURCE:
     case AUDIO_USAGE_ASSISTANT:
+    case AUDIO_USAGE_CALL_ASSISTANT:
         break;
     default:
         return false;
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)
 {