Moving device profile structures into streams rather than the device.

Decoupling this worthwhile change from the rest of multi-usb stuff.

Bug:111397675
Test: Connect to various USB interfaces and confirm correct behavior.
Change-Id: I8a5a89a1e99547a168423becea4c424b627bff9c
diff --git a/modules/usbaudio/audio_hal.c b/modules/usbaudio/audio_hal.c
index d797a21..cddcc14 100644
--- a/modules/usbaudio/audio_hal.c
+++ b/modules/usbaudio/audio_hal.c
@@ -15,7 +15,7 @@
  */
 
 #define LOG_TAG "modules.usbaudio.audio_hal"
-/*#define LOG_NDEBUG 0*/
+/* #define LOG_NDEBUG 0 */
 
 #include <errno.h>
 #include <inttypes.h>
@@ -56,11 +56,9 @@
     pthread_mutex_t lock; /* see note below on mutex acquisition order */
 
     /* output */
-    alsa_device_profile out_profile;
     struct listnode output_stream_list;
 
     /* input */
-    alsa_device_profile in_profile;
     struct listnode input_stream_list;
 
     /* lock input & output sample rates */
@@ -69,8 +67,6 @@
 
     bool mic_muted;
 
-    bool standby;
-
     int32_t inputs_open; /* number of input streams currently open. */
 };
 
