Merge "disable AwesomePlayer for Ogg vorbis" into lmp-dev
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 8774117..e2bcb1e 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1433,6 +1433,10 @@
             format->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC);
             break;
 
+        case VIDEO_ENCODER_VP8:
+            format->setString("mime", MEDIA_MIMETYPE_VIDEO_VP8);
+            break;
+
         default:
             CHECK(!"Should not be here, unsupported video encoding.");
             break;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 5e7ecfa..0a9b65c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -148,6 +148,8 @@
       mVideoIsAVC(false),
       mOffloadAudio(false),
       mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
+      mAudioDecoderGeneration(0),
+      mVideoDecoderGeneration(0),
       mAudioEOS(false),
       mVideoEOS(false),
       mScanSourcesPending(false),
@@ -691,6 +693,25 @@
         {
             bool audio = msg->what() == kWhatAudioNotify;
 
+            int32_t currentDecoderGeneration =
+                (audio? mAudioDecoderGeneration : mVideoDecoderGeneration);
+            int32_t requesterGeneration = currentDecoderGeneration - 1;
+            CHECK(msg->findInt32("generation", &requesterGeneration));
+
+            if (requesterGeneration != currentDecoderGeneration) {
+                ALOGV("got message from old %s decoder, generation(%d:%d)",
+                        audio ? "audio" : "video", requesterGeneration,
+                        currentDecoderGeneration);
+                sp<AMessage> reply;
+                if (!(msg->findMessage("reply", &reply))) {
+                    return;
+                }
+
+                reply->setInt32("err", INFO_DISCONTINUITY);
+                reply->post();
+                return;
+            }
+
             int32_t what;
             CHECK(msg->findInt32("what", &what));
 
@@ -782,6 +803,14 @@
                     err = UNKNOWN_ERROR;
                 }
                 mRenderer->queueEOS(audio, err);
+                if (audio && mFlushingAudio != NONE) {
+                    mAudioDecoder.clear();
+                    mFlushingAudio = SHUT_DOWN;
+                } else if (!audio && mFlushingVideo != NONE){
+                    mVideoDecoder.clear();
+                    mFlushingVideo = SHUT_DOWN;
+                }
+                finishFlushIfPossible();
             } else if (what == Decoder::kWhatDrainThisBuffer) {
                 renderBuffer(audio, msg);
             } else {
@@ -943,11 +972,13 @@
 }
 
 void NuPlayer::finishFlushIfPossible() {
-    if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
+    if (mFlushingAudio != NONE && mFlushingAudio != FLUSHED
+            && mFlushingAudio != SHUT_DOWN) {
         return;
     }
 
-    if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
+    if (mFlushingVideo != NONE && mFlushingVideo != FLUSHED
+            && mFlushingVideo != SHUT_DOWN) {
         return;
     }
 
@@ -958,11 +989,11 @@
         mTimeDiscontinuityPending = false;
     }
 
-    if (mAudioDecoder != NULL) {
+    if (mAudioDecoder != NULL && mFlushingAudio == FLUSHED) {
         mAudioDecoder->signalResume();
     }
 
-    if (mVideoDecoder != NULL) {
+    if (mVideoDecoder != NULL && mFlushingVideo == FLUSHED) {
         mVideoDecoder->signalResume();
     }
 
@@ -1061,6 +1092,7 @@
             }
             ALOGV("openAudioSink: try to open AudioSink in offload mode");
             flags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+            flags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
             audioSinkChanged = true;
             mAudioSink->close();
             err = mAudioSink->open(
@@ -1150,17 +1182,21 @@
         }
     }
 
-    sp<AMessage> notify =
-        new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
-                     id());
-
     if (audio) {
+        sp<AMessage> notify = new AMessage(kWhatAudioNotify, id());
+        ++mAudioDecoderGeneration;
+        notify->setInt32("generation", mAudioDecoderGeneration);
+
         if (mOffloadAudio) {
             *decoder = new DecoderPassThrough(notify);
         } else {
             *decoder = new Decoder(notify);
         }
     } else {
+        sp<AMessage> notify = new AMessage(kWhatVideoNotify, id());
+        ++mVideoDecoderGeneration;
+        notify->setInt32("generation", mVideoDecoderGeneration);
+
         *decoder = new Decoder(notify, mNativeWindow);
     }
     (*decoder)->init();
