Merge "audio policy: add support for device combo with speaker safe" into mnc-dev
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 8bf47b1..b696746 100755
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -4313,6 +4313,14 @@
 
     if ((!mIsAVC && !mIsHEVC)|| mWantsNALFragments) {
         if (newBuffer) {
+            if (!isInRange((size_t)0u, mBuffer->size(), size)) {
+                mBuffer->release();
+                mBuffer = NULL;
+
+                ALOGE("fragmentedRead ERROR_MALFORMED size %zu", size);
+                return ERROR_MALFORMED;
+            }
+
             ssize_t num_bytes_read =
                 mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
 
@@ -4320,7 +4328,7 @@
                 mBuffer->release();
                 mBuffer = NULL;
 
-                ALOGV("i/o error");
+                ALOGE("i/o error");
                 return ERROR_IO;
             }
 
@@ -4392,18 +4400,40 @@
         ssize_t num_bytes_read = 0;
         int32_t drm = 0;
         bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
+        void *data = NULL;
+        bool isMalFormed = false;
         if (usesDRM) {
-            num_bytes_read =
-                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
+            if (mBuffer == NULL || !isInRange((size_t)0u, mBuffer->size(), size)) {
+                isMalFormed = true;
+            } else {
+                data = mBuffer->data();
+            }
         } else {
-            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
+            int32_t max_size;
+            if (mFormat == NULL
+                    || !mFormat->findInt32(kKeyMaxInputSize, &max_size)
+                    || !isInRange((size_t)0u, (size_t)max_size, size)) {
+                isMalFormed = true;
+            } else {
+                data = mSrcBuffer;
+            }
         }
 
+        if (isMalFormed || data == NULL) {
+            ALOGE("isMalFormed size %zu", size);
+            if (mBuffer != NULL) {
+                mBuffer->release();
+                mBuffer = NULL;
+            }
+            return ERROR_MALFORMED;
+        }
+        num_bytes_read = mDataSource->readAt(offset, data, size);
+
         if (num_bytes_read < (ssize_t)size) {
             mBuffer->release();
             mBuffer = NULL;
 
-            ALOGV("i/o error");
+            ALOGE("i/o error");
             return ERROR_IO;
         }
 
@@ -4417,16 +4447,18 @@
             size_t dstOffset = 0;
 
             while (srcOffset < size) {
-                bool isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
+                isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
                 size_t nalLength = 0;
                 if (!isMalFormed) {
                     nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
                     srcOffset += mNALLengthSize;
-                    isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength);
+                    isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength)
+                            || !isInRange((size_t)0u, mBuffer->size(), dstOffset, (size_t)4u)
+                            || !isInRange((size_t)0u, mBuffer->size(), dstOffset + 4, nalLength);
                 }
 
                 if (isMalFormed) {
-                    ALOGE("Video is malformed");
+                    ALOGE("Video is malformed; nalLength %zu", nalLength);
                     mBuffer->release();
                     mBuffer = NULL;
                     return ERROR_MALFORMED;
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index f3af777..a616b40 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -115,6 +115,7 @@
             kProfileLevels, ARRAY_SIZE(kProfileLevels),
             320 /* width */, 240 /* height */, callbacks,
             appData, component),
+      mCodecCtx(NULL),
       mMemRecords(NULL),
       mFlushOutBuffer(NULL),
       mOmxColorFormat(OMX_COLOR_FormatYUV420Planar),
@@ -122,7 +123,8 @@
       mNewWidth(mWidth),
       mNewHeight(mHeight),
       mNewLevel(0),
-      mChangingResolution(false) {
+      mChangingResolution(false),
+      mSignalledError(false) {
     initPorts(
             kNumBuffers, INPUT_BUF_SIZE, kNumBuffers, CODEC_MIME_TYPE);
 
@@ -132,7 +134,7 @@
     GENERATE_FILE_NAMES();
     CREATE_DUMP_FILE(mInFile);
 
-    CHECK_EQ(initDecoder(), (status_t)OK);
+    CHECK_EQ(initDecoder(mWidth, mHeight), (status_t)OK);
 }
 
 SoftAVC::~SoftAVC() {
@@ -232,6 +234,7 @@
         ALOGE("Error in reset: 0x%x", s_ctl_op.u4_error_code);
         return UNKNOWN_ERROR;
     }
+    mSignalledError = false;
 
     /* Set the run-time (dynamic) parameters */
     setParams(outputBufferWidth());
@@ -285,7 +288,7 @@
     return OK;
 }
 
