Merge "agm: add SYS_NICE capability to inherit RT priority"
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 200f44e..a728797 100644
--- a/ipc/HwBinders/agm_ipc_client/src/agm_client_wrapper.cpp
+++ b/ipc/HwBinders/agm_ipc_client/src/agm_client_wrapper.cpp
@@ -997,3 +997,29 @@
}
return -EINVAL;
}
+
+int agm_session_write_datapath_params(uint32_t session_id, struct agm_buff *buf)
+{
+ ALOGV("%s called with session id = %d \n", __func__, session_id);
+
+ if (!agm_server_died) {
+ android::sp<IAGM> agm_client = get_agm_server();
+ hidl_vec<AgmBuff> buf_hidl;
+ buf_hidl.resize(sizeof(struct agm_buff));
+ AgmBuff *agmBuff = buf_hidl.data();
+ agmBuff->size = buf->size;
+ agmBuff->buffer.resize(buf->size);
+ agmBuff->flags = buf->flags;
+ agmBuff->timestamp = buf->timestamp;
+ if (buf->size && buf->addr)
+ memcpy(agmBuff->buffer.data(), buf->addr, buf->size);
+ else {
+ ALOGE("%s: buf size or addr is null", __func__);
+ return -EINVAL;
+ }
+
+ return agm_client->ipc_agm_session_write_datapath_params(
+ session_id, buf_hidl);
+ }
+ return -EINVAL;
+}
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 99c5c2d..e5e0b6d 100644
--- a/ipc/HwBinders/agm_ipc_service/inc/agm_server_wrapper.h
+++ b/ipc/HwBinders/agm_ipc_service/inc/agm_server_wrapper.h
@@ -255,6 +255,8 @@
const hidl_vec<AgmGroupMediaConfig>& media_config) override;
Return<void> ipc_agm_get_group_aif_info_list(uint32_t num_groups,
ipc_agm_get_aif_info_list_cb _hidl_cb) override;
+ Return<int32_t> ipc_agm_session_write_datapath_params(uint32_t session_id,
+ const hidl_vec<AgmBuff>& buff) override;
int is_agm_initialized() { return agm_initialized;}
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 a3c599a..f05167e 100644
--- a/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
+++ b/ipc/HwBinders/agm_ipc_service/src/agm_server_wrapper.cpp
@@ -1312,6 +1312,40 @@
return Void();
}
+Return<int32_t> AGM::ipc_agm_session_write_datapath_params(uint32_t session_id,
+ const hidl_vec<AgmBuff>& buff_hidl)
+{
+ int32_t ret = -EINVAL;
+ struct agm_buff buf;
+ uint32_t bufSize;
+ buf.addr = nullptr;
+ buf.metadata = nullptr;
+
+ bufSize = buff_hidl.data()->size;
+ buf.addr = (uint8_t *)calloc(1, bufSize);
+ if (!buf.addr) {
+ ALOGE("%s: failed to calloc", __func__);
+ goto exit;
+ }
+ buf.size = (size_t)bufSize;
+ buf.timestamp = buff_hidl.data()->timestamp;
+ buf.flags = buff_hidl.data()->flags;
+
+ if (bufSize)
+ memcpy(buf.addr, buff_hidl.data()->buffer.data(), bufSize);
+ else {
+ ALOGE("%s: buf size is null", __func__);
+ goto exit;
+ }
+ ALOGV("%s: sz %d", __func__, bufSize);
+ ret = agm_session_write_datapath_params(session_id, &buf);
+
+exit:
+ if (buf.addr != nullptr)
+ free(buf.addr);
+ return ret;
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace AGMIPC
diff --git a/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal b/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal
index 75cfea3..02b39a6 100644
--- a/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal
+++ b/ipc/HwBinders/interfaces/AGMIPC/1.0/IAGM.hal
@@ -127,4 +127,7 @@
ipc_agm_get_group_aif_info_list(uint32_t num_groups)
generates (int32_t ret, vec<AifInfo> aif_group_list_ret,
uint32_t num_groups_ret);
+ ipc_agm_session_write_datapath_params(uint32_t session_id, vec<AgmBuff> buff)
+ generates (int32_t ret);
+
};
diff --git a/ipc/HwBinders/interfaces/AGMIPC/current.txt b/ipc/HwBinders/interfaces/AGMIPC/current.txt
new file mode 100644
index 0000000..d178fa3
--- /dev/null
+++ b/ipc/HwBinders/interfaces/AGMIPC/current.txt
@@ -0,0 +1,4 @@
+# Hash for vendor.qti.hardware.AGMIPC@1.0 package
+14e9644e8ff286a5d00825c97d46056b12af94c103f81976a4c3b71fc681909d vendor.qti.hardware.AGMIPC@1.0::types
+7c4ef018df8bcf680fc3ba4c740b9d34873ca0495955e412a4312ea6f6715e76 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 a66ed88..22553d2 100644
--- a/plugins/tinyalsa/src/agm_mixer_plugin.c
+++ b/plugins/tinyalsa/src/agm_mixer_plugin.c
@@ -118,7 +118,7 @@
"event",
"setCalibration",
"getParam",
- "getBufInfo"
+ "getBufInfo",
/* Add new ones below, be sure to update enum as well */
};
@@ -138,10 +138,12 @@
enum {
PCM_RX_CTL_NAME_SIDETONE = 0,
+ PCM_RX_CTL_NAME_DATAPATH_PARAMS,
};
/* strings should be at the index as per the enum */
static char *amp_pcm_rx_ctl_names[] = {
"sidetone",
+ "datapathParams",
};
struct amp_dev_info {
@@ -1457,6 +1459,29 @@
return 0;
}
+static int amp_pcm_write_datapath_params_get(struct mixer_plugin *plugin __unused,
+ struct snd_control *ctl __unused, struct snd_ctl_elem_value *ev __unused)
+{
+ return 0;
+}
+
+static int amp_pcm_write_datapath_params_put(struct mixer_plugin *plugin,
+ struct snd_control *ctl, struct snd_ctl_elem_value *ev)
+{
+ struct agm_buff *buffer;
+ int pcm_idx = ctl->private_value;
+ int ret;
+
+ AGM_LOGV("%s: enter sesid:%d ev pointer %p\n", __func__, pcm_idx, ev->value.bytes.data);
+ buffer = (struct agm_buff *)ev->value.bytes.data;
+
+ ret = agm_session_write_datapath_params(pcm_idx, buffer);
+ if (ret)
+ AGM_LOGE("%s: write_with_metadata failed, err %d\n",
+ __func__, ret);
+ return ret;
+}
+
/* 512 max bytes for non-tlv controls, reserving 16 for future use */
static struct snd_value_bytes pcm_event_bytes =
SND_VALUE_BYTES(512 - 16);
@@ -1480,6 +1505,8 @@
SND_VALUE_TLV_BYTES(128 * 1024, amp_pcm_get_param_get, amp_pcm_get_param_put);
static struct snd_value_bytes pcm_buf_info_bytes =
SND_VALUE_BYTES(512 - 16);
+static struct snd_value_bytes pcm_write_datapath_params_bytes =
+ SND_VALUE_BYTES(512 - 16);
static struct snd_value_int media_fmt_int =
SND_VALUE_INTEGER(4, 0, 384000, 1);
@@ -1696,6 +1723,20 @@
pval, pdata);
}
+static void amp_create_pcm_write_with_metadata_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_DATAPATH_PARAMS]);
+
+ INIT_SND_CONTROL_BYTES(ctl, ctl_name, amp_pcm_write_datapath_params_get,
+ amp_pcm_write_datapath_params_put, pcm_write_datapath_params_bytes,
+ pval, pdata);
+}
+
/* BE related mixer control creations here */
static void amp_create_metadata_ctl(struct amp_priv *amp_priv,
char *be_name, int ctl_idx, int pval, void *pdata)
@@ -1870,6 +1911,8 @@
/* Create sidetone control, enum values are TX backends */
amp_create_pcm_sidetone_ctl(amp_priv, name, (*ctl_idx)++,
&be_tx_adi->dev_enum, idx, rx_adi);
+ amp_create_pcm_write_with_metadata_ctl(amp_priv, name, (*ctl_idx)++,
+ idx, rx_adi);
}
return 0;
diff --git a/service/inc/private/agm/graph.h b/service/inc/private/agm/graph.h
index 9cea7d7..3564392 100644
--- a/service/inc/private/agm/graph.h
+++ b/service/inc/private/agm/graph.h
@@ -416,4 +416,6 @@
*/
int32_t graph_enable_acdb_persistence(uint8_t enable_flag);
+
+int graph_set_media_config_datapath(struct graph_obj *gph_obj);
#endif /*GPH_OBJ_H*/
diff --git a/service/inc/public/agm/agm_api.h b/service/inc/public/agm/agm_api.h
index e23d8cf..99fb5f3 100644
--- a/service/inc/public/agm/agm_api.h
+++ b/service/inc/public/agm/agm_api.h
@@ -60,6 +60,9 @@
/**< true if buffer is marked as EOF */
#define AGM_BUFF_FLAG_EOF 0x4
+/**< true if buffer contains media format */
+#define AGM_BUFF_FLAG_MEDIA_FORMAT 0x8
+
/*Enables SRCM event in metadata on the read path*/
#define AGM_SESSION_FLAG_INBAND_SRCM 0x1
@@ -1094,6 +1097,16 @@
int agm_aif_group_set_media_config(uint32_t aif_group_id,
struct agm_group_media_config *media_config);
+/**
+ * \brief Write buffers containing codec params to session on datapath
+ *
+ * \param[in] session_id - Valid audio session id
+ * \param[in] buff: agm_buffer where data will be copied from
+ *
+ * \return 0 on success, error code otherwise
+ */
+int agm_session_write_datapath_params(uint32_t session_id, struct agm_buff *buff);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/service/src/agm.c b/service/src/agm.c
index c6276de..2dbb010 100644
--- a/service/src/agm.c
+++ b/service/src/agm.c
@@ -848,3 +848,19 @@
in_buffer_config,
out_buffer_config);
}
+
+int agm_session_write_datapath_params(uint32_t session_id, struct agm_buff *buff)
+{
+ struct session_obj *obj = NULL;
+ int ret = 0;
+ size_t consumed_size = 0;
+
+ ret = session_obj_get(session_id, &obj);
+ if (ret) {
+ AGM_LOGE("Error:%d retrieving session obj with session id=%d\n",
+ ret, session_id);
+ return ret;
+ }
+
+ return session_obj_write_with_metadata(obj, buff, &consumed_size);
+}
diff --git a/service/src/graph.c b/service/src/graph.c
index 63f31a7..fb988b4 100644
--- a/service/src/graph.c
+++ b/service/src/graph.c
@@ -1934,3 +1934,49 @@
{
return gsl_enable_acdb_persistence(enable_flag);
}
+
+static bool is_media_config_needed_on_datapath(enum agm_media_format format)
+{
+ bool ret = false;
+
+ switch (format) {
+ case AGM_FORMAT_MP3:
+ case AGM_FORMAT_AAC:
+ case AGM_FORMAT_FLAC:
+ case AGM_FORMAT_ALAC:
+ case AGM_FORMAT_APE:
+ case AGM_FORMAT_WMASTD:
+ case AGM_FORMAT_WMAPRO:
+ ret = true;
+ break;
+ default:
+ AGM_LOGE("Entered default, format %d", format);
+ break;
+ }
+ return ret;
+}
+
+int graph_set_media_config_datapath(struct graph_obj *graph_obj)
+{
+ int ret = 0;
+ struct listnode *node = NULL;
+ module_info_t *mod = NULL;
+ struct session_obj *sess_obj = graph_obj->sess_obj;
+
+ if (is_media_config_needed_on_datapath(sess_obj->out_media_config.format)) {
+ list_for_each(node, &graph_obj->tagged_mod_list) {
+ mod = node_to_item(node, module_info_t, list);
+ if (mod->tag == STREAM_INPUT_MEDIA_FORMAT) {
+ ret = mod->configure(mod, graph_obj);
+ if (ret != 0) {
+ AGM_LOGE("Module configuration for miid %x, mid %x, tag %x, failed:%d\n",
+ mod->miid, mod->mid, mod->tag, ret);
+ }
+ }
+ }
+ } else {
+ AGM_LOGD("Media configuration on dataptah is not needed for format %d",
+ sess_obj->out_media_config.format);
+ }
+ return ret;
+}
diff --git a/service/src/graph_module.c b/service/src/graph_module.c
index fb8dc1f..5592d2b 100644
--- a/service/src/graph_module.c
+++ b/service/src/graph_module.c
@@ -1354,6 +1354,71 @@
return ret;
}
+static int configure_compress_shared_mem_ep_datapath(struct module_info *mod,
+ struct graph_obj *graph_obj)
+{
+ int ret = 0;
+ struct session_obj *sess_obj = graph_obj->sess_obj;
+ struct media_format_t *media_fmt_hdr;
+ uint8_t *payload = NULL;
+ size_t payload_size = 0, real_fmt_id = 0;
+ struct agm_buff buffer = {0};
+ size_t consumed_size = 0;
+
+ if (is_format_bypassed(sess_obj->out_media_config.format) ||
+ sess_obj->stream_config.sess_mode == AGM_SESSION_NON_TUNNEL) {
+ AGM_LOGI("bypass shared mem ep config for format %x or sess_mode %d",
+ sess_obj->out_media_config.format, sess_obj->stream_config.sess_mode);
+ return 0;
+ }
+
+ ret = get_media_fmt_id_and_size(sess_obj->out_media_config.format,
+ &payload_size, &real_fmt_id);
+ if (ret) {
+ AGM_LOGD("module is not configured for format: %d\n",
+ sess_obj->out_media_config.format);
+ /* If ret is non-zero then shared memory module would be
+ * configured by client so return from here.
+ */
+ return 0;
+ }
+
+ payload_size = payload_size - sizeof(struct apm_module_param_data_t);
+ media_fmt_hdr = (struct media_format_t *) calloc(1, (size_t)payload_size);
+ if (!media_fmt_hdr) {
+ AGM_LOGE("Not enough memory for payload\n");
+ return -ENOMEM;
+ }
+
+
+ buffer.timestamp = 0x0;
+ buffer.flags = AGM_BUFF_FLAG_MEDIA_FORMAT;
+ buffer.size = payload_size;
+ buffer.addr = (uint8_t *)media_fmt_hdr;
+
+ ret = set_compressed_media_format(sess_obj->out_media_config.format,
+ media_fmt_hdr, sess_obj);
+ if (ret) {
+ AGM_LOGD("Shared mem EP is not configured for format: %d\n",
+ sess_obj->out_media_config.format);
+ /* If ret is non-zero then shared memory module would be
+ * configured by client so return from here.
+ */
+ goto free_payload;
+ }
+
+ ret = graph_write(graph_obj, &buffer, &consumed_size);
+ if (ret != 0) {
+ ret = ar_err_get_lnx_err_code(ret);
+ AGM_LOGE("custom_config command for module %d failed with error %d",
+ mod->tag, ret);
+ }
+
+free_payload:
+ free(media_fmt_hdr);
+ return ret;
+}
+
int configure_pcm_shared_mem_ep(struct module_info *mod,
struct graph_obj *graph_obj)
{
@@ -1459,8 +1524,12 @@
*/
if (is_format_pcm(sess_obj->out_media_config.format))
ret = configure_pcm_shared_mem_ep(mod, graph_obj);
- else
- ret = configure_compress_shared_mem_ep(mod, graph_obj);
+ else {
+ if (graph_obj->state != STARTED)
+ ret = configure_compress_shared_mem_ep(mod, graph_obj);
+ else
+ ret = configure_compress_shared_mem_ep_datapath(mod, graph_obj);
+ }
if (ret)
return ret;
diff --git a/service/src/session_obj.c b/service/src/session_obj.c
index 8407baa..303aad4 100644
--- a/service/src/session_obj.c
+++ b/service/src/session_obj.c
@@ -1996,7 +1996,7 @@
struct agm_media_config *media_config,
struct agm_buffer_config *buffer_config)
{
-
+ int ret = 0;
pthread_mutex_lock(&sess_obj->lock);
sess_obj->stream_config = *stream_config;
@@ -2009,10 +2009,15 @@
/*Playback session config*/
sess_obj->out_media_config = *media_config;
sess_obj->out_buffer_config = *buffer_config;
+ if (sess_obj->state == SESSION_STARTED) {
+ ret = graph_set_media_config_datapath(sess_obj->graph);
+ if (ret < 0)
+ AGM_LOGE("Failed to set media config on datapath ret %d", ret);
+ }
}
pthread_mutex_unlock(&sess_obj->lock);
- return 0;
+ return ret;
}
int session_obj_prepare(struct session_obj *sess_obj)