audio: Dedicated usecase for voip call (uplink and downlink)

Add dedicated usecases for voip call.

coauthored-by: Vikram Panduranga <vpandura@codeaurora.org>

Bug: 62393776
Test: hangout call
Change-Id: Iff8911aa8d4f072923e2f2649098a44a4bc4485c
Signed-off-by: David Lin <dtwlin@google.com>
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index cca56ec..44a0216 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -67,6 +67,7 @@
 /* ToDo: Check and update a proper value in msec */
 #define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
 #define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
+#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
 
 #define PROXY_OPEN_RETRY_COUNT           100
 #define PROXY_OPEN_WAIT_TIME             20
@@ -204,6 +205,14 @@
     .avail_min = MMAP_PERIOD_SIZE, //1 ms
 };
 
+struct pcm_config pcm_config_voip = {
+    .channels = 1,
+    .period_count = 2,
+    .format = PCM_FORMAT_S16_LE,
+    .stop_threshold = INT_MAX,
+    .avail_min = 0,
+};
+
 #define AFE_PROXY_CHANNEL_COUNT 2
 #define AFE_PROXY_SAMPLING_RATE 48000
 
@@ -270,6 +279,8 @@
     [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
     [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
 
+    [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
+    [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
 };
 
 
@@ -1440,7 +1451,6 @@
 error_config:
     adev->active_input = NULL;
     ALOGW("%s: exit: status(%d)", __func__, ret);
-
     return ret;
 }
 
@@ -1896,17 +1906,18 @@
     return 0;
 }
 
-static size_t get_input_buffer_size(uint32_t sample_rate,
-                                    audio_format_t format,
-                                    int channel_count,
-                                    bool is_low_latency)
+static size_t get_stream_buffer_size(size_t duration_ms,
+                                     uint32_t sample_rate,
+                                     audio_format_t format,
+                                     int channel_count,
+                                     bool is_low_latency)
 {
     size_t size = 0;
 
     if (check_input_parameters(sample_rate, format, channel_count) != 0)
         return 0;
 
-    size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
+    size = (sample_rate * duration_ms) / 1000;
     if (is_low_latency)
         size = configured_low_latency_capture_period_size;
 
@@ -2366,6 +2377,23 @@
         volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
         mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
         return 0;
+    } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
+        int gain_cfg[4];
+        const char *mixer_ctl_name = "App Type Gain";
+        struct audio_device *adev = out->dev;
+        struct mixer_ctl *ctl;
+        ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+        if (!ctl) {
+            ALOGE("%s: Could not get volume ctl mixer %s", __func__,
+                  mixer_ctl_name);
+            return -EINVAL;
+        }
+        gain_cfg[0] = 0;
+        gain_cfg[1] = out->app_type_cfg.app_type;
+        gain_cfg[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
+        gain_cfg[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
+        mixer_ctl_set_array(ctl, gain_cfg, sizeof(gain_cfg)/sizeof(gain_cfg[0]));
+        return 0;
     }
 
     return -ENOSYS;
@@ -2900,7 +2928,6 @@
 static size_t in_get_buffer_size(const struct audio_stream *stream)
 {
     struct stream_in *in = (struct stream_in *)stream;
-
     return in->config.period_size * in->af_period_multiplier *
         audio_stream_in_frame_size((const struct audio_stream_in *)stream);
 }
@@ -3572,6 +3599,27 @@
         out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
         out->config = pcm_config_afe_proxy_playback;
         adev->voice_tx_output = out;
+    } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
+               (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
+                               AUDIO_OUTPUT_FLAG_VOIP_RX))) {
+        uint32_t buffer_size, frame_size;
+        out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
+        out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
+        out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
+        out->config = pcm_config_voip;
+        out->config.format = pcm_format_from_audio_format(config->format);
+        out->config.rate = config->sample_rate;
+        out->config.channels =
+                audio_channel_count_from_out_mask(config->channel_mask);
+        buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
+                                             config->sample_rate,
+                                             config->format,
+                                             out->config.channels,
+                                             false /*is_low_latency*/);
+        frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
+        out->config.period_size = buffer_size / frame_size;
+        out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
+        out->af_period_multiplier = 1;
     } else {
         if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
             out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
@@ -3983,8 +4031,10 @@
 {
     int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
 
-    return get_input_buffer_size(config->sample_rate, config->format, channel_count,
-            false /* is_low_latency: since we don't know, be conservative */);
+    return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
+                                 config->sample_rate, config->format,
+                                 channel_count,
+                                 false /* is_low_latency: since we don't know, be conservative */);
 }
 
 static bool adev_input_allow_hifi_record(struct audio_device *adev,
@@ -4161,10 +4211,11 @@
         in->usecase = USECASE_AUDIO_RECORD_HIFI;
         in->config = pcm_config_audio_capture;
         frame_size = audio_stream_in_frame_size(&in->stream);
-        buffer_size = get_input_buffer_size(config->sample_rate,
-                                            config->format,
-                                            channel_count,
-                                            false /*is_low_latency*/);
+        buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
+                                             config->sample_rate,
+                                             config->format,
+                                             channel_count,
+                                             false /*is_low_latency*/);
         in->config.period_size = buffer_size / frame_size;
         in->config.rate = config->sample_rate;
         in->af_period_multiplier = 1;
@@ -4181,10 +4232,11 @@
             if (!in->realtime) {
                 in->config = pcm_config_audio_capture;
                 frame_size = audio_stream_in_frame_size(&in->stream);
-                buffer_size = get_input_buffer_size(config->sample_rate,
-                                                    config->format,
-                                                    channel_count,
-                                                    is_low_latency);
+                buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
+                                                     config->sample_rate,
+                                                     config->format,
+                                                     channel_count,
+                                                     is_low_latency);
                 in->config.period_size = buffer_size / frame_size;
                 in->config.rate = config->sample_rate;
                 in->af_period_multiplier = 1;
@@ -4204,13 +4256,33 @@
             in->stream.get_mmap_position = in_get_mmap_position;
             in->af_period_multiplier = 1;
             ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
+        } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
+                   in->dev->mode == AUDIO_MODE_IN_COMMUNICATION &&
+                   (config->sample_rate == 8000 ||
+                    config->sample_rate == 16000 ||
+                    config->sample_rate == 32000 ||
+                    config->sample_rate == 48000) &&
+                   channel_count == 1) {
+            in->usecase = USECASE_AUDIO_RECORD_VOIP;
+            in->config = pcm_config_audio_capture;
+            frame_size = audio_stream_in_frame_size(&in->stream);
+            buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
+                                                 config->sample_rate,
+                                                 config->format,
+                                                 channel_count, false /*is_low_latency*/);
+            in->config.period_size = buffer_size / frame_size;
+            in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
+            in->config.rate = config->sample_rate;
+            in->af_period_multiplier = 1;
+            in->flags |= AUDIO_INPUT_FLAG_VOIP_TX;
         } else {
             in->config = pcm_config_audio_capture;
             frame_size = audio_stream_in_frame_size(&in->stream);
-            buffer_size = get_input_buffer_size(config->sample_rate,
-                                                config->format,
-                                                channel_count,
-                                                is_low_latency);
+            buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
+                                                 config->sample_rate,
+                                                 config->format,
+                                                 channel_count,
+                                                 is_low_latency);
             in->config.period_size = buffer_size / frame_size;
             in->config.rate = config->sample_rate;
             in->af_period_multiplier = 1;
@@ -4220,6 +4292,7 @@
     }
 
     in->config.channels = channel_count;
+    in->sample_rate  = in->config.rate;
 
     /* This stream could be for sound trigger lab,
        get sound trigger pcm if present */