Merge "hal: expose offload functions only for offload playback"
diff --git a/hal/Android.mk b/hal/Android.mk
index 1973178..e7ba38f 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -231,10 +231,6 @@
     LOCAL_SRC_FILES += audio_extn/source_track.c
 endif
 
-ifeq ($(strip $(AUDIO_FEATURE_ENABLED_AUDIOSPHERE)),true)
-    LOCAL_CFLAGS += -DAUDIOSPHERE_ENABLED
-endif
-
 LOCAL_SHARED_LIBRARIES := \
 	liblog \
 	libcutils \
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index 96b0a8b..9d80112 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -72,6 +72,8 @@
 #define AUDIO_OFFLOAD_CODEC_APE_SAMPLE_RATE "music_offload_ape_sample_rate"
 #define AUDIO_OFFLOAD_CODEC_APE_SEEK_TABLE_PRESENT "music_offload_seek_table_present"
 
+#define AUDIO_OFFLOAD_CODEC_VORBIS_BITSTREAM_FMT "music_offload_vorbis_bitstream_fmt"
+
 /* Query handle fm parameter*/
 #define AUDIO_PARAMETER_KEY_HANDLE_FM "handle_fm"
 
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 34da4fe..39ad4d1 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -81,8 +81,6 @@
 /* Query offload playback instances count */
 #define AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE "offload_num_active"
 #define AUDIO_PARAMETER_HPX            "HPX"
-#define AUDIO_PARAMETER_KEY_ASPHERE_ENABLE   "asphere_enable"
-#define AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH "asphere_strength"
 
 #ifndef FM_ENABLED
 #define audio_extn_fm_set_parameters(adev, parms) (0)
@@ -558,103 +556,6 @@
     return ret;
 }
 
