Merge "CameraNDK: remove unused error enum values" into nyc-dev
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 35f439b..cd91e72 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -2150,7 +2150,7 @@
         //
         // The underrun event is sent once per track underrun; the condition is reset
         // when more data is sent to the AudioTrack.
-        ALOGI("callbackwrapper: EVENT_UNDERRUN (discarded)");
+        ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)");
         break;
 
     default:
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 238cd35..99996ed 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -5704,7 +5704,8 @@
 
                 OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
 
-                int32_t isCSD;
+                MetadataBufferType metaType = mCodec->mInputMetadataType;
+                int32_t isCSD = 0;
                 if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
                     if (mCodec->mIsLegacyVP9Decoder) {
                         ALOGV("[%s] is legacy VP9 decoder. Ignore %u codec specific data",
@@ -5713,6 +5714,7 @@
                         break;
                     }
                     flags |= OMX_BUFFERFLAG_CODECCONFIG;
+                    metaType = kMetadataBufferTypeInvalid;
                 }
 
                 if (eos) {
@@ -5726,7 +5728,7 @@
                          buffer.get(), info->mCodecData.get());
 
                     sp<DataConverter> converter = mCodec->mConverter[kPortIndexInput];
-                    if (converter == NULL) {
+                    if (converter == NULL || isCSD) {
                         converter = getCopyConverter();
                     }
                     status_t err = converter->convert(buffer, info->mCodecData);
@@ -5772,14 +5774,50 @@
                     }
                 }
                 info->checkReadFence("onInputBufferFilled");
