audio: Correctly handle out of memory conditions

Change-Id: Id7e0ab1085d3e38c1eaa7905a17726e9d1a68cc9
diff --git a/audio/audio_hw.c b/audio/audio_hw.c
index cd47e14..e77c167 100644
--- a/audio/audio_hw.c
+++ b/audio/audio_hw.c
@@ -356,6 +356,7 @@
     char mixer_path[PATH_MAX];
     struct mixer_card *mixer_card;
     struct listnode *node;
+    int ret = 0;
 
     list_init(&adev->mixer_list);
 
@@ -369,6 +370,7 @@
                     if (++retry_num > RETRY_NUMBER) {
                         ALOGE("%s unable to open the mixer for--card %d, aborting.",
                               __func__, card);
+                        ret = -ENODEV;
                         goto error;
                     }
                     usleep(RETRY_US);
@@ -380,9 +382,14 @@
             if (!audio_route) {
                 ALOGE("%s: Failed to init audio route controls for card %d, aborting.",
                       __func__, card);
+                ret = -ENODEV;
                 goto error;
             }
             mixer_card = calloc(1, sizeof(struct mixer_card));
+            if (mixer_card == NULL) {
+                ret = -ENOMEM;
+                goto error;
+            }
             mixer_card->card = card;
             mixer_card->mixer = mixer;
             mixer_card->audio_route = audio_route;
@@ -394,7 +401,7 @@
 
 error:
     free_mixer_list(adev);
-    return -ENODEV;
+    return ret;
 }
 
 static const char *get_snd_device_name(snd_device_t snd_device)
@@ -1178,6 +1185,9 @@
         }
 
         ref_device = (struct pcm_device *)calloc(1, sizeof(struct pcm_device));
+        if (ref_device == NULL) {
+            return -ENOMEM;
+        }
         ref_device->pcm_profile = ref_pcm_profile;
 
         ALOGV("%s: ref_device rate:%d, ch:%d", __func__, ref_pcm_profile->config.rate, ref_pcm_profile->config.channels);
@@ -1932,6 +1942,10 @@
     }
 
     uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
+    if (uc_info == NULL) {
+        ret = -ENOMEM;
+        goto error_config;
+    }
     uc_info->id = in->usecase;
     uc_info->type = PCM_CAPTURE;
     uc_info->stream = (struct audio_stream *)in;
@@ -1940,6 +1954,12 @@
     uc_info->out_snd_device = SND_DEVICE_NONE;
 
     pcm_device = (struct pcm_device *)calloc(1, sizeof(struct pcm_device));
+    if (pcm_device == NULL) {
+        free(uc_info);
+        ret = -ENOMEM;
+        goto error_config;
+    }
+
     pcm_device->pcm_profile = pcm_profile;
     list_init(&in->pcm_dev_list);
     list_add_tail(&in->pcm_dev_list, &pcm_device->stream_list_node);
@@ -2119,6 +2139,9 @@
 
     while ((pcm_profile = get_pcm_device(usecase->type, devices)) != NULL) {
         pcm_device = calloc(1, sizeof(struct pcm_device));
+        if (pcm_device == NULL) {
+            return -ENOMEM;
+        }
         pcm_device->pcm_profile = pcm_profile;
         list_add_tail(&out->pcm_dev_list, &pcm_device->stream_list_node);
         mixer_card = uc_get_mixer_for_card(usecase, pcm_profile->card);
@@ -2234,12 +2257,16 @@
     return 0;
 }
 
-void enable_output_path_l(struct stream_out *out)
+int enable_output_path_l(struct stream_out *out)
 {
     struct audio_device *adev = out->dev;
     struct audio_usecase *uc_info;
 
     uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
+    if (uc_info == NULL) {
+        return -ENOMEM;
+    }
+
     uc_info->id = out->usecase;
     uc_info->type = PCM_PLAYBACK;
     uc_info->stream = (struct audio_stream *)out;
@@ -2250,6 +2277,8 @@
 
     list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
     select_devices(adev, out->usecase);
+
+    return 0;
 }
 
 static int stop_output_stream(struct stream_out *out)
@@ -2278,7 +2307,10 @@
     ALOGV("%s: enter: usecase(%d: %s) devices(%#x) channels(%d)",
           __func__, out->usecase, use_case_table[out->usecase], out->devices, out->config.channels);
 