-#ifndef AUDIOSPHERE_ENABLED
-#define audio_extn_asphere_set_parameters(adev, parms)  (0)
-#define audio_extn_asphere_get_parameters(adev, query, reply) (0)
-#else
-int32_t audio_extn_asphere_set_parameters(const struct audio_device *adev,
-                                     struct str_parms *parms)
-{
-    int ret = 0, val[2];
-    char value[32] = {0};
-    int set_enable, set_strength;
-    int enable = -1, strength = -1;
-    struct mixer_ctl *ctl = NULL;
-    const char *mixer_ctl_name = "MSM ASphere Set Param";
-    char propValue[PROPERTY_VALUE_MAX] = {0};
-    bool asphere_prop_enabled = false;
-
-    if (property_get("audio.pp.asphere.enabled", propValue, "false")) {
-        if (!strncmp("true", propValue, 4))
-            asphere_prop_enabled = true;
-    }
-
-    if (!asphere_prop_enabled) {
-        ALOGV("%s: property not set!!! not doing anything", __func__);
-        return ret;
-    }
-
-    set_enable = str_parms_get_str(parms,
-                            AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
-                            value, sizeof(value));
-    if (set_enable > 0)
-        enable = atoi(value);
-
-    set_strength = str_parms_get_str(parms,
-                            AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
-                            value, sizeof(value));
-    if (set_strength > 0)
-        strength = atoi(value);
-
-    if (set_enable >= 0 || set_strength >= 0) {
-        ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
-        if (!ctl) {
-            ALOGE("%s: could not get ctl for mixer cmd - %s",
-                  __func__, mixer_ctl_name);
-            return -EINVAL;
-        }
-        ALOGD("%s: set ctl \"%s:%d,%d\"",
-              __func__, mixer_ctl_name, enable, strength);
-        val[0] = enable;
-        val[1] = strength;
-        ret = mixer_ctl_set_array(ctl, val, sizeof(val)/sizeof(val[0]));
-        if (ret)
-            ALOGE("%s: set ctl failed!!!\"%s:%d,%d\"",
-                  __func__, mixer_ctl_name, enable, strength);
-    }
-    ALOGV("%s: exit ret %d", __func__, ret);
-    return ret;
-}
-
-int32_t audio_extn_asphere_get_parameters(const struct audio_device *adev,
-                                          struct str_parms *query,
-                                          struct str_parms *reply)
-{
-    int ret = 0, val[2] = {-1, -1};
-    char value[32] = {0};
-    int get_enable, get_strength;
-    struct mixer_ctl *ctl = NULL;
-    const char *mixer_ctl_name = "MSM ASphere Set Param";
-
-    get_enable = str_parms_get_str(query,
-                                   AUDIO_PARAMETER_KEY_ASPHERE_ENABLE,
-                                   value, sizeof(value));
-    get_strength = str_parms_get_str(query,
-                                     AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH,
-                                     value, sizeof(value));
-    if (get_enable > 0 || get_strength > 0) {
-        ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
-        if (!ctl) {
-            ALOGE("%s: could not get ctl for mixer cmd - %s",
-                  __func__, mixer_ctl_name);
-            return -EINVAL;
-        }
-        ret = mixer_ctl_get_array(ctl, val, sizeof(val)/sizeof(val[0]));
-        if (ret)
-            ALOGE("%s: got ctl failed!!! \"%s:%d,%d\"",
-                   __func__, mixer_ctl_name, val[0], val[1]);
-        if (get_enable > 0)
-            str_parms_add_int(reply,
-                              AUDIO_PARAMETER_KEY_ASPHERE_ENABLE, val[0]);
-        if (get_strength > 0)
-            str_parms_add_int(reply,
-                              AUDIO_PARAMETER_KEY_ASPHERE_STRENGTH, val[1]);
-    }
-    ALOGV("%s: exit ret %d", __func__, ret);
-    return ret;
-}
-#endif
-
 void audio_extn_set_parameters(struct audio_device *adev,
                                struct str_parms *parms)
 {
@@ -672,7 +573,8 @@
    audio_extn_hpx_set_parameters(adev, parms);
    audio_extn_pm_set_parameters(parms);
    audio_extn_source_track_set_parameters(adev, parms);
-   audio_extn_asphere_set_parameters(adev, parms);
+   if (adev->offload_effects_set_parameters != NULL)
+       adev->offload_effects_set_parameters(parms);
 }
 
 void audio_extn_get_parameters(const struct audio_device *adev,
@@ -686,7 +588,8 @@
     audio_extn_dts_eagle_get_parameters(adev, query, reply);
     audio_extn_hpx_get_parameters(query, reply);
     audio_extn_source_track_get_parameters(adev, query, reply);
-    audio_extn_asphere_get_parameters(adev, query, reply);
+    if (adev->offload_effects_get_parameters != NULL)
+        adev->offload_effects_get_parameters(query, reply);
 
     kv_pairs = str_parms_to_str(reply);
     ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs);