-                status_t err2 = mCodec->mOMX->emptyBuffer(
-                    mCodec->mNode,
-                    bufferID,
-                    0,
-                    info->mCodecData->size(),
-                    flags,
-                    timeUs,
-                    info->mFenceFd);
+
+                status_t err2 = OK;
+                switch (metaType) {
+                case kMetadataBufferTypeInvalid:
+                    break;
+#ifndef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+                case kMetadataBufferTypeNativeHandleSource:
+                    if (info->mCodecData->size() >= sizeof(VideoNativeHandleMetadata)) {
+                        VideoNativeHandleMetadata *vnhmd =
+                            (VideoNativeHandleMetadata*)info->mCodecData->base();
+                        err2 = mCodec->mOMX->updateNativeHandleInMeta(
+                                mCodec->mNode, kPortIndexInput,
+                                NativeHandle::create(vnhmd->pHandle, false /* ownsHandle */),
+                                bufferID);
+                    }
+                    break;
+                case kMetadataBufferTypeANWBuffer:
+                    if (info->mCodecData->size() >= sizeof(VideoNativeMetadata)) {
+                        VideoNativeMetadata *vnmd = (VideoNativeMetadata*)info->mCodecData->base();
+                        err2 = mCodec->mOMX->updateGraphicBufferInMeta(
+                                mCodec->mNode, kPortIndexInput,
+                                new GraphicBuffer(vnmd->pBuffer, false /* keepOwnership */),
+                                bufferID);
+                    }
+                    break;
+#endif
+                default:
+                    ALOGW("Can't marshall %s data in %zu sized buffers in %zu-bit mode",
+                            asString(metaType), info->mCodecData->size(),
+                            sizeof(buffer_handle_t) * 8);
+                    err2 = ERROR_UNSUPPORTED;
+                    break;
+                }
+
+                if (err2 == OK) {
+                    err2 = mCodec->mOMX->emptyBuffer(
+                        mCodec->mNode,
+                        bufferID,
+                        0,
+                        info->mCodecData->size(),
+                        flags,
+                        timeUs,
+                        info->mFenceFd);
+                }
                 info->mFenceFd = -1;
                 if (err2 != OK) {
                     mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index 4dde5f6..7279f6c 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -207,9 +207,13 @@
 // static
 MuxOMX::node_location MuxOMX::getPreferredCodecLocation(const char *name) {
     if (sCodecProcessEnabled) {
-        // all non-secure decoders plus OMX.google.* encoders can go in the codec process
-        if ((strcasestr(name, "decoder") && !strcasestr(name, "secure")) ||
-                !strncasecmp(name, "OMX.google.", 11)) {
+        // all non-secure decoders, OMX.google.* codecs and encoders can go in the codec process
+        // (non-OMX.google.* encoders can be excluded using system property.)
+        if ((strcasestr(name, "decoder")
+                        && strcasestr(name, ".secure") != name + strlen(name) - 7)
+                || (strcasestr(name, "encoder")
+                        && !property_get_bool("media.stagefright.legacyencoder", false))
+                || !strncasecmp(name, "OMX.google.", 11)) {
             return CODECPROCESS;
         }
         // everything else runs in the media server
@@ -409,8 +413,16 @@
 status_t MuxOMX::createPersistentInputSurface(
         sp<IGraphicBufferProducer> *bufferProducer,
         sp<IGraphicBufferConsumer> *bufferConsumer) {
-    // TODO: local or remote? Always use remote for now
-    return mMediaServerOMX->createPersistentInputSurface(
+    sp<IOMX> omx;
+    {
+        Mutex::Autolock autoLock(mLock);
+        if (property_get_bool("media.stagefright.legacyencoder", false)) {
+            omx = mMediaServerOMX;
+        } else {
+            omx = mMediaCodecOMX;
+        }
+    }
+    return omx->createPersistentInputSurface(
             bufferProducer, bufferConsumer);
 }
 
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index 1e64b49..973c528 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -638,6 +638,8 @@
                 mChangingResolution = false;
                 resetDecoder();
                 resetPlugin();
+                mStride = outputBufferWidth();
+                setParams(mStride);
                 continue;
             }
 
diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
index 8283ab5..27f860e 100644
--- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
+++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
@@ -74,7 +74,8 @@
       mIvColorFormat(IV_YUV_420P),
       mNewWidth(mWidth),
       mNewHeight(mHeight),
-      mChangingResolution(false) {
+      mChangingResolution(false),
+      mStride(mWidth) {
     initPorts(kNumBuffers, INPUT_BUF_SIZE, kNumBuffers, CODEC_MIME_TYPE);
 
     // If input dump is enabled, then open create an empty file
@@ -202,6 +203,8 @@
     /* Set number of cores/threads to be used by the codec */
     setNumCores();
 
+    mStride = 0;
+
     return OK;
 }
 
@@ -384,7 +387,8 @@
     resetPlugin();
 
     /* Set the run time (dynamic) parameters */
-    setParams(displayStride);
+    mStride = outputBufferWidth();
+    setParams(mStride);
 
     /* Set number of cores/threads to be used by the codec */
     setNumCores();
@@ -548,6 +552,12 @@
     List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
     List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
 
+    if (outputBufferWidth() != mStride) {
+        /* Set the run-time (dynamic) parameters */
+        mStride = outputBufferWidth();
+        setParams(mStride);
+    }
+
     /* If input EOS is seen and decoder is not in flush mode,
      * set the decoder in flush mode.
      * There can be a case where EOS is sent along with last picture data
@@ -686,6 +696,8 @@
                 mChangingResolution = false;
                 resetDecoder();
                 resetPlugin();
+                mStride = outputBufferWidth();
+                setParams(mStride);
                 continue;
             }
 
diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
index f48b70b..025e9a0 100644
--- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
+++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
@@ -106,6 +106,7 @@
     bool mChangingResolution;
     bool mFlushNeeded;
     bool mWaitForI;
+    size_t mStride;
 
     status_t initDecoder();
     status_t deInitDecoder();
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 20d124c..7ad7fee 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -1092,6 +1092,13 @@
             // fall through
         } else {
             if (mPlaylist != NULL) {
+                if (mSeqNumber >= firstSeqNumberInPlaylist + (int32_t)mPlaylist->size()
+                        && !mPlaylist->isComplete()) {
+                    // Live playlists
+                    ALOGW("sequence number %d not yet available", mSeqNumber);
+                    postMonitorQueue(delayUsToRefreshPlaylist());
+                    return false;
+                }
                 ALOGE("Cannot find sequence number %d in playlist "
                      "(contains %d - %d)",
                      mSeqNumber, firstSeqNumberInPlaylist,
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index e98156e..060b6be 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -241,9 +241,14 @@
             OMX_BUFFERHEADERTYPE *header,
             OMX_U32 flags, OMX_TICKS timestamp, intptr_t debugAddr, int fenceFd);
 
+    // Updates the graphic buffer handle in the metadata buffer for |buffer| and |header| to
+    // |graphicBuffer|'s handle. If |updateCodecBuffer| is true, the update will happen in
+    // the actual codec buffer (use this if not using emptyBuffer (with no _l) later to
+    // pass the buffer to the codec, as only emptyBuffer copies the backup buffer to the codec
+    // buffer.)
     status_t updateGraphicBufferInMeta_l(
             OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
-            OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header);
+            OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header, bool updateCodecBuffer);
 
     status_t createGraphicBufferSource(
             OMX_U32 portIndex, sp<IGraphicBufferConsumer> consumer /* nullable */,
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 31bab70..5445944 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -842,7 +842,7 @@
 
 status_t OMXNodeInstance::updateGraphicBufferInMeta_l(
         OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
-        OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header) {
+        OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header, bool updateCodecBuffer) {
     // No need to check |graphicBuffer| since NULL is valid for it as below.
     if (header == NULL) {
         ALOGE("b/25884056");
@@ -854,20 +854,27 @@
     }
 
     BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
+    sp<ABuffer> data = bufferMeta->getBuffer(
+            header, !updateCodecBuffer /* backup */, false /* limit */);
     bufferMeta->setGraphicBuffer(graphicBuffer);
-    if (mMetadataType[portIndex] == kMetadataBufferTypeGrallocSource
-            && header->nAllocLen >= sizeof(VideoGrallocMetadata)) {
-        VideoGrallocMetadata &metadata = *(VideoGrallocMetadata *)(header->pBuffer);
+    MetadataBufferType metaType = mMetadataType[portIndex];
+    // we use gralloc source only in the codec buffers
+    if (metaType == kMetadataBufferTypeGrallocSource && !updateCodecBuffer) {
+        metaType = kMetadataBufferTypeANWBuffer;
+    }
+    if (metaType == kMetadataBufferTypeGrallocSource
+            && data->capacity() >= sizeof(VideoGrallocMetadata)) {
+        VideoGrallocMetadata &metadata = *(VideoGrallocMetadata *)(data->data());
         metadata.eType = kMetadataBufferTypeGrallocSource;
         metadata.pHandle = graphicBuffer == NULL ? NULL : graphicBuffer->handle;
-    } else if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer
-            && header->nAllocLen >= sizeof(VideoNativeMetadata)) {
-        VideoNativeMetadata &metadata = *(VideoNativeMetadata *)(header->pBuffer);
+    } else if (metaType == kMetadataBufferTypeANWBuffer
+            && data->capacity() >= sizeof(VideoNativeMetadata)) {
+        VideoNativeMetadata &metadata = *(VideoNativeMetadata *)(data->data());
         metadata.eType = kMetadataBufferTypeANWBuffer;
         metadata.pBuffer = graphicBuffer == NULL ? NULL : graphicBuffer->getNativeBuffer();
         metadata.nFenceFd = -1;
     } else {
-        CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x bad type (%d) or size (%u)",
+        CLOG_ERROR(updateGraphicBufferInMeta, BAD_VALUE, "%s:%u, %#x bad type (%d) or size (%u)",
             portString(portIndex), portIndex, buffer, mMetadataType[portIndex], header->nAllocLen);
         return BAD_VALUE;
     }
@@ -883,7 +890,10 @@
         OMX::buffer_id buffer) {
     Mutex::Autolock autoLock(mLock);
     OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
-    return updateGraphicBufferInMeta_l(portIndex, graphicBuffer, buffer, header);
+    // update backup buffer for input, codec buffer for output
+    return updateGraphicBufferInMeta_l(
+            portIndex, graphicBuffer, buffer, header,
+            portIndex == kPortIndexOutput /* updateCodecBuffer */);
 }
 
 status_t OMXNodeInstance::updateNativeHandleInMeta(
@@ -1388,7 +1398,9 @@
 
     Mutex::Autolock autoLock(mLock);
     OMX::buffer_id buffer = findBufferID(header);
-    status_t err = updateGraphicBufferInMeta_l(kPortIndexInput, graphicBuffer, buffer, header);
+    status_t err = updateGraphicBufferInMeta_l(
+            kPortIndexInput, graphicBuffer, buffer, header,
+            true /* updateCodecBuffer */);
     if (err != OK) {
         CLOG_ERROR(emptyGraphicBuffer, err, FULL_BUFFER(
                 (intptr_t)header->pBuffer, header, fenceFd));
@@ -1396,7 +1408,13 @@
     }
 
     header->nOffset = 0;
-    header->nFilledLen = graphicBuffer == NULL ? 0 : header->nAllocLen;
+    if (graphicBuffer == NULL) {
+        header->nFilledLen = 0;
+    } else if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource) {
+        header->nFilledLen = sizeof(VideoGrallocMetadata);
+    } else {
+        header->nFilledLen = sizeof(VideoNativeMetadata);
+    }
     return emptyBuffer_l(header, flags, timestamp, (intptr_t)header->pBuffer, fenceFd);
 }
 
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 1d575b3..2b0d4c8 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1843,8 +1843,7 @@
 
         PlaybackThread *thread;
         if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
-            thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady,
-                                       config->offload_info.bit_rate);
+            thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady);
             ALOGV("openOutput_l() created offload output: ID %d thread %p", *output, thread);
         } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
                 || !isValidPcmSinkFormat(config->format)
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index bee0447..d296ee3 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -110,12 +110,7 @@
 // direct outputs can be a scarce resource in audio hardware and should
 // be released as quickly as possible.
 static const int8_t kMaxTrackRetriesDirect = 2;
-// retry count before removing active track in case of underrun on offloaded thread:
-// we need to make sure that AudioTrack client has enough time to send large buffers
-//FIXME may be more appropriate if expressed in time units. Need to revise how underrun is handled
-// for offloaded tracks
-static const int8_t kMaxTrackRetriesOffload = 10;
-static const int8_t kMaxTrackStartupRetriesOffload = 100;
+
 
 
 // don't warn about blocked writes or record buffer overflows more often than this
@@ -148,10 +143,6 @@
 // Direct output thread minimum sleep time in idle or active(underrun) state
 static const nsecs_t kDirectMinSleepTimeUs = 10000;
 
-// Offloaded output bit rate in bits per second when unknown.
-// Used for sleep time calculation, so use a high default bitrate to be conservative on sleep time.
-static const uint32_t kOffloadDefaultBitRateBps = 1500000;
-
 
 // Whether to use fast mixer
 static const enum {
@@ -1567,8 +1558,7 @@
                                              audio_io_handle_t id,
                                              audio_devices_t device,
                                              type_t type,
-                                             bool systemReady,
-                                             uint32_t bitRate)
+                                             bool systemReady)
     :   ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type, systemReady),
         mNormalFrameCount(0), mSinkBuffer(NULL),
         mMixerBufferEnabled(AudioFlinger::kEnableExtendedPrecision),
