Merge "audio: fix crashes upon USB device connection" into lmp-dev
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 7e4a1d9..a68adea 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -251,7 +251,7 @@
     status_t setupAACCodec(
             bool encoder,
             int32_t numChannels, int32_t sampleRate, int32_t bitRate,
-            int32_t aacProfile, bool isADTS);
+            int32_t aacProfile, bool isADTS, int32_t sbrMode);
 
     status_t setupAC3Codec(bool encoder, int32_t numChannels, int32_t sampleRate);
 
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 5b6e59e..b81674d 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1289,16 +1289,20 @@
             err = INVALID_OPERATION;
         } else {
             int32_t isADTS, aacProfile;
+            int32_t sbrMode;
             if (!msg->findInt32("is-adts", &isADTS)) {
                 isADTS = 0;
             }
             if (!msg->findInt32("aac-profile", &aacProfile)) {
                 aacProfile = OMX_AUDIO_AACObjectNull;
             }
+            if (!msg->findInt32("aac-sbr-mode", &sbrMode)) {
+                sbrMode = -1;
+            }
 
             err = setupAACCodec(
                     encoder, numChannels, sampleRate, bitRate, aacProfile,
-                    isADTS != 0);
+                    isADTS != 0, sbrMode);
         }
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
         err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
@@ -1460,7 +1464,7 @@
 
 status_t ACodec::setupAACCodec(
         bool encoder, int32_t numChannels, int32_t sampleRate,
-        int32_t bitRate, int32_t aacProfile, bool isADTS) {
+        int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode) {
     if (encoder && isADTS) {
         return -EINVAL;
     }
@@ -1527,6 +1531,32 @@
         profile.nAACERtools = OMX_AUDIO_AACERNone;
         profile.eAACProfile = (OMX_AUDIO_AACPROFILETYPE) aacProfile;
         profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
+        switch (sbrMode) {
+        case 0:
+            // disable sbr
+            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
+            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
+            break;
+        case 1:
+            // enable single-rate sbr
+            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
+            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
+            break;
+        case 2:
+            // enable dual-rate sbr
+            profile.nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
+            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
+            break;
+        case -1:
+            // enable both modes -> the codec will decide which mode should be used
+            profile.nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
+            profile.nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
+            break;
+        default:
+            // unsupported sbr mode
+            return BAD_VALUE;
+        }
+
 
         err = mOMX->setParameter(
                 mNode, OMX_IndexParamAudioAac, &profile, sizeof(profile));
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
index 6093621..35aa883 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include "SoftAACEncoder2.h"
+#include <OMX_AudioExt.h>
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/hexdump.h>
@@ -44,6 +45,8 @@
       mNumChannels(1),
       mSampleRate(44100),
       mBitRate(0),
+      mSBRMode(-1),
+      mSBRRatio(0),
       mAACProfile(OMX_AUDIO_AACObjectLC),
       mSentCodecSpecificData(false),
       mInputSize(0),
@@ -156,6 +159,41 @@
             aacParams->nSampleRate = mSampleRate;
             aacParams->nFrameLength = 0;
 
+            switch (mSBRMode) {
+            case 1: // sbr on
+                switch (mSBRRatio) {
+                case 0:
+                    // set both OMX AAC tool flags
+                    aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
+                    aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
+                    break;
+                case 1:
+                    // set single-rate SBR active
+                    aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
+                    aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
+                    break;
+                case 2:
+                    // set dual-rate SBR active
+                    aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
+                    aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
+                    break;
+                default:
+                    ALOGE("invalid SBR ratio %d", mSBRRatio);
+                    TRESPASS();
+                }
+                break;
+            case 0:  // sbr off
+            case -1: // sbr undefined
+                aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
+                aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
+                break;
+            default:
+                ALOGE("invalid SBR mode %d", mSBRMode);
+                TRESPASS();
+            }
+
+
+
             return OMX_ErrorNone;
         }
 
@@ -243,6 +281,23 @@
                 mAACProfile = aacParams->eAACProfile;
             }
 
