Merge "alsa_sound: Add support for custom LPA buffer size" into cm-10.2
diff --git a/alsa_sound/ALSADevice.cpp b/alsa_sound/ALSADevice.cpp
index 641eb36..d5b0d8c 100644
--- a/alsa_sound/ALSADevice.cpp
+++ b/alsa_sound/ALSADevice.cpp
@@ -2027,6 +2027,11 @@
                     return strdup(SND_USE_CASE_DEV_VOICE_RECOGNITION ); /* VOICE RECOGNITION TX */
                 }
 #endif
+#ifdef SEPERATED_CAMCORDER
+                if (mInputSource == AUDIO_SOURCE_CAMCORDER) {
+                    return strdup(SND_USE_CASE_DEV_CAMCORDER_TX); /* CAMCORDER TX */
+                }
+#endif
 #ifdef SEPERATED_VOIP
                 if (mCallMode == AUDIO_MODE_IN_COMMUNICATION) {
                     if (!strncmp(rxDevice, SND_USE_CASE_DEV_VOIP_EARPIECE,
@@ -2121,8 +2126,6 @@
 #ifdef SEPERATED_AUDIO_INPUT
                 if (mCallMode == AUDIO_MODE_IN_CALL) {
                     return strdup(SND_USE_CASE_DEV_VOC_LINE); /* Voice BUILTIN-MIC TX */
-                } else if(mInputSource == AUDIO_SOURCE_CAMCORDER) {
-                    return strdup(SND_USE_CASE_DEV_CAMCORDER_TX ); /* CAMCORDER TX */
                 } else
 #endif
                     return strdup(SND_USE_CASE_DEV_LINE); /* BUILTIN-MIC TX */
@@ -2666,6 +2669,7 @@
         }
 
         mProxyParams.mAvail = pcm_avail(capture_handle);
+        mAvailInMs = (mProxyParams.mAvail*1000)/(AFE_PROXY_SAMPLE_RATE);
         ALOGV("avail is = %d frames = %ld, avai_min = %d\n",\
                       mProxyParams.mAvail,  mProxyParams.mFrames,(int)capture_handle->sw_p->avail_min);
         if (mProxyParams.mAvail < capture_handle->sw_p->avail_min) {
diff --git a/alsa_sound/Android.mk b/alsa_sound/Android.mk
index 08d0b85..ac6a5af 100644
--- a/alsa_sound/Android.mk
+++ b/alsa_sound/Android.mk
@@ -73,6 +73,10 @@
     common_cflags += -DSEPERATED_AUDIO_INPUT
 endif
 
+ifeq ($(strip $(BOARD_USES_SEPERATED_CAMCORDER)),true)
+    common_cflags += -DSEPERATED_CAMCORDER
+endif
+
 ifeq ($(strip $(BOARD_USES_SEPERATED_VOICE_SPEAKER)),true)
     common_cflags += -DSEPERATED_VOICE_SPEAKER
 endif
diff --git a/alsa_sound/AudioHardwareALSA.cpp b/alsa_sound/AudioHardwareALSA.cpp
index 71f7d45..788ea78 100644
--- a/alsa_sound/AudioHardwareALSA.cpp
+++ b/alsa_sound/AudioHardwareALSA.cpp
@@ -881,12 +881,6 @@
         param.add(key, value);
     }
 
-    key = String8("tunneled-input-formats");
-    if ( param.get(key,value) == NO_ERROR ) {
-        ALOGD("Add tunnel AWB to audio parameter");
-        param.addInt(String8("AWB"), true );
-    }
-
     key = String8(AudioParameter::keyRouting);
     if (param.getInt(key, device) == NO_ERROR) {
         param.addInt(key, mCurDevice);
@@ -1755,6 +1749,20 @@
                                     sizeof(alsa_handle.useCase));
                         }
                     }
+                } else if (*channels & AUDIO_CHANNEL_IN_VOICE_UPLINK) {
+                    if (mFusion3Platform) {
+                        mALSADevice->setVocRecMode(INCALL_REC_MONO);
+                        strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
+                                sizeof(alsa_handle.useCase));
+                    } else {
+                        if (*format == AUDIO_FORMAT_AMR_WB) {
+                            strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC_COMPRESSED,
+                                    sizeof(alsa_handle.useCase));
+                        } else {
+                            strlcpy(alsa_handle.useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC,
+                                    sizeof(alsa_handle.useCase));
+                        }
+                    }
                 }
 #if defined(QCOM_FM_ENABLED) || defined(STE_FM)
             } else if((devices == AudioSystem::DEVICE_IN_FM_RX)) {
@@ -1864,6 +1872,15 @@
             }
 #endif
         }
+#ifdef QCOM_USBAUDIO_ENABLED
+        if((devices == AudioSystem::DEVICE_IN_COMMUNICATION) &&
+           ((mCurDevice == AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET)||
+           (mCurDevice ==  AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET))){
+               ALOGD("Starting recording in openInputstream, musbRecordingState: %d", musbRecordingState);
+               startUsbRecordingIfNotStarted();
+               musbRecordingState |= USBRECBIT_VOIPCALL;
+        }
+#endif
         if(sampleRate) {
             it->sampleRate = *sampleRate;
         }