@@ -1631,13 +1621,6 @@
         mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream);
         mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
     }
-
-    if (audio_has_proportional_frames(mFormat)) {
-        mBufferDurationUs = (uint32_t)((mNormalFrameCount * 1000000LL) / mSampleRate);
-    } else {
-        bitRate = bitRate != 0 ? bitRate : kOffloadDefaultBitRateBps;
-        mBufferDurationUs = (uint32_t)((mBufferSize * 8 * 1000000LL) / bitRate);
-    }
 }
 
 AudioFlinger::PlaybackThread::~PlaybackThread()
@@ -2049,12 +2032,18 @@
 
         // set retry count for buffer fill
         if (track->isOffloaded()) {
-            track->mRetryCount = kMaxTrackStartupRetriesOffload;
+            if (track->isStopping_1()) {
+                track->mRetryCount = kMaxTrackStopRetriesOffload;
+            } else {
+                track->mRetryCount = kMaxTrackStartupRetriesOffload;
+            }
+            track->mFillingUpStatus = mStandby ? Track::FS_FILLING : Track::FS_FILLED;
         } else {
             track->mRetryCount = kMaxTrackStartupRetries;
+            track->mFillingUpStatus =
+                    track->sharedBuffer() != 0 ? Track::FS_FILLED : Track::FS_FILLING;
         }
 