+            if (!(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR)
+                    && !(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) {
+                mSBRMode = 0;
+                mSBRRatio = 0;
+            } else if ((aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR)
+                    && !(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) {
+                mSBRMode = 1;
+                mSBRRatio = 1;
+            } else if (!(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR)
+                    && (aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) {
+                mSBRMode = 1;
+                mSBRRatio = 2;
+            } else {
+                mSBRMode = -1; // codec default sbr mode
+                mSBRRatio = 0;
+            }
+
             if (setAudioParams() != OK) {
                 return OMX_ErrorUndefined;
             }
@@ -305,11 +360,11 @@
 }
 
 status_t SoftAACEncoder2::setAudioParams() {
-    // We call this whenever sample rate, number of channels or bitrate change
+    // We call this whenever sample rate, number of channels, bitrate or SBR mode change
     // in reponse to setParameter calls.
 
-    ALOGV("setAudioParams: %u Hz, %u channels, %u bps",
-         mSampleRate, mNumChannels, mBitRate);
+    ALOGV("setAudioParams: %u Hz, %u channels, %u bps, %i sbr mode, %i sbr ratio",
+         mSampleRate, mNumChannels, mBitRate, mSBRMode, mSBRRatio);
 
     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT,
             getAOTFromProfile(mAACProfile))) {
@@ -335,6 +390,24 @@
         return UNKNOWN_ERROR;
     }
 
+    if (mSBRMode != -1 && mAACProfile == OMX_AUDIO_AACObjectELD) {
+        if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_MODE, mSBRMode)) {
+            ALOGE("Failed to set AAC encoder parameters");
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    /* SBR ratio parameter configurations:
+       0: Default configuration wherein SBR ratio is configured depending on audio object type by
+          the FDK.
+       1: Downsampled SBR (default for ELD)
+       2: Dualrate SBR (default for HE-AAC)
+     */
+    if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_RATIO, mSBRRatio)) {
+        ALOGE("Failed to set AAC encoder parameters");
+        return UNKNOWN_ERROR;
+    }
+
     return OK;
 }
 
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.h b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.h
index 2603f4f..bce9c24 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.h
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.h
@@ -53,6 +53,8 @@
     OMX_U32 mNumChannels;
     OMX_U32 mSampleRate;
     OMX_U32 mBitRate;
+    OMX_S32 mSBRMode;
+    OMX_S32 mSBRRatio;
     OMX_U32 mAACProfile;
 
     bool mSentCodecSpecificData;
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 3a9c162..c519593 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -88,6 +88,7 @@
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_SPDIF),
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_FM),
     STRING_TO_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
+    STRING_TO_ENUM(AUDIO_DEVICE_IN_AMBIENT),
     STRING_TO_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
     STRING_TO_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
     STRING_TO_ENUM(AUDIO_DEVICE_IN_ALL_SCO),
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 9721e13..046988e 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -810,7 +810,9 @@
             return res;
         }
     }
-    if (params.zslMode && !params.recordingHint) {
+
+    if (params.zslMode && !params.recordingHint &&
+            getRecordingStreamId() == NO_STREAM) {
         res = updateProcessorStream(mZslProcessor, params);
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to update ZSL stream: %s (%d)",
@@ -1033,6 +1035,36 @@
             return res;
         }
     }
+
+    if (mZslProcessor->getStreamId() != NO_STREAM) {
+        ALOGV("%s: Camera %d: Clearing out zsl stream before "
+                "creating recording stream", __FUNCTION__, mCameraId);
+        res = mStreamingProcessor->stopStream();
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Can't stop streaming to delete callback stream",
+                    __FUNCTION__, mCameraId);
+            return res;
+        }
+        res = mDevice->waitUntilDrained();
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Waiting to stop streaming failed: %s (%d)",
+                    __FUNCTION__, mCameraId, strerror(-res), res);
+        }
+        res = mZslProcessor->clearZslQueue();
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Can't clear zsl queue",
+                    __FUNCTION__, mCameraId);
+            return res;
+        }
+        res = mZslProcessor->deleteStream();
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Unable to delete zsl stream before "
+                    "record: %s (%d)", __FUNCTION__, mCameraId,
+                    strerror(-res), res);
+            return res;
+        }
+    }
+
     // Disable callbacks if they're enabled; can't record and use callbacks,
     // and we can't fail record start without stagefright asserting.
     params.previewCallbackFlags = 0;