@@ -2960,10 +2977,10 @@
             }
         }
         err = mALSADevice->readFromProxy(&data, &size);
-        if(err < 0) {
-           ALOGE("ALSADevice readFromProxy returned err = %d,data = %p,\
-                    size = %d", err, data, size);
-           continue;
+        if (err < 0) {
+            ALOGE("ALSADevice readFromProxy returned err = %d,data = %p,\
+                    size = %ld", err, data, size);
+            continue;
         }
 
 #ifdef OUTPUT_BUFFER_LOG
diff --git a/alsa_sound/AudioHardwareALSA.h b/alsa_sound/AudioHardwareALSA.h
index ced6e81..f2638e0 100644
--- a/alsa_sound/AudioHardwareALSA.h
+++ b/alsa_sound/AudioHardwareALSA.h
@@ -352,6 +352,7 @@
     int mADSPState;
     bool mSSRComplete;
     int mCurDevice;
+    long mAvailInMs;
 protected:
     friend class AudioHardwareALSA;
 private:
diff --git a/alsa_sound/AudioSessionOut.cpp b/alsa_sound/AudioSessionOut.cpp
index 01c9d88..6e5d31c 100644
--- a/alsa_sound/AudioSessionOut.cpp
+++ b/alsa_sound/AudioSessionOut.cpp
@@ -754,7 +754,23 @@
 uint32_t AudioSessionOutALSA::latency() const
 {
     // Android wants latency in milliseconds.
-    return USEC_TO_MSEC (mAlsaHandle->latency);
+    uint32_t latency = mAlsaHandle->latency;
+    if ( ((mParent->mCurRxDevice & AudioSystem::DEVICE_OUT_ALL_A2DP) &&
+         (mParent->mExtOutStream == mParent->mA2dpStream))
+         && (mParent->mA2dpStream != NULL) ) {
+        uint32_t bt_latency = mParent->mA2dpStream->get_latency(mParent->mA2dpStream);
+        uint32_t proxy_latency = mParent->mALSADevice->mAvailInMs;
+        latency += bt_latency*1000 + proxy_latency*1000;
+        ALOGV("latency = %d, bt_latency = %d, proxy_latency = %d", latency, bt_latency, proxy_latency);
+    }
+    else if ( ((mParent->mCurRxDevice & AudioSystem::DEVICE_OUT_ALL_USB) &&
+         (mParent->mExtOutStream == mParent->mUsbStream))
+         && (mParent->mUsbStream != NULL) ) {
+        uint32_t usb_latency = mParent->mUsbStream->get_latency(mParent->mUsbStream);
+        latency += usb_latency*1000;
+    }
+
+    return USEC_TO_MSEC (latency);
 }
 
 status_t AudioSessionOutALSA::setObserver(void *observer)
diff --git a/alsa_sound/AudioStreamOutALSA.cpp b/alsa_sound/AudioStreamOutALSA.cpp
index df4b1d5..22dbbe6 100644
--- a/alsa_sound/AudioStreamOutALSA.cpp
+++ b/alsa_sound/AudioStreamOutALSA.cpp
@@ -412,7 +412,23 @@
 uint32_t AudioStreamOutALSA::latency() const
 {
     // Android wants latency in milliseconds.
-    return USEC_TO_MSEC (mHandle->latency);
+    uint32_t latency = mHandle->latency;
+    if ( ((mParent->mCurRxDevice & AudioSystem::DEVICE_OUT_ALL_A2DP) &&
+         (mParent->mExtOutStream == mParent->mA2dpStream))
+         && (mParent->mA2dpStream != NULL) ) {
+        uint32_t bt_latency = mParent->mA2dpStream->get_latency(mParent->mA2dpStream);
+        uint32_t proxy_latency = mParent->mALSADevice->mAvailInMs;
+        latency += bt_latency*1000 + proxy_latency*1000;
+        ALOGV("latency = %d, bt_latency = %d, proxy_latency = %d", latency, bt_latency, proxy_latency);
+    }
+    else if ( ((mParent->mCurRxDevice & AudioSystem::DEVICE_OUT_ALL_USB) &&
+         (mParent->mExtOutStream == mParent->mUsbStream))
+         && (mParent->mUsbStream != NULL) ) {
+        uint32_t usb_latency = mParent->mUsbStream->get_latency(mParent->mUsbStream);
+        latency += usb_latency*1000;
+    }
+
+    return USEC_TO_MSEC (latency);
 }
 
 // return the number of audio frames written by the audio dsp to DAC since
diff --git a/alsa_sound/audio_hw_hal.cpp b/alsa_sound/audio_hw_hal.cpp
index c3d052b..6b34090 100644
--- a/alsa_sound/audio_hw_hal.cpp
+++ b/alsa_sound/audio_hw_hal.cpp
@@ -792,6 +792,11 @@
                         reinterpret_cast<struct audio_hw_device *>(device);
     struct qcom_audio_device *qadev = to_ladev(hwdev);
 
+#ifdef USES_AUDIO_AMPLIFIER
+    if (amplifier_close() != 0)
+        ALOGE("Amplifier close failed");
+#endif
+
     if (!qadev)
         return 0;
 
@@ -848,6 +853,11 @@
 
     *device = &qadev->device.common;
 
+#ifdef USES_AUDIO_AMPLIFIER
+    if (amplifier_open() != 0)
+        ALOGE("Amplifier initialization failed");
+#endif
+
     return 0;
 
 err_create_audio_hw:
diff --git a/libalsa-intf/alsa_mixer.c b/libalsa-intf/alsa_mixer.c
index 7bf6557..5fd1839 100644
--- a/libalsa-intf/alsa_mixer.c
+++ b/libalsa-intf/alsa_mixer.c
@@ -128,6 +128,10 @@
 {
     unsigned n,m;
 
+    if (!mixer) {
+         ALOGE("mixer_close:Invalid Mixer Control");
+         return;
+    }
     if (mixer->fd >= 0)
         close(mixer->fd);
 
diff --git a/libalsa-intf/alsa_pcm.c b/libalsa-intf/alsa_pcm.c
index 2e7130f..8dd873f 100644
--- a/libalsa-intf/alsa_pcm.c
+++ b/libalsa-intf/alsa_pcm.c
@@ -469,9 +469,26 @@
      }
 }
 