-        track->mFillingUpStatus = track->sharedBuffer() != 0 ? Track::FS_FILLED : Track::FS_FILLING;
         track->mResetDone = false;
         track->mPresentationCompleteFrames = 0;
         mActiveTracks.add(track);
@@ -3181,32 +3170,9 @@
 
             } else {
                 ATRACE_BEGIN("sleep");
-                if ((mType == OFFLOAD) && !audio_has_proportional_frames(mFormat)) {
-                    Mutex::Autolock _l(mLock);
-                    if (!mSignalPending && !exitPending()) {
-                        // If more than one buffer has been written to the audio HAL since exiting
-                        // standby or last flush, do not sleep more than one buffer duration
-                        // since last write and not less than kDirectMinSleepTimeUs.
-                        // Wake up if a command is received
-                        uint32_t timeoutUs = mSleepTimeUs;
-                        if (mBytesWritten >= (int64_t) mBufferSize) {
-                            nsecs_t now = systemTime();
-                            uint32_t deltaUs = (uint32_t)((now - mLastWriteTime) / 1000);
-                            if (timeoutUs + deltaUs > mBufferDurationUs) {
-                                if (mBufferDurationUs > deltaUs) {
-                                    timeoutUs = mBufferDurationUs - deltaUs;
-                                    if (timeoutUs < kDirectMinSleepTimeUs) {
-                                        timeoutUs = kDirectMinSleepTimeUs;
-                                    }
-                                } else {
-                                    timeoutUs = kDirectMinSleepTimeUs;
-                                }
-                            }
-                        }
-                        mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)timeoutUs));
-                    }
-                } else {
-                    usleep(mSleepTimeUs);
+                Mutex::Autolock _l(mLock);
+                if (!mSignalPending && mConfigEvents.isEmpty() && !exitPending()) {
+                    mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)mSleepTimeUs));
                 }
                 ATRACE_END();
             }