@@ -1195,8 +1231,8 @@
     sp<AMessage> reply;
     CHECK(msg->findMessage("reply", &reply));
 
-    if ((audio && IsFlushingState(mFlushingAudio))
-            || (!audio && IsFlushingState(mFlushingVideo))) {
+    if ((audio && mFlushingAudio != NONE)
+            || (!audio && mFlushingVideo != NONE)) {
         reply->setInt32("err", INFO_DISCONTINUITY);
         reply->post();
         return OK;
@@ -1276,15 +1312,6 @@
                     }
                 } else {
                     // This stream is unaffected by the discontinuity
-
-                    if (audio) {
-                        mFlushingAudio = FLUSHED;
-                    } else {
-                        mFlushingVideo = FLUSHED;
-                    }
-
-                    finishFlushIfPossible();
-
                     return -EWOULDBLOCK;
                 }
             }
@@ -1335,7 +1362,8 @@
     sp<AMessage> reply;
     CHECK(msg->findMessage("reply", &reply));
 
-    if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) {
+    if ((audio && mFlushingAudio != NONE)
+            || (!audio && mFlushingVideo != NONE)) {
         // We're currently attempting to flush the decoder, in order
         // to complete this, the decoder wants all its buffers back,
         // so we don't want any output buffers it sent us (from before
@@ -1480,27 +1508,13 @@
         needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
 
     if (audio) {
-        CHECK(mFlushingAudio == NONE
-                || mFlushingAudio == AWAITING_DISCONTINUITY);
-
+        ALOGE_IF(mFlushingAudio != NONE,
+                "audio flushDecoder() is called in state %d", mFlushingAudio);
         mFlushingAudio = newStatus;
-
-        if (mFlushingVideo == NONE) {
-            mFlushingVideo = (mVideoDecoder != NULL)
-                ? AWAITING_DISCONTINUITY
-                : FLUSHED;
-        }
     } else {
-        CHECK(mFlushingVideo == NONE
-                || mFlushingVideo == AWAITING_DISCONTINUITY);
-
+        ALOGE_IF(mFlushingVideo != NONE,
+                "video flushDecoder() is called in state %d", mFlushingVideo);
         mFlushingVideo = newStatus;
-
-        if (mFlushingAudio == NONE) {
-            mFlushingAudio = (mAudioDecoder != NULL)
-                ? AWAITING_DISCONTINUITY
-                : FLUSHED;
-        }
     }
 }
 
@@ -1590,18 +1604,6 @@
         // an intermediate state, i.e. one more more decoders are currently
         // flushing or shutting down.
 
-        if (mRenderer != NULL) {
-            // There's an edge case where the renderer owns all output
-            // buffers and is paused, therefore the decoder will not read
-            // more input data and will never encounter the matching
-            // discontinuity. To avoid this, we resume the renderer.
-
-            if (mFlushingAudio == AWAITING_DISCONTINUITY
-                    || mFlushingVideo == AWAITING_DISCONTINUITY) {
-                mRenderer->resume();
-            }
-        }
-
         if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
             // We're currently flushing, postpone the reset until that's
             // completed.
@@ -1666,14 +1668,6 @@
 
     mTimeDiscontinuityPending = true;
 
-    if (mFlushingAudio == NONE && (!audio || mAudioDecoder == NULL)) {
-        mFlushingAudio = FLUSHED;
-    }
-
-    if (mFlushingVideo == NONE && (!video || mVideoDecoder == NULL)) {
-        mFlushingVideo = FLUSHED;
-    }
-
     if (audio && mAudioDecoder != NULL) {
         flushDecoder(true /* audio */, true /* needShutdown */);
     }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 48882c5..96306db 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -129,6 +129,8 @@
     sp<CCDecoder> mCCDecoder;
     sp<Renderer> mRenderer;
     sp<ALooper> mRendererLooper;
+    int32_t mAudioDecoderGeneration;
+    int32_t mVideoDecoderGeneration;
 
     List<sp<Action> > mDeferredActions;
 
@@ -143,7 +145,6 @@
 
     enum FlushStatus {
         NONE,
-        AWAITING_DISCONTINUITY,
         FLUSHING_DECODER,
         FLUSHING_DECODER_SHUTDOWN,
         SHUTTING_DOWN_DECODER,
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 8fce2f4..60c645a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -44,11 +44,11 @@
     // Every decoder has its own looper because MediaCodec operations
     // are blocking, but NuPlayer needs asynchronous operations.
     mDecoderLooper = new ALooper;
-    mDecoderLooper->setName("NuPlayerDecoder");
+    mDecoderLooper->setName("NPDecoder");
     mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
 
     mCodecLooper = new ALooper;
-    mCodecLooper->setName("NuPlayerDecoder-MC");
+    mCodecLooper->setName("NPDecoder-CL");
     mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index bf7542f..8a63cfe 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -167,6 +167,16 @@
                 mCondition.wait(mLock);
             }
             return (mState == STATE_PREPARED) ? OK : UNKNOWN_ERROR;
+        case STATE_STOPPED:
+            // this is really just paused. handle as seek to start
+            mAtEOS = false;
+            mState = STATE_STOPPED_AND_PREPARING;
+            mIsAsyncPrepare = false;
+            mPlayer->seekToAsync(0);
+            while (mState == STATE_STOPPED_AND_PREPARING) {
+                mCondition.wait(mLock);
+            }
+            return (mState == STATE_STOPPED_AND_PREPARED) ? OK : UNKNOWN_ERROR;
         default:
             return INVALID_OPERATION;
     };