@@ -705,25 +608,23 @@
     if (out->format == AUDIO_FORMAT_FLAC) {
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
         if (ret >= 0) {
-            out->gapless_mdata.min_blk_size =
             out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
         if (ret >= 0) {
-            out->gapless_mdata.max_blk_size =
             out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ALOGV("FLAC metadata: min_blk_size %d, max_blk_size %d min_frame_size %d max_frame_size %d",
               out->compr_config.codec->options.flac_dec.min_blk_size,
@@ -736,63 +637,63 @@
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_FRAME_LENGTH, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.alac.frame_length = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_COMPATIBLE_VERSION, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.alac.compatible_version = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_BIT_DEPTH, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.alac.bit_depth = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_PB, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.alac.pb = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MB, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.alac.mb = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
 
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_KB, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.alac.kb = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_NUM_CHANNELS, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.alac.num_channels = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MAX_RUN, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.alac.max_run = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_MAX_FRAME_BYTES, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.alac.max_frame_bytes = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_AVG_BIT_RATE, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.alac.avg_bit_rate = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_SAMPLING_RATE, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.alac.sample_rate = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_ALAC_CHANNEL_LAYOUT_TAG, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.alac.channel_layout_tag = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ALOGV("ALAC CSD values: frameLength %d bitDepth %d numChannels %d"
                 " maxFrameBytes %d, avgBitRate %d, sampleRate %d",
@@ -808,52 +709,52 @@
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_COMPATIBLE_VERSION, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.ape.compatible_version = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_COMPRESSION_LEVEL, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.ape.compression_level = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_FORMAT_FLAGS, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.ape.format_flags = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_BLOCKS_PER_FRAME, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.ape.blocks_per_frame = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_FINAL_FRAME_BLOCKS, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.ape.final_frame_blocks = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_TOTAL_FRAMES, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.ape.total_frames = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_BITS_PER_SAMPLE, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.ape.bits_per_sample = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_NUM_CHANNELS, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.ape.num_channels = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_SAMPLE_RATE, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.ape.sample_rate = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_APE_SEEK_TABLE_PRESENT, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.ape.seek_table_present = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ALOGV("APE CSD values: compatibleVersion %d compressionLevel %d"
                 " formatFlags %d blocksPerFrame %d finalFrameBlocks %d"
@@ -872,49 +773,59 @@
     }
 
     else if (out->format == AUDIO_FORMAT_VORBIS) {
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_VORBIS_BITSTREAM_FMT, value, sizeof(value));
+        if (ret >= 0) {
         // transcoded bitstream mode
-        out->compr_config.codec->options.vorbis_dec.bit_stream_fmt = 1;
-        out->send_new_metadata = 1;
+            out->compr_config.codec->options.vorbis_dec.bit_stream_fmt = (atoi(value) > 0) ? 1 : 0;
+            out->is_compr_metadata_avail = true;
+        }
     }
 
     else if (out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->format = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
+        }
+        ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
+        if (ret >= 0) {
+            out->compr_config.codec->options.wma.avg_bit_rate = atoi(value);
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.wma.super_block_align = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.wma.channelmask = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.wma.encodeopt = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
         ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
         if (ret >= 0) {
             out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
-            out->send_new_metadata = 1;
+            out->is_compr_metadata_avail = true;
         }
-        ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
+        ALOGV("WMA params: fmt %x, bit rate %x, balgn %x, sr %d, chmsk %x"
+                " encop %x, op1 %x, op2 %x",
                 out->compr_config.codec->format,
+                out->compr_config.codec->options.wma.avg_bit_rate,
                 out->compr_config.codec->options.wma.super_block_align,
                 out->compr_config.codec->options.wma.bits_per_sample,
                 out->compr_config.codec->options.wma.channelmask,
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index f54b4a7..80a9278 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1174,6 +1174,11 @@
 
 error_config:
     adev->active_input = NULL;
+    /*
+     * sleep 50ms to allow sufficient time for kernel
+     * drivers to recover incases like SSR.
+     */
+    usleep(50000);
     ALOGD("%s: exit: status(%d)", __func__, ret);
 
     return ret;
@@ -1326,6 +1331,10 @@
                 ALOGE("%s: Next track returned error %d",__func__, ret);
             if (ret != -ENETRESET) {
                 send_callback = true;
+                pthread_mutex_lock(&out->lock);
+                out->send_new_metadata = 1;
+                out->send_next_track_params = true;
+                pthread_mutex_unlock(&out->lock);
                 event = STREAM_CBK_EVENT_DRAIN_READY;
                 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
             } else
@@ -1345,7 +1354,7 @@
         pthread_mutex_lock(&out->lock);
         out->offload_thread_blocked = false;
         pthread_cond_signal(&out->cond);
-        if (send_callback) {
+        if (send_callback && out->offload_callback) {
             ALOGVV("%s: sending offload_callback event %d", __func__, event);
             out->offload_callback(event, NULL, out->offload_cookie);
         }
@@ -1655,6 +1664,9 @@
             ret = -EIO;
             goto error_open;
         }
+        /* compress_open sends params of the track, so reset the flag here */
+        out->is_compr_metadata_avail = false;
+
         if (out->offload_callback)
             compress_nonblock(out->compr, out->non_blocking);
 
@@ -1690,6 +1702,11 @@
 error_open:
     stop_output_stream(out);
 error_config:
+    /*
+     * sleep 50ms to allow sufficient time for kernel
+     * drivers to recover incases like SSR.
+     */
+    usleep(50000);
     return ret;
 }
 
@@ -1834,6 +1851,8 @@
         } else {
             ALOGD("copl(%p):standby", out);
             stop_compressed_output_l(out);
+            out->send_next_track_params = false;
+            out->is_compr_metadata_avail = false;
             out->gapless_mdata.encoder_delay = 0;
             out->gapless_mdata.encoder_padding = 0;
             if (out->compr != NULL) {
@@ -1859,7 +1878,6 @@
 {
     int ret = 0;
     char value[32];
-    bool is_meta_data_params = false;
 
     if (!out || !parms) {
         ALOGE("%s: return invalid ",__func__);
@@ -1868,31 +1886,15 @@
 
     ret = audio_extn_parse_compress_metadata(out, parms);
 
-    ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
-    if(ret >= 0)
-        is_meta_data_params = true;
-    ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
-    if(ret >= 0)
-        is_meta_data_params = true;
-    ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
-    if(ret >= 0)
-        is_meta_data_params = true;
     ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
     if (ret >= 0) {
-        is_meta_data_params = true;
         out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
     }
     ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
     if (ret >= 0) {
-        is_meta_data_params = true;
         out->gapless_mdata.encoder_padding = atoi(value);
     }
 
-    if(!is_meta_data_params) {
-        ALOGV("%s: Not gapless meta data params", __func__);
-        return 0;
-    }
-    out->send_new_metadata = 1;
     ALOGV("%s new encoder delay %u and padding %u", __func__,
           out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
 
@@ -2186,6 +2188,12 @@
             ALOGD("copl(%p):send new gapless metadata", out);
             compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
             out->send_new_metadata = 0;
+            if (out->send_next_track_params && out->is_compr_metadata_avail) {
+                ALOGD("copl(%p):send next track params in gapless", out);
+                compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
+                out->send_next_track_params = false;
+                out->is_compr_metadata_avail = false;
+            }
         }
 
         ret = compress_write(out->compr, buffer, bytes);
@@ -3016,6 +3024,8 @@
         }
 
         out->send_new_metadata = 1;
+        out->send_next_track_params = false;
+        out->is_compr_metadata_avail = false;
         out->offload_state = OFFLOAD_STATE_IDLE;
         out->playback_started = 0;
 
@@ -3809,6 +3819,13 @@
             adev->offload_effects_set_hpx_state =
                         (int (*)(bool))dlsym(adev->offload_effects_lib,
                                          "offload_effects_bundle_set_hpx_state");
+            adev->offload_effects_get_parameters =
+                        (void (*)(struct str_parms *, struct str_parms *))
+                                         dlsym(adev->offload_effects_lib,
+                                         "offload_effects_bundle_get_parameters");
+            adev->offload_effects_set_parameters =
+                        (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
+                                         "offload_effects_bundle_set_parameters");
         }
     }
 
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 070ebf6..5c1ea1d 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -218,6 +218,8 @@
     void *offload_cookie;
     struct compr_gapless_mdata gapless_mdata;
     int send_new_metadata;
+    bool send_next_track_params;
+    bool is_compr_metadata_avail;
     unsigned int bit_width;
 
     struct audio_device *dev;
@@ -346,6 +348,10 @@
     adm_deregister_stream_t adm_deregister_stream;
     adm_request_focus_t adm_request_focus;
     adm_abandon_focus_t adm_abandon_focus;
+
+    void (*offload_effects_get_parameters)(struct str_parms *,
+                                           struct str_parms *);
+    void (*offload_effects_set_parameters)(struct str_parms *);
 };
 
 int select_devices(struct audio_device *adev,