-status_t SoftAVC::initDecoder() {
+status_t SoftAVC::initDecoder(uint32_t width, uint32_t height) {
     IV_API_CALL_STATUS_T status;
 
     UWORD32 u4_num_reorder_frames;
@@ -294,14 +297,15 @@
     WORD32 i4_level;
 
     mNumCores = GetCPUCoreCount();
+    mCodecCtx = NULL;
 
     /* Initialize number of ref and reorder modes (for H264) */
     u4_num_reorder_frames = 16;
     u4_num_ref_frames = 16;
     u4_share_disp_buf = 0;
 
-    uint32_t displayStride = outputBufferWidth();
-    uint32_t displayHeight = outputBufferHeight();
+    uint32_t displayStride = mIsAdaptive ? mAdaptiveMaxWidth : width;
+    uint32_t displayHeight = mIsAdaptive ? mAdaptiveMaxHeight : height;
     uint32_t displaySizeY = displayStride * displayHeight;
 
     if(mNewLevel == 0){
@@ -435,6 +439,7 @@
 
         status = ivdec_api_function(mCodecCtx, (void *)&s_init_ip, (void *)&s_init_op);
         if (status != IV_SUCCESS) {
+            mCodecCtx = NULL;
             ALOGE("Error in init: 0x%x",
                     s_init_op.s_ivd_init_op_t.u4_error_code);
             return UNKNOWN_ERROR;
@@ -494,12 +499,12 @@
     return OK;
 }
 
-status_t SoftAVC::reInitDecoder() {
+status_t SoftAVC::reInitDecoder(uint32_t width, uint32_t height) {
     status_t ret;
 
     deInitDecoder();
 
-    ret = initDecoder();
+    ret = initDecoder(width, height);
     if (OK != ret) {
         ALOGE("Create failure");
         deInitDecoder();
@@ -511,6 +516,7 @@
 void SoftAVC::onReset() {
     SoftVideoDecoderOMXComponent::onReset();
 
+    mSignalledError = false;
     resetDecoder();
     resetPlugin();
 }
@@ -520,7 +526,12 @@
     const uint32_t oldHeight = mHeight;
     OMX_ERRORTYPE ret = SoftVideoDecoderOMXComponent::internalSetParameter(index, params);
     if (mWidth != oldWidth || mHeight != oldHeight) {
-        reInitDecoder();
+        status_t err = reInitDecoder(mNewWidth, mNewHeight);
+        if (err != OK) {
+            notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
+            mSignalledError = true;
+            return OMX_ErrorUnsupportedSetting;
+        }
     }
     return ret;
 }
@@ -595,6 +606,9 @@
 void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
     UNUSED(portIndex);
 
+    if (mSignalledError) {
+        return;
+    }
     if (mOutputPortSettingsChange != NONE) {
         return;
     }
@@ -653,9 +667,15 @@
         // update output port's definition and reinitialize decoder.
         if (mInitNeeded && !mIsInFlush) {
             bool portWillReset = false;
-            handlePortSettingsChange(&portWillReset, mNewWidth, mNewHeight);
 
-            CHECK_EQ(reInitDecoder(), (status_t)OK);
+            status_t err = reInitDecoder(mNewWidth, mNewHeight);
+            if (err != OK) {
+                notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
+                mSignalledError = true;
+                return;
+            }
+
+            handlePortSettingsChange(&portWillReset, mNewWidth, mNewHeight);
             return;
         }
 
@@ -714,13 +734,22 @@
                 mTimeStampsValid[timeStampIx] = false;
             }
 
+
             // This is needed to handle CTS DecoderTest testCodecResetsH264WithoutSurface,
             // which is not sending SPS/PPS after port reconfiguration and flush to the codec.
             if (unsupportedDimensions && !mFlushNeeded) {
                 bool portWillReset = false;
-                handlePortSettingsChange(&portWillReset, s_dec_op.u4_pic_wd, s_dec_op.u4_pic_ht);
+                mNewWidth = s_dec_op.u4_pic_wd;
+                mNewHeight = s_dec_op.u4_pic_ht;
 
-                CHECK_EQ(reInitDecoder(), (status_t)OK);
+                status_t err = reInitDecoder(mNewWidth, mNewHeight);
+                if (err != OK) {
+                    notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
+                    mSignalledError = true;
+                    return;
+                }
+
+                handlePortSettingsChange(&portWillReset, mNewWidth, mNewHeight);
 
                 setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);
 
@@ -732,7 +761,12 @@
 
                 mNewLevel = 51;
 
-                CHECK_EQ(reInitDecoder(), (status_t)OK);
+                status_t err = reInitDecoder(mNewWidth, mNewHeight);
+                if (err != OK) {
+                    notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
+                    mSignalledError = true;
+                    return;
+                }
 
                 setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);
 
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.h b/media/libstagefright/codecs/avcdec/SoftAVCDec.h
index 2067810..1ec8991 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.h
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.h
@@ -105,8 +105,9 @@
     // codec. So the codec is switching to decode the new resolution.
     bool mChangingResolution;
     bool mFlushNeeded;
+    bool mSignalledError;
 
-    status_t initDecoder();
+    status_t initDecoder(uint32_t width, uint32_t height);
     status_t deInitDecoder();
     status_t setFlushMode();
     status_t setParams(size_t stride);
@@ -114,7 +115,7 @@
     status_t setNumCores();
     status_t resetDecoder();
     status_t resetPlugin();
-    status_t reInitDecoder();
+    status_t reInitDecoder(uint32_t width, uint32_t height);
 
     void setDecodeArgs(
             ivd_video_decode_ip_t *ps_dec_ip,
diff --git a/services/audioflinger/AudioStreamOut.cpp b/services/audioflinger/AudioStreamOut.cpp
index e6d8f09..f953cc8 100644
--- a/services/audioflinger/AudioStreamOut.cpp
+++ b/services/audioflinger/AudioStreamOut.cpp
@@ -27,25 +27,59 @@
 namespace android {
 
 // ----------------------------------------------------------------------------
-
 AudioStreamOut::AudioStreamOut(AudioHwDevice *dev, audio_output_flags_t flags)
         : audioHwDev(dev)
         , stream(NULL)
         , flags(flags)
+        , mFramesWritten(0)
+        , mFramesWrittenAtStandby(0)
+        , mRenderPosition(0)
+        , mRateMultiplier(1)
+        , mHalFormatIsLinearPcm(false)
+        , mHalFrameSize(0)
 {
 }
 
-audio_hw_device_t* AudioStreamOut::hwDev() const
+audio_hw_device_t *AudioStreamOut::hwDev() const
 {
     return audioHwDev->hwDevice();
 }
 
-status_t AudioStreamOut::getRenderPosition(uint32_t *frames)
+status_t AudioStreamOut::getRenderPosition(uint64_t *frames)
 {
     if (stream == NULL) {
         return NO_INIT;
     }
-    return stream->get_render_position(stream, frames);
+
+    uint32_t halPosition = 0;
+    status_t status = stream->get_render_position(stream, &halPosition);
+    if (status != NO_ERROR) {
+        return status;
+    }
+
+    // Maintain a 64-bit render position using the 32-bit result from the HAL.
+    // This delta calculation relies on the arithmetic overflow behavior
+    // of integers. For example (100 - 0xFFFFFFF0) = 116.
+    uint32_t truncatedPosition = (uint32_t)mRenderPosition;
+    int32_t deltaHalPosition = (int32_t)(halPosition - truncatedPosition);
+    if (deltaHalPosition > 0) {
+        mRenderPosition += deltaHalPosition;
+    }
+    // Scale from HAL sample rate to application rate.
+    *frames = mRenderPosition / mRateMultiplier;
+
+    return status;
+}
+
+// return bottom 32-bits of the render position
+status_t AudioStreamOut::getRenderPosition(uint32_t *frames)
+{
+    uint64_t position64 = 0;
+    status_t status = getRenderPosition(&position64);
+    if (status == NO_ERROR) {
+        *frames = (uint32_t)position64;
+    }
+    return status;
 }
 
 status_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timespec *timestamp)
@@ -53,7 +87,26 @@
     if (stream == NULL) {
         return NO_INIT;
     }
-    return stream->get_presentation_position(stream, frames, timestamp);
+
+    uint64_t halPosition = 0;
+    status_t status = stream->get_presentation_position(stream, &halPosition, timestamp);
+    if (status != NO_ERROR) {
+        return status;
+    }
+
+    // Adjust for standby using HAL rate frames.
+    // Only apply this correction if the HAL is getting PCM frames.
+    if (mHalFormatIsLinearPcm) {
+        uint64_t adjustedPosition = (halPosition <= mFramesWrittenAtStandby) ?
+                0 : (halPosition - mFramesWrittenAtStandby);
+        // Scale from HAL sample rate to application rate.
+        *frames = adjustedPosition / mRateMultiplier;
+    } else {
+        // For offloaded MP3 and other compressed formats.
+        *frames = halPosition;
+    }
+
+    return status;
 }
 
 status_t AudioStreamOut::open(
@@ -62,7 +115,7 @@
         struct audio_config *config,
         const char *address)
 {
-    audio_stream_out_t* outStream;
+    audio_stream_out_t *outStream;
     int status = hwDev()->open_output_stream(
             hwDev(),
             handle,
@@ -82,6 +135,9 @@
 
     if (status == NO_ERROR) {
         stream = outStream;
+        mHalFormatIsLinearPcm = audio_is_linear_pcm(config->format);
+        ALOGI("AudioStreamOut::open(), mHalFormatIsLinearPcm = %d", (int)mHalFormatIsLinearPcm);
+        mHalFrameSize = audio_stream_out_frame_size(stream);
     }
 
     return status;
@@ -89,13 +145,15 @@
 
 size_t AudioStreamOut::getFrameSize()
 {
-    ALOG_ASSERT(stream != NULL);
-    return audio_stream_out_frame_size(stream);
+    return mHalFrameSize;
 }
 
 int AudioStreamOut::flush()
 {
     ALOG_ASSERT(stream != NULL);
+    mRenderPosition = 0;
+    mFramesWritten = 0;
+    mFramesWrittenAtStandby = 0;
     if (stream->flush != NULL) {
         return stream->flush(stream);
     }
@@ -105,13 +163,20 @@
 int AudioStreamOut::standby()
 {
     ALOG_ASSERT(stream != NULL);
+    mRenderPosition = 0;
+    mFramesWrittenAtStandby = mFramesWritten;
+    ALOGI("AudioStreamOut::standby(), mFramesWrittenAtStandby = %llu", mFramesWrittenAtStandby);
     return stream->common.standby(&stream->common);
 }
 
-ssize_t AudioStreamOut::write(const void* buffer, size_t bytes)
+ssize_t AudioStreamOut::write(const void *buffer, size_t numBytes)
 {
     ALOG_ASSERT(stream != NULL);
-    return stream->write(stream, buffer, bytes);
+    ssize_t bytesWritten = stream->write(stream, buffer, numBytes);
+    if (bytesWritten > 0 && mHalFrameSize > 0) {
+        mFramesWritten += bytesWritten / mHalFrameSize;
+    }
+    return bytesWritten;
 }
 
 } // namespace android
diff --git a/services/audioflinger/AudioStreamOut.h b/services/audioflinger/AudioStreamOut.h
index e91ca9c..761e771 100644
--- a/services/audioflinger/AudioStreamOut.h
+++ b/services/audioflinger/AudioStreamOut.h
@@ -53,7 +53,10 @@
 
     virtual ~AudioStreamOut() { }
 
-    virtual status_t getRenderPosition(uint32_t *frames);
+    // Get the bottom 32-bits of the 64-bit render position.
+    status_t getRenderPosition(uint32_t *frames);
+
+    virtual status_t getRenderPosition(uint64_t *frames);
 
     virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp);
 
@@ -76,6 +79,14 @@
 
     virtual status_t flush();
     virtual status_t standby();
+
+protected:
+    uint64_t             mFramesWritten; // reset by flush
+    uint64_t             mFramesWrittenAtStandby;
+    uint64_t             mRenderPosition; // reset by flush or standby
+    int                  mRateMultiplier;
+    bool                 mHalFormatIsLinearPcm;
+    size_t               mHalFrameSize;
 };
 
 } // namespace android
diff --git a/services/audioflinger/SpdifStreamOut.cpp b/services/audioflinger/SpdifStreamOut.cpp
index ac637ef..6af7bce 100644
--- a/services/audioflinger/SpdifStreamOut.cpp
+++ b/services/audioflinger/SpdifStreamOut.cpp
@@ -36,10 +36,7 @@
             audio_output_flags_t flags,
             audio_format_t format)
         : AudioStreamOut(dev,flags)
-        , mRateMultiplier(1)
         , mSpdifEncoder(this, format)
-        , mRenderPositionHal(0)
-        , mPreviousHalPosition32(0)
 {
 }
 
@@ -97,62 +94,18 @@
     return status;
 }
 