-    enable_output_path_l(out);
+    ret = enable_output_path_l(out);
+    if (ret != 0) {
+        goto error_config;
+    }
 
     if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
         out->compr = NULL;
@@ -2346,10 +2378,16 @@
 static int start_voice_call(struct audio_device *adev)
 {
     struct audio_usecase *uc_info;
+    int ret = 0;
 
     ALOGV("%s: enter", __func__);
 
     uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
+    if (uc_info == NULL) {
+        ret = -ENOMEM;
+        goto exit;
+    }
+
     uc_info->id = USECASE_VOICE_CALL;
     uc_info->type = VOICE_CALL;
     uc_info->stream = (struct audio_stream *)adev->primary_output;
@@ -2370,8 +2408,9 @@
     set_voice_volume_l(adev, adev->voice_volume);
 
     adev->in_call = true;
+exit:
     ALOGV("%s: exit", __func__);
-    return 0;
+    return ret;
 }
 
 static int check_input_parameters(uint32_t sample_rate,
@@ -3569,13 +3608,17 @@
 {
     struct audio_device *adev = (struct audio_device *)dev;
     struct stream_out *out;
-    int i, ret;
+    int i, ret = 0;
     struct pcm_device_profile *pcm_profile;
 
     ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
           __func__, config->sample_rate, config->channel_mask, devices, flags);
     *stream_out = NULL;
     out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
+    if (out == NULL) {
+        ret = -ENOMEM;
+        goto error_config;
+    }
 
     if (devices == AUDIO_DEVICE_NONE)
         devices = AUDIO_DEVICE_OUT_SPEAKER;
@@ -3612,6 +3655,10 @@
 
         out->compr_config.codec = (struct snd_codec *)
                                     calloc(1, sizeof(struct snd_codec));
+        if (out->compr_config.codec == NULL) {
+            ret = -ENOMEM;
+            goto error_open;
+        }
 
         out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
         if (config->offload_info.channel_mask)
@@ -3718,6 +3765,7 @@
 error_open:
     free(out);
     *stream_out = NULL;
+error_config:
     ALOGV("%s: exit: ret %d", __func__, ret);
     return ret;
 }
@@ -3962,6 +4010,9 @@
         return -EINVAL;
 
     in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
+    if (in == NULL) {
+        return -ENOMEM;
+    }
 
     in->stream.common.get_sample_rate = in_get_sample_rate;
     in->stream.common.set_sample_rate = in_set_sample_rate;
@@ -4109,7 +4160,12 @@
     ALOGV("%s: enter", __func__);
     if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
 
+    *device = NULL;
+
     adev = calloc(1, sizeof(struct audio_device));
+    if (adev == NULL) {
+        return -ENOMEM;
+    }
 
     adev->device.common.tag = HARDWARE_DEVICE_TAG;
     adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
@@ -4143,6 +4199,10 @@
     adev->in_call = false;
     /* adev->cur_hdmi_channels = 0;  by calloc() */
     adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
+    if (adev->snd_dev_ref_cnt == NULL) {
+        free(adev);
+        return -ENOMEM;
+    }
 
     adev->dualmic_config = DUALMIC_CONFIG_NONE;
     adev->ns_in_voice_rec = false;
diff --git a/audio/compress_offload.c b/audio/compress_offload.c
index 6a62647..5ce865e 100644
--- a/audio/compress_offload.c
+++ b/audio/compress_offload.c
@@ -53,7 +53,7 @@
                               struct audio_usecase *uc_info,
                               snd_device_t snd_device,
                               bool update_mixer);
-void enable_output_path_l(struct stream_out *out);
+int enable_output_path_l(struct stream_out *out);
 int disable_output_path_l(struct stream_out *out);
 
 /* must be called with out->lock locked */
@@ -268,8 +268,11 @@
     if (out->offload_state == OFFLOAD_STATE_PAUSED_FLUSHED) {
         ALOGV("start offload write from pause state");
         pthread_mutex_lock(&adev->lock);
-        enable_output_path_l(out);
+        ret = enable_output_path_l(out);
         pthread_mutex_unlock(&adev->lock);
+        if (ret != 0) {
+            return ret;
+        }
     }
 
     if (out->send_new_metadata) {