@@ -4592,17 +4558,16 @@
 // ----------------------------------------------------------------------------
 
 AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
-        AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady,
-        uint32_t bitRate)
-    :   PlaybackThread(audioFlinger, output, id, device, DIRECT, systemReady, bitRate)
+        AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady)
+    :   PlaybackThread(audioFlinger, output, id, device, DIRECT, systemReady)
         // mLeftVolFloat, mRightVolFloat
 {
 }
 
 AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
         AudioStreamOut* output, audio_io_handle_t id, uint32_t device,
-        ThreadBase::type_t type, bool systemReady, uint32_t bitRate)
-    :   PlaybackThread(audioFlinger, output, id, device, type, systemReady, bitRate)
+        ThreadBase::type_t type, bool systemReady)
+    :   PlaybackThread(audioFlinger, output, id, device, type, systemReady)
         // mLeftVolFloat, mRightVolFloat
 {
 }
@@ -4908,14 +4873,7 @@
     }
     if (mSleepTimeUs == 0) {
         if (mMixerStatus == MIXER_TRACKS_ENABLED) {
-            // For compressed offload, use faster sleep time when underruning until more than an
-            // entire buffer was written to the audio HAL
-            if (!audio_has_proportional_frames(mFormat) &&
-                    (mType == OFFLOAD) && (mBytesWritten < (int64_t) mBufferSize)) {
-                mSleepTimeUs = kDirectMinSleepTimeUs;
-            } else {
-                mSleepTimeUs = mActiveSleepTimeUs;
-            }
+            mSleepTimeUs = mActiveSleepTimeUs;
         } else {
             mSleepTimeUs = mIdleSleepTimeUs;
         }
@@ -5187,9 +5145,8 @@
 
 // ----------------------------------------------------------------------------
 AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
-        AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady,
-        uint32_t bitRate)
-    :   DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady, bitRate),
+        AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady)
+    :   DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady),
         mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true)
 {
     //FIXME: mStandby should be set to true by ThreadBase constructor
@@ -5273,7 +5230,11 @@
             }
             tracksToRemove->add(track);
         } else if (track->isFlushPending()) {
-            track->mRetryCount = kMaxTrackRetriesOffload;
+            if (track->isStopping_1()) {
+                track->mRetryCount = kMaxTrackStopRetriesOffload;
+            } else {
+                track->mRetryCount = kMaxTrackRetriesOffload;
+            }
             track->flushAck();
             if (last) {
                 mFlushPending = true;
@@ -5334,38 +5295,47 @@
                 }
                 mPreviousTrack = track;
                 // reset retry count
-                track->mRetryCount = kMaxTrackRetriesOffload;
+                if (track->isStopping_1()) {
+                    track->mRetryCount = kMaxTrackStopRetriesOffload;
+                } else {
+                    track->mRetryCount = kMaxTrackRetriesOffload;
+                }
                 mActiveTrack = t;
                 mixerStatus = MIXER_TRACKS_READY;
             }
         } else {
             ALOGVV("OffloadThread: track %d s=%08x [NOT READY]", track->name(), cblk->mServer);
             if (track->isStopping_1()) {
-                // Hardware buffer can hold a large amount of audio so we must
-                // wait for all current track's data to drain before we say
-                // that the track is stopped.
-                if (mBytesRemaining == 0) {
-                    // Only start draining when all data in mixbuffer
-                    // has been written
-                    ALOGV("OffloadThread: underrun and STOPPING_1 -> draining, STOPPING_2");
-                    track->mState = TrackBase::STOPPING_2; // so presentation completes after drain
-                    // do not drain if no data was ever sent to HAL (mStandby == true)
-                    if (last && !mStandby) {
-                        // do not modify drain sequence if we are already draining. This happens
-                        // when resuming from pause after drain.
-                        if ((mDrainSequence & 1) == 0) {
-                            mSleepTimeUs = 0;
-                            mStandbyTimeNs = systemTime() + mStandbyDelayNs;
-                            mixerStatus = MIXER_DRAIN_TRACK;
-                            mDrainSequence += 2;
-                        }
-                        if (mHwPaused) {
-                            // It is possible to move from PAUSED to STOPPING_1 without
-                            // a resume so we must ensure hardware is running
-                            doHwResume = true;
-                            mHwPaused = false;
+                if (--(track->mRetryCount) <= 0) {
+                    // Hardware buffer can hold a large amount of audio so we must
+                    // wait for all current track's data to drain before we say
+                    // that the track is stopped.
+                    if (mBytesRemaining == 0) {
+                        // Only start draining when all data in mixbuffer
+                        // has been written
+                        ALOGV("OffloadThread: underrun and STOPPING_1 -> draining, STOPPING_2");
+                        track->mState = TrackBase::STOPPING_2; // so presentation completes after
+                        // drain do not drain if no data was ever sent to HAL (mStandby == true)
+                        if (last && !mStandby) {
+                            // do not modify drain sequence if we are already draining. This happens
+                            // when resuming from pause after drain.
+                            if ((mDrainSequence & 1) == 0) {
+                                mSleepTimeUs = 0;
+                                mStandbyTimeNs = systemTime() + mStandbyDelayNs;
+                                mixerStatus = MIXER_DRAIN_TRACK;
+                                mDrainSequence += 2;
+                            }
+                            if (mHwPaused) {
+                                // It is possible to move from PAUSED to STOPPING_1 without
+                                // a resume so we must ensure hardware is running
+                                doHwResume = true;
+                                mHwPaused = false;
+                            }
                         }
                     }
+                } else if (last) {
+                    ALOGV("stopping1 underrun retries left %d", track->mRetryCount);
+                    mixerStatus = MIXER_TRACKS_ENABLED;
                 }
             } else if (track->isStopping_2()) {
                 // Drain has completed or we are in standby, signal presentation complete
@@ -5456,20 +5426,6 @@
     }
 }
 
-uint32_t AudioFlinger::OffloadThread::activeSleepTimeUs() const
-{
-    uint32_t time;
-    if (audio_has_proportional_frames(mFormat)) {
-        time = PlaybackThread::activeSleepTimeUs();
-    } else {
-        // sleep time is half the duration of an audio HAL buffer.
-        // Note: This can be problematic in case of underrun with variable bit rate and
-        // current rate is much less than initial rate.
-        time = (uint32_t)max(kDirectMinSleepTimeUs, mBufferDurationUs / 2);
-    }
-    return time;
-}
-
 void AudioFlinger::OffloadThread::invalidateTracks(audio_stream_type_t streamType)
 {
     Mutex::Autolock _l(mLock);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 0ddd279..1cceb6d 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -486,9 +486,16 @@
         // suspend by audio policy manager is orthogonal to mixer state
     };
 
+    // retry count before removing active track in case of underrun on offloaded thread:
+    // we need to make sure that AudioTrack client has enough time to send large buffers
+    //FIXME may be more appropriate if expressed in time units. Need to revise how underrun is
+    // handled for offloaded tracks
+    static const int8_t kMaxTrackRetriesOffload = 20;
+    static const int8_t kMaxTrackStartupRetriesOffload = 100;
+    static const int8_t kMaxTrackStopRetriesOffload = 2;
+
     PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
-                   audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady,
-                   uint32_t bitRate = 0);
+                   audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady);
     virtual             ~PlaybackThread();
 
                 void        dump(int fd, const Vector<String16>& args);
@@ -843,8 +850,6 @@
                 bool        mHwSupportsPause;
                 bool        mHwPaused;
                 bool        mFlushPending;
-                uint32_t    mBufferDurationUs;      // estimated duration of an audio HAL buffer
-                                                    // based on initial bit rate (offload only)
 };
 
 class MixerThread : public PlaybackThread {
@@ -935,8 +940,7 @@
 public:
 
     DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
-                       audio_io_handle_t id, audio_devices_t device, bool systemReady,
-                       uint32_t bitRate = 0);
+                       audio_io_handle_t id, audio_devices_t device, bool systemReady);
     virtual                 ~DirectOutputThread();
 
     // Thread virtuals
