agm: changes to enable session flush using sessionId
Previous flush implementation was doing graph stop and then doing graph
start in next write call. This was causing stream and device subgraphs
to stop even though slimbus sink was kept running. This behavior was
leading to stuttering sound during seek operation done for offloaded
streams.
The new approach is to call into agm session flush API using sessionId.
This change adds support for this in AGM.
Change-Id: Ieb8a9423243c495a44c789def41124ca01ef885e
diff --git a/ipc/HwBinders/agm_ipc_client/src/agm_client_wrapper.cpp b/ipc/HwBinders/agm_ipc_client/src/agm_client_wrapper.cpp
index 520a2af..3558700 100644
--- a/ipc/HwBinders/agm_ipc_client/src/agm_client_wrapper.cpp
+++ b/ipc/HwBinders/agm_ipc_client/src/agm_client_wrapper.cpp
@@ -314,6 +314,16 @@
return -EINVAL;
}
+int agm_sessionid_flush(uint32_t session_id)
+{
+ ALOGV("%s called with session id = %d", __func__, session_id);
+ if (!agm_server_died) {
+ android::sp<IAGM> agm_client = get_agm_server();
+ return agm_client->ipc_agm_sessionid_flush(session_id);
+ }
+ return -EINVAL;
+}
+
int agm_session_resume(uint64_t handle){
ALOGV("%s called with handle = %llx \n", __func__, (unsigned long long) handle);
if (!agm_server_died) {
diff --git a/ipc/HwBinders/agm_ipc_service/inc/agm_server_wrapper.h b/ipc/HwBinders/agm_ipc_service/inc/agm_server_wrapper.h
index 9ad0a2d..4c31633 100644
--- a/ipc/HwBinders/agm_ipc_service/inc/agm_server_wrapper.h
+++ b/ipc/HwBinders/agm_ipc_service/inc/agm_server_wrapper.h
@@ -200,6 +200,7 @@
Return<int32_t> ipc_agm_session_stop(uint64_t hndl) override;
Return<int32_t> ipc_agm_session_pause(uint64_t hndl) override;
Return<int32_t> ipc_agm_session_flush(uint64_t hndl) override;
+ Return<int32_t> ipc_agm_sessionid_flush(uint32_t session_id) override;
Return<int32_t> ipc_agm_session_resume(uint64_t hndl) override;
Return<int32_t> ipc_agm_session_suspend(uint64_t hndl) override;
Return<void> ipc_agm_session_read(uint64_t hndl, uint32_t count,
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 b8dd8c7..fdc5888 100644
--- a/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
+++ b/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
@@ -1032,6 +1032,12 @@
return agm_session_flush(hndl);
}
+Return<int32_t> AGM::ipc_agm_sessionid_flush(uint32_t session_id) {
+ ALOGV("%s called with session id = %d", __func__, session_id);
+
+ return agm_sessionid_flush(session_id);
+}
+
Return<int32_t> AGM::ipc_agm_session_resume(uint64_t hndl) {
ALOGV("%s called with handle = %llx \n", __func__, (unsigned long long) hndl);
diff --git a/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal b/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal
index 0e797a4..280cc5d 100644
--- a/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal
+++ b/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal
@@ -125,6 +125,7 @@
ipc_agm_session_stop(uint64_t hndl) generates (int32_t ret);
ipc_agm_session_pause(uint64_t hndl) generates (int32_t ret);
ipc_agm_session_flush(uint64_t hndl) generates (int32_t ret);
+ ipc_agm_sessionid_flush(uint32_t session_id) generates (int32_t ret);
ipc_agm_session_resume(uint64_t hndl) generates (int32_t ret);
ipc_agm_session_suspend(uint64_t hndl) generates (int32_t ret);
ipc_agm_session_read(uint64_t hndl, uint32_t count)
diff --git a/ipc/HwBinders/interfaces/AGMIPC/current.txt b/ipc/HwBinders/interfaces/AGMIPC/current.txt
index ae21480..8eae287 100644
--- a/ipc/HwBinders/interfaces/AGMIPC/current.txt
+++ b/ipc/HwBinders/interfaces/AGMIPC/current.txt
@@ -1,4 +1,4 @@
# Hash for vendor.qti.hardware.AGMIPC@1.0 package
1846dac975898187405fcd011ea43c98415334e187a74a2e4fcaea123e0064b7 vendor.qti.hardware.AGMIPC@1.0::types
-c75ed15965f38d53fe69c0a641fb7c9ae043560cb5dcd4e73ea31499251a8dc5 vendor.qti.hardware.AGMIPC@1.0::IAGM
+a1545123ef5e6f4536cd2f2902c74a202b39bac323bcbc0ed703ab1437056d4c vendor.qti.hardware.AGMIPC@1.0::IAGM
e8d1ca223a57cfacc7373f6418555330bb545c43a1e9d2c3a1fdd984fcec4a14 vendor.qti.hardware.AGMIPC@1.0::IAGMCallback
diff --git a/plugins/tinyalsa/src/agm_mixer_plugin.c b/plugins/tinyalsa/src/agm_mixer_plugin.c
index 819ed25..cb85c9d 100644
--- a/plugins/tinyalsa/src/agm_mixer_plugin.c
+++ b/plugins/tinyalsa/src/agm_mixer_plugin.c
@@ -144,17 +144,19 @@
"loopback",
"echoReference",
"bufTimestamp",
- /* Add new ones here, be sue to update enum as well */
+ /* Add new ones here, be sure to update enum as well */
};
enum {
PCM_RX_CTL_NAME_SIDETONE = 0,
PCM_RX_CTL_NAME_DATAPATH_PARAMS,
+ PCM_RX_CTL_NAME_FLUSH,
};
/* strings should be at the index as per the enum */
static char *amp_pcm_rx_ctl_names[] = {
"sidetone",
"datapathParams",
+ "flush",
};
struct amp_get_param_info {
@@ -1678,6 +1680,26 @@
return ret;
}
+/* Dummy implementation for flush_get */
+static int amp_pcm_flush_get(struct mixer_plugin *plugin __unused,
+ struct snd_control *ctl __unused, struct snd_ctl_elem_value *ev __unused)
+{
+ return 0;
+}
+
+static int amp_pcm_flush_put(struct mixer_plugin *plugin,
+ struct snd_control *ctl, struct snd_ctl_elem_value *ev)
+{
+ uint32_t pcm_idx = ctl->private_value;
+ bool flush = !!(ev->value.integer.value[0]);
+ int ret = 0;
+
+ if (flush)
+ ret = agm_sessionid_flush(pcm_idx);
+
+ return ret;
+}
+
/* 512 max bytes for non-tlv controls, reserving 16 for future use */
static struct snd_value_bytes pcm_calibration_bytes =
SND_VALUE_BYTES(512 - 16);
@@ -1714,6 +1736,9 @@
static struct snd_value_int group_media_fmt_int =
SND_VALUE_INTEGER(5, 0, 384000, 1);
+static struct snd_value_int flush_param_int =
+ SND_VALUE_INTEGER(1, 0, 1, 1);
+
static struct snd_value_tlv_bytes be_setparam_bytes =
SND_VALUE_TLV_BYTES(64 * 1024, amp_be_set_param_get, amp_be_set_param_put);
@@ -1957,6 +1982,18 @@
pcm_getacdbtunnel_bytes, pval, pdata);
}
+static void amp_create_pcm_flush_ctl(struct amp_priv *amp_priv,
+ char *name, int ctl_idx, int pval, void *pdata)
+{
+ struct snd_control *ctl = AMP_PRIV_GET_CTL_PTR(amp_priv, ctl_idx);
+ char *ctl_name = AMP_PRIV_GET_CTL_NAME_PTR(amp_priv, ctl_idx);
+
+ snprintf(ctl_name, AIF_NAME_MAX_LEN + 16, "%s %s",
+ name, amp_pcm_rx_ctl_names[PCM_RX_CTL_NAME_FLUSH]);
+
+ INIT_SND_CONTROL_INTEGER(ctl, ctl_name, amp_pcm_flush_get,
+ amp_pcm_flush_put, flush_param_int, pval, pdata);
+}
/* BE related mixer control creations here */
static void amp_create_metadata_ctl(struct amp_priv *amp_priv,
@@ -2140,6 +2177,8 @@
&be_tx_adi->dev_enum, idx, rx_adi);
amp_create_pcm_write_with_metadata_ctl(amp_priv, name, (*ctl_idx)++,
idx, rx_adi);
+ amp_create_pcm_flush_ctl(amp_priv, name, (*ctl_idx)++,
+ idx, rx_adi);
}
return 0;
diff --git a/service/inc/private/agm/session_obj.h b/service/inc/private/agm/session_obj.h
index 4679117..b6969d0 100644
--- a/service/inc/private/agm/session_obj.h
+++ b/service/inc/private/agm/session_obj.h
@@ -111,6 +111,7 @@
int session_obj_deinit();
int session_obj_valid_check(uint64_t hndl);
int session_obj_get(int session_id, struct session_obj **sess_obj);
+struct session_obj *session_obj_retrieve_from_pool(uint32_t session_id);
int session_obj_open(uint32_t session_id,
enum agm_session_mode sess_mode,
struct session_obj **sess_obj);
diff --git a/service/inc/public/agm/agm_api.h b/service/inc/public/agm/agm_api.h
index 8680fa1..3ff08f7 100644
--- a/service/inc/public/agm/agm_api.h
+++ b/service/inc/public/agm/agm_api.h
@@ -960,6 +960,16 @@
int agm_session_flush(uint64_t hndl);
/**
+ * \brief flush the session. session must be in pause state
+ * before flushing.
+ *
+ * \param[in] session_id - Valid audio session id
+ *
+ * \return 0 on success, error code otherwise
+ */
+int agm_sessionid_flush(uint32_t session_id);
+
+/**
* \brief Resume the session. session must be in paused state
* before resuming.
*
diff --git a/service/src/agm.c b/service/src/agm.c
index bc8bb0c..45bbbcd 100644
--- a/service/src/agm.c
+++ b/service/src/agm.c
@@ -792,6 +792,20 @@
return session_obj_flush(handle);
}
+int agm_sessionid_flush(uint32_t session_id)
+{
+ struct session_obj *handle = NULL;
+ int ret = 0;
+
+ handle = session_obj_retrieve_from_pool(session_id);
+ if (!handle) {
+ AGM_LOGE("Incorrect session_id:%d, doesn't match sess_obj from pool",
+ session_id);
+ return -EINVAL;
+ }
+ return session_obj_flush(handle);
+}
+
int agm_session_resume(uint64_t hndl)
{
struct session_obj *handle = (struct session_obj *) hndl;