-// Account for possibly higher sample rate.
-status_t SpdifStreamOut::getRenderPosition(uint32_t *frames)
-{
-    uint32_t halPosition = 0;
-    status_t status = AudioStreamOut::getRenderPosition(&halPosition);
-    if (status != NO_ERROR) {
-        return status;
-    }
-
-    // Accumulate a 64-bit position so that we wrap at the right place.
-    if (mRateMultiplier != 1) {
-        // Maintain a 64-bit render position.
-        int32_t deltaHalPosition = (int32_t)(halPosition - mPreviousHalPosition32);
-        mPreviousHalPosition32 = halPosition;
-        mRenderPositionHal += deltaHalPosition;
-
-        // Scale from device sample rate to application rate.
-        uint64_t renderPositionApp = mRenderPositionHal / mRateMultiplier;
-        ALOGV("SpdifStreamOut::getRenderPosition() "
-            "renderPositionAppRate = %llu = %llu / %u\n",
-            renderPositionApp, mRenderPositionHal, mRateMultiplier);
-
-        *frames = (uint32_t)renderPositionApp;
-    } else {
-        *frames = halPosition;
-    }
-    return status;
-}
-
 int SpdifStreamOut::flush()
 {
     mSpdifEncoder.reset();
-    mRenderPositionHal = 0;
-    mPreviousHalPosition32 = 0;
     return AudioStreamOut::flush();
 }
 
 int SpdifStreamOut::standby()
 {
     mSpdifEncoder.reset();
-    mRenderPositionHal = 0;
-    mPreviousHalPosition32 = 0;
     return AudioStreamOut::standby();
 }
 
