hal: Remove in_get_stream and out_get_stream

Remove in_get_stream and out_get_stream and
add in_ctxt and out_ctxt members to stream_in/out
structs to track and directly access stream contexts.
Mitigate race conditions with the active_in/outputs_list
when in/out_get_stream reads the list.

Change-Id: Iefc77d3c862b16dce8086e1afba15cf0210155b4
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index ca06e59..d3b2935 100755
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -6228,8 +6228,6 @@
 {
     if(auto_hal_init) {
         auto_hal_init_config_t auto_hal_init_config;
-        auto_hal_init_config.fp_in_get_stream = in_get_stream;
-        auto_hal_init_config.fp_out_get_stream = out_get_stream;
         auto_hal_init_config.fp_audio_extn_ext_hw_plugin_usecase_start = audio_extn_ext_hw_plugin_usecase_start;
         auto_hal_init_config.fp_audio_extn_ext_hw_plugin_usecase_stop = audio_extn_ext_hw_plugin_usecase_stop;
         auto_hal_init_config.fp_get_usecase_from_list = get_usecase_from_list;
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 2c7711d..64b77e8 100755
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
  * Not a Contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -1390,16 +1390,12 @@
                                 audio_usecase_t uc_id);
 snd_device_t audio_extn_auto_hal_get_snd_device_for_car_audio_stream(int car_audio_stream);
 
-typedef streams_input_ctxt_t* (*fp_in_get_stream_t)(struct audio_device*, audio_io_handle_t);
-typedef streams_output_ctxt_t* (*fp_out_get_stream_t)(struct audio_device*, audio_io_handle_t);
 typedef size_t (*fp_get_output_period_size_t)(uint32_t, audio_format_t, int, int);
 typedef int (*fp_audio_extn_ext_hw_plugin_set_audio_gain_t)(void*, struct audio_usecase*, uint32_t);
 typedef struct stream_in* (*fp_adev_get_active_input_t)(const struct audio_device*);
 typedef audio_patch_handle_t (*fp_generate_patch_handle_t)(void);
 
 typedef struct auto_hal_init_config {
-    fp_in_get_stream_t                           fp_in_get_stream;
-    fp_out_get_stream_t                          fp_out_get_stream;
     fp_audio_extn_ext_hw_plugin_usecase_start_t  fp_audio_extn_ext_hw_plugin_usecase_start;
     fp_audio_extn_ext_hw_plugin_usecase_stop_t   fp_audio_extn_ext_hw_plugin_usecase_stop;
     fp_get_usecase_from_list_t                   fp_get_usecase_from_list;
diff --git a/hal/audio_extn/auto_hal.c b/hal/audio_extn/auto_hal.c
index 9276c9c..39f2838 100755
--- a/hal/audio_extn/auto_hal.c
+++ b/hal/audio_extn/auto_hal.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-2021, 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
@@ -47,8 +47,6 @@
 #endif
 
 //external feature dependency
-static fp_in_get_stream_t                           fp_in_get_stream;
-static fp_out_get_stream_t                          fp_out_get_stream;
 static fp_audio_extn_ext_hw_plugin_usecase_start_t  fp_audio_extn_ext_hw_plugin_usecase_start;
 static fp_audio_extn_ext_hw_plugin_usecase_stop_t   fp_audio_extn_ext_hw_plugin_usecase_stop;
 static fp_get_usecase_from_list_t                   fp_get_usecase_from_list;
@@ -937,8 +935,6 @@
 
     auto_hal->adev = adev;
 
-    fp_in_get_stream = init_config.fp_in_get_stream;
-    fp_out_get_stream = init_config.fp_out_get_stream;
     fp_audio_extn_ext_hw_plugin_usecase_start = init_config.fp_audio_extn_ext_hw_plugin_usecase_start;
     fp_audio_extn_ext_hw_plugin_usecase_stop = init_config.fp_audio_extn_ext_hw_plugin_usecase_stop;
     fp_get_usecase_from_list = init_config.fp_get_usecase_from_list;
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 212043b..83c35c7 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -7440,38 +7440,6 @@
     return add_remove_audio_effect(stream, effect, false);
 }
 
-streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
-                                  audio_io_handle_t input)
-{
-    struct listnode *node;
-
-    list_for_each(node, &dev->active_inputs_list) {
-        streams_input_ctxt_t *in_ctxt = node_to_item(node,
-                                                     streams_input_ctxt_t,
-                                                     list);
-        if (in_ctxt->input->capture_handle == input) {
-            return in_ctxt;
-        }
-    }
-    return NULL;
-}
-
-streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
-                                  audio_io_handle_t output)
-{
-    struct listnode *node;
-
-    list_for_each(node, &dev->active_outputs_list) {
-        streams_output_ctxt_t *out_ctxt = node_to_item(node,
-                                                     streams_output_ctxt_t,
-                                                     list);
-        if (out_ctxt->output->handle == output) {
-            return out_ctxt;
-        }
-    }
-    return NULL;
-}
-
 static int in_stop(const struct audio_stream_in* stream)
 {
     struct stream_in *in = (struct stream_in *)stream;
@@ -7797,15 +7765,6 @@
 
     *stream_out = NULL;
 
-    pthread_mutex_lock(&adev->lock);
-    if (out_get_stream(adev, handle) != NULL) {
-        ALOGW("%s, output stream already opened", __func__);
-        ret = -EEXIST;
-    }
-    pthread_mutex_unlock(&adev->lock);
-    if (ret)
-        return ret;
-
     out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
 
     ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
@@ -8643,17 +8602,10 @@
     if (ret != 0)
         goto error_open;
 
-    streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
-        calloc(1, sizeof(streams_output_ctxt_t));
-    if (out_ctxt == NULL) {
-        ALOGE("%s fail to allocate output ctxt", __func__);
-        ret = -ENOMEM;
-        goto error_open;
-    }
-    out_ctxt->output = out;
+    out->out_ctxt.output = out;
 
     pthread_mutex_lock(&adev->lock);
-    list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
+    list_add_tail(&adev->active_outputs_list, &out->out_ctxt.list);
     pthread_mutex_unlock(&adev->lock);
 
     ALOGV("%s: exit", __func__);
@@ -8679,6 +8631,12 @@
 
     io_streams_map_remove(adev, out->handle);
 
+    // remove out_ctxt early to prevent the stream
+    // being opened in a race condition
+    pthread_mutex_lock(&adev->lock);
+    list_remove(&out->out_ctxt.list);
+    pthread_mutex_unlock(&adev->lock);
+
     // must deregister from sndmonitor first to prevent races
     // between the callback and close_stream
     audio_extn_snd_mon_unregister_listener(out);
@@ -8741,13 +8699,6 @@
     pthread_mutex_destroy(&out->position_query_lock);
 
     pthread_mutex_lock(&adev->lock);
-    streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
-    if (out_ctxt != NULL) {
-        list_remove(&out_ctxt->list);
-        free(out_ctxt);
-    } else {
-        ALOGW("%s, output stream already closed", __func__);
-    }
     free(stream);
     pthread_mutex_unlock(&adev->lock);
     ALOGV("%s: exit", __func__);
@@ -9386,15 +9337,6 @@
             return -EINVAL;
     }
 