@@ -181,6 +191,13 @@
             mIsAsyncPrepare = true;
             mPlayer->prepareAsync();
             return OK;
+        case STATE_STOPPED:
+            // this is really just paused. handle as seek to start
+            mAtEOS = false;
+            mState = STATE_STOPPED_AND_PREPARING;
+            mIsAsyncPrepare = true;
+            mPlayer->seekToAsync(0);
+            return OK;
         default:
             return INVALID_OPERATION;
     };
@@ -210,7 +227,7 @@
 
             if (mStartupSeekTimeUs >= 0) {
                 if (mStartupSeekTimeUs == 0) {
-                    notifySeekComplete();
+                    notifySeekComplete_l();
                 } else {
                     mPlayer->seekToAsync(mStartupSeekTimeUs);
                 }
@@ -224,6 +241,7 @@
             break;
 
         case STATE_PAUSED:
+        case STATE_STOPPED_AND_PREPARED:
         {
             mPlayer->resume();
             break;
@@ -239,7 +257,29 @@
 }
 
 status_t NuPlayerDriver::stop() {
-    return pause();
+    Mutex::Autolock autoLock(mLock);
+
+    switch (mState) {
+        case STATE_RUNNING:
+            mPlayer->pause();
+            // fall through
+
+        case STATE_PAUSED:
+            notifyListener(MEDIA_STOPPED);
+            // fall through
+
+        case STATE_PREPARED:
+        case STATE_STOPPED:
+        case STATE_STOPPED_AND_PREPARING:
+        case STATE_STOPPED_AND_PREPARED:
+            mState = STATE_STOPPED;
+            break;
+
+        default:
+            return INVALID_OPERATION;
+    }
+
+    return OK;
 }
 
 status_t NuPlayerDriver::pause() {
@@ -280,7 +320,7 @@
             // pretend that the seek completed. It will actually happen when starting playback.
             // TODO: actually perform the seek here, so the player is ready to go at the new
             // location
-            notifySeekComplete();
+            notifySeekComplete_l();
             break;
         }
 
@@ -348,7 +388,9 @@
             break;
     }
 
-    notifyListener(MEDIA_STOPPED);
+    if (mState != STATE_STOPPED) {
+        notifyListener(MEDIA_STOPPED);
+    }
 
     mState = STATE_RESET_IN_PROGRESS;
     mPlayer->resetAsync();