-// Account for possibly higher sample rate.
-// This is much easier when all the values are 64-bit.
-status_t SpdifStreamOut::getPresentationPosition(uint64_t *frames,
-        struct timespec *timestamp)
-{
-    uint64_t halFrames = 0;
-    status_t status = AudioStreamOut::getPresentationPosition(&halFrames, timestamp);
-    *frames = halFrames / mRateMultiplier;
-    return status;
-}
-
 size_t SpdifStreamOut::getFrameSize()
 {
     return sizeof(int8_t);
diff --git a/services/audioflinger/SpdifStreamOut.h b/services/audioflinger/SpdifStreamOut.h
index d81c064..a61a7bd 100644
--- a/services/audioflinger/SpdifStreamOut.h
+++ b/services/audioflinger/SpdifStreamOut.h
@@ -49,10 +49,6 @@
             struct audio_config *config,
             const char *address);
 
-    virtual status_t getRenderPosition(uint32_t *frames);
-
-    virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp);
-
     /**
     * Write audio buffer to driver. Returns number of bytes written, or a
     * negative status_t. If at least one frame was written successfully prior to the error,
@@ -92,13 +88,8 @@
         SpdifStreamOut * const mSpdifStreamOut;
     };
 
-    int                  mRateMultiplier;
     MySPDIFEncoder       mSpdifEncoder;
 
-    // Used to implement getRenderPosition()
-    int64_t              mRenderPositionHal;
-    uint32_t             mPreviousHalPosition32;
-
     ssize_t  writeDataBurst(const void* data, size_t bytes);
     ssize_t  writeInternal(const void* buffer, size_t bytes);