@@ -82,16 +78,13 @@
 struct stream_out {
     struct audio_stream_out stream;
 
-    struct stream_lock  lock;
+    struct stream_lock lock;
 
     bool standby;
 
     struct audio_device *adev;           /* hardware information - only using this for the lock */
 
-    const alsa_device_profile *profile; /* Points to the alsa_device_profile in the audio_device.
-                                         * Const, so modifications go through adev->out_profile
-                                         * and thus should have the hardware lock and ensure
-                                         * stream is not active and no other open output streams.
+    alsa_device_profile profile;        /* The profile of the ALSA device connected to the stream.
                                          */
 
     alsa_device_proxy proxy;            /* state of the stream */
@@ -124,10 +117,7 @@
 
     struct audio_device *adev;           /* hardware information - only using this for the lock */
 
-    const alsa_device_profile *profile; /* Points to the alsa_device_profile in the audio_device.
-                                         * Const, so modifications go through adev->out_profile
-                                         * and thus should have the hardware lock and ensure
-                                         * stream is not active and no other open input streams.
+    alsa_device_profile profile;        /* The profile of the ALSA device connected to the stream.
                                          */
 
     alsa_device_proxy proxy;            /* state of the stream */
@@ -347,9 +337,7 @@
 
     stream_lock(&out->lock);
     if (!out->standby) {
-        device_lock(out->adev);
         proxy_close(&out->proxy);
-        device_unlock(out->adev);
         out->standby = true;
     }
     stream_unlock(&out->lock);
@@ -361,7 +349,7 @@
 
     if (out_stream != NULL) {
         dprintf(fd, "Output Profile:\n");
-        profile_dump(out_stream->profile, fd);
+        profile_dump(&out_stream->profile, fd);
 
         dprintf(fd, "Output Proxy:\n");
         proxy_dump(&out_stream->proxy, fd);
@@ -386,27 +374,23 @@
     }
 
     stream_lock(&out->lock);
-    /* Lock the device because that is where the profile lives */
-    device_lock(out->adev);
-
-    if (!profile_is_cached_for(out->profile, card, device)) {
+    if (!profile_is_cached_for(&out->profile, card, device)) {
         /* cannot read pcm device info if playback is active */
         if (!out->standby)
             ret_value = -ENOSYS;
         else {
-            int saved_card = out->profile->card;
-            int saved_device = out->profile->device;
-            out->adev->out_profile.card = card;
-            out->adev->out_profile.device = device;
-            ret_value = profile_read_device_info(&out->adev->out_profile) ? 0 : -EINVAL;
+            int saved_card = out->profile.card;
+            int saved_device = out->profile.device;
+            out->profile.card = card;
+            out->profile.device = device;
+            ret_value = profile_read_device_info(&out->profile) ? 0 : -EINVAL;
             if (ret_value != 0) {
-                out->adev->out_profile.card = saved_card;
-                out->adev->out_profile.device = saved_device;
+                out->profile.card = saved_card;
+                out->profile.device = saved_device;
             }
         }
     }
 
-    device_unlock(out->adev);
     stream_unlock(&out->lock);
 
     return ret_value;
@@ -416,11 +400,7 @@
 {
     struct stream_out *out = (struct stream_out *)stream;
     stream_lock(&out->lock);
-    device_lock(out->adev);
-
-    char * params_str =  device_get_parameters(out->profile, keys);
-
-    device_unlock(out->adev);
+    char * params_str =  device_get_parameters(&out->profile, keys);
     stream_unlock(&out->lock);
     return params_str;
 }
@@ -439,7 +419,7 @@
 /* must be called with hw device and output stream mutexes locked */
 static int start_output_stream(struct stream_out *out)
 {
-    ALOGV("start_output_stream(card:%d device:%d)", out->profile->card, out->profile->device);
+    ALOGV("start_output_stream(card:%d device:%d)", out->profile.card, out->profile.device);
 
     return proxy_open(&out->proxy);
 }
@@ -451,9 +431,7 @@
 
     stream_lock(&out->lock);
     if (out->standby) {
-        device_lock(out->adev);
         ret = start_output_stream(out);
-        device_unlock(out->adev);
         if (ret != 0) {
             goto err;
         }
@@ -576,44 +554,45 @@
     stream_lock_init(&out->lock);
 
     out->adev = (struct audio_device *)hw_dev;
-    device_lock(out->adev);
-    out->profile = &out->adev->out_profile;
+
+    profile_init(&out->profile, PCM_OUT);
 
     // build this to hand to the alsa_device_proxy
     struct pcm_config proxy_config;
     memset(&proxy_config, 0, sizeof(proxy_config));
 
     /* Pull out the card/device pair */
-    parse_card_device_params(address, &out->adev->out_profile.card, &out->adev->out_profile.device);
+    parse_card_device_params(address, &out->profile.card, &out->profile.device);
 
-    profile_read_device_info(&out->adev->out_profile);
+    profile_read_device_info(&out->profile);
 
     int ret = 0;
 
     /* Rate */
     if (config->sample_rate == 0) {
-        proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(out->profile);
-    } else if (profile_is_sample_rate_valid(out->profile, config->sample_rate)) {
+        proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(&out->profile);
+    } else if (profile_is_sample_rate_valid(&out->profile, config->sample_rate)) {
         proxy_config.rate = config->sample_rate;
     } else {
-        proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(out->profile);
+        proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(&out->profile);
         ret = -EINVAL;
     }
 
     /* TODO: This is a problem if the input does not support this rate */
+    device_lock(out->adev);
     out->adev->device_sample_rate = config->sample_rate;
     device_unlock(out->adev);
 
     /* Format */
     if (config->format == AUDIO_FORMAT_DEFAULT) {
-        proxy_config.format = profile_get_default_format(out->profile);
+        proxy_config.format = profile_get_default_format(&out->profile);
         config->format = audio_format_from_pcm_format(proxy_config.format);
     } else {
         enum pcm_format fmt = pcm_format_from_audio_format(config->format);
-        if (profile_is_format_valid(out->profile, fmt)) {
+        if (profile_is_format_valid(&out->profile, fmt)) {
             proxy_config.format = fmt;
         } else {
-            proxy_config.format = profile_get_default_format(out->profile);
+            proxy_config.format = profile_get_default_format(&out->profile);
             config->format = audio_format_from_pcm_format(proxy_config.format);
             ret = -EINVAL;
         }
@@ -623,7 +602,7 @@
     bool calc_mask = false;
     if (config->channel_mask == AUDIO_CHANNEL_NONE) {
         /* query case */
-        out->hal_channel_count = profile_get_default_channel_count(out->profile);
+        out->hal_channel_count = profile_get_default_channel_count(&out->profile);
         calc_mask = true;
     } else {
         /* explicit case */
@@ -651,8 +630,9 @@
     // Validate the "logical" channel count against support in the "actual" profile.
     // if they differ, choose the "actual" number of channels *closest* to the "logical".
     // and store THAT in proxy_config.channels
-    proxy_config.channels = profile_get_closest_channel_count(out->profile, out->hal_channel_count);
-    proxy_prepare(&out->proxy, out->profile, &proxy_config);
+    proxy_config.channels =
+            profile_get_closest_channel_count(&out->profile, out->hal_channel_count);
+    proxy_prepare(&out->proxy, &out->profile, &proxy_config);
 
     /* TODO The retry mechanism isn't implemented in AudioPolicyManager/AudioFlinger
      * So clear any errors that may have occurred above.
@@ -676,9 +656,7 @@
                                      struct audio_stream_out *stream)
 {
     struct stream_out *out = (struct stream_out *)stream;
-    ALOGV("adev_close_output_stream(c:%d d:%d)", out->profile->card, out->profile->device);
-
-    adev_remove_stream_from_list(out->adev, &out->list_node);
+    ALOGV("adev_close_output_stream(c:%d d:%d)", out->profile.card, out->profile.device);
 
     /* Close the pcm device */
     out_standby(&stream->common);
@@ -688,6 +666,8 @@
     out->conversion_buffer = NULL;
     out->conversion_buffer_size = 0;
 
+    adev_remove_stream_from_list(out->adev, &out->list_node);
+
     device_lock(out->adev);
     out->adev->device_sample_rate = 0;
     device_unlock(out->adev);
@@ -750,12 +730,9 @@
 
     stream_lock(&in->lock);
     if (!in->standby) {
-        device_lock(in->adev);
         proxy_close(&in->proxy);
-        device_unlock(in->adev);
         in->standby = true;
     }
-
     stream_unlock(&in->lock);
 
     return 0;
@@ -766,7 +743,7 @@
   const struct stream_in* in_stream = (const struct stream_in*)stream;
   if (in_stream != NULL) {
       dprintf(fd, "Input Profile:\n");
-      profile_dump(in_stream->profile, fd);
+      profile_dump(&in_stream->profile, fd);
 
       dprintf(fd, "Input Proxy:\n");
       proxy_dump(&in_stream->proxy, fd);
@@ -793,19 +770,20 @@
     stream_lock(&in->lock);
     device_lock(in->adev);
 
-    if (card >= 0 && device >= 0 && !profile_is_cached_for(in->profile, card, device)) {
-        /* cannot read pcm device info if playback is active, or more than one open stream */
+    if (card >= 0 && device >= 0 && !profile_is_cached_for(&in->profile, card, device)) {
+        /* cannot read pcm device info if capture is active, or more than one open stream */
         if (!in->standby || in->adev->inputs_open > 1)
             ret_value = -ENOSYS;
         else {
-            int saved_card = in->profile->card;
-            int saved_device = in->profile->device;
-            in->adev->in_profile.card = card;
-            in->adev->in_profile.device = device;
-            ret_value = profile_read_device_info(&in->adev->in_profile) ? 0 : -EINVAL;
+            int saved_card = in->profile.card;
+            int saved_device = in->profile.device;
+            in->profile.card = card;
+            in->profile.device = device;
+            ret_value = profile_read_device_info(&in->profile) ? 0 : -EINVAL;
             if (ret_value != 0) {
-                in->adev->in_profile.card = saved_card;
-                in->adev->in_profile.device = saved_device;
+                ALOGE("Can't read device profile. card:%d, device:%d", card, device);
+                in->profile.card = saved_card;
+                in->profile.device = saved_device;
             }
         }
     }
@@ -821,11 +799,7 @@
     struct stream_in *in = (struct stream_in *)stream;
 
     stream_lock(&in->lock);
-    device_lock(in->adev);
-
-    char * params_str =  device_get_parameters(in->profile, keys);
-
-    device_unlock(in->adev);
+    char * params_str =  device_get_parameters(&in->profile, keys);
     stream_unlock(&in->lock);
 
     return params_str;
@@ -849,7 +823,7 @@
 /* must be called with hw device and output stream mutexes locked */
 static int start_input_stream(struct stream_in *in)
 {
-    ALOGV("start_input_stream(card:%d device:%d)", in->profile->card, in->profile->device);
+    ALOGV("start_input_stream(card:%d device:%d)", in->profile.card, in->profile.device);
 
     return proxy_open(&in->proxy);
 }
@@ -866,9 +840,7 @@
 
     stream_lock(&in->lock);
     if (in->standby) {
-        device_lock(in->adev);
         ret = start_input_stream(in);
-        device_unlock(in->adev);
         if (ret != 0) {
             goto err;
         }
@@ -994,32 +966,34 @@
     stream_lock_init(&in->lock);
 
     in->adev = (struct audio_device *)hw_dev;
-    device_lock(in->adev);
 
-    in->profile = &in->adev->in_profile;
+    profile_init(&in->profile, PCM_IN);
 
     struct pcm_config proxy_config;
     memset(&proxy_config, 0, sizeof(proxy_config));
 
     int ret = 0;
+    device_lock(in->adev);
+    int num_open_inputs = in->adev->inputs_open;
+    device_unlock(in->adev);
+
     /* Check if an input stream is already open */
-    if (in->adev->inputs_open > 0) {
-        if (!profile_is_cached_for(in->profile, card, device)) {
+    if (num_open_inputs > 0) {
+        if (!profile_is_cached_for(&in->profile, card, device)) {
             ALOGW("%s fail - address card:%d device:%d doesn't match existing profile",
                     __func__, card, device);
             ret = -EINVAL;
         }
     } else {
         /* Read input profile only if necessary */
-        in->adev->in_profile.card = card;
-        in->adev->in_profile.device = device;
-        if (!profile_read_device_info(&in->adev->in_profile)) {
+        in->profile.card = card;
+        in->profile.device = device;
+        if (!profile_read_device_info(&in->profile)) {
             ALOGW("%s fail - cannot read profile", __func__);
             ret = -EINVAL;
         }
     }
     if (ret != 0) {
-        device_unlock(in->adev);
         free(in);
         *stream_in = NULL;
         return ret;
@@ -1028,13 +1002,13 @@
     /* Rate */
     int request_config_rate = config->sample_rate;
     if (config->sample_rate == 0) {
-        config->sample_rate = profile_get_default_sample_rate(in->profile);
+        config->sample_rate = profile_get_default_sample_rate(&in->profile);
     }
 
     if (in->adev->device_sample_rate != 0 &&   /* we are playing, so lock the rate if possible */
         in->adev->device_sample_rate >= RATELOCK_THRESHOLD) {/* but only for high sample rates */
         if (config->sample_rate != in->adev->device_sample_rate) {
-            unsigned highest_rate = profile_get_highest_sample_rate(in->profile);
+            unsigned highest_rate = profile_get_highest_sample_rate(&in->profile);
             if (highest_rate == 0) {
                 ret = -EINVAL; /* error with device */
             } else {
@@ -1049,25 +1023,23 @@
                 }
             }
         }
-    } else if (profile_is_sample_rate_valid(in->profile, config->sample_rate)) {
+    } else if (profile_is_sample_rate_valid(&in->profile, config->sample_rate)) {
         proxy_config.rate = config->sample_rate;
     } else {
-        proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(in->profile);
+        proxy_config.rate = config->sample_rate = profile_get_default_sample_rate(&in->profile);
         ret = -EINVAL;
     }
 
-    device_unlock(in->adev);
-
     /* Format */
     if (config->format == AUDIO_FORMAT_DEFAULT) {
-        proxy_config.format = profile_get_default_format(in->profile);
+        proxy_config.format = profile_get_default_format(&in->profile);
         config->format = audio_format_from_pcm_format(proxy_config.format);
     } else {
         enum pcm_format fmt = pcm_format_from_audio_format(config->format);
-        if (profile_is_format_valid(in->profile, fmt)) {
+        if (profile_is_format_valid(&in->profile, fmt)) {
             proxy_config.format = fmt;
         } else {
-            proxy_config.format = profile_get_default_format(in->profile);
+            proxy_config.format = profile_get_default_format(&in->profile);
             config->format = audio_format_from_pcm_format(proxy_config.format);
             ret = -EINVAL;
         }
@@ -1077,7 +1049,7 @@
     bool calc_mask = false;
     if (config->channel_mask == AUDIO_CHANNEL_NONE) {
         /* query case */
-        in->hal_channel_count = profile_get_default_channel_count(in->profile);
+        in->hal_channel_count = profile_get_default_channel_count(&in->profile);
         calc_mask = true;
     } else {
         /* explicit case */
@@ -1114,8 +1086,8 @@
         // if they differ, choose the "actual" number of channels *closest* to the "logical".
         // and store THAT in proxy_config.channels
         proxy_config.channels =
-                profile_get_closest_channel_count(in->profile, in->hal_channel_count);
-        ret = proxy_prepare(&in->proxy, in->profile, &proxy_config);
+                profile_get_closest_channel_count(&in->profile, in->hal_channel_count);
+        ret = proxy_prepare(&in->proxy, &in->profile, &proxy_config);
         if (ret == 0) {
             in->standby = true;
 
@@ -1155,7 +1127,7 @@
                                     struct audio_stream_in *stream)
 {
     struct stream_in *in = (struct stream_in *)stream;
-    ALOGV("adev_close_input_stream(c:%d d:%d)", in->profile->card, in->profile->device);
+    ALOGV("adev_close_input_stream(c:%d d:%d)", in->profile.card, in->profile.device);
 
     adev_remove_stream_from_list(in->adev, &in->list_node);
 
@@ -1283,8 +1255,7 @@
     if (!adev)
         return -ENOMEM;
 
-    profile_init(&adev->out_profile, PCM_OUT);
-    profile_init(&adev->in_profile, PCM_IN);
+    pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
 
     list_init(&adev->output_stream_list);
     list_init(&adev->input_stream_list);