@@ -969,7 +973,7 @@
 
     DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
                         audio_io_handle_t id, uint32_t device, ThreadBase::type_t type,
-                        bool systemReady, uint32_t bitRate = 0);
+                        bool systemReady);
     void processVolume_l(Track *track, bool lastTrack);
 
     // prepareTracks_l() tells threadLoop_mix() the name of the single active track
@@ -985,8 +989,7 @@
 public:
 
     OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
-                        audio_io_handle_t id, uint32_t device,
-                        bool systemReady, uint32_t bitRate);
+                        audio_io_handle_t id, uint32_t device, bool systemReady);
     virtual                 ~OffloadThread() {};
     virtual     void        flushHw_l();
 
@@ -995,8 +998,6 @@
     virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
     virtual     void        threadLoop_exit();
 
-    virtual     uint32_t    activeSleepTimeUs() const;
-
     virtual     bool        waitingAsyncCallback();
     virtual     bool        waitingAsyncCallback_l();
     virtual     void        invalidateTracks(audio_stream_type_t streamType);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 41cb030..364e339 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -373,7 +373,7 @@
     // client == 0 implies sharedBuffer == 0
     ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
 
-    ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(),
+    ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %zu", sharedBuffer->pointer(),
             sharedBuffer->size());
 
     if (mCblk == NULL) {
@@ -728,6 +728,9 @@
                 // For an offloaded track this starts a drain and state will
                 // move to STOPPING_2 when drain completes and then STOPPED
                 mState = STOPPING_1;
+                if (isOffloaded()) {
+                    mRetryCount = PlaybackThread::kMaxTrackStopRetriesOffload;
+                }
             }
             playbackThread->broadcast_l();
             ALOGV("not stopping/stopped => stopping/stopped (%d) on thread %p", mName,
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index 211bdae..a2c9712 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -334,6 +334,7 @@
             currentFormat != (uint32_t)params.videoFormat ||
             currentDataSpace != params.videoDataSpace) {
         *needsUpdate = true;
+        return res;
     }
     *needsUpdate = false;
     return res;