-    pthread_mutex_lock(&adev->lock);
-    if (in_get_stream(adev, handle) != NULL) {
-        ALOGW("%s, input stream already opened", __func__);
-        ret = -EEXIST;
-    }
-    pthread_mutex_unlock(&adev->lock);
-    if (ret)
-        return ret;
-
     in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
 
     if (!in) {
@@ -9781,17 +9723,10 @@
     if (ret != 0)
         goto err_open;
 
-    streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
-        calloc(1, sizeof(streams_input_ctxt_t));
-    if (in_ctxt == NULL) {
-        ALOGE("%s fail to allocate input ctxt", __func__);
-        ret = -ENOMEM;
-        goto err_open;
-    }
-    in_ctxt->input = in;
+    in->in_ctxt.input = in;
 
     pthread_mutex_lock(&adev->lock);
-    list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
+    list_add_tail(&adev->active_inputs_list, &in->in_ctxt.list);
     pthread_mutex_unlock(&adev->lock);
 
     ALOGV("%s: exit", __func__);
@@ -9823,6 +9758,12 @@
     }
     io_streams_map_remove(adev, in->capture_handle);
 
+    // remove out_ctxt early to prevent the stream
+    // being opened in a race condition
+    pthread_mutex_lock(&adev->lock);
+    list_remove(&in->in_ctxt.list);
+    pthread_mutex_unlock(&adev->lock);
+
     /* must deregister from sndmonitor first to prevent races
      * between the callback and close_stream
      */
