alsa_sound: add support for low latency playback and recording

b/6865729

- Add deep buffer output in config file
- Configure deep buffer output if flag
  AUDIO_OUTPUT_FLAG_DEEP_BUFFER is set,
  otherwise configure low latency output.
- Add support for low latency recording
- Enable low latency recording path with
  system property
- For 2 buffers and 2048 bytes, reduce
  PLAYBACK_LOW_LATENCY to 21.5 ms

Change-Id: I3c0d54fa473fe89df5a3924de483f16975f4000e
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/alsa_sound/AudioHardwareALSA.cpp b/alsa_sound/AudioHardwareALSA.cpp
index 2bf3fce..232cb43 100644
--- a/alsa_sound/AudioHardwareALSA.cpp
+++ b/alsa_sound/AudioHardwareALSA.cpp
@@ -685,7 +685,10 @@
     ALOGV("openOutputStream: devices 0x%x channels %d sampleRate %d",
          devices, *channels, *sampleRate);
 
+    audio_output_flags_t flag = static_cast<audio_output_flags_t> (*status);
+
     status_t err = BAD_VALUE;
+    *status = NO_ERROR;
     AudioStreamOutALSA *out = 0;
     ALSAHandleList::iterator it;
 
@@ -694,6 +697,8 @@
         ALOGE("openOutputStream called with bad devices");
         return out;
     }
+
+
 # if 0
     if((devices == AudioSystem::DEVICE_OUT_DIRECTOUTPUT) &&
        ((*sampleRate == VOIP_SAMPLING_RATE_8K) || (*sampleRate == VOIP_SAMPLING_RATE_16K))) {
@@ -804,13 +809,28 @@
       alsa_handle.latency = PLAYBACK_LATENCY;
       alsa_handle.rxHandle = 0;
       alsa_handle.ucMgr = mUcMgr;
+      alsa_handle.isDeepbufferOutput = false;
 
       char *use_case;
       snd_use_case_get(mUcMgr, "_verb", (const char **)&use_case);
-      if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
-          strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI, sizeof(alsa_handle.useCase));
+
+      if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
+	  ALOGD("openOutputStream: DeepBuffer Output");
+          alsa_handle.isDeepbufferOutput = true;
+          if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
+               strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI, sizeof(alsa_handle.useCase));
+          } else {
+               strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC, sizeof(alsa_handle.useCase));
+          }
       } else {
-          strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_MUSIC, sizeof(alsa_handle.useCase));
+	  ALOGD("openOutputStream: Lowlatency Output");
+          alsa_handle.bufferSize = PLAYBACK_LOW_LATENCY_BUFFER_SIZE;
+          alsa_handle.latency = PLAYBACK_LOW_LATENCY;
+          if ((use_case == NULL) || (!strcmp(use_case, SND_USE_CASE_VERB_INACTIVE))) {
+               strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
+          } else {
+               strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
+          }
       }
       free(use_case);
       mDeviceList.push_back(alsa_handle);
@@ -825,10 +845,18 @@
       }
 #endif
       mALSADevice->route(&(*it), devices, mode());
-      if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI)) {
-          snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI);
+      if (flag & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
+          if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI)) {
+             snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI);
+          } else {
+             snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC);
+          }
       } else {
-          snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_MUSIC);
+          if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) {
+             snd_use_case_set(mUcMgr, "_verb", SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC);
+          } else {
+             snd_use_case_set(mUcMgr, "_enamod", SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC);
+          }
       }
       err = mALSADevice->open(&(*it));
       if (err) {
@@ -1068,6 +1096,8 @@
         {
             if((0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_HIFI_REC, MAX_UC_LEN))
               ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, MAX_UC_LEN))
+              ||(0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, MAX_UC_LEN))
+              ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, MAX_UC_LEN))
               ||(0 == strncmp(itDev->useCase, SND_USE_CASE_MOD_CAPTURE_FM, MAX_UC_LEN))
 #ifdef QCOM_FM_ENABLED
               ||(0 == strncmp(itDev->useCase, SND_USE_CASE_VERB_FM_REC, MAX_UC_LEN))
@@ -1141,7 +1171,13 @@
                 strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM, sizeof(alsa_handle.useCase));
 #endif
             } else {
-                strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, sizeof(alsa_handle.useCase));
+		char value[128];
+		property_get("persist.audio.lowlatency.rec",value,"0");
+                if (!strcmp("true", value)) {
+                    strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC, sizeof(alsa_handle.useCase));
+                } else {
+                    strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, sizeof(alsa_handle.useCase));
+                }
             }
         } else {
             if ((devices == AudioSystem::DEVICE_IN_VOICE_CALL) &&
@@ -1175,7 +1211,13 @@
                 strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_FM_A2DP_REC, sizeof(alsa_handle.useCase));
 #endif
             } else {
-                strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_REC, sizeof(alsa_handle.useCase));
+                char value[128];
+                property_get("persist.audio.lowlatency.rec",value,"0");
+                if (!strcmp("true", value)) {
+                    strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC, sizeof(alsa_handle.useCase));
+                } else {
+                    strlcpy(alsa_handle.useCase, SND_USE_CASE_VERB_HIFI_REC, sizeof(alsa_handle.useCase));
+                }
             }
         }
         free(use_case);
@@ -1221,6 +1263,7 @@
         }
 
         if(!strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_REC) ||
+           !strcmp(it->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC) ||
 #ifdef QCOM_FM_ENABLED
            !strcmp(it->useCase, SND_USE_CASE_VERB_FM_REC) ||
            !strcmp(it->useCase, SND_USE_CASE_VERB_FM_A2DP_REC) ||