+void appl_pt_forward(struct pcm *pcm)
+{
+	struct snd_pcm_sync_ptr *sync_ptr = pcm->sync_ptr;
+	snd_pcm_uframes_t appl_ptr = sync_ptr->c.control.appl_ptr;
+
+	if (appl_ptr >= pcm->sw_p->boundary) {
+		appl_ptr -= pcm->sw_p->boundary;
+		ALOGE("appl_ptr %ld set to ld",
+			sync_ptr->c.control.appl_ptr, appl_ptr);
+		sync_ptr->c.control.appl_ptr = appl_ptr;
+	}
+}
+
 int sync_ptr(struct pcm *pcm)
 {
     int err;
+
+    if (pcm->flags & PCM_MMAP)
+        appl_pt_forward(pcm);
+
     err = ioctl(pcm->fd, SNDRV_PCM_IOCTL_SYNC_PTR, pcm->sync_ptr);
     if (err < 0) {
         err = errno;
diff --git a/libalsa-intf/alsa_ucm.c b/libalsa-intf/alsa_ucm.c
index f182d26..cafd154 100644
--- a/libalsa-intf/alsa_ucm.c
+++ b/libalsa-intf/alsa_ucm.c
@@ -722,6 +722,7 @@
         strlen(SND_USE_CASE_VERB_IP_VOICECALL)))) {
         voice_acdb = 1;
     }
+//The ident_value should store latest/current modifier
     if (voice_acdb != 1) {
         list_size =
         snd_ucm_get_size_of_list(uc_mgr->card_ctxt_ptr->mod_list_head);
@@ -739,9 +740,6 @@
                     strlen(SND_USE_CASE_MOD_PLAY_VOIP)))) {
                     voice_acdb = 1;
                     strlcpy(current_mod, ident_value, MAX_STR_LEN);
-                    free(ident_value);
-                    ident_value = NULL;
-                    break;
                 }
                 free(ident_value);
                 ident_value = NULL;
@@ -802,9 +800,8 @@
                     && tx_id == DEVICE_HANDSET_TX_FV5_ACDB_ID) {
                     tx_id = DEVICE_SPEAKER_TX_FV5_ACDB_ID;
                 }
-
-                if ((rx_id != uc_mgr->current_rx_device) ||
-                    (tx_id != uc_mgr->current_tx_device)) {
+/* Despite no change in rx and tx devices, calibration data can be required to be sent.
+This happens when the modifier changes*/
                     uc_mgr->current_rx_device = rx_id;
                     uc_mgr->current_tx_device = tx_id;
                     ALOGD("Voice acdb: rx id %d tx id %d verb:%s modifier:%s",
@@ -816,7 +813,7 @@
                           strlen(SND_USE_CASE_VERB_IP_VOICECALL)) ||
                           (!strncmp(current_mod, SND_USE_CASE_MOD_PLAY_VOIP,
                            strlen(SND_USE_CASE_MOD_PLAY_VOIP)))) ||
-                          (!uc_mgr->isFusion3Platform))
+                          (!uc_mgr->isFusion3Platform)) {
                         if (uc_mgr->acdb_handle) {
                             acdb_send_voice_cal = dlsym(uc_mgr->acdb_handle,"acdb_loader_send_voice_cal");
                             if (acdb_send_voice_cal == NULL) {
@@ -826,11 +823,7 @@
                                         uc_mgr->current_tx_device);
                             }
                         }
-                } else {
-                    ALOGV("Voice acdb: Required acdb already pushed \
-                         rx id %d tx id %d", uc_mgr->current_rx_device,
-                         uc_mgr->current_tx_device);
-                }
+                    }
             }
             free(ident_value);
             ident_value = NULL;