@@ -9885,13 +9826,6 @@
         ALOGV("%s: sound trigger pcm stop lab", __func__);
         audio_extn_sound_trigger_stop_lab(in);
     }
-    streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
-    if (in_ctxt != NULL) {
-        list_remove(&in_ctxt->list);
-        free(in_ctxt);
-    } else {
-        ALOGW("%s, input stream already closed", __func__);
-    }
     free(stream);
     pthread_mutex_unlock(&adev->lock);
     return;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 05382e4..8caefe8 100755
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
  * Not a contribution.
  *
  * Copyright (C) 2013 The Android Open Source Project
@@ -361,6 +361,16 @@
     unsigned int bit_width;
 };
 
+typedef struct streams_input_ctxt {
+    struct listnode list;
+    struct stream_in *input;
+} streams_input_ctxt_t;
+
+typedef struct streams_output_ctxt {
+    struct listnode list;
+    struct stream_out *output;
+} streams_output_ctxt_t;
+
 struct stream_inout {
     pthread_mutex_t lock; /* see note below on mutex acquisition order */
     pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */
@@ -409,6 +419,7 @@
     int64_t mmap_time_offset_nanos; /* fudge factor to correct inaccuracies in DSP */
     int     mmap_shared_memory_fd; /* file descriptor associated with MMAP NOIRQ shared memory */
     audio_io_handle_t handle;
+    streams_output_ctxt_t out_ctxt;
     struct stream_app_type_cfg app_type_cfg;
 
     int non_blocking;
@@ -515,6 +526,7 @@
     int64_t mmap_time_offset_nanos; /* fudge factor to correct inaccuracies in DSP */
     int     mmap_shared_memory_fd; /* file descriptor associated with MMAP NOIRQ shared memory */
     audio_io_handle_t capture_handle;
+    streams_input_ctxt_t in_ctxt;
     audio_input_flags_t flags;
     char profile[MAX_STREAM_PROFILE_STR_LEN];
     bool is_st_session;
@@ -623,16 +635,6 @@
     struct stream_app_type_cfg app_type_cfg;
 };
 
-typedef struct streams_input_ctxt {
-    struct listnode list;
-    struct stream_in *input;
-} streams_input_ctxt_t;
-
-typedef struct streams_output_ctxt {
-    struct listnode list;
-    struct stream_out *output;
-} streams_output_ctxt_t;
-
 typedef void* (*adm_init_t)();
 typedef void (*adm_deinit_t)(void *);
 typedef void (*adm_register_output_stream_t)(void *, audio_io_handle_t, audio_output_flags_t);
@@ -814,11 +816,6 @@
 
 bool is_interactive_usecase(audio_usecase_t uc_id);
 
-streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
-                                  audio_io_handle_t input);
-streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
-                                  audio_io_handle_t output);
-
 size_t get_output_period_size(uint32_t sample_rate,
                             audio_format_t format,
                             int channel_count,