st-hal: Add buffering thread independent of callback thread
Currently, the callback thread handles detections and buffering
which causes complicated synchronization support. This change
simplifies buffering by adding a dedicated thread so that the
callback thread can return to waiting for detection events.
Change-Id: I994e1524207e967d67f7a262934b476d58778358
diff --git a/st_hw_session.h b/st_hw_session.h
index 4a8218d..6188d10 100644
--- a/st_hw_session.h
+++ b/st_hw_session.h
@@ -3,7 +3,7 @@
* This file contains the API to load sound models with
* DSP and start/stop detection of associated key phrases.
*
- * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -50,6 +50,7 @@
typedef enum st_hw_sess_event_id {
ST_HW_SESS_EVENT_DETECTED,
+ ST_HW_SESS_EVENT_BUFFERING_STOPPED,
ST_HW_SESS_EVENT_MAX
} st_hw_sess_event_id_t;
diff --git a/st_hw_session_lsm.c b/st_hw_session_lsm.c
index 85a2a17..f2f1abb 100644
--- a/st_hw_session_lsm.c
+++ b/st_hw_session_lsm.c
@@ -771,8 +771,10 @@
}
}
-void process_raw_lab_data_ape(st_hw_session_lsm_t *p_lsm_ses)
+static void *buffer_thread_loop(void *context)
{
+ st_hw_session_lsm_t *p_lsm_ses =
+ (st_hw_session_lsm_t *)context;
int status = 0;
struct listnode *node = NULL, *tmp_node = NULL;
st_arm_second_stage_t *st_sec_stage = NULL;
@@ -782,190 +784,237 @@
bool real_time_check = true;
uint64_t frame_receive_time = 0, frame_send_time = 0;
uint64_t frame_read_time = 0, buffering_start_time = 0;
+ st_hw_sess_event_t hw_sess_event = {0};
- ST_DBG_DECLARE(FILE *fptr_drv = NULL; static int file_cnt = 0);
- if (p_lsm_ses->common.stdev->enable_debug_dumps) {
- ST_DBG_FILE_OPEN_WR(fptr_drv, ST_DEBUG_DUMP_LOCATION,
- "st_lab_drv_data_ape", "pcm", file_cnt++);
+ if (p_lsm_ses == NULL) {
+ ALOGE("%s: input is NULL, exiting", __func__);
+ return NULL;
}
pthread_mutex_lock(&p_lsm_ses->lock);
- p_lsm_ses->lab_processing_active = true;
- p_lsm_ses->unread_bytes = 0;
- p_lsm_ses->bytes_written = 0;
-
- st_buffer_reset(p_lsm_ses->common.buffer);
-
- if (p_lsm_ses->common.enable_second_stage) {
- if (p_lsm_ses->common.sthw_cfg.client_req_hist_buf) {
- kw_duration_bytes =
- convert_ms_to_bytes(
- p_lsm_ses->common.sthw_cfg.client_req_hist_buf,
- &p_lsm_ses->common.config);
- } else {
- kw_duration_bytes =
- convert_ms_to_bytes(
- p_lsm_ses->common.vendor_uuid_info->kw_duration,
- &p_lsm_ses->common.config);
+ while (!p_lsm_ses->exit_buffer_thread) {
+ ALOGV("%s: waiting to start buffering", __func__);
+ pthread_cond_wait(&p_lsm_ses->cond, &p_lsm_ses->lock);
+ ALOGV("%s: done waiting to start buffering, exit = %d", __func__,
+ p_lsm_ses->exit_buffer_thread);
+ if (p_lsm_ses->exit_buffer_thread) {
+ pthread_mutex_unlock(&p_lsm_ses->lock);
+ return NULL;
}
- list_for_each_safe(node, tmp_node, p_lsm_ses->common.second_stage_list) {
- st_sec_stage = node_to_item(node, st_arm_second_stage_t, list_node);
- /*
- * At the start of buffering, initialize the variables needed by the
- * second stage sessions.
- */
- pthread_mutex_lock(&st_sec_stage->ss_session->lock);
- /*
- * In the generic detection event usecase, the start of the buffer
- * sent to 2nd stage is determined by the 1st stage keyword start
- * index. This index can have some error, so the start of the buffer
- * is moved forward to ensure there are no resulting missed
- * detections. Similarly, error tolerance is added to the end of the
- * buffer for generic and non generic detection event usecases.
- */
- if (st_sec_stage->ss_info->sm_detection_type ==
- ST_SM_TYPE_KEYWORD_DETECTION) {
- cnn_prepend_bytes =
- convert_ms_to_bytes(
- p_lsm_ses->common.vendor_uuid_info->kw_start_tolerance,
- &p_lsm_ses->common.config);
-
- if (p_lsm_ses->common.kw_start_idx > cnn_prepend_bytes) {
- st_sec_stage->ss_session->buf_start =
- p_lsm_ses->common.kw_start_idx - cnn_prepend_bytes;
- } else {
- st_sec_stage->ss_session->buf_start = 0;
- }
-
- cnn_append_bytes =
- convert_ms_to_bytes(
- (p_lsm_ses->common.vendor_uuid_info->kw_end_tolerance +
- st_sec_stage->ss_info->data_after_kw_end),
- &p_lsm_ses->common.config);
-
- if (p_lsm_ses->common.kw_end_idx < kw_duration_bytes) {
- st_sec_stage->ss_session->buf_end =
- p_lsm_ses->common.kw_end_idx + cnn_append_bytes;
- } else {
- st_sec_stage->ss_session->buf_end = kw_duration_bytes +
- cnn_append_bytes;
- }
- /*
- * The first second-stage keyword buffer frame needs to contain
- * ((kwd_start_idx - kwd_start_tolerance) - kwd_end_idx) from
- * the first stage keyword.
- */
- st_sec_stage->ss_session->buff_sz = (p_lsm_ses->common.kw_end_idx -
- st_sec_stage->ss_session->buf_start);
- st_sec_stage->ss_session->lab_buf_sz = p_lsm_ses->lab_drv_buf_size;
- st_sec_stage->ss_session->det_status = KEYWORD_DETECTION_PENDING;
- } else if (st_sec_stage->ss_info->sm_detection_type ==
- ST_SM_TYPE_USER_VERIFICATION) {
- vop_prepend_bytes =
- convert_ms_to_bytes(
- st_sec_stage->ss_info->data_before_kw_start,
- &p_lsm_ses->common.config);
-
- if (p_lsm_ses->common.kw_start_idx > vop_prepend_bytes) {
- st_sec_stage->ss_session->buf_start =
- p_lsm_ses->common.kw_start_idx - vop_prepend_bytes;
- } else {
- st_sec_stage->ss_session->buf_start = 0;
- }
-
- vop_append_bytes =
- convert_ms_to_bytes(
- p_lsm_ses->common.vendor_uuid_info->kw_end_tolerance,
- &p_lsm_ses->common.config);
-
- if ((p_lsm_ses->common.kw_end_idx + vop_append_bytes) <
- kw_duration_bytes) {
- st_sec_stage->ss_session->buf_end =
- p_lsm_ses->common.kw_end_idx + vop_append_bytes;
- } else {
- st_sec_stage->ss_session->buf_end = kw_duration_bytes;
- }
-
- st_sec_stage->ss_session->buff_sz = (st_sec_stage->ss_session->buf_end -
- st_sec_stage->ss_session->buf_start);
- st_sec_stage->ss_session->det_status = USER_VERIFICATION_PENDING;
- }
- st_sec_stage->ss_session->unread_bytes = 0;
- st_sec_stage->ss_session->exit_buffering = false;
- st_sec_stage->ss_session->bytes_processed = 0;
- st_sec_stage->ss_session->start_processing = false;
- st_sec_stage->ss_session->confidence_score = 0;
- pthread_mutex_unlock(&st_sec_stage->ss_session->lock);
- }
-
- if (p_lsm_ses->common.enable_second_stage &&
- !p_lsm_ses->common.sthw_cfg.client_req_hist_buf)
- p_lsm_ses->move_client_ptr = true;
- else
- p_lsm_ses->move_client_ptr = false;
- }
-
- buffering_start_time = get_current_time_ns();
-
- while (!p_lsm_ses->exit_lab_processing) {
- ALOGVV("%s: pcm_read reading bytes=%d", __func__, p_lsm_ses->lab_drv_buf_size);
- pthread_mutex_unlock(&p_lsm_ses->lock);
- frame_send_time = get_current_time_ns();
- ATRACE_ASYNC_BEGIN("sthal:lsm:ape: pcm_read",
- p_lsm_ses->common.sm_handle);
- status = pcm_read(p_lsm_ses->pcm, p_lsm_ses->lab_drv_buf, p_lsm_ses->lab_drv_buf_size);
- ATRACE_ASYNC_END("sthal:lsm:ape: pcm_read",
- p_lsm_ses->common.sm_handle);
- pthread_mutex_lock(&p_lsm_ses->lock);
- frame_receive_time = get_current_time_ns();
-
- ALOGVV("%s: pcm_read done", __func__);
+ ST_DBG_DECLARE(FILE *fptr_drv = NULL; static int file_cnt = 0);
if (p_lsm_ses->common.stdev->enable_debug_dumps) {
- ST_DBG_FILE_WRITE(fptr_drv, p_lsm_ses->lab_drv_buf,
- p_lsm_ses->lab_drv_buf_size);
+ ST_DBG_FILE_OPEN_WR(fptr_drv, ST_DEBUG_DUMP_LOCATION,
+ "st_lab_drv_data_ape", "pcm", file_cnt++);
}
+ ATRACE_BEGIN("sthal:lsm: buffer_thread_loop");
+
+ status = 0;
+ real_time_check = true;
+ p_lsm_ses->unread_bytes = 0;
+ p_lsm_ses->bytes_written = 0;
+
+ st_buffer_reset(p_lsm_ses->common.buffer);
+
+ if (p_lsm_ses->common.enable_second_stage) {
+ if (p_lsm_ses->common.sthw_cfg.client_req_hist_buf) {
+ kw_duration_bytes =
+ convert_ms_to_bytes(
+ p_lsm_ses->common.sthw_cfg.client_req_hist_buf,
+ &p_lsm_ses->common.config);
+ } else {
+ kw_duration_bytes =
+ convert_ms_to_bytes(
+ p_lsm_ses->common.vendor_uuid_info->kw_duration,
+ &p_lsm_ses->common.config);
+ }
+
+ list_for_each_safe(node, tmp_node,
+ p_lsm_ses->common.second_stage_list) {
+ st_sec_stage = node_to_item(node, st_arm_second_stage_t,
+ list_node);
+ /*
+ * At the start of buffering, initialize the variables needed
+ * by the second stage sessions.
+ */
+ pthread_mutex_lock(&st_sec_stage->ss_session->lock);
+ /*
+ * In the generic detection event usecase, the start of the
+ * buffer sent to 2nd stage is determined by the 1st stage
+ * keyword start index. This index can have some error, so the
+ * start of the buffer is moved forward to ensure there are no
+ * resulting missed detections. Similarly, error tolerance is
+ * added to the end of the buffer for generic and non generic
+ * detection event usecases.
+ */
+ if (st_sec_stage->ss_info->sm_detection_type ==
+ ST_SM_TYPE_KEYWORD_DETECTION) {
+ cnn_prepend_bytes =
+ convert_ms_to_bytes(
+ p_lsm_ses->common.vendor_uuid_info->kw_start_tolerance,
+ &p_lsm_ses->common.config);
+
+ if (p_lsm_ses->common.kw_start_idx > cnn_prepend_bytes) {
+ st_sec_stage->ss_session->buf_start =
+ p_lsm_ses->common.kw_start_idx - cnn_prepend_bytes;
+ } else {
+ st_sec_stage->ss_session->buf_start = 0;
+ }
+
+ cnn_append_bytes =
+ convert_ms_to_bytes(
+ (p_lsm_ses->common.vendor_uuid_info->kw_end_tolerance +
+ st_sec_stage->ss_info->data_after_kw_end),
+ &p_lsm_ses->common.config);
+
+ if (p_lsm_ses->common.kw_end_idx < kw_duration_bytes) {
+ st_sec_stage->ss_session->buf_end =
+ p_lsm_ses->common.kw_end_idx + cnn_append_bytes;
+ } else {
+ st_sec_stage->ss_session->buf_end = kw_duration_bytes +
+ cnn_append_bytes;
+ }
+ /*
+ * The first second-stage keyword buffer frame needs to
+ * contain ((kwd_start_idx - kwd_start_tolerance) -
+ * kwd_end_idx) from the first stage keyword.
+ */
+ st_sec_stage->ss_session->buff_sz =
+ (p_lsm_ses->common.kw_end_idx -
+ st_sec_stage->ss_session->buf_start);
+ st_sec_stage->ss_session->lab_buf_sz =
+ p_lsm_ses->lab_drv_buf_size;
+ st_sec_stage->ss_session->det_status =
+ KEYWORD_DETECTION_PENDING;
+ } else if (st_sec_stage->ss_info->sm_detection_type ==
+ ST_SM_TYPE_USER_VERIFICATION) {
+ vop_prepend_bytes =
+ convert_ms_to_bytes(
+ st_sec_stage->ss_info->data_before_kw_start,
+ &p_lsm_ses->common.config);
+
+ if (p_lsm_ses->common.kw_start_idx > vop_prepend_bytes) {
+ st_sec_stage->ss_session->buf_start =
+ p_lsm_ses->common.kw_start_idx - vop_prepend_bytes;
+ } else {
+ st_sec_stage->ss_session->buf_start = 0;
+ }
+
+ vop_append_bytes =
+ convert_ms_to_bytes(
+ p_lsm_ses->common.vendor_uuid_info->kw_end_tolerance,
+ &p_lsm_ses->common.config);
+
+ if ((p_lsm_ses->common.kw_end_idx + vop_append_bytes) <
+ kw_duration_bytes) {
+ st_sec_stage->ss_session->buf_end =
+ p_lsm_ses->common.kw_end_idx + vop_append_bytes;
+ } else {
+ st_sec_stage->ss_session->buf_end = kw_duration_bytes;
+ }
+
+ st_sec_stage->ss_session->buff_sz =
+ (st_sec_stage->ss_session->buf_end -
+ st_sec_stage->ss_session->buf_start);
+ st_sec_stage->ss_session->det_status =
+ USER_VERIFICATION_PENDING;
+ }
+ st_sec_stage->ss_session->unread_bytes = 0;
+ st_sec_stage->ss_session->exit_buffering = false;
+ st_sec_stage->ss_session->bytes_processed = 0;
+ st_sec_stage->ss_session->start_processing = false;
+ st_sec_stage->ss_session->confidence_score = 0;
+ pthread_mutex_unlock(&st_sec_stage->ss_session->lock);
+ }
+
+ if (p_lsm_ses->common.enable_second_stage &&
+ !p_lsm_ses->common.sthw_cfg.client_req_hist_buf)
+ p_lsm_ses->move_client_ptr = true;
+ else
+ p_lsm_ses->move_client_ptr = false;
+ }
+
+ buffering_start_time = get_current_time_ns();
+
+ while (!p_lsm_ses->exit_lab_processing) {
+ ALOGVV("%s: pcm_read reading bytes=%d", __func__,
+ p_lsm_ses->lab_drv_buf_size);
+ pthread_mutex_unlock(&p_lsm_ses->lock);
+ frame_send_time = get_current_time_ns();
+ ATRACE_ASYNC_BEGIN("sthal:lsm:ape: pcm_read",
+ p_lsm_ses->common.sm_handle);
+ status = pcm_read(p_lsm_ses->pcm, p_lsm_ses->lab_drv_buf,
+ p_lsm_ses->lab_drv_buf_size);
+ ATRACE_ASYNC_END("sthal:lsm:ape: pcm_read",
+ p_lsm_ses->common.sm_handle);
+ pthread_mutex_lock(&p_lsm_ses->lock);
+ frame_receive_time = get_current_time_ns();
+
+ ALOGVV("%s: pcm_read done", __func__);
+ if (p_lsm_ses->common.stdev->enable_debug_dumps) {
+ ST_DBG_FILE_WRITE(fptr_drv, p_lsm_ses->lab_drv_buf,
+ p_lsm_ses->lab_drv_buf_size);
+ }
+
+ if (status) {
+ ALOGE("%s: pcm read failed status %d - %s", __func__, status,
+ pcm_get_error(p_lsm_ses->pcm));
+ pcm_stop(p_lsm_ses->pcm);
+ pcm_start(p_lsm_ses->pcm);
+ break;
+ }
+
+ status = write_pcm_data_ape(p_lsm_ses, p_lsm_ses->lab_drv_buf,
+ p_lsm_ses->lab_drv_buf_size);
+ if (status) {
+ ALOGE("%s: Failed to write to circ buff, status %d", __func__,
+ status);
+ break;
+ }
+ frame_read_time = frame_receive_time - frame_send_time;
+ if (real_time_check &&
+ (frame_read_time > APE_MAX_LAB_FTRT_FRAME_RD_TIME_NS)) {
+ uint32_t ftrt_bytes_written_ms =
+ convert_bytes_to_ms(p_lsm_ses->bytes_written -
+ p_lsm_ses->lab_drv_buf_size, &p_lsm_ses->common.config);
+
+ ALOGD("%s: FTRT data transfer: %dms of data received in %llums",
+ __func__, ftrt_bytes_written_ms, ((frame_send_time -
+ buffering_start_time) / NSECS_PER_MSEC));
+
+ if (p_lsm_ses->common.enable_second_stage &&
+ !p_lsm_ses->common.is_generic_event) {
+ ALOGD("%s: First real time frame took %llums", __func__,
+ (frame_read_time / NSECS_PER_MSEC));
+ adjust_ss_buff_end(&p_lsm_ses->common, cnn_append_bytes,
+ vop_append_bytes);
+ }
+ real_time_check = false;
+ }
+ }
+ ALOGV("%s: Exited buffering, status=%d", __func__, status);
+ ape_stop_buffering(&p_lsm_ses->common);
+ p_lsm_ses->lab_on_detection = false;
+ p_lsm_ses->lab_processing_active = false;
+ pthread_cond_broadcast(&p_lsm_ses->cond);
+ if (p_lsm_ses->common.stdev->enable_debug_dumps)
+ ST_DBG_FILE_CLOSE(fptr_drv);
+ ATRACE_END();
+
if (status) {
- ALOGE("%s: pcm read failed status %d - %s", __func__, status,
- pcm_get_error(p_lsm_ses->pcm));
- pcm_stop(p_lsm_ses->pcm);
- pcm_start(p_lsm_ses->pcm);
- break;
- }
-
- write_pcm_data_ape(p_lsm_ses, p_lsm_ses->lab_drv_buf, p_lsm_ses->lab_drv_buf_size);
- frame_read_time = frame_receive_time - frame_send_time;
- if (real_time_check &&
- (frame_read_time > APE_MAX_LAB_FTRT_FRAME_RD_TIME_NS)) {
- uint32_t ftrt_bytes_written_ms =
- convert_bytes_to_ms(p_lsm_ses->bytes_written -
- p_lsm_ses->lab_drv_buf_size, &p_lsm_ses->common.config);
-
- ALOGD("%s: FTRT data transfer: %dms of data received in %llums",
- __func__, ftrt_bytes_written_ms, ((frame_send_time -
- buffering_start_time) / NSECS_PER_MSEC));
-
- if (p_lsm_ses->common.enable_second_stage && !p_lsm_ses->common.is_generic_event) {
- ALOGD("%s: First real time frame took %llums", __func__,
- (frame_read_time / NSECS_PER_MSEC));
- adjust_ss_buff_end(&p_lsm_ses->common, cnn_append_bytes,
- vop_append_bytes);
- }
- real_time_check = false;
+ hw_sess_event.event_id = ST_HW_SESS_EVENT_BUFFERING_STOPPED;
+ pthread_mutex_unlock(&p_lsm_ses->lock);
+ p_lsm_ses->common.callback_to_st_session(&hw_sess_event,
+ p_lsm_ses->common.cookie);
+ pthread_mutex_lock(&p_lsm_ses->lock);
}
}
-
- ape_stop_buffering(&p_lsm_ses->common);
- p_lsm_ses->lab_on_detection = false;
- p_lsm_ses->lab_processing_active = false;
- pthread_cond_broadcast(&p_lsm_ses->cond);
pthread_mutex_unlock(&p_lsm_ses->lock);
- if (p_lsm_ses->common.stdev->enable_debug_dumps)
- ST_DBG_FILE_CLOSE(fptr_drv);
- ALOGVV("%s: Exit status=%d", __func__, status);
+ return NULL;
}
+
static void *callback_thread_loop(void *context)
{
st_hw_session_lsm_t *p_lsm_ses =
@@ -1127,6 +1176,12 @@
}
p_ses->lab_buffers_allocated = false;
+ p_ses->exit_buffer_thread = true;
+ pthread_mutex_lock(&p_ses->lock);
+ pthread_cond_signal(&p_ses->cond);
+ pthread_mutex_unlock(&p_ses->lock);
+ pthread_join(p_ses->buffer_thread, NULL);
+
return 0;
}
@@ -1135,6 +1190,7 @@
int status = 0, circ_buff_sz = 0;
struct st_vendor_info *v_info = p_lsm_ses->common.vendor_uuid_info;
unsigned int rt_bytes_one_sec;
+ pthread_attr_t attr;
p_lsm_ses->lab_drv_buf_size = pcm_frames_to_bytes(p_lsm_ses->pcm,
p_lsm_ses->common.config.period_size);
@@ -1172,6 +1228,12 @@
ALOGV("%s: Allocated out buffer size=%d", __func__, circ_buff_sz);
p_lsm_ses->lab_buffers_allocated = true;
+ p_lsm_ses->exit_buffer_thread = false;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+ pthread_create(&p_lsm_ses->buffer_thread, &attr,
+ buffer_thread_loop, p_lsm_ses);
+
return status;
error_exit:
@@ -2392,9 +2454,10 @@
{
st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t *)p_ses;
- ATRACE_BEGIN("sthal:lsm: process_raw_lab_data_ape");
- process_raw_lab_data_ape(p_lsm_ses);
- ATRACE_END();
+ pthread_mutex_lock(&p_lsm_ses->lock);
+ p_lsm_ses->lab_processing_active = true;
+ pthread_cond_signal(&p_lsm_ses->cond);
+ pthread_mutex_unlock(&p_lsm_ses->lock);
}
int route_send_custom_chmix_coeff_ape(st_hw_session_t *p_ses, char *str)
diff --git a/st_hw_session_lsm.h b/st_hw_session_lsm.h
index ed65330..d99a7bc 100644
--- a/st_hw_session_lsm.h
+++ b/st_hw_session_lsm.h
@@ -124,6 +124,9 @@
pthread_t callback_thread;
bool exit_callback_thread;
+ pthread_t buffer_thread;
+ bool exit_buffer_thread;
+
int pcm_id;
struct pcm *pcm;
struct pcm_config lab_config;
diff --git a/st_session.c b/st_session.c
index 152315c..a32b71d 100644
--- a/st_session.c
+++ b/st_session.c
@@ -203,6 +203,7 @@
ev.payload.detected.detect_status = 3;
DISPATCH_EVENT(st_ses, ev, status);
+ break;
}
if (!lock_status)
@@ -210,11 +211,51 @@
break;
}
+ case ST_HW_SESS_EVENT_BUFFERING_STOPPED:
+ {
+ st_session_ev_t ev;
+ ev.ev_id = ST_SES_EV_DEFERRED_STOP;
+ ev.stc_ses = st_ses->det_stc_ses;
+
+ /*
+ * If detection is sent to client while in buffering state,
+ * and if internal buffering is stopped due to errors, stop
+ * session internally as client is expected to restart the
+ * detection if required.
+ * Note: It is possible that detection event is not sent to
+ * client if second stage is not yet detected during internal
+ * buffering stop, in which case restart is posted from second
+ * stage thread for further detections. Only if the second
+ * stage detection hasn't be started due to internal buffering
+ * stop too early, restart session should be explictily issued.
+ */
+
+ do {
+ lock_status = pthread_mutex_trylock(&st_ses->lock);
+ } while (lock_status && !st_ses->det_stc_ses->pending_stop &&
+ (st_ses->current_state == buffering_state_fn));
+
+ if (st_ses->det_stc_ses->pending_stop)
+ ALOGV("%s:[%d] pending stop already queued, ignore event",
+ __func__, st_ses->sm_handle);
+ else if (!st_ses->det_stc_ses->detection_sent)
+ ALOGV("%s:[%d] client callback hasn't been called, ignore event",
+ __func__, st_ses->sm_handle);
+ else if (st_ses->current_state != buffering_state_fn)
+ ALOGV("%s:[%d] session already stopped buffering, ignore event",
+ __func__, st_ses->sm_handle);
+ else if (!lock_status)
+ DISPATCH_EVENT(st_ses, ev, status);
+
+ if (!lock_status)
+ pthread_mutex_unlock(&st_ses->lock);
+ break;
+ }
+
default:
ALOGD("%s:[%d] unhandled event", __func__, st_ses->sm_handle);
break;
};
-
}
static inline void free_array_ptrs(char **arr, unsigned int arr_len)
@@ -4652,6 +4693,7 @@
*/
if (st_ses->lab_enabled)
hw_ses->fptrs->stop_buffering(hw_ses);
+ pthread_mutex_unlock(&st_ses->lock);
break;
}
st_ses->det_stc_ses = stc_ses;
@@ -4677,6 +4719,7 @@
hw_ses->fptrs->stop_buffering(hw_ses);
if (event)
free(event);
+ pthread_mutex_unlock(&st_ses->lock);
break;
}
} else {
@@ -4742,6 +4785,7 @@
status = -EINVAL;
if (event)
free(event);
+ pthread_mutex_unlock(&st_ses->lock);
break;
}
/*
@@ -4758,15 +4802,22 @@
__func__, stc_ses->sm_handle);
ATRACE_ASYNC_END("sthal: detection success",
st_ses->sm_handle);
+ if (!lab_enabled) {
+ st_session_ev_t deferred_ev = {
+ .ev_id = ST_SES_EV_DEFERRED_STOP,
+ .stc_ses = stc_ses
+ };
+ DISPATCH_EVENT(st_ses, deferred_ev, status);
+ }
pthread_mutex_unlock(&st_ses->lock);
ATRACE_BEGIN("sthal: client detection callback");
callback(event, cookie);
ATRACE_END();
+ if (event)
+ free(event);
} else {
pthread_mutex_unlock(&st_ses->lock);
}
- if (event)
- free(event);
/*
* TODO: Add RECOGNITION_STATUS_GET_STATE_RESPONSE to
@@ -4779,88 +4830,6 @@
/* Cache lab data to internal buffers (blocking call) */
hw_ses->fptrs->process_lab_capture(hw_ses);
}
-
- /*
- * It is possible that the client may start/stop/unload the session
- * with the same lock held, before we aqcuire lock here.
- * We need further processing only if client starts in detected state
- * or buffering state if lab was enabled, else return gracefully.
- * For multi-client scenario, only one client is assumed to be
- * detected/bufffering, so the logic remains same.
- */
- do {
- status = pthread_mutex_trylock(&st_ses->lock);
- } while (status && ((st_ses->current_state == detected_state_fn) ||
- (st_ses->current_state == buffering_state_fn)) &&
- !st_ses->stdev->ssr_offline_received);
-
- if (st_ses->current_state != detected_state_fn) {
- ALOGV("%s:[%d] client not in detected state, lock status %d",
- __func__, st_ses->sm_handle, status);
- if (!status) {
- /*
- * If detection is sent to client while in buffering state,
- * and if internal buffering is stopped due to errors, stop
- * session internally as client is expected to restart the
- * detection if required.
- * Note: It is possible that detection event is not sent to
- * client if second stage is not yet detected during internal
- * buffering stop, in which case restart is posted from second
- * stage thread for further detections. Only if the second
- * stage detection hasn't be started due to internal buffering
- * stop too early, restart session should be explictily issued.
- */
- if (st_ses->current_state == buffering_state_fn) {
- if (stc_ses->detection_sent) {
- if (!stc_ses->pending_stop) {
- ALOGD("%s:[%d] buffering stopped internally, post c%d stop",
- __func__, st_ses->sm_handle,
- st_ses->det_stc_ses->sm_handle);
- status = hw_session_notifier_enqueue(stc_ses->sm_handle,
- ST_SES_EV_DEFERRED_STOP,
- ST_SES_DEFERRED_STOP_SS_DELAY_MS);
- if (!status)
- stc_ses->pending_stop = true;
- }
- } else {
- list_for_each(node, &stc_ses->second_stage_list) {
- st_sec_stage = node_to_item(node, st_arm_second_stage_t,
- list_node);
- if (!st_sec_stage->ss_session->start_processing) {
- st_session_ev_t ev = {.ev_id = ST_SES_EV_RESTART,
- .stc_ses = stc_ses};
- DISPATCH_EVENT(st_ses, ev, status);
- break;
- }
- }
- }
- }
- pthread_mutex_unlock(&st_ses->lock);
- }
- status = 0;
- break;
- }
-
- /*
- * If we are not buffering (i.e capture is not requested), then
- * trigger a deferred stop. Most applications issue (re)start
- * almost immediately. Delaying stop allows unnecessary teardown
- * and reinitialization of backend.
- */
- if (!lab_enabled) {
- /*
- * Note that this event will only be posted to the detected state
- * The current state may switch to active if the client
- * issues start/restart before control of the callback thread
- * reaches this point.
- */
- st_session_ev_t deferred_ev = { .ev_id = ST_SES_EV_DEFERRED_STOP,
- .stc_ses = stc_ses};
- DISPATCH_EVENT(st_ses, deferred_ev, status);
- } else {
- ALOGE("%s:[%d] capture is requested but state is still detected!?",
- __func__, st_ses->sm_handle);
- }
break;
case ST_SES_EV_SSR_OFFLINE:
@@ -5188,6 +5157,15 @@
}
break;
+ case ST_SES_EV_DEFERRED_STOP:
+ ALOGD("%s:[%d] post internal deferred stop from buffering state",
+ __func__, st_ses->sm_handle);
+ status = hw_session_notifier_enqueue(stc_ses->sm_handle,
+ ST_SES_EV_DEFERRED_STOP, ST_SES_DEFERRED_STOP_DELAY_MS);
+ if (!status)
+ stc_ses->pending_stop = true;
+ break;
+
case ST_SES_EV_STOP:
ALOGD("%s:[c%d-%d] handle event STOP", __func__, stc_ses->sm_handle,
st_ses->sm_handle);