@@ -483,7 +525,28 @@
 }
 
 void NuPlayerDriver::notifySeekComplete() {
-    notifyListener(MEDIA_SEEK_COMPLETE);
+    Mutex::Autolock autoLock(mLock);
+    notifySeekComplete_l();
+}
+
+void NuPlayerDriver::notifySeekComplete_l() {
+    bool wasSeeking = true;
+    if (mState == STATE_STOPPED_AND_PREPARING) {
+        wasSeeking = false;
+        mState = STATE_STOPPED_AND_PREPARED;
+        mCondition.broadcast();
+        if (!mIsAsyncPrepare) {
+            // if we are preparing synchronously, no need to notify listener
+            return;
+        }
+    } else if (mState == STATE_STOPPED) {
+        // no need to notify listener
+        return;
+    }
+    // note: notifyListener called with lock released
+    mLock.unlock();
+    notifyListener(wasSeeking ? MEDIA_SEEK_COMPLETE : MEDIA_PREPARED);
+    mLock.lock();
 }
 
 void NuPlayerDriver::notifyFrameStats(
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index a9ff8b6..a006d8f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -69,6 +69,7 @@
     void notifyDuration(int64_t durationUs);
     void notifyPosition(int64_t positionUs);
     void notifySeekComplete();
+    void notifySeekComplete_l();
     void notifyFrameStats(int64_t numFramesTotal, int64_t numFramesDropped);
     void notifyListener(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL);
     void notifyFlagsChanged(uint32_t flags);
@@ -86,6 +87,9 @@
         STATE_RUNNING,
         STATE_PAUSED,
         STATE_RESET_IN_PROGRESS,
+        STATE_STOPPED,                  // equivalent to PAUSED
+        STATE_STOPPED_AND_PREPARING,    // equivalent to PAUSED, but seeking
+        STATE_STOPPED_AND_PREPARED,     // equivalent to PAUSED, but seek complete
     };
 
     mutable Mutex mLock;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 3640038..1213a18 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -93,10 +93,14 @@
     {
         Mutex::Autolock autoLock(mFlushLock);
         if (audio) {
-            CHECK(!mFlushingAudio);
+            if (mFlushingAudio) {
+                return;
+            }
             mFlushingAudio = true;
         } else {
-            CHECK(!mFlushingVideo);
+            if (mFlushingVideo) {
+                return;
+            }
             mFlushingVideo = true;
         }
     }
@@ -115,6 +119,14 @@
     mSyncQueues = false;
 }
 
+void NuPlayer::Renderer::signalAudioSinkChanged() {
+    (new AMessage(kWhatAudioSinkChanged, id()))->post();
+}
+
+void NuPlayer::Renderer::signalDisableOffloadAudio() {
+    (new AMessage(kWhatDisableOffloadAudio, id()))->post();
+}
+
 void NuPlayer::Renderer::pause() {
     (new AMessage(kWhatPause, id()))->post();
 }
@@ -251,14 +263,6 @@
     msg->post(delayUs);
 }
 
-void NuPlayer::Renderer::signalAudioSinkChanged() {
-    (new AMessage(kWhatAudioSinkChanged, id()))->post();
-}
-
-void NuPlayer::Renderer::signalDisableOffloadAudio() {
-    (new AMessage(kWhatDisableOffloadAudio, id()))->post();
-}
-
 void NuPlayer::Renderer::prepareForMediaRenderingStart() {
     mAudioRenderingStartGeneration = mAudioQueueGeneration;
     mVideoRenderingStartGeneration = mVideoQueueGeneration;
@@ -318,6 +322,7 @@
     bool hasEOS = false;
 
     size_t sizeCopied = 0;
+    bool firstEntry = true;
     while (sizeCopied < size && !mAudioQueue.empty()) {
         QueueEntry *entry = &*mAudioQueue.begin();
 
@@ -328,14 +333,14 @@
             break;
         }
 
-        if (entry->mOffset == 0) {
+        if (firstEntry && entry->mOffset == 0) {
+            firstEntry = false;
             int64_t mediaTimeUs;
             CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
             ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
             if (mFirstAudioTimeUs == -1) {
                 mFirstAudioTimeUs = mediaTimeUs;
             }
-            mAnchorTimeMediaUs = mediaTimeUs;
 
             uint32_t numFramesPlayed;
             CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
@@ -716,6 +721,15 @@
     int32_t audio;
     CHECK(msg->findInt32("audio", &audio));
 
+    {
+        Mutex::Autolock autoLock(mFlushLock);
+        if (audio) {
+            mFlushingAudio = false;
+        } else {
+            mFlushingVideo = false;
+        }
+    }
+
     // If we're currently syncing the queues, i.e. dropping audio while
     // aligning the first audio/video buffer times and only one of the
     // two queues has data, we may starve that queue by not requesting
@@ -734,17 +748,18 @@
         {
             Mutex::Autolock autoLock(mLock);
             flushQueue(&mAudioQueue);
+
+            ++mAudioQueueGeneration;
+            prepareForMediaRenderingStart();
+
+            if (offloadingAudio()) {
+                mFirstAudioTimeUs = -1;
+            }
         }
 
-        Mutex::Autolock autoLock(mFlushLock);
-        mFlushingAudio = false;
-
         mDrainAudioQueuePending = false;
-        ++mAudioQueueGeneration;
 
-        prepareForMediaRenderingStart();
         if (offloadingAudio()) {
-            mFirstAudioTimeUs = -1;
             mAudioSink->pause();
             mAudioSink->flush();
             mAudioSink->start();
@@ -752,9 +767,6 @@
     } else {
         flushQueue(&mVideoQueue);
 
-        Mutex::Autolock autoLock(mFlushLock);
-        mFlushingVideo = false;
-
         mDrainVideoQueuePending = false;
         ++mVideoQueueGeneration;
 
@@ -852,13 +864,15 @@
 void NuPlayer::Renderer::onPause() {
     CHECK(!mPaused);
 
+    {
+        Mutex::Autolock autoLock(mLock);
+        ++mAudioQueueGeneration;
+        ++mVideoQueueGeneration;
+        prepareForMediaRenderingStart();
+    }
+
     mDrainAudioQueuePending = false;
-    ++mAudioQueueGeneration;
-
     mDrainVideoQueuePending = false;
-    ++mVideoQueueGeneration;
-
-    prepareForMediaRenderingStart();
 
     if (mHasAudio) {
         mAudioSink->pause();
@@ -895,7 +909,12 @@
     uint32_t numFramesPlayed;
     CHECK_EQ(mAudioSink->getPosition(&numFramesPlayed), (status_t)OK);
 
-    int64_t currentPositionUs = mFirstAudioTimeUs
+    int64_t firstAudioTimeUs;
+    {
+        Mutex::Autolock autoLock(mLock);
+        firstAudioTimeUs = mFirstAudioTimeUs;
+    }
+    int64_t currentPositionUs = firstAudioTimeUs
             + (numFramesPlayed * mAudioSink->msecsPerFrame()) * 1000ll;
 
     mAudioSink->stop();
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 7bb7ed9..814adab 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -716,7 +716,8 @@
                     CHECK(msg->findInt32("err", &err));
                     CHECK(msg->findInt32("actionCode", &actionCode));
 
-                    ALOGE("Codec reported err %#x, actionCode %d", err, actionCode);
+                    ALOGE("Codec reported err %#x, actionCode %d, while in state %d",
+                            err, actionCode, mState);
                     if (err == DEAD_OBJECT) {
                         mFlags |= kFlagSawMediaServerDie;
                     }
@@ -767,8 +768,12 @@
 
                         case FLUSHING:
                         {
-                            setState(
-                                    (mFlags & kFlagIsAsync) ? FLUSHED : STARTED);
+                            if (actionCode == ACTION_CODE_FATAL) {
+                                setState(UNINITIALIZED);
+                            } else {
+                                setState(
+                                        (mFlags & kFlagIsAsync) ? FLUSHED : STARTED);
+                            }
                             break;
                         }
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 3d1d40e..78758da 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -2500,12 +2500,6 @@
                        data1, data2);
 
             if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
-                // There is no need to check whether mFilledBuffers is empty or not
-                // when the OMX_EventPortSettingsChanged is not meant for reallocating
-                // the output buffers.
-                if (data1 == kPortIndexOutput) {
-                    CHECK(mFilledBuffers.empty());
-                }
                 onPortSettingsChanged(data1);
             } else if (data1 == kPortIndexOutput &&
                         (data2 == OMX_IndexConfigCommonOutputCrop ||
@@ -2899,7 +2893,7 @@
 void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
     CODEC_LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
 
-    CHECK_EQ((int)mState, (int)EXECUTING);
+    CHECK(mState == EXECUTING || mState == EXECUTING_TO_IDLE);
     CHECK_EQ(portIndex, (OMX_U32)kPortIndexOutput);
     CHECK(!mOutputPortSettingsChangedPending);
 
diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
index 98b50dd..76f8f54 100644
--- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
+++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp
@@ -249,11 +249,15 @@
         mPackets.push_back(buffer);
     } else {
         // hexdump(buffer->data(), buffer->size());
+        if (buffer->size() < 2) {
+            return MALFORMED_PACKET;
+        }
 
-        CHECK_GE(buffer->size(), 2u);
         unsigned AU_headers_length = U16_AT(buffer->data());  // in bits
 
-        CHECK_GE(buffer->size(), 2 + (AU_headers_length + 7) / 8);
+        if (buffer->size() < 2 + (AU_headers_length + 7) / 8) {
+            return MALFORMED_PACKET;
+        }
 
         List<AUHeader> headers;
 
@@ -342,7 +346,9 @@
              it != headers.end(); ++it) {
             const AUHeader &header = *it;
 
-            CHECK_LE(offset + header.mSize, buffer->size());
+            if (buffer->size() < offset + header.mSize) {
+                return MALFORMED_PACKET;
+            }
 
             sp<ABuffer> accessUnit = new ABuffer(header.mSize);
             memcpy(accessUnit->data(), buffer->data() + offset, header.mSize);
@@ -352,8 +358,6 @@
             CopyTimes(accessUnit, buffer);
             mPackets.push_back(accessUnit);
         }
-
-        CHECK_EQ(offset, buffer->size());
     }
 
     queue->erase(queue->begin());
@@ -400,6 +404,7 @@
         const sp<ARTPSource> &source) {
     AssemblyStatus status = addPacket(source);
     if (status == MALFORMED_PACKET) {
+        ALOGI("access unit is damaged");
         mAccessUnitDamaged = true;
     }
     return status;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 7766b90..fd5a426 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -487,12 +487,12 @@
         }
         if (client == NULL) {
             needsNewClient = true;
-            ret = connectHelperLocked(/*cameraClient*/NULL, // Empty binder callbacks
+            ret = connectHelperLocked(/*out*/client,
+                                      /*cameraClient*/NULL, // Empty binder callbacks
                                       cameraId,
                                       internalPackageName,
                                       uid,
-                                      pid,
-                                      client);
+                                      pid);
 
             if (ret != OK) {
                 // Error already logged by callee
@@ -659,14 +659,17 @@
     return true;
 }
 
-status_t CameraService::connectHelperLocked(const sp<ICameraClient>& cameraClient,
-                                      int cameraId,
-                                      const String16& clientPackageName,
-                                      int clientUid,
-                                      int callingPid,
-                                      /*out*/
-                                      sp<Client>& client,
-                                      int halVersion) {
+status_t CameraService::connectHelperLocked(
+        /*out*/
+        sp<Client>& client,
+        /*in*/
+        const sp<ICameraClient>& cameraClient,
+        int cameraId,
+        const String16& clientPackageName,
+        int clientUid,
+        int callingPid,
+        int halVersion,
+        bool legacyMode) {
 
     int facing = -1;
     int deviceVersion = getDeviceVersion(cameraId, &facing);
@@ -678,7 +681,7 @@
           case CAMERA_DEVICE_API_VERSION_1_0:
             client = new CameraClient(this, cameraClient,
                     clientPackageName, cameraId,
-                    facing, callingPid, clientUid, getpid());
+                    facing, callingPid, clientUid, getpid(), legacyMode);
             break;
           case CAMERA_DEVICE_API_VERSION_2_0:
           case CAMERA_DEVICE_API_VERSION_2_1:
@@ -687,7 +690,7 @@
           case CAMERA_DEVICE_API_VERSION_3_2:
             client = new Camera2Client(this, cameraClient,
                     clientPackageName, cameraId,
-                    facing, callingPid, clientUid, getpid());
+                    facing, callingPid, clientUid, getpid(), legacyMode);
             break;
           case -1:
             ALOGE("Invalid camera id %d", cameraId);
@@ -704,7 +707,7 @@
             // Only support higher HAL version device opened as HAL1.0 device.
             client = new CameraClient(this, cameraClient,
                     clientPackageName, cameraId,
-                    facing, callingPid, clientUid, getpid());
+                    facing, callingPid, clientUid, getpid(), legacyMode);
         } else {
             // Other combinations (e.g. HAL3.x open as HAL2.x) are not supported yet.
             ALOGE("Invalid camera HAL version %x: HAL %x device can only be"
@@ -760,12 +763,12 @@
             return OK;
         }
 
-        status = connectHelperLocked(cameraClient,
+        status = connectHelperLocked(/*out*/client,
+                                     cameraClient,
                                      cameraId,
                                      clientPackageName,
                                      clientUid,
-                                     callingPid,
-                                     client);
+                                     callingPid);
         if (status != OK) {
             return status;
         }
@@ -823,13 +826,14 @@
             return OK;
         }
 
-        status = connectHelperLocked(cameraClient,
+        status = connectHelperLocked(/*out*/client,
+                                     cameraClient,
                                      cameraId,
                                      clientPackageName,
                                      clientUid,
                                      callingPid,
-                                     client,
-                                     halVersion);
+                                     halVersion,
+                                     /*legacyMode*/true);
         if (status != OK) {
             return status;
         }
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index cb98c96..a7328cf 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -452,14 +452,17 @@
      *
      * Returns OK on success, or a negative error code.
      */
-    status_t            connectHelperLocked(const sp<ICameraClient>& cameraClient,
-                                      int cameraId,
-                                      const String16& clientPackageName,
-                                      int clientUid,
-                                      int callingPid,
-                                      /*out*/
-                                      sp<Client>& client,
-                                      int halVersion = CAMERA_HAL_API_VERSION_UNSPECIFIED);
+    status_t            connectHelperLocked(
+            /*out*/
+            sp<Client>& client,
+            /*in*/
+            const sp<ICameraClient>& cameraClient,
+            int cameraId,
+            const String16& clientPackageName,
+            int clientUid,
+            int callingPid,
+            int halVersion = CAMERA_HAL_API_VERSION_UNSPECIFIED,
+            bool legacyMode = false);
 };
 
 } // namespace android
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 5eb5181..bc40971 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -53,7 +53,8 @@
         int cameraFacing,
         int clientPid,
         uid_t clientUid,
-        int servicePid):
+        int servicePid,
+        bool legacyMode):
         Camera2ClientBase(cameraService, cameraClient, clientPackageName,
                 cameraId, cameraFacing, clientPid, clientUid, servicePid),
         mParameters(cameraId, cameraFacing)
@@ -62,6 +63,8 @@
 
     SharedParameters::Lock l(mParameters);
     l.mParameters.state = Parameters::DISCONNECTED;
+
+    mLegacyMode = legacyMode;
 }
 
 status_t Camera2Client::initialize(camera_module_t *module)
@@ -1449,6 +1452,13 @@
         return OK;
     }
 
+    // the camera2 api legacy mode can unconditionally disable the shutter sound
+    if (mLegacyMode) {
+        ALOGV("%s: Disable shutter sound in legacy mode", __FUNCTION__);
+        l.mParameters.playShutterSound = false;
+        return OK;
+    }
+
     // Disabling shutter sound may not be allowed. In that case only
     // allow the mediaserver process to disable the sound.
     char value[PROPERTY_VALUE_MAX];
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index 5ce757a..f5c3a30 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -89,7 +89,8 @@
             int cameraFacing,
             int clientPid,
             uid_t clientUid,
-            int servicePid);
+            int servicePid,
+            bool legacyMode);
 
     virtual ~Camera2Client();
 
@@ -203,6 +204,7 @@
     bool mAfInMotion;
 
     /** Utility members */
+    bool mLegacyMode;
 
     // Wait until the camera device has received the latest control settings
     status_t syncWithDevice();
diff --git a/services/camera/libcameraservice/api1/CameraClient.cpp b/services/camera/libcameraservice/api1/CameraClient.cpp
index fb6b678..abe1235 100644
--- a/services/camera/libcameraservice/api1/CameraClient.cpp
+++ b/services/camera/libcameraservice/api1/CameraClient.cpp
@@ -38,7 +38,7 @@
         const String16& clientPackageName,
         int cameraId, int cameraFacing,
         int clientPid, int clientUid,
-        int servicePid):
+        int servicePid, bool legacyMode):
         Client(cameraService, cameraClient, clientPackageName,
                 cameraId, cameraFacing, clientPid, clientUid, servicePid)
 {
@@ -54,6 +54,7 @@
     // Callback is disabled by default
     mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
     mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
+    mLegacyMode = legacyMode;
     mPlayShutterSound = true;
     LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
 }
@@ -576,6 +577,13 @@
         return OK;
     }
 
+    // the camera2 api legacy mode can unconditionally disable the shutter sound
+    if (mLegacyMode) {
+        ALOGV("%s: Disable shutter sound in legacy mode", __FUNCTION__);
+        mPlayShutterSound = false;
+        return OK;
+    }
+
     // Disabling shutter sound may not be allowed. In that case only
     // allow the mediaserver process to disable the sound.
     char value[PROPERTY_VALUE_MAX];
diff --git a/services/camera/libcameraservice/api1/CameraClient.h b/services/camera/libcameraservice/api1/CameraClient.h
index 4b89564..6779f5e 100644
--- a/services/camera/libcameraservice/api1/CameraClient.h
+++ b/services/camera/libcameraservice/api1/CameraClient.h
@@ -64,7 +64,8 @@
             int cameraFacing,
             int clientPid,
             int clientUid,
-            int servicePid);
+            int servicePid,
+            bool legacyMode = false);
     ~CameraClient();
 
     status_t initialize(camera_module_t *module);
@@ -129,6 +130,7 @@
     int                             mPreviewCallbackFlag;
     int                             mOrientation;     // Current display orientation
     bool                            mPlayShutterSound;
+    bool                            mLegacyMode; // camera2 api legacy mode?
 
     // Ensures atomicity among the public methods
     mutable Mutex                   mLock;
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index b448e06..e7f9a78 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -644,8 +644,17 @@
         focusMode = Parameters::FOCUS_MODE_AUTO;
         params.set(CameraParameters::KEY_FOCUS_MODE,
                 CameraParameters::FOCUS_MODE_AUTO);
-        String8 supportedFocusModes(CameraParameters::FOCUS_MODE_INFINITY);
-        bool addComma = true;
+        String8 supportedFocusModes;
+        bool addComma = false;
+        camera_metadata_ro_entry_t focusDistanceCalibration =
+            staticInfo(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION, 0, 0, false);
+
+        if (focusDistanceCalibration.count &&
+                focusDistanceCalibration.data.u8[0] !=
+                ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED) {
+            supportedFocusModes += CameraParameters::FOCUS_MODE_INFINITY;
+            addComma = true;
+        }
 
         for (size_t i=0; i < availableAfModes.count; i++) {
             if (addComma) supportedFocusModes += ",";
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index d7b1871..3f6254f 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -381,18 +381,7 @@
     if (hal3Device->common.version >= CAMERA_DEVICE_API_VERSION_3_2) {
         ALOGV("%s: register_stream_buffers unused as of HAL3.2", __FUNCTION__);
 
-        /**
-         * Skip the NULL check if camera.dev.register_stream is 1.
-         *
-         * For development-validation purposes only.
-         *
-         * TODO: Remove the property check before shipping L (b/13914251).
-         */
-        char value[PROPERTY_VALUE_MAX] = { '\0', };
-        property_get("camera.dev.register_stream", value, "0");
-        int propInt = atoi(value);
-
-        if (propInt == 0 && hal3Device->ops->register_stream_buffers != NULL) {
+        if (hal3Device->ops->register_stream_buffers != NULL) {
             ALOGE("%s: register_stream_buffers is deprecated in HAL3.2; "
                     "must be set to NULL in camera3_device::ops", __FUNCTION__);
             return INVALID_OPERATION;