Merge "AGM: support ACDB parameter read"
diff --git a/ipc/HwBinders/agm_ipc_service/Android.mk b/ipc/HwBinders/agm_ipc_service/Android.mk
index 596e4ae..69e6850 100644
--- a/ipc/HwBinders/agm_ipc_service/Android.mk
+++ b/ipc/HwBinders/agm_ipc_service/Android.mk
@@ -22,6 +22,10 @@
     vendor.qti.hardware.AGMIPC@1.0 \
     libagm
 
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_AGM_HIDL)),true)
+  LOCAL_CFLAGS += -DAGM_HIDL_ENABLED
+endif
+
 include $(BUILD_SHARED_LIBRARY)
 
 ifneq ($(strip $(AUDIO_FEATURE_ENABLED_AGM_HIDL)),true)
diff --git a/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp b/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
index 042dd21..e596251 100644
--- a/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
+++ b/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
@@ -1575,11 +1575,13 @@
 Return<int32_t> AGM::ipc_agm_dump(const hidl_vec<AgmDumpInfo>& dump_info) {
     struct agm_dump_info *d_info =
             (struct agm_dump_info *)dump_info.data();
+#ifndef AGM_HIDL_ENABLED
     if (d_info->signal) {
         ALOGD("%s: client with pid %d received signal %d",
                   __func__, d_info->pid, d_info->signal);
         dumpAgmStackTrace(d_info);
     }
+#endif
     return agm_dump(d_info);
 }
 
diff --git a/plugins/tinyalsa/src/agm_compress_plugin.c b/plugins/tinyalsa/src/agm_compress_plugin.c
index fef9143..d8f5cdf 100644
--- a/plugins/tinyalsa/src/agm_compress_plugin.c
+++ b/plugins/tinyalsa/src/agm_compress_plugin.c
@@ -25,6 +25,39 @@
 ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 ** OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 ** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+** Changes from Qualcomm Innovation Center are provided under the following license:
+** Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted (subject to the limitations in the
+** disclaimer below) provided that the following conditions are met:
+**
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**
+**   * Redistributions in binary form must reproduce the above
+**     copyright notice, this list of conditions and the following
+**     disclaimer in the documentation and/or other materials provided
+**     with the distribution.
+**
+**   * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+** NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+** GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+** HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+** IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **/
 #define LOG_TAG "PLUGIN: compress"
 
@@ -215,8 +248,10 @@
         will be called before start() */
     if (!priv->prepared) {
         ret = agm_session_prepare(handle);
-        if (ret)
+        if (ret) {
+            errno = ret;
             return ret;
+        }
         priv->prepared = true;
     }
 
@@ -253,6 +288,7 @@
     struct agm_compress_priv *priv = plugin->priv;
     uint64_t handle;
     int ret = 0, buf_cnt = 0;
+    AGM_LOGV("Enter");
 
     ret = agm_get_session_handle(priv, &handle);
     if (ret)
@@ -270,20 +306,11 @@
     }
     pthread_mutex_lock(&priv->lock);
 
-    buf_cnt = count / priv->buffer_config.size;
-    if (count % priv->buffer_config.size != 0)
-        buf_cnt +=1;
-
-    /* Avalible buffer size is always multiple of fragment size */
-    priv->bytes_avail -= (buf_cnt * priv->buffer_config.size);
-    if (priv->bytes_avail < 0)
-        AGM_LOGE("%s: err: bytes_avail = %lld", __func__, (long long) priv->bytes_avail);
-
     priv->bytes_read += count;
 
     pthread_mutex_unlock(&priv->lock);
-
-    return 0;
+    AGM_LOGV("Exit: read bytes: %d",count);
+    return count;
 }
 
 int agm_compress_tstamp(struct compress_plugin *plugin,
@@ -373,70 +400,95 @@
     media_cfg->rate =  params->codec.sample_rate;
     media_cfg->channels = params->codec.ch_out;
 
-    switch (params->codec.id) {
-    case SND_AUDIOCODEC_MP3:
-        media_cfg->format = AGM_FORMAT_MP3;
-        break;
-    case SND_AUDIOCODEC_AAC:
-        media_cfg->format = AGM_FORMAT_AAC;
-        if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4LATM)
-            sess_cfg->codec.aac_dec.aac_fmt_flag = 0x04;
-        else if (params->codec.format == SND_AUDIOSTREAMFORMAT_ADIF)
-            sess_cfg->codec.aac_dec.aac_fmt_flag = 0x02;
-        else if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)
-            sess_cfg->codec.aac_dec.aac_fmt_flag = 0x00;
-        else
-            sess_cfg->codec.aac_dec.aac_fmt_flag = 0x03;
-        sess_cfg->codec.aac_dec.num_channels = params->codec.ch_in;
-        sess_cfg->codec.aac_dec.sample_rate = media_cfg->rate;
-        break;
-    case SND_AUDIOCODEC_FLAC:
-        media_cfg->format = AGM_FORMAT_FLAC;
-        sess_cfg->codec.flac_dec.num_channels = params->codec.ch_in;
-        sess_cfg->codec.flac_dec.sample_rate = media_cfg->rate;
-        break;
-#ifdef SND_AUDIOCODEC_ALAC
-    case SND_AUDIOCODEC_ALAC:
-        media_cfg->format = AGM_FORMAT_ALAC;
-        sess_cfg->codec.alac_dec.num_channels = params->codec.ch_in;
-        sess_cfg->codec.alac_dec.sample_rate = media_cfg->rate;
-        break;
-#endif
-#ifdef SND_AUDIOCODEC_APE
-    case SND_AUDIOCODEC_APE:
-        media_cfg->format = AGM_FORMAT_APE;
-        sess_cfg->codec.ape_dec.num_channels = params->codec.ch_in;
-        sess_cfg->codec.ape_dec.sample_rate = media_cfg->rate;
-        break;
-#endif
-    case SND_AUDIOCODEC_WMA:
-#ifdef SND_AUDIOPROFILE_WMA9_LOSSLESS
-        if ((params->codec.profile == SND_AUDIOPROFILE_WMA9_PRO) ||
-            (params->codec.profile == SND_AUDIOPROFILE_WMA9_LOSSLESS) ||
-            (params->codec.profile == SND_AUDIOPROFILE_WMA10_LOSSLESS)) {
-#else
-        if ((params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM0) ||
-            (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM1) ||
-            (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM2)) {
-#endif
-            media_cfg->format = AGM_FORMAT_WMAPRO;
-            sess_cfg->codec.wmapro_dec.fmt_tag = params->codec.format;
-            sess_cfg->codec.wmapro_dec.num_channels = params->codec.ch_in;
-            sess_cfg->codec.wmapro_dec.sample_rate = media_cfg->rate;
-        } else {
-            media_cfg->format = AGM_FORMAT_WMASTD;
-            sess_cfg->codec.wma_dec.fmt_tag = params->codec.format;
-            sess_cfg->codec.wma_dec.num_channels = params->codec.ch_in;
-            sess_cfg->codec.wma_dec.sample_rate = media_cfg->rate;
+    if (sess_cfg->dir == RX) {
+        switch (params->codec.id) {
+        case SND_AUDIOCODEC_MP3:
+            media_cfg->format = AGM_FORMAT_MP3;
+            break;
+        case SND_AUDIOCODEC_AAC:
+            media_cfg->format = AGM_FORMAT_AAC;
+            if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4LATM)
+                sess_cfg->codec.aac_dec.aac_fmt_flag = 0x04;
+            else if (params->codec.format == SND_AUDIOSTREAMFORMAT_ADIF)
+                sess_cfg->codec.aac_dec.aac_fmt_flag = 0x02;
+            else if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)
+                sess_cfg->codec.aac_dec.aac_fmt_flag = 0x00;
+            else
+                sess_cfg->codec.aac_dec.aac_fmt_flag = 0x03;
+            sess_cfg->codec.aac_dec.num_channels = params->codec.ch_in;
+            sess_cfg->codec.aac_dec.sample_rate = media_cfg->rate;
+            break;
+        case SND_AUDIOCODEC_FLAC:
+            media_cfg->format = AGM_FORMAT_FLAC;
+            sess_cfg->codec.flac_dec.num_channels = params->codec.ch_in;
+            sess_cfg->codec.flac_dec.sample_rate = media_cfg->rate;
+            break;
+    #ifdef SND_AUDIOCODEC_ALAC
+        case SND_AUDIOCODEC_ALAC:
+            media_cfg->format = AGM_FORMAT_ALAC;
+            sess_cfg->codec.alac_dec.num_channels = params->codec.ch_in;
+            sess_cfg->codec.alac_dec.sample_rate = media_cfg->rate;
+            break;
+    #endif
+    #ifdef SND_AUDIOCODEC_APE
+        case SND_AUDIOCODEC_APE:
+            media_cfg->format = AGM_FORMAT_APE;
+            sess_cfg->codec.ape_dec.num_channels = params->codec.ch_in;
+            sess_cfg->codec.ape_dec.sample_rate = media_cfg->rate;
+            break;
+    #endif
+        case SND_AUDIOCODEC_WMA:
+    #ifdef SND_AUDIOPROFILE_WMA9_LOSSLESS
+            if ((params->codec.profile == SND_AUDIOPROFILE_WMA9_PRO) ||
+                (params->codec.profile == SND_AUDIOPROFILE_WMA9_LOSSLESS) ||
+                (params->codec.profile == SND_AUDIOPROFILE_WMA10_LOSSLESS)) {
+    #else
+            if ((params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM0) ||
+                (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM1) ||
+                (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM2)) {
+    #endif
+                media_cfg->format = AGM_FORMAT_WMAPRO;
+                sess_cfg->codec.wmapro_dec.fmt_tag = params->codec.format;
+                sess_cfg->codec.wmapro_dec.num_channels = params->codec.ch_in;
+                sess_cfg->codec.wmapro_dec.sample_rate = media_cfg->rate;
+            } else {
+                media_cfg->format = AGM_FORMAT_WMASTD;
+                sess_cfg->codec.wma_dec.fmt_tag = params->codec.format;
+                sess_cfg->codec.wma_dec.num_channels = params->codec.ch_in;
+                sess_cfg->codec.wma_dec.sample_rate = media_cfg->rate;
+            }
+            break;
+        case SND_AUDIOCODEC_VORBIS:
+            media_cfg->format = AGM_FORMAT_VORBIS;
+            break;
+        default:
+            break;
         }
-        break;
-    case SND_AUDIOCODEC_VORBIS:
-        media_cfg->format = AGM_FORMAT_VORBIS;
-        break;
-    default:
-        break;
     }
 
+    // capture path
+    if (sess_cfg->dir == TX) {
+        switch (params->codec.id) {
+        case SND_AUDIOCODEC_AAC:
+            media_cfg->format = AGM_FORMAT_AAC;
+
+            sess_cfg->codec.aac_enc.aac_bit_rate = params->codec.bit_rate;
+            sess_cfg->codec.aac_enc.enc_cfg.aac_enc_mode =
+                params->codec.profile;
+            sess_cfg->codec.aac_enc.enc_cfg.aac_fmt_flag = params->codec.format;
+
+            AGM_LOGD(
+                "%s: requested configuration, AAC encode mode: %x, AAC format "
+                "flag: %x, AAC bit rate: %d",
+                __func__, sess_cfg->codec.aac_enc.enc_cfg.aac_enc_mode,
+                sess_cfg->codec.aac_enc.enc_cfg.aac_fmt_flag,
+                sess_cfg->codec.aac_enc.aac_bit_rate);
+            break;
+
+        default:
+            break;
+        }
+    }
     agm_session_update_codec_options(sess_cfg, params);
 
     AGM_LOGD("%s: format = %d rate = %d, channels = %d\n", __func__,
@@ -465,14 +517,20 @@
     priv->total_buf_size = buf_cfg->size * buf_cfg->count;
 
     sess_cfg = &priv->session_config;
+
     if (sess_cfg->dir == RX)
         priv->bytes_avail = priv->total_buf_size;
     else
-        priv->bytes_avail = 0;
+        priv->bytes_avail = priv->total_buf_size;
 
     sess_cfg->start_threshold = 0;
     sess_cfg->stop_threshold = 0;
-    sess_cfg->data_mode = AGM_DATA_NON_BLOCKING;
+
+    if (sess_cfg->dir == RX)
+        sess_cfg->data_mode = AGM_DATA_NON_BLOCKING;
+    else
+        sess_cfg->data_mode = AGM_DATA_BLOCKING;
+
     /* Populate each codec format specific params */
     ret = agm_session_update_codec_config(priv, params);
     if (ret)
@@ -526,6 +584,20 @@
     if (ret)
         return ret;
 
+    /**
+     * Unlike playback, for capture case, call
+     * agm_session_prepare it in start.
+     * For playback it is called in write.
+     * */
+    if (!priv->prepared) {
+        ret = agm_session_prepare(handle);
+        if (ret) {
+            errno = ret;
+            return ret;
+        }
+        priv->prepared = true;
+    }
+
     ret = agm_session_start(handle);
     if (ret)
         errno = ret;
@@ -746,10 +818,13 @@
     if (ret)
         return;
 
-    ret = agm_session_register_cb(priv->session_id, NULL,
-                                  AGM_EVENT_DATA_PATH, plugin);
-    ret = agm_session_register_cb(priv->session_id, NULL,
-                                  AGM_EVENT_MODULE, plugin);
+    if (priv->session_config.dir == RX) {
+        ret = agm_session_register_cb(priv->session_id, NULL,
+                                    AGM_EVENT_DATA_PATH, plugin);
+        ret = agm_session_register_cb(priv->session_id, NULL,
+                                    AGM_EVENT_MODULE, plugin);
+    }
+
     ret = agm_session_close(handle);
     if (ret)
         AGM_LOGE("%s: agm_session_close failed \n", __func__);
@@ -805,7 +880,12 @@
 static int agm_populate_codec_caps(struct agm_compress_priv *priv)
 {
     int codec_count = 0;
-    priv->compr_cap.direction = SND_COMPRESS_PLAYBACK;
+
+    if (priv->session_config.dir == RX)
+        priv->compr_cap.direction = SND_COMPRESS_PLAYBACK;
+    else
+        priv->compr_cap.direction = SND_COMPRESS_CAPTURE;
+
     priv->compr_cap.min_fragment_size =
                     COMPR_PLAYBACK_MIN_FRAGMENT_SIZE;
     priv->compr_cap.max_fragment_size =
@@ -887,6 +967,8 @@
     priv->session_config.sess_mode = sess_mode;
     priv->session_config.dir = (flags & COMPRESS_IN) ? RX : TX;
     priv->session_id = session_id;
+    AGM_LOGD("%s: requested agm session mode: %zu", __func__,
+             priv->session_config.sess_mode);
 
     if ((priv->session_config.dir == RX) && !is_playback) {
         AGM_LOGE("%s: Playback is supported for device %d \n",
@@ -904,13 +986,26 @@
         errno = ret;
         goto err_card_put;
     }
-    ret = agm_session_register_cb(session_id, &agm_compress_event_cb,
-                                  AGM_EVENT_DATA_PATH, agm_compress_plugin);
-    if (ret)
-        goto err_sess_cls;
 
-    ret = agm_session_register_cb(session_id, &agm_compress_event_cb,
+    // TODO introduce nonblock flag here
+    // instead of checking with direction and then registering callback
+    // use nonblock flag and then register call back
+    /**
+     * the agm call back aren't required for capture usecase. since
+     * the read calls to agm are data blocking.
+     * */
+    if (priv->session_config.dir == RX) {
+        ret = agm_session_register_cb(session_id, &agm_compress_event_cb,
+                                  AGM_EVENT_DATA_PATH, agm_compress_plugin);
+        if (ret)
+            goto err_sess_cls;
+
+        ret = agm_session_register_cb(session_id, &agm_compress_event_cb,
                                   AGM_EVENT_MODULE, agm_compress_plugin);
+        if (ret)
+            goto err_sess_cls;
+    }
+
     agm_populate_codec_caps(priv);
     priv->handle = handle;
     *plugin = agm_compress_plugin;
@@ -942,70 +1037,84 @@
 
     union snd_codec_options *copt = &params->codec.options;
 
-    switch (params->codec.id) {
-    case SND_AUDIOCODEC_AAC:
-        sess_cfg->codec.aac_dec.audio_obj_type = copt->generic.reserved[0];
-        sess_cfg->codec.aac_dec.total_size_of_PCE_bits = copt->generic.reserved[1];
-        break;
-    case SND_AUDIOCODEC_FLAC:
-        sess_cfg->codec.flac_dec.sample_size = copt->generic.reserved[0];
-        sess_cfg->codec.flac_dec.min_blk_size = copt->generic.reserved[1];
-        sess_cfg->codec.flac_dec.max_blk_size = copt->generic.reserved[2];
-        sess_cfg->codec.flac_dec.min_frame_size = copt->generic.reserved[3];
-        sess_cfg->codec.flac_dec.max_frame_size = copt->generic.reserved[4];
-        break;
-#ifdef SND_AUDIOCODEC_ALAC
-    case SND_AUDIOCODEC_ALAC:
-        sess_cfg->codec.alac_dec.frame_length = copt->generic.reserved[0];
-        sess_cfg->codec.alac_dec.compatible_version = copt->generic.reserved[1];
-        sess_cfg->codec.alac_dec.bit_depth = copt->generic.reserved[2];
-        sess_cfg->codec.alac_dec.pb = copt->generic.reserved[3];
-        sess_cfg->codec.alac_dec.mb = copt->generic.reserved[4];
-        sess_cfg->codec.alac_dec.kb = copt->generic.reserved[5];
-        sess_cfg->codec.alac_dec.max_run = copt->generic.reserved[6];
-        sess_cfg->codec.alac_dec.max_frame_bytes = copt->generic.reserved[7];
-        sess_cfg->codec.alac_dec.avg_bit_rate = copt->generic.reserved[8];
-        sess_cfg->codec.alac_dec.channel_layout_tag = copt->generic.reserved[9];
-        break;
-#endif
-#ifdef SND_AUDIOCODEC_APE
-    case SND_AUDIOCODEC_APE:
-        sess_cfg->codec.ape_dec.bit_width = copt->generic.reserved[0];
-        sess_cfg->codec.ape_dec.compatible_version = copt->generic.reserved[1];
-        sess_cfg->codec.ape_dec.compression_level = copt->generic.reserved[2];
-        sess_cfg->codec.ape_dec.format_flags = copt->generic.reserved[3];
-        sess_cfg->codec.ape_dec.blocks_per_frame = copt->generic.reserved[4];
-        sess_cfg->codec.ape_dec.final_frame_blocks = copt->generic.reserved[5];
-        sess_cfg->codec.ape_dec.total_frames = copt->generic.reserved[6];
-        sess_cfg->codec.ape_dec.seek_table_present = copt->generic.reserved[7];
-        break;
-#endif
-    case SND_AUDIOCODEC_WMA:
-#ifdef SND_AUDIOPROFILE_WMA9_LOSSLESS
-        if ((params->codec.profile == SND_AUDIOPROFILE_WMA9_PRO) ||
-            (params->codec.profile == SND_AUDIOPROFILE_WMA9_LOSSLESS) ||
-            (params->codec.profile == SND_AUDIOPROFILE_WMA10_LOSSLESS)) {
-#else
-        if ((params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM0) ||
-            (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM1) ||
-            (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM2)) {
-#endif
-            sess_cfg->codec.wmapro_dec.avg_bytes_per_sec = copt->generic.reserved[0];
-            sess_cfg->codec.wmapro_dec.blk_align = copt->generic.reserved[1];
-            sess_cfg->codec.wmapro_dec.bits_per_sample = copt->generic.reserved[2];
-            sess_cfg->codec.wmapro_dec.channel_mask = copt->generic.reserved[3];
-            sess_cfg->codec.wmapro_dec.enc_options = copt->generic.reserved[4];
-            sess_cfg->codec.wmapro_dec.advanced_enc_option = copt->generic.reserved[5];
-            sess_cfg->codec.wmapro_dec.advanced_enc_option2 = copt->generic.reserved[6];
-        } else {
-            sess_cfg->codec.wma_dec.avg_bytes_per_sec = copt->generic.reserved[0];
-            sess_cfg->codec.wma_dec.blk_align = copt->generic.reserved[1];
-            sess_cfg->codec.wma_dec.bits_per_sample = copt->generic.reserved[2];
-            sess_cfg->codec.wma_dec.channel_mask = copt->generic.reserved[3];
-            sess_cfg->codec.wma_dec.enc_options = copt->generic.reserved[4];
+    // playback
+    if (sess_cfg->dir == RX) {
+        switch (params->codec.id) {
+        case SND_AUDIOCODEC_AAC:
+            sess_cfg->codec.aac_dec.audio_obj_type = copt->generic.reserved[0];
+            sess_cfg->codec.aac_dec.total_size_of_PCE_bits = copt->generic.reserved[1];
+            break;
+        case SND_AUDIOCODEC_FLAC:
+            sess_cfg->codec.flac_dec.sample_size = copt->generic.reserved[0];
+            sess_cfg->codec.flac_dec.min_blk_size = copt->generic.reserved[1];
+            sess_cfg->codec.flac_dec.max_blk_size = copt->generic.reserved[2];
+            sess_cfg->codec.flac_dec.min_frame_size = copt->generic.reserved[3];
+            sess_cfg->codec.flac_dec.max_frame_size = copt->generic.reserved[4];
+            break;
+    #ifdef SND_AUDIOCODEC_ALAC
+        case SND_AUDIOCODEC_ALAC:
+            sess_cfg->codec.alac_dec.frame_length = copt->generic.reserved[0];
+            sess_cfg->codec.alac_dec.compatible_version = copt->generic.reserved[1];
+            sess_cfg->codec.alac_dec.bit_depth = copt->generic.reserved[2];
+            sess_cfg->codec.alac_dec.pb = copt->generic.reserved[3];
+            sess_cfg->codec.alac_dec.mb = copt->generic.reserved[4];
+            sess_cfg->codec.alac_dec.kb = copt->generic.reserved[5];
+            sess_cfg->codec.alac_dec.max_run = copt->generic.reserved[6];
+            sess_cfg->codec.alac_dec.max_frame_bytes = copt->generic.reserved[7];
+            sess_cfg->codec.alac_dec.avg_bit_rate = copt->generic.reserved[8];
+            sess_cfg->codec.alac_dec.channel_layout_tag = copt->generic.reserved[9];
+            break;
+    #endif
+    #ifdef SND_AUDIOCODEC_APE
+        case SND_AUDIOCODEC_APE:
+            sess_cfg->codec.ape_dec.bit_width = copt->generic.reserved[0];
+            sess_cfg->codec.ape_dec.compatible_version = copt->generic.reserved[1];
+            sess_cfg->codec.ape_dec.compression_level = copt->generic.reserved[2];
+            sess_cfg->codec.ape_dec.format_flags = copt->generic.reserved[3];
+            sess_cfg->codec.ape_dec.blocks_per_frame = copt->generic.reserved[4];
+            sess_cfg->codec.ape_dec.final_frame_blocks = copt->generic.reserved[5];
+            sess_cfg->codec.ape_dec.total_frames = copt->generic.reserved[6];
+            sess_cfg->codec.ape_dec.seek_table_present = copt->generic.reserved[7];
+            break;
+    #endif
+        case SND_AUDIOCODEC_WMA:
+    #ifdef SND_AUDIOPROFILE_WMA9_LOSSLESS
+            if ((params->codec.profile == SND_AUDIOPROFILE_WMA9_PRO) ||
+                (params->codec.profile == SND_AUDIOPROFILE_WMA9_LOSSLESS) ||
+                (params->codec.profile == SND_AUDIOPROFILE_WMA10_LOSSLESS)) {
+    #else
+            if ((params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM0) ||
+                (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM1) ||
+                (params->codec.profile == SND_AUDIOMODE_WMAPRO_LEVELM2)) {
+    #endif
+                sess_cfg->codec.wmapro_dec.avg_bytes_per_sec = copt->generic.reserved[0];
+                sess_cfg->codec.wmapro_dec.blk_align = copt->generic.reserved[1];
+                sess_cfg->codec.wmapro_dec.bits_per_sample = copt->generic.reserved[2];
+                sess_cfg->codec.wmapro_dec.channel_mask = copt->generic.reserved[3];
+                sess_cfg->codec.wmapro_dec.enc_options = copt->generic.reserved[4];
+                sess_cfg->codec.wmapro_dec.advanced_enc_option = copt->generic.reserved[5];
+                sess_cfg->codec.wmapro_dec.advanced_enc_option2 = copt->generic.reserved[6];
+            } else {
+                sess_cfg->codec.wma_dec.avg_bytes_per_sec = copt->generic.reserved[0];
+                sess_cfg->codec.wma_dec.blk_align = copt->generic.reserved[1];
+                sess_cfg->codec.wma_dec.bits_per_sample = copt->generic.reserved[2];
+                sess_cfg->codec.wma_dec.channel_mask = copt->generic.reserved[3];
+                sess_cfg->codec.wma_dec.enc_options = copt->generic.reserved[4];
+            }
+            break;
+        default:
+            break;
         }
-        break;
-    default:
-        break;
+    }
+
+    // capture
+    if (sess_cfg->dir == TX) {
+        switch (params->codec.id) {
+        case SND_AUDIOCODEC_AAC:
+            break;
+
+        default:
+            break;
+        }
     }
 }
diff --git a/plugins/tinyalsa/src/agm_pcm_plugin.c b/plugins/tinyalsa/src/agm_pcm_plugin.c
index 53c86b3..8c271d7 100644
--- a/plugins/tinyalsa/src/agm_pcm_plugin.c
+++ b/plugins/tinyalsa/src/agm_pcm_plugin.c
@@ -76,6 +76,7 @@
     snd_pcm_uframes_t avail_min; /* RW: min available frames for wakeup */
     uint32_t wall_clk_msw;
     uint32_t wall_clk_lsw;
+    uint32_t frame_counter;
 };
 
 struct agm_mmap_buffer_port {
@@ -299,6 +300,7 @@
         if (frame_cnt1 != frame_cnt2)
             continue;
 
+        pos_buf->frame_counter = frame_cnt1;
         return 0;
     }
 
@@ -316,6 +318,7 @@
     int ret = 0;
     uint32_t period_size = priv->period_size; /** in frames */
     uint32_t crossed_boundary = 0;
+    uint32_t old_frame_counter = priv->pos_buf->frame_counter;
 
     do {
         ret = agm_pcm_plugin_get_shared_pos(priv->pos_buf,
@@ -371,8 +374,11 @@
         }
 
         priv->pos_buf->hw_ptr = new_hw_ptr;
-        priv->pos_buf->wall_clk_lsw = wall_clk_lsw;
-        priv->pos_buf->wall_clk_msw = wall_clk_msw;
+        // cache wall clk only when there's data update in shared buffer
+        if (priv->pos_buf->frame_counter != old_frame_counter) {
+            priv->pos_buf->wall_clk_lsw = wall_clk_lsw;
+            priv->pos_buf->wall_clk_msw = wall_clk_msw;
+        }
         clock_gettime(CLOCK_MONOTONIC, &priv->pos_buf->tstamp);
     }
 
diff --git a/plugins/tinyalsa/test/agmcompresscap.c b/plugins/tinyalsa/test/agmcompresscap.c
index d5e1794..7fc39d6 100644
--- a/plugins/tinyalsa/test/agmcompresscap.c
+++ b/plugins/tinyalsa/test/agmcompresscap.c
@@ -271,7 +271,8 @@
     if (verbose)
         fprintf(finfo, "%s: entry, reading %u bytes\n", __func__, length);
         if (!name) {
-                file = STDOUT_FILENO;
+            file = STDOUT_FILENO;
+            exit(EXIT_FAILURE);
         } else {
             file = open(name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
             if (file == -1) {
@@ -469,7 +470,7 @@
 
 int main(int argc, char **argv)
 {
-    char *file = NULL;
+    char *file;
     unsigned long buffer_size = 0;
     unsigned int card = 0, device = 0, frag = 0, length = 0;
     unsigned int rate = DEFAULT_RATE, channels = DEFAULT_CHANNELS;
@@ -493,6 +494,7 @@
 
     verbose = 0;
 
+    file = argv[1];
     /* parse command line arguments */
     argv += 2;
     while (*argv) {
diff --git a/plugins/tinyalsa/test/agmcompressplay.c b/plugins/tinyalsa/test/agmcompressplay.c
index 0e5018a..1bfbeec 100644
--- a/plugins/tinyalsa/test/agmcompressplay.c
+++ b/plugins/tinyalsa/test/agmcompressplay.c
@@ -295,7 +295,8 @@
         } else if (strcmp(*argv, "-i") == 0) {
             intf_name = (char**) malloc(intf_num * sizeof(char*));
             if (!intf_name) {
-                printf("invalid memory\n");
+                printf("insufficient memory\n");
+                return 1;
             }
             for (i = 0; i < intf_num ; i++){
                 argv++;
@@ -306,6 +307,7 @@
             device_kv = (unsigned int *) malloc(intf_num * sizeof(unsigned int));
             if (!device_kv) {
                 printf(" insufficient memory\n");
+                return 1;
             }
             for (i = 0; i < intf_num ; i++) {
                 argv++;
@@ -326,6 +328,7 @@
             devicepp_kv = (unsigned int *) malloc(intf_num * sizeof(unsigned int));
             if (!devicepp_kv) {
                 printf(" insufficient memory\n");
+                return 1;
             }
             for (i = 0; i < intf_num ; i++) {
                 devicepp_kv[i] = DEVICEPP_RX_AUDIO_MBDRC;
@@ -377,11 +380,22 @@
     char *buffer;
     int num_read, wrote;
     unsigned int channels = 0, rate = 0, bits = 0;
-    struct device_config *dev_config = (struct device_config *)malloc(intf_num*sizeof(struct device_config *));
-    struct group_config *grp_config = (struct group_config *)malloc(intf_num*sizeof(struct group_config *));
+    struct device_config *dev_config = NULL;
+    struct group_config *grp_config = NULL;
     int size, index, ret = 0;
     uint32_t miid = 0;
 
+    dev_config = (struct device_config *) malloc(intf_num * sizeof(struct device_config *));
+    if (!dev_config) {
+        printf("Failed to allocate memory for dev config");
+        return;
+    }
+    grp_config = (struct group_config *) malloc(intf_num * sizeof(struct group_config *));
+    if (!grp_config) {
+        printf("Failed to allocate memory for group config");
+        return;
+    }
+
     stream_kv = stream_kv ? stream_kv : COMPRESSED_OFFLOAD_PLAYBACK;
 
     if (verbose)
diff --git a/plugins/tinyalsa/test/agmmixer.c b/plugins/tinyalsa/test/agmmixer.c
old mode 100644
new mode 100755
index b7ef20c..7458d27
--- a/plugins/tinyalsa/test/agmmixer.c
+++ b/plugins/tinyalsa/test/agmmixer.c
@@ -27,6 +27,42 @@
 ** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **/
 
+/*
+* Changes from Qualcomm Innovation Center are provided under the following license:
+*
+* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted (subject to the limitations in the
+* disclaimer below) provided that the following conditions are met:
+*
+*    * Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*
+*    * Redistributions in binary form must reproduce the above
+*      copyright notice, this list of conditions and the following
+*      disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*
+*    * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
+*      contributors may be used to endorse or promote products derived
+*      from this software without specific prior written permission.
+*
+* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+* GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+* HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
 #include <errno.h>
 #include <expat.h>
 #include <tinyalsa/asoundlib.h>
@@ -582,7 +618,7 @@
     struct agm_key_value *gkv = NULL, *ckv = NULL;
     struct prop_data *prop = NULL;
     uint8_t *metadata = NULL;
-    uint32_t num_gkv = 1, num_ckv = 2, num_props = 0;
+    uint32_t num_gkv = 1, num_ckv = 3, num_props = 0;
     uint32_t gkv_size, ckv_size, prop_size, ckv_index = 0;
     int ctl_len = 0, offset = 0;
     int ret = 0;
@@ -627,6 +663,10 @@
     ckv[ckv_index].key = BITWIDTH;
     ckv[ckv_index].value = bitwidth;
 
+    ckv_index++;
+    ckv[ckv_index].key = GAIN;;
+    ckv[ckv_index].value = 0;
+
     prop->prop_id = 0;  //Update prop_id here
     prop->num_values = num_props;
 
diff --git a/plugins/tinyalsa/test/agmplay.c b/plugins/tinyalsa/test/agmplay.c
index 3b3386e..44bd986 100644
--- a/plugins/tinyalsa/test/agmplay.c
+++ b/plugins/tinyalsa/test/agmplay.c
@@ -96,13 +96,12 @@
     struct chunk_fmt chunk_fmt;
     unsigned int card = 100, device = 100, i=0;
     int intf_num = 1;
-    unsigned int *device_kv = 0;
+    unsigned int *device_kv = NULL;
     unsigned int stream_kv = 0;
     unsigned int instance_kv = INSTANCE_1;
     unsigned int *devicepp_kv = NULL;
     bool haptics = false;
     char **intf_name = NULL;
-    struct device_config config;
     char *filename;
     int more_chunks = 1, ret = 0;
 
@@ -164,7 +163,8 @@
         } else if (strcmp(*argv, "-i") == 0) {
             intf_name = (char**) malloc(intf_num * sizeof(char*));
             if (!intf_name) {
-                printf("invalid memory\n");
+                printf("insufficient memory\n");
+                return 1;
             }
             for (i = 0; i < intf_num ; i++){
                 argv++;
@@ -179,6 +179,7 @@
             device_kv = (unsigned int *) malloc(intf_num * sizeof(unsigned int));
             if (!device_kv) {
                 printf(" insufficient memory\n");
+                return 1;
             }
             for (i = 0; i < intf_num ; i++) {
                 argv++;
@@ -199,6 +200,7 @@
             devicepp_kv = (unsigned int *) malloc(intf_num * sizeof(unsigned int));
             if (!devicepp_kv) {
                 printf(" insufficient memory\n");
+                return 1;
             }
             for (i = 0; i < intf_num ; i++) {
                 devicepp_kv[i] = DEVICEPP_RX_AUDIO_MBDRC;
@@ -217,7 +219,7 @@
             argv++;
     }
 
-    if (*intf_name == NULL)
+    if (intf_name == NULL)
         return 1;
 
     play_sample(file, card, device, device_kv, stream_kv, instance_kv, devicepp_kv,
@@ -245,10 +247,22 @@
     int playback_path, playback_value;
     int size, index, ret = 0;
     int num_read;
-    struct group_config *grp_config = (struct group_config *)malloc(intf_num*sizeof(struct group_config *));
-    struct device_config *dev_config = (struct device_config *)malloc(intf_num*sizeof(struct device_config *));
+    struct group_config *grp_config = NULL;
+    struct device_config *dev_config = NULL;
     uint32_t miid = 0;
 
+    grp_config = (struct group_config *) malloc(intf_num * sizeof(struct group_config *));
+    if (!grp_config) {
+        printf("Failed to allocate memory for group config");
+        return;
+    }
+
+    dev_config = (struct device_config *) malloc(intf_num * sizeof(struct device_config *));
+    if (!dev_config) {
+        printf("Failed to allocate memory for dev config");
+        return;
+    }
+
     memset(&config, 0, sizeof(config));
     config.channels = fmt.num_channels;
     config.rate = fmt.sample_rate;
diff --git a/service/inc/private/agm/device.h b/service/inc/private/agm/device.h
index 5546720..0324658 100644
--- a/service/inc/private/agm/device.h
+++ b/service/inc/private/agm/device.h
@@ -240,5 +240,5 @@
 int device_get_group_list(struct aif_info *aif_list, size_t *num_groups);
 
 int device_get_start_refcnt(struct device_obj *dev_obj);
-bool get_file_path_extn(char* file_path_extn);
+bool get_file_path_extn(char* file_path_extn, char* file_path_extn_wo_variant);
 #endif
diff --git a/service/inc/public/agm/agm_api.h b/service/inc/public/agm/agm_api.h
index 06de0c2..8680fa1 100644
--- a/service/inc/public/agm/agm_api.h
+++ b/service/inc/public/agm/agm_api.h
@@ -58,6 +58,40 @@
  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+**
+** Changes from Qualcomm Innovation Center are provided under the following license:
+** Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted (subject to the limitations in the
+** disclaimer below) provided that the following conditions are met:
+**
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**
+**   * Redistributions in binary form must reproduce the above
+**     copyright notice, this list of conditions and the following
+**     disclaimer in the documentation and/or other materials provided
+**     with the distribution.
+**
+**   * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+** NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+** GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+** HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+** IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef _AGM_INTF_H_
@@ -180,6 +214,7 @@
     AGM_SESSION_NO_HOST,         /**< Hostless mode */
     AGM_SESSION_NON_TUNNEL,      /**< Non tunnel mode */
     AGM_SESSION_NO_CONFIG,       /**< No Config mode*/
+    AGM_SESSION_COMPRESS,        /**< Compress mode*/
 };
 
 struct agm_extern_alloc_buff_info{
@@ -219,6 +254,19 @@
 };
 
 /**
+ * AAC encoder parameters
+ */
+struct agm_session_aac_enc_cfg {
+    uint16_t aac_enc_mode; /**< AAC encoder mode */
+    uint16_t aac_fmt_flag; /**< AAC format flag */
+};
+
+struct agm_session_aac_enc {
+    uint32_t aac_bit_rate;
+    struct agm_session_aac_enc_cfg enc_cfg;
+};
+
+/**
  * FLAC decoder parameters
  */
 struct agm_session_flac_dec {
@@ -302,6 +350,7 @@
 union agm_session_codec
 {
     struct agm_session_aac_dec aac_dec;        /**< AAC decoder config */
+    struct agm_session_aac_enc aac_enc;        /**< AAC encoder config */
     struct agm_session_flac_dec flac_dec;      /**< Flac decoder config */
     struct agm_session_alac_dec alac_dec;      /**< Alac decoder config */
     struct agm_session_ape_dec ape_dec;        /**< APE decoder config */
diff --git a/service/src/device.c b/service/src/device.c
index ffa36a6..ea03c7f 100644
--- a/service/src/device.c
+++ b/service/src/device.c
@@ -1120,7 +1120,8 @@
 #endif
 }
 
-static void split_snd_card_name(const char * in_snd_card_name, char* file_path_extn)
+static void split_snd_card_name(const char * in_snd_card_name, char* file_path_extn,
+                                char* file_path_extn_wo_variant)
 {
     /* Sound card name follows below mentioned convention:
        <target name>-<form factor>-<variant>-snd-card.
@@ -1143,6 +1144,7 @@
 
     while ((card_sub_str = strtok_r(NULL, "-", &tmp))) {
         if (strncmp(card_sub_str, "snd", strlen("snd"))) {
+            strlcpy(file_path_extn_wo_variant, file_path_extn, FILE_PATH_EXTN_MAX_SIZE);
             strlcat(file_path_extn, "_", FILE_PATH_EXTN_MAX_SIZE);
             strlcat(file_path_extn, card_sub_str, FILE_PATH_EXTN_MAX_SIZE);
         }
@@ -1244,7 +1246,7 @@
     return is_updated;
 }
 
-bool get_file_path_extn(char* file_path_extn)
+bool get_file_path_extn(char* file_path_extn, char* file_path_extn_wo_variant)
 {
     int snd_card_found = false, retry = 0;
     char snd_card_name[FILE_PATH_EXTN_MAX_SIZE];
@@ -1253,7 +1255,7 @@
         snd_card_found = update_snd_card_info(snd_card_name);
 
         if (snd_card_found) {
-            split_snd_card_name(snd_card_name, file_path_extn);
+            split_snd_card_name(snd_card_name, file_path_extn, file_path_extn_wo_variant);
             AGM_LOGV("Found Codec sound card");
             break;
         } else {
diff --git a/service/src/graph.c b/service/src/graph.c
index 39e0409..aea9e75 100644
--- a/service/src/graph.c
+++ b/service/src/graph.c
@@ -26,6 +26,39 @@
  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+** Changes from Qualcomm Innovation Center are provided under the following license:
+** Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted (subject to the limitations in the
+** disclaimer below) provided that the following conditions are met:
+**
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**
+**   * Redistributions in binary form must reproduce the above
+**     copyright notice, this list of conditions and the following
+**     disclaimer in the documentation and/or other materials provided
+**     with the distribution.
+**
+**   * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+** NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+** GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+** HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+** IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #define LOG_TAG "AGM: graph"
 
@@ -242,6 +275,9 @@
 
         if (mode == AGM_DATA_PUSH_PULL)
             buf_config.shmem_ep_tag = PULL_PUSH_SHMEM_ENDPOINT;
+        else if ((sess_obj->stream_config.sess_mode == AGM_SESSION_COMPRESS) &&
+                 (sess_obj->stream_config.dir == TX))
+            buf_config.shmem_ep_tag = RD_SHMEM_ENDPOINT;
         else
             buf_config.shmem_ep_tag = SHMEM_ENDPOINT;
         /**
@@ -289,6 +325,7 @@
     struct gsl_init_data init_data;
     const char *delta_file_path;
     char file_path_extn[FILE_PATH_EXTN_MAX_SIZE] = {0};
+    char file_path_extn_wo_variant[FILE_PATH_EXTN_MAX_SIZE] = {0};
     bool snd_card_found = false;
 
 #ifndef ACDB_PATH
@@ -297,7 +334,7 @@
     /*Populate acdbfiles from the shared file path*/
     acdb_files.num_files = 0;
 
-    snd_card_found = get_file_path_extn(file_path_extn);
+    snd_card_found = get_file_path_extn(file_path_extn, file_path_extn_wo_variant);
     if (snd_card_found) {
         snprintf(acdb_path, ACDB_PATH_MAX_LENGTH, "%s%s", ACDB_PATH, file_path_extn);
     } else {
@@ -307,8 +344,15 @@
     AGM_LOGI("acdb file path: %s\n", acdb_path);
 
     ret = get_acdb_files_from_directory(acdb_path, &acdb_files);
-    if (ret)
-       goto err;
+    if (ret) {
+        /* if acdb_path is not found, try without variant */
+        snprintf(acdb_path, ACDB_PATH_MAX_LENGTH, "%s%s", ACDB_PATH,
+                file_path_extn_wo_variant);
+        AGM_LOGI("trying - acdb file path: %s\n", acdb_path);
+        ret = get_acdb_files_from_directory(acdb_path, &acdb_files);
+        if (ret)
+            goto err;
+    }
 
 #ifdef ACDB_DELTA_FILE_PATH
     delta_file_path = CONV_TO_STRING(ACDB_DELTA_FILE_PATH);
@@ -1329,6 +1373,10 @@
     if ((graph_obj->sess_obj->stream_config.sess_mode == AGM_SESSION_NON_TUNNEL) &&
         (graph_obj->sess_obj->stream_config.dir == (RX | TX)))
          read_mod_tag = RD_SHMEM_ENDPOINT;
+    else if ((graph_obj->sess_obj->stream_config.sess_mode ==
+              AGM_SESSION_COMPRESS) &&
+             (graph_obj->sess_obj->stream_config.dir == TX))
+         read_mod_tag = RD_SHMEM_ENDPOINT;
 
     gsl_buff.timestamp = buffer->timestamp;
     gsl_buff.flags = buffer->flags;
diff --git a/service/src/graph_module.c b/service/src/graph_module.c
index 83e5c10..f77aa0f 100644
--- a/service/src/graph_module.c
+++ b/service/src/graph_module.c
@@ -59,6 +59,39 @@
  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+** Changes from Qualcomm Innovation Center are provided under the following license:
+** Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted (subject to the limitations in the
+** disclaimer below) provided that the following conditions are met:
+**
+**   * Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**
+**   * Redistributions in binary form must reproduce the above
+**     copyright notice, this list of conditions and the following
+**     disclaimer in the documentation and/or other materials provided
+**     with the distribution.
+**
+**   * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
+**     contributors may be used to endorse or promote products derived
+**     from this software without specific prior written permission.
+**
+** NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
+** GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
+** HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+** IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+** IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #define LOG_TAG "AGM: graph_module"
@@ -215,8 +248,9 @@
     case AGM_FORMAT_MP3:
     case AGM_FORMAT_AAC:
     default:
-         break;
+        break;
     }
+    AGM_LOGD("%s: bit width: %d", __func__, bit_width);
 
     return bit_width;
 }
@@ -1264,6 +1298,149 @@
 }
 
 /**
+ *  codec specific encoder config only for TX type
+ */
+int configure_encoder_output_media_format(struct module_info *mod,
+                                          struct graph_obj *graph_obj) {
+    int ret = 0;
+    struct session_obj *sess_obj = graph_obj->sess_obj;
+    struct apm_module_param_data_t *header;
+    struct param_id_encoder_output_config_t *enc_out_conf_param;
+    uint8_t *payload = NULL;
+    size_t payload_size = 0;
+    size_t size_apm_module = sizeof(struct apm_module_param_data_t);
+    size_t size_encoder_config =
+        sizeof(struct param_id_encoder_output_config_t);
+    size_t size_apm_and_encoder_config = size_apm_module + size_encoder_config;
+    AGM_LOGV("Enter");
+
+    /**
+     * For Encoder module, PARAM_ID_ENCODER_OUTPUT_CONFIG
+     * */
+
+    /**
+     * only TX session, hence in media config
+     * */
+    switch (sess_obj->in_media_config.format) {
+        case AGM_FORMAT_AAC: {
+            size_t size_aac_cfg = sizeof(struct aac_enc_cfg_t);
+            payload_size = size_apm_and_encoder_config + size_aac_cfg;
+
+            /*ensure that the payloadszie is byte multiple atleast*/
+            ALIGN_PAYLOAD(payload_size, 8);
+            payload = (uint8_t *)calloc(1, payload_size);
+            if (!payload) {
+                AGM_LOGE("Not enough memory for payload");
+                ret = -ENOMEM;
+                goto err;
+            }
+
+            struct param_id_encoder_output_config_t enc_out_conf_param;
+            enc_out_conf_param.data_format = AGM_DATA_FORMAT_FIXED_POINT;
+            enc_out_conf_param.fmt_id = MEDIA_FMT_AAC;
+            enc_out_conf_param.payload_size = size_aac_cfg;
+            memcpy(payload + size_apm_module, &enc_out_conf_param,
+                   size_encoder_config);
+
+            memcpy(payload + size_apm_and_encoder_config,
+                   &(sess_obj->stream_config.codec.aac_enc.enc_cfg),
+                   size_aac_cfg);
+            break;
+        }
+
+        default:
+            ret = -EINVAL;
+            goto err;
+            break;
+    }
+
+    header = (struct apm_module_param_data_t *)(payload);
+    header->module_instance_id = mod->miid;
+    header->param_id = PARAM_ID_ENCODER_OUTPUT_CONFIG;
+    header->error_code = 0x0;
+    header->param_size = sizeof(struct param_id_encoder_output_config_t);
+
+    ret = gsl_set_custom_config(graph_obj->graph_handle, payload, payload_size);
+    if (ret != 0) {
+        ret = ar_err_get_lnx_err_code(ret);
+        AGM_LOGE(
+            "custom_config command for module %d with "
+            "PARAM_ID_ENCODER_OUTPUT_CONFIG failed with error %d",
+            mod->tag, ret);
+        goto err;
+    } else {
+        struct aac_enc_cfg_t *aac_cfg =
+            (struct aac_enc_cfg_t *)(payload + size_apm_and_encoder_config);
+        AGM_LOGD("AAC encode mode: 0x%x, fmt_flag: 0x%x", aac_cfg->enc_mode,
+                 aac_cfg->aac_fmt_flag);
+        free(payload);
+        payload = NULL;
+    }
+
+    /**
+     * For Encoder Module, PARAM_ID_ENC_BITRATE
+     * */
+    switch (sess_obj->in_media_config.format) {
+        case AGM_FORMAT_AAC: {
+            struct param_id_enc_bitrate_param_t *bitrate_param = NULL;
+            size_t bitrate_param_size =
+                sizeof(struct param_id_enc_bitrate_param_t);
+            payload_size = size_apm_module + bitrate_param_size;
+            /*ensure that the payloadszie is byte multiple atleast*/
+            ALIGN_PAYLOAD(payload_size, 8);
+            payload = (uint8_t *)calloc(1, payload_size);
+            if (!payload) {
+                AGM_LOGE("Not enough memory for payload");
+                ret = -ENOMEM;
+                goto err;
+            }
+
+            bitrate_param =
+                (struct param_id_enc_bitrate_param_t *)(payload +
+                                                        size_apm_module);
+            bitrate_param->bitrate =
+                sess_obj->stream_config.codec.aac_enc.aac_bit_rate;
+            break;
+        }
+
+        default:
+            ret = -EINVAL;
+            goto err;
+            break;
+    }
+    header = (struct apm_module_param_data_t *)(payload);
+    header->module_instance_id = mod->miid;
+    header->param_id = PARAM_ID_ENC_BITRATE;
+    header->error_code = 0x0;
+    header->param_size = sizeof(struct param_id_enc_bitrate_param_t);
+
+    ret = gsl_set_custom_config(graph_obj->graph_handle, payload, payload_size);
+    if (ret != 0) {
+        ret = ar_err_get_lnx_err_code(ret);
+        AGM_LOGE(
+            "custom_config command for module %d with "
+            "PARAM_ID_ENC_BITRATE failed with error %d",
+            mod->tag, ret);
+        goto err;
+    } else {
+        struct param_id_enc_bitrate_param_t *bitrate_param =
+            (struct param_id_enc_bitrate_param_t *)(payload + size_apm_module);
+        AGM_LOGD("AAC bitrate: %d", bitrate_param->bitrate);
+        free(payload);
+        payload = NULL;
+    }
+
+err:
+done:
+    if (payload) {
+        free(payload);
+        payload = NULL;
+    }
+    AGM_LOGV("Exit: %d", ret);
+    return ret;
+}
+
+/**
  *Configure placeholder encoder
 */
 int configure_placeholder_enc(struct module_info *mod,
@@ -1282,6 +1459,14 @@
     }
     sess_obj = graph_obj->sess_obj;
 
+    /* configure only in case of compress capture */
+    if (sess_obj->stream_config.sess_mode == AGM_SESSION_COMPRESS &&
+        sess_obj->stream_config.dir == TX) {
+        ret = configure_encoder_output_media_format(mod, graph_obj);
+        if (ret != 0)
+            AGM_LOGE("configure_encoder_output_media_format failed: %d", ret);
+    }
+
     /* 1. Configure placeholder encoder with Real ID */
     ret = get_media_fmt_id_and_size(sess_obj->in_media_config.format,
                                     &payload_size, &real_fmt_id);
@@ -1590,14 +1775,18 @@
     uint8_t *payload = NULL;
     size_t payload_size = 0;
 
+    AGM_LOGD("Enter");
+
     /*
-     *Note: read shared mem ep is configured only in case of non-tunnel
+     *Note: read shared mem ep is configured in case of non-tunnel
      *decode sessions where the client has configured the session with
      *AGM_SESSION_FLAG_INBAND_SRCM flag
      *In case of non-tunnel encode sessions, we set the num_frames_per_buff cfg
      *as a part of calibration itself.
+     *In case of compress capture case also , read shared mem ep is configured.
      */
-    if (!(sess_obj->stream_config.sess_flags & AGM_SESSION_FLAG_INBAND_SRCM))
+    if (!(sess_obj->stream_config.sess_flags & AGM_SESSION_FLAG_INBAND_SRCM) &&
+        !(sess_obj->stream_config.sess_mode == AGM_SESSION_COMPRESS))
         goto done;
 
     AGM_LOGD("entry mod tag %x miid %x mid %x sess_flags %x",mod->tag, mod->miid, mod->mid,
@@ -1630,16 +1819,25 @@
      *In NT mode session in_media config represents config for data being captured
      *Hence for NT Mode decode it would mean PCM data.
      */
-    if (is_format_pcm(sess_obj->in_media_config.format))
-       rd_sh_mem_cfg->num_frames_per_buffer = 0x0; /*As many frames as possible*/
-    else
-       /*TODO:This is encode usecase hence ideally client wont enable SRCM event
-        *Even if the client wants it enabled, then we configure 1 frame every for
-        *every read call;
-        */
-       rd_sh_mem_cfg->num_frames_per_buffer = 0x1;
+    if (sess_obj->stream_config.sess_mode == AGM_SESSION_NON_TUNNEL) {
+        rd_sh_mem_cfg->metadata_control_flags = 0x2; /*ENABLE_MEDIA_FORMAT_MD*/
+        if (is_format_pcm(sess_obj->in_media_config.format))
+            rd_sh_mem_cfg->num_frames_per_buffer = 0x0; /*As many frames as possible*/
+        else
+        /*TODO:This is encode usecase hence ideally client wont enable SRCM event
+            *Even if the client wants it enabled, then we configure 1 frame every for
+            *every read call;
+            */
+            rd_sh_mem_cfg->num_frames_per_buffer = 0x1;
+    }
 
-    rd_sh_mem_cfg->metadata_control_flags = 0x2; /*ENABLE_MEDIA_FORMAT_MD*/
+    /* For compress capture */
+    if (sess_obj->stream_config.sess_mode == AGM_SESSION_COMPRESS &&
+        sess_obj->stream_config.dir == TX) {
+        rd_sh_mem_cfg->num_frames_per_buffer = 0x1;
+        AGM_LOGD("compress capture uses 1 frame per buffer");
+    }
+
 
     ret = gsl_set_custom_config(graph_obj->graph_handle, payload, payload_size);
     if (ret != 0) {