hal:qap-test: Support for input buffer available event

-This change includes test app changes to support event
mechanasim for getting buffer availability.
-As soon as module has the free space to copy the input
buffer, it will raise an event to the testapp notifing that a
new buffer can be sent.
-This will replace the exising polling mechanasim,
where testapp periodically queries the module to check if
a new input buffer can be sent or not.

Change-Id: I84f6f8a574f2589643733b4543348ad7992208c5
diff --git a/qahw_api/test/qahw_playback_test.c b/qahw_api/test/qahw_playback_test.c
index d42f89d..ba7f4bf 100644
--- a/qahw_api/test/qahw_playback_test.c
+++ b/qahw_api/test/qahw_playback_test.c
@@ -256,6 +256,8 @@
         pthread_cond_init(&stream_param[i].write_cond, (const pthread_condattr_t *) NULL);
         pthread_mutex_init(&stream_param[i].drain_lock, (const pthread_mutexattr_t *)NULL);
         pthread_cond_init(&stream_param[i].drain_cond, (const pthread_condattr_t *) NULL);
+        pthread_mutex_init(&stream_param[i].input_buffer_available_lock, (const pthread_mutexattr_t *)NULL);
+        pthread_cond_init(&stream_param[i].input_buffer_available_cond, (const pthread_condattr_t *) NULL);
 
         stream_param[i].handle                              =   stream_handle;
         stream_handle--;
@@ -264,6 +266,21 @@
     pthread_cond_init(&dual_main_cond, (const pthread_condattr_t *) NULL);
 }
 
+static void deinit_streams(void)
+{
+    int i = 0;
+    for ( i = 0; i < MAX_PLAYBACK_STREAMS; i++) {
+        pthread_cond_destroy(&stream_param[i].write_cond);
+        pthread_mutex_destroy(&stream_param[i].write_lock);
+        pthread_cond_destroy(&stream_param[i].drain_cond);
+        pthread_mutex_destroy(&stream_param[i].drain_lock);
+        pthread_cond_destroy(&stream_param[i].input_buffer_available_cond);
+        pthread_mutex_destroy(&stream_param[i].input_buffer_available_lock);
+    }
+    pthread_cond_destroy(&dual_main_cond);
+    pthread_mutex_destroy(&dual_main_lock);
+}
+
 void read_kvpair(char *kvpair, char* kvpair_values, int filetype)
 {
     char *kvpair_type = NULL;
@@ -2600,6 +2617,7 @@
         }
     }
 
+    deinit_streams();
     rc = unload_hals();
 
     if ((log_file != stdout) && (log_file != nullptr))
diff --git a/qahw_api/test/qahw_playback_test.h b/qahw_api/test/qahw_playback_test.h
index b643c1d..66229f5 100644
--- a/qahw_api/test/qahw_playback_test.h
+++ b/qahw_api/test/qahw_playback_test.h
@@ -140,9 +140,11 @@
     qahw_mix_matrix_params_t mm_params_downmix;
     int mix_ctrl;
     int pan_scale_ctrl;
+    pthread_cond_t input_buffer_available_cond;
+    pthread_mutex_t input_buffer_available_lock;
+    uint32_t input_buffer_available_size;
 }stream_config;
 
-
 qahw_module_handle_t * load_hal(audio_devices_t dev);
 int unload_hals();
 int get_wav_header_length (FILE* file_stream);
diff --git a/qahw_api/test/qap_wrapper_extn.c b/qahw_api/test/qap_wrapper_extn.c
index 3240cb6..4b27674 100644
--- a/qahw_api/test/qap_wrapper_extn.c
+++ b/qahw_api/test/qap_wrapper_extn.c
@@ -790,7 +790,36 @@
     primary_stream_close = true;
 }
 
-void qap_wrapper_session_callback(qap_session_handle_t session_handle __unused, void* priv_data __unused, qap_callback_event_t event_id, int size __unused, void *data)
+void qap_wrapper_module_callback(qap_module_handle_t module_handle, void* priv_data, qap_module_callback_event_t event_id, int size, void *data)
+{
+    stream_config *p_stream_param = (stream_config*)priv_data;
+    if(p_stream_param == NULL) {
+        ALOGE("%s %d, callback handle is null.",__func__,__LINE__);
+    }
+    ALOGV("%s %d Received event id %d\n", __func__, __LINE__, event_id);
+
+    switch (event_id) {
+        case QAP_MODULE_CALLBACK_EVENT_SEND_INPUT_BUFFER:
+        {
+            if (size < sizeof(qap_send_buffer_t)) {
+                ALOGE("%s %d event id %d, wrong payload size %d\n",
+                      __func__, __LINE__, event_id, size);
+                break;
+            }
+            qap_send_buffer_t *p_send_buffer_event = (qap_send_buffer_t*)data;
+            pthread_mutex_lock(&p_stream_param->input_buffer_available_lock);
+            p_stream_param->input_buffer_available_size = p_send_buffer_event->bytes_available;
+            pthread_cond_signal(&p_stream_param->input_buffer_available_cond);
+            pthread_mutex_unlock(&p_stream_param->input_buffer_available_lock);
+
+            break;
+        }
+        default:
+        break;
+    }
+}
+
+void qap_wrapper_session_callback(qap_session_handle_t session_handle __unused, void* priv_data __unused, qap_callback_event_t event_id, int size, void *data)
 {
     int ret = 0;
     int bytes_written = 0;
@@ -1368,7 +1397,7 @@
         }
     }
 
-    ret = qap_session_set_callback(qap_session_handle, &qap_wrapper_session_callback);
+    ret = qap_session_set_callback(qap_session_handle, &qap_wrapper_session_callback, NULL);
     if (ret != QAP_STATUS_OK) {
         fprintf(stderr, "!!!! Please specify appropriate Session\n");
         return -EINVAL;
@@ -1556,6 +1585,7 @@
                       __FUNCTION__, __LINE__,bytes_read, bytes_consumed);
             if (stream_info->filetype == FILE_DTS) {
                 if (bytes_consumed < 0) {
+#if 0
                     while (!is_buffer_available) {
                         usleep(1000);
                         ret = qap_module_cmd(qap_module_handle, QAP_MODULE_CMD_GET_PARAM,
@@ -1570,7 +1600,24 @@
                         ALOGV("%s : %d, dts clip reply_data is %d buffer availabale is %d",
                               __FUNCTION__, __LINE__, reply_data, is_buffer_available);
                     }
+#else
+                    pthread_mutex_lock(&stream_info->input_buffer_available_lock);
+                    stream_info->input_buffer_available_size = 0;
+                    pthread_mutex_unlock(&stream_info->input_buffer_available_lock);
 
+                    while (buffer->common_params.size > stream_info->input_buffer_available_size) {
+                        ALOGV("%s %d: %s waiting for input buffer availability.",
+                                     __FUNCTION__, __LINE__, stream_info->filename);
+                        pthread_mutex_lock(&stream_info->input_buffer_available_lock);
+                        pthread_cond_wait(&stream_info->input_buffer_available_cond,
+                                          &stream_info->input_buffer_available_lock);
+                        pthread_mutex_unlock(&stream_info->input_buffer_available_lock);
+                        ALOGV("%s %d: %s input buffer available, size %lu.",
+                                     __FUNCTION__, __LINE__,
+                                     stream_info->filename,
+                                     stream_info->input_buffer_available_size);
+                    }
+#endif
                     if(kpi_mode && time_index > 5) {
                         gettimeofday(&tcont_ts1, NULL);
                         data_input_st_arr[time_index] = (tcont_ts1.tv_sec) * 1000 + (tcont_ts1.tv_usec) / 1000;
@@ -1633,20 +1680,15 @@
 
 qap_module_handle_t qap_wrapper_stream_open(void* stream_data)
 {
-    qap_module_config_t *input_config = NULL;
+    qap_module_config_t input_config = {0};
     int ret = 0;
     int i = 0;
     stream_config *stream_info = (stream_config *)stream_data;
     qap_module_handle_t qap_module_handle = NULL;
 
-    input_config = (qap_module_config_t *) calloc(1, sizeof(qap_module_config_t));
-    if (input_config == NULL) {
-        fprintf(stderr, "%s::%d Memory Alloc Error\n", __func__, __LINE__);
-        return NULL;
-    }
-    input_config->sample_rate = stream_info->config.sample_rate;
-    input_config->channels = stream_info->channels;
-    input_config->bit_width = stream_info->config.offload_info.bit_width;
+    input_config.sample_rate = stream_info->config.sample_rate;
+    input_config.channels = stream_info->channels;
+    input_config.bit_width = stream_info->config.offload_info.bit_width;
 
     if (stream_info->filetype == FILE_DTS)
         stream_info->bytes_to_read = FRAME_SIZE;
@@ -1655,18 +1697,18 @@
     input_streams_count++;
     if (input_streams_count == 2) {
         if (stream_info->filetype == FILE_WAV) {
-            input_config->flags = QAP_MODULE_FLAG_SYSTEM_SOUND;
+            input_config.flags = QAP_MODULE_FLAG_SYSTEM_SOUND;
             stream_info->system_input = true;
             has_system_input = true;
             ALOGV("%s::%d Set Secondary System Sound Flag", __func__, __LINE__);
         } else if (stream_info->filetype != FILE_WAV) {
             if (stream_info->flags & AUDIO_OUTPUT_FLAG_ASSOCIATED) {
                  ALOGV("%s::%d Set Secondary Assoc Input Flag", __func__, __LINE__);
-                 input_config->flags = QAP_MODULE_FLAG_SECONDARY;
+                 input_config.flags = QAP_MODULE_FLAG_SECONDARY;
                  stream_info->sec_input = true;
             } else {
                 ALOGV("%s::%d Set Secondary Main Input Flag", __func__, __LINE__);
-                input_config->flags = QAP_MODULE_FLAG_PRIMARY;
+                input_config.flags = QAP_MODULE_FLAG_PRIMARY;
                 stream_info->sec_input = true;
             }
         }
@@ -1674,29 +1716,31 @@
     } else {
         if (stream_info->filetype == FILE_WAV) {
             ALOGV("%s::%d Set Secondary System Sound Flag", __func__, __LINE__);
-            input_config->flags = QAP_MODULE_FLAG_SYSTEM_SOUND;
+            input_config.flags = QAP_MODULE_FLAG_SYSTEM_SOUND;
             stream_info->system_input = true;
         } else {
             ALOGV("%s::%d Set Primary Main Input Flag", __func__, __LINE__);
-            input_config->flags = QAP_MODULE_FLAG_PRIMARY;
+            input_config.flags = QAP_MODULE_FLAG_PRIMARY;
         }
     }
 
     if (!encode)
-        input_config->module_type = QAP_MODULE_DECODER;
+        input_config.module_type = QAP_MODULE_DECODER;
     else
-        input_config->module_type = QAP_MODULE_ENCODER;
+        input_config.module_type = QAP_MODULE_ENCODER;
 
-    ret = qap_wrapper_map_input_format(stream_info->config.offload_info.format, &input_config->format);
+    ret = qap_wrapper_map_input_format(stream_info->config.offload_info.format, &input_config.format);
     if (ret == -EINVAL)
         return NULL;
 
-    ret = qap_module_init(qap_session_handle, input_config, &qap_module_handle);
+    ret = qap_module_init(qap_session_handle, &input_config, &qap_module_handle);
     if (qap_module_handle == NULL) {
         fprintf(stderr, "%s Module Handle is Null\n", __func__);
         return NULL;
     }
 
+    qap_module_set_callback(qap_module_handle, &qap_wrapper_module_callback, stream_info);
+
     primary_stream_close = false;
     stream_cnt++;
     return qap_module_handle;