Merge "Shorten thread names"
diff --git a/cmds/stagefright/SimplePlayer.cpp b/cmds/stagefright/SimplePlayer.cpp
index f269e80..fac3a8c 100644
--- a/cmds/stagefright/SimplePlayer.cpp
+++ b/cmds/stagefright/SimplePlayer.cpp
@@ -396,7 +396,7 @@
     for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
         CodecState *state = &mStateByTrackIndex.editValueAt(i);
 
-        CHECK_EQ(state->mCodec->stop(), (status_t)OK);
+        CHECK_EQ(state->mCodec->release(), (status_t)OK);
     }
 
     mStartTimeRealUs = -1ll;
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index b850190..fbf800c 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -295,7 +295,7 @@
     for (size_t i = 0; i < stateByTrack.size(); ++i) {
         CodecState *state = &stateByTrack.editValueAt(i);
 
-        CHECK_EQ((status_t)OK, state->mCodec->stop());
+        CHECK_EQ((status_t)OK, state->mCodec->release());
     }
 
     return 0;
diff --git a/drm/drmserver/main_drmserver.cpp b/drm/drmserver/main_drmserver.cpp
index e61b269..434d561 100644
--- a/drm/drmserver/main_drmserver.cpp
+++ b/drm/drmserver/main_drmserver.cpp
@@ -17,15 +17,10 @@
 #define LOG_TAG "drmserver"
 //#define LOG_NDEBUG 0
 
-#include <sys/types.h>
-#include <unistd.h>
-#include <grp.h>
-
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
 #include <utils/Log.h>
-#include <private/android_filesystem_config.h>
 
 #include <DrmManagerService.h>
 
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 437a89c..b0c581a 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -225,7 +225,7 @@
 
     /* get sample rate for this record track
      */
-            uint32_t    getSampleRate();
+            uint32_t    getSampleRate() const;
 
     /* Sets marker position. When record reaches the number of frames specified,
      * a callback with event type EVENT_MARKER is called. Calling setMarkerPosition
@@ -242,7 +242,7 @@
      *  - INVALID_OPERATION: the AudioRecord has no callback installed.
      */
             status_t    setMarkerPosition(uint32_t marker);
-            status_t    getMarkerPosition(uint32_t *marker);
+            status_t    getMarkerPosition(uint32_t *marker) const;
 
 
     /* Sets position update period. Every time the number of frames specified has been recorded,
@@ -261,7 +261,7 @@
      *  - INVALID_OPERATION: the AudioRecord has no callback installed.
      */
             status_t    setPositionUpdatePeriod(uint32_t updatePeriod);
-            status_t    getPositionUpdatePeriod(uint32_t *updatePeriod);
+            status_t    getPositionUpdatePeriod(uint32_t *updatePeriod) const;
 
 
     /* Gets record head position. The position is the  total number of frames
@@ -275,7 +275,7 @@
      *  - NO_ERROR: successful operation
      *  - BAD_VALUE:  position is NULL
      */
-            status_t    getPosition(uint32_t *position);
+            status_t    getPosition(uint32_t *position) const;
 
     /* returns a handle on the audio input used by this AudioRecord.
      *
@@ -285,7 +285,7 @@
      * Returned value:
      *  handle on audio hardware input
      */
-            audio_io_handle_t    getInput();
+            audio_io_handle_t    getInput() const;
 
     /* returns the audio session ID associated to this AudioRecord.
      *
@@ -295,7 +295,7 @@
      * Returned value:
      *  AudioRecord session ID.
      */
-            int    getSessionId();
+            int    getSessionId() const;
 
     /* obtains a buffer of "frameCount" frames. The buffer must be
      * filled entirely. If the track is stopped, obtainBuffer() returns
@@ -326,7 +326,7 @@
      * Such loss typically occurs when the user space process is blocked longer than the capacity of audio driver buffers.
      * Unit: the number of input audio frames
      */
-            unsigned int  getInputFramesLost();
+            unsigned int  getInputFramesLost() const;
 
 private:
     /* copying audio tracks is not allowed */
@@ -360,7 +360,7 @@
     sp<IMemory>             mCblkMemory;
     sp<ClientRecordThread>  mClientRecordThread;
     status_t                mReadyToRun;
-    Mutex                   mLock;
+    mutable Mutex           mLock;
     Condition               mCondition;
 
     uint32_t                mFrameCount;
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 70799a6..6735aff 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -49,7 +49,7 @@
     void initiateSetup(const sp<AMessage> &msg);
     void signalFlush();
     void signalResume();
-    void initiateShutdown();
+    void initiateShutdown(bool keepComponentAllocated = false);
 
     void initiateAllocateComponent(const sp<AMessage> &msg);
     void initiateConfigureComponent(const sp<AMessage> &msg);
@@ -61,6 +61,7 @@
 private:
     struct BaseState;
     struct UninitializedState;
+    struct LoadedState;
     struct LoadedToIdleState;
     struct IdleToExecutingState;
     struct ExecutingState;
@@ -107,6 +108,7 @@
     sp<AMessage> mNotify;
 
     sp<UninitializedState> mUninitializedState;
+    sp<LoadedState> mLoadedState;
     sp<LoadedToIdleState> mLoadedToIdleState;
     sp<IdleToExecutingState> mIdleToExecutingState;
     sp<ExecutingState> mExecutingState;
@@ -131,6 +133,12 @@
     bool mSentFormat;
     bool mIsEncoder;
 
+    bool mShutdownInProgress;
+
+    // If "mKeepComponentAllocated" we only transition back to Loaded state
+    // and do not release the component instance.
+    bool mKeepComponentAllocated;
+
     status_t allocateBuffersOnPort(OMX_U32 portIndex);
     status_t freeBuffersOnPort(OMX_U32 portIndex);
     status_t freeBuffer(OMX_U32 portIndex, size_t i);
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 8c11c9c..72ac56a 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -53,8 +53,15 @@
             uint32_t flags);
 
     status_t start();
+
+    // Returns to a state in which the component remains allocated but
+    // unconfigured.
     status_t stop();
 
+    // Client MUST call release before releasing final reference to this
+    // object.
+    status_t release();
+
     status_t flush();
 
     status_t queueInputBuffer(
@@ -97,6 +104,7 @@
         STARTED,
         FLUSHING,
         STOPPING,
+        RELEASING,
     };
 
     enum {
@@ -109,6 +117,7 @@
         kWhatConfigure                  = 'conf',
         kWhatStart                      = 'strt',
         kWhatStop                       = 'stop',
+        kWhatRelease                    = 'rele',
         kWhatDequeueInputBuffer         = 'deqI',
         kWhatQueueInputBuffer           = 'queI',
         kWhatDequeueOutputBuffer        = 'deqO',
diff --git a/media/libstagefright/timedtext/TimedTextDriver.h b/include/media/stagefright/timedtext/TimedTextDriver.h
similarity index 100%
rename from media/libstagefright/timedtext/TimedTextDriver.h
rename to include/media/stagefright/timedtext/TimedTextDriver.h
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index dd73a8e..943f3af 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -386,7 +386,7 @@
     return !mActive;
 }
 
-uint32_t AudioRecord::getSampleRate()
+uint32_t AudioRecord::getSampleRate() const
 {
     AutoMutex lock(mLock);
     return mCblk->sampleRate;
@@ -402,7 +402,7 @@
     return NO_ERROR;
 }
 
-status_t AudioRecord::getMarkerPosition(uint32_t *marker)
+status_t AudioRecord::getMarkerPosition(uint32_t *marker) const
 {
     if (marker == NULL) return BAD_VALUE;
 
@@ -423,7 +423,7 @@
     return NO_ERROR;
 }
 
-status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod)
+status_t AudioRecord::getPositionUpdatePeriod(uint32_t *updatePeriod) const
 {
     if (updatePeriod == NULL) return BAD_VALUE;
 
@@ -432,7 +432,7 @@
     return NO_ERROR;
 }
 
-status_t AudioRecord::getPosition(uint32_t *position)
+status_t AudioRecord::getPosition(uint32_t *position) const
 {
     if (position == NULL) return BAD_VALUE;
 
@@ -442,7 +442,7 @@
     return NO_ERROR;
 }
 
-unsigned int AudioRecord::getInputFramesLost()
+unsigned int AudioRecord::getInputFramesLost() const
 {
     if (mActive)
         return AudioSystem::getInputFramesLost(mInput);
@@ -597,7 +597,7 @@
     mCblk->stepUser(audioBuffer->frameCount);
 }
 
-audio_io_handle_t AudioRecord::getInput()
+audio_io_handle_t AudioRecord::getInput() const
 {
     AutoMutex lock(mLock);
     return mInput;
@@ -615,7 +615,7 @@
     return mInput;
 }
 
-int AudioRecord::getSessionId()
+int AudioRecord::getSessionId() const
 {
     return mSessionId;
 }
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 85bd7ba..9a9d094 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -165,18 +165,36 @@
 
 protected:
     virtual bool onMessageReceived(const sp<AMessage> &msg);
+    virtual void stateEntered();
 
 private:
     void onSetup(const sp<AMessage> &msg);
-    void onAllocateComponent(const sp<AMessage> &msg);
-    void onConfigureComponent(const sp<AMessage> &msg);
-    void onStart();
+    bool onAllocateComponent(const sp<AMessage> &msg);
 
     DISALLOW_EVIL_CONSTRUCTORS(UninitializedState);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 
+struct ACodec::LoadedState : public ACodec::BaseState {
+    LoadedState(ACodec *codec);
+
+protected:
+    virtual bool onMessageReceived(const sp<AMessage> &msg);
+    virtual void stateEntered();
+
+private:
+    friend struct ACodec::UninitializedState;
+
+    bool onConfigureComponent(const sp<AMessage> &msg);
+    void onStart();
+    void onShutdown(bool keepComponentAllocated);
+
+    DISALLOW_EVIL_CONSTRUCTORS(LoadedState);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
 struct ACodec::LoadedToIdleState : public ACodec::BaseState {
     LoadedToIdleState(ACodec *codec);
 
@@ -312,8 +330,10 @@
 ACodec::ACodec()
     : mNode(NULL),
       mSentFormat(false),
-      mIsEncoder(false) {
+      mIsEncoder(false),
+      mShutdownInProgress(false) {
     mUninitializedState = new UninitializedState(this);
+    mLoadedState = new LoadedState(this);
     mLoadedToIdleState = new LoadedToIdleState(this);
     mIdleToExecutingState = new IdleToExecutingState(this);
     mExecutingState = new ExecutingState(this);
@@ -369,8 +389,10 @@
     (new AMessage(kWhatResume, id()))->post();
 }
 
-void ACodec::initiateShutdown() {
-    (new AMessage(kWhatShutdown, id()))->post();
+void ACodec::initiateShutdown(bool keepComponentAllocated) {
+    sp<AMessage> msg = new AMessage(kWhatShutdown, id());
+    msg->setInt32("keepComponentAllocated", keepComponentAllocated);
+    msg->post();
 }
 
 status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
@@ -2492,6 +2514,10 @@
     : BaseState(codec) {
 }
 
+void ACodec::UninitializedState::stateEntered() {
+    ALOGV("Now uninitialized");
+}
+
 bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
     bool handled = false;
 
@@ -2511,22 +2537,13 @@
             break;
         }
 
-        case ACodec::kWhatConfigureComponent:
-        {
-            onConfigureComponent(msg);
-            handled = true;
-            break;
-        }
-
-        case ACodec::kWhatStart:
-        {
-            onStart();
-            handled = true;
-            break;
-        }
-
         case ACodec::kWhatShutdown:
         {
+            int32_t keepComponentAllocated;
+            CHECK(msg->findInt32(
+                        "keepComponentAllocated", &keepComponentAllocated));
+            CHECK(!keepComponentAllocated);
+
             sp<AMessage> notify = mCodec->mNotify->dup();
             notify->setInt32("what", ACodec::kWhatShutdownCompleted);
             notify->post();
@@ -2554,22 +2571,16 @@
 
 void ACodec::UninitializedState::onSetup(
         const sp<AMessage> &msg) {
-    onAllocateComponent(msg);
-    onConfigureComponent(msg);
-    onStart();
+    if (onAllocateComponent(msg)
+            && mCodec->mLoadedState->onConfigureComponent(msg)) {
+        mCodec->mLoadedState->onStart();
+    }
 }
 
-void ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
+bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
     ALOGV("onAllocateComponent");
 
-    if (mCodec->mNode != NULL) {
-        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
-
-        mCodec->mNativeWindow.clear();
-        mCodec->mNode = NULL;
-        mCodec->mOMX.clear();
-        mCodec->mComponentName.clear();
-    }
+    CHECK(mCodec->mNode == NULL);
 
     OMXClient client;
     CHECK_EQ(client.connect(), (status_t)OK);
@@ -2628,7 +2639,7 @@
         }
 
         mCodec->signalError(OMX_ErrorComponentNotFound);
-        return;
+        return false;
     }
 
     sp<AMessage> notify = new AMessage(kWhatOMXMessage, mCodec->id());
@@ -2649,9 +2660,96 @@
         notify->setString("componentName", mCodec->mComponentName.c_str());
         notify->post();
     }
+
+    mCodec->changeState(mCodec->mLoadedState);
+
+    return true;
 }
 
-void ACodec::UninitializedState::onConfigureComponent(
+////////////////////////////////////////////////////////////////////////////////
+
+ACodec::LoadedState::LoadedState(ACodec *codec)
+    : BaseState(codec) {
+}
+
+void ACodec::LoadedState::stateEntered() {
+    ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
+
+    if (mCodec->mShutdownInProgress) {
+        bool keepComponentAllocated = mCodec->mKeepComponentAllocated;
+
+        mCodec->mShutdownInProgress = false;
+        mCodec->mKeepComponentAllocated = false;
+
+        onShutdown(keepComponentAllocated);
+    }
+}
+
+void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
+    if (!keepComponentAllocated) {
+        CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
+
+        mCodec->mNativeWindow.clear();
+        mCodec->mNode = NULL;
+        mCodec->mOMX.clear();
+        mCodec->mComponentName.clear();
+
+        mCodec->changeState(mCodec->mUninitializedState);
+    }
+
+    sp<AMessage> notify = mCodec->mNotify->dup();
+    notify->setInt32("what", ACodec::kWhatShutdownCompleted);
+    notify->post();
+}
+
+bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
+    bool handled = false;
+
+    switch (msg->what()) {
+        case ACodec::kWhatConfigureComponent:
+        {
+            onConfigureComponent(msg);
+            handled = true;
+            break;
+        }
+
+        case ACodec::kWhatStart:
+        {
+            onStart();
+            handled = true;
+            break;
+        }
+
+        case ACodec::kWhatShutdown:
+        {
+            int32_t keepComponentAllocated;
+            CHECK(msg->findInt32(
+                        "keepComponentAllocated", &keepComponentAllocated));
+
+            onShutdown(keepComponentAllocated);
+
+            handled = true;
+            break;
+        }
+
+        case ACodec::kWhatFlush:
+        {
+            sp<AMessage> notify = mCodec->mNotify->dup();
+            notify->setInt32("what", ACodec::kWhatFlushCompleted);
+            notify->post();
+
+            handled = true;
+            break;
+        }
+
+        default:
+            return BaseState::onMessageReceived(msg);
+    }
+
+    return handled;
+}
+
+bool ACodec::LoadedState::onConfigureComponent(
         const sp<AMessage> &msg) {
     ALOGV("onConfigureComponent");
 
@@ -2664,7 +2762,7 @@
 
     if (err != OK) {
         mCodec->signalError(OMX_ErrorUndefined, err);
-        return;
+        return false;
     }
 
     sp<RefBase> obj;
@@ -2682,9 +2780,11 @@
         notify->setInt32("what", ACodec::kWhatComponentConfigured);
         notify->post();
     }
+
+    return true;
 }
 
-void ACodec::UninitializedState::onStart() {
+void ACodec::LoadedState::onStart() {
     ALOGV("onStart");
 
     CHECK_EQ(mCodec->mOMX->sendCommand(
@@ -2873,6 +2973,13 @@
     switch (msg->what()) {
         case kWhatShutdown:
         {
+            int32_t keepComponentAllocated;
+            CHECK(msg->findInt32(
+                        "keepComponentAllocated", &keepComponentAllocated));
+
+            mCodec->mShutdownInProgress = true;
+            mCodec->mKeepComponentAllocated = keepComponentAllocated;
+
             mActive = false;
 
             CHECK_EQ(mCodec->mOMX->sendCommand(
@@ -3210,20 +3317,7 @@
             CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
             CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
 
-            ALOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
-
-            CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
-
-            mCodec->mNativeWindow.clear();
-            mCodec->mNode = NULL;
-            mCodec->mOMX.clear();
-            mCodec->mComponentName.clear();
-
-            mCodec->changeState(mCodec->mUninitializedState);
-
-            sp<AMessage> notify = mCodec->mNotify->dup();
-            notify->setInt32("what", ACodec::kWhatShutdownCompleted);
-            notify->post();
+            mCodec->changeState(mCodec->mLoadedState);
 
             return true;
         }
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index cfb1e29..95bcada 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -58,6 +58,7 @@
 LOCAL_C_INCLUDES:= \
 	$(JNI_H_INCLUDE) \
         $(TOP)/frameworks/base/include/media/stagefright/openmax \
+        $(TOP)/frameworks/base/include/media/stagefright/timedtext \
         $(TOP)/external/flac/include \
         $(TOP)/external/tremolo \
         $(TOP)/external/openssl/include \
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 8cfb8d3..b21e86a 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -30,13 +30,12 @@
 #include "include/MPEG2TSExtractor.h"
 #include "include/WVMExtractor.h"
 
-#include "timedtext/TimedTextDriver.h"
-
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <media/IMediaPlayerService.h>
 #include <media/stagefright/foundation/hexdump.h>
 #include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/timedtext/TimedTextDriver.h>
 #include <media/stagefright/AudioPlayer.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/FileSource.h>
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index e14b1c4..a9e7f36 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -164,6 +164,13 @@
     return PostAndAwaitResponse(msg, &response);
 }
 
+status_t MediaCodec::release() {
+    sp<AMessage> msg = new AMessage(kWhatRelease, id());
+
+    sp<AMessage> response;
+    return PostAndAwaitResponse(msg, &response);
+}
+
 status_t MediaCodec::queueInputBuffer(
         size_t index,
         size_t offset,
@@ -422,6 +429,7 @@
                         }
 
                         case STOPPING:
+                        case RELEASING:
                         {
                             // Ignore the error, assuming we'll still get
                             // the shutdown complete notification.
@@ -577,7 +585,9 @@
                 {
                     /* size_t index = */updateBuffers(kPortIndexInput, msg);
 
-                    if (mState == FLUSHING || mState == STOPPING) {
+                    if (mState == FLUSHING
+                            || mState == STOPPING
+                            || mState == RELEASING) {
                         returnBuffersToCodecOnPort(kPortIndexInput);
                         break;
                     }
@@ -596,7 +606,9 @@
                 {
                     /* size_t index = */updateBuffers(kPortIndexOutput, msg);
 
-                    if (mState == FLUSHING || mState == STOPPING) {
+                    if (mState == FLUSHING
+                            || mState == STOPPING
+                            || mState == RELEASING) {
                         returnBuffersToCodecOnPort(kPortIndexOutput);
                         break;
                     }
@@ -628,8 +640,12 @@
 
                 case ACodec::kWhatShutdownCompleted:
                 {
-                    CHECK_EQ(mState, STOPPING);
-                    setState(UNINITIALIZED);
+                    if (mState == STOPPING) {
+                        setState(INITIALIZED);
+                    } else {
+                        CHECK_EQ(mState, RELEASING);
+                        setState(UNINITIALIZED);
+                    }
 
                     (new AMessage)->postReply(mReplyID);
                     break;
@@ -767,6 +783,28 @@
             mReplyID = replyID;
             setState(STOPPING);
 
+            mCodec->initiateShutdown(true /* keepComponentAllocated */);
+            returnBuffersToCodec();
+            break;
+        }
+
+        case kWhatRelease:
+        {
+            uint32_t replyID;
+            CHECK(msg->senderAwaitsResponse(&replyID));
+
+            if (mState != INITIALIZED
+                    && mState != CONFIGURED && mState != STARTED) {
+                sp<AMessage> response = new AMessage;
+                response->setInt32("err", INVALID_OPERATION);
+
+                response->postReply(replyID);
+                break;
+            }
+
+            mReplyID = replyID;
+            setState(RELEASING);
+
             mCodec->initiateShutdown();
             returnBuffersToCodec();
             break;
diff --git a/media/libstagefright/timedtext/Android.mk b/media/libstagefright/timedtext/Android.mk
index dde2066..d2d5f7b 100644
--- a/media/libstagefright/timedtext/Android.mk
+++ b/media/libstagefright/timedtext/Android.mk
@@ -12,6 +12,7 @@
 LOCAL_CFLAGS += -Wno-multichar
 LOCAL_C_INCLUDES:= \
         $(JNI_H_INCLUDE) \
+        $(TOP)/frameworks/base/include/media/stagefright/timedtext \
         $(TOP)/frameworks/base/media/libstagefright
 
 LOCAL_MODULE:= libstagefright_timedtext
diff --git a/media/libstagefright/timedtext/TimedTextDriver.cpp b/media/libstagefright/timedtext/TimedTextDriver.cpp
index 9ec9415..c70870e 100644
--- a/media/libstagefright/timedtext/TimedTextDriver.cpp
+++ b/media/libstagefright/timedtext/TimedTextDriver.cpp
@@ -27,8 +27,7 @@
 #include <media/stagefright/Utils.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
-
-#include "TimedTextDriver.h"
+#include <media/stagefright/timedtext/TimedTextDriver.h>
 
 #include "TextDescriptions.h"
 #include "TimedTextPlayer.h"
diff --git a/media/libstagefright/timedtext/TimedTextPlayer.cpp b/media/libstagefright/timedtext/TimedTextPlayer.cpp
index bf7cbf6..bda7b46 100644
--- a/media/libstagefright/timedtext/TimedTextPlayer.cpp
+++ b/media/libstagefright/timedtext/TimedTextPlayer.cpp
@@ -20,12 +20,12 @@
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/timedtext/TimedTextDriver.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/MediaPlayerInterface.h>
 
 #include "TimedTextPlayer.h"
 
-#include "TimedTextDriver.h"
 #include "TimedTextSource.h"
 
 namespace android {
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index b7ddbb5..8f7b35c 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1993,9 +1993,12 @@
 
 bool AudioFlinger::MixerThread::threadLoop()
 {
+    // DirectOutputThread has single trackToRemove instead of Vector
     Vector< sp<Track> > tracksToRemove;
+    // DirectOutputThread has activeTrack here
     nsecs_t standbyTime = systemTime();
     size_t mixBufferSize = mFrameCount * mFrameSize;
+
     // FIXME: Relaxed timing because of a certain device that can't meet latency
     // Should be reduced to 2x after the vendor fixes the driver issue
     // increase threshold again due to low power audio mode. The way this warning threshold is
@@ -2003,18 +2006,26 @@
     nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
     nsecs_t lastWarning = 0;
     bool longStandbyExit = false;
+
     uint32_t activeSleepTime = activeSleepTimeUs();
     uint32_t idleSleepTime = idleSleepTimeUs();
     uint32_t sleepTime = idleSleepTime;
+
     uint32_t sleepTimeShift = 0;
-    Vector< sp<EffectChain> > effectChains;
     CpuStats cpuStats;
 
+    // DirectOutputThread has shorter standbyDelay
+
     acquireWakeLock();
 
     while (!exitPending())
     {
         cpuStats.sample();
+
+        // DirectOutputThread has rampVolume, leftVol, rightVol
+
+        Vector< sp<EffectChain> > effectChains;
+
         processConfigEvents();
 
         mixer_state mixerStatus = MIXER_IDLE;
@@ -2024,28 +2035,29 @@
 
             if (checkForNewParameters_l()) {
                 mixBufferSize = mFrameCount * mFrameSize;
+
                 // FIXME: Relaxed timing because of a certain device that can't meet latency
                 // Should be reduced to 2x after the vendor fixes the driver issue
                 // increase threshold again due to low power audio mode. The way this warning
                 // threshold is calculated and its usefulness should be reconsidered anyway.
                 maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
+
                 activeSleepTime = activeSleepTimeUs();
                 idleSleepTime = idleSleepTimeUs();
+                // DirectOutputThread updates standbyDelay also
             }
 
-            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
-
             // put audio hardware into standby after short delay
-            if (CC_UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
-                        mSuspended)) {
+            if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
+                        mSuspended > 0)) {
                 if (!mStandby) {
-                    ALOGV("Audio hardware entering standby, mixer %p, mSuspended %d", this, mSuspended);
+                    ALOGV("Audio hardware entering standby, mixer %p, suspend count %u", this, mSuspended);
                     mOutput->stream->common.standby(&mOutput->stream->common);
                     mStandby = true;
                     mBytesWritten = 0;
                 }
 
-                if (!activeTracks.size() && mConfigEvents.isEmpty()) {
+                if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
                     // we're about to wait, flush the binder command buffer
                     IPCThreadState::self()->flushCommands();
 
@@ -2068,7 +2080,7 @@
                 }
             }
 
-            mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
+            mixerStatus = prepareTracks_l(&tracksToRemove);
 
             // prevent any changes in effect chain list and in each effect chain
             // during mixing and effect process as the audio buffers could be deleted
@@ -2130,12 +2142,15 @@
             // TODO add standby time extension fct of effect tail
         }
 
-        if (mSuspended) {
+        if (mSuspended > 0) {
             sleepTime = suspendSleepTimeUs();
         }
 
         // only process effects if we're going to write
         if (sleepTime == 0) {
+
+            // DirectOutputThread adds applyVolume here
+
             for (size_t i = 0; i < effectChains.size(); i ++) {
                 effectChains[i]->process_l();
             }
@@ -2146,14 +2161,16 @@
 
         // sleepTime == 0 means we must write to audio hardware
         if (sleepTime == 0) {
+            // FIXME Only in MixerThread, and rewrite to reduce number of system calls
             mLastWriteTime = systemTime();
             mInWrite = true;
             mBytesWritten += mixBufferSize;
-
             int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
             if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
             mNumWrites++;
             mInWrite = false;
+
+            // Only in MixerThread: start of write blocked detection
             nsecs_t now = systemTime();
             nsecs_t delta = now - mLastWriteTime;
             if (!mStandby && delta > maxPeriod) {
@@ -2167,12 +2184,14 @@
                     longStandbyExit = true;
                 }
             }
+            // end of write blocked detection
+
             mStandby = false;
         } else {
             usleep(sleepTime);
         }
 
-        // finally let go of all our tracks, without the lock held
+        // finally let go of removed track(s), without the lock held
         // since we can't guarantee the destructors won't acquire that
         // same lock.
         tracksToRemove.clear();
@@ -2180,8 +2199,12 @@
         // Effect chains will be actually deleted here if they were removed from
         // mEffectChains list during mixing or effects processing
         effectChains.clear();
+
+        // FIXME Note that the above .clear() is no longer necessary since effectChains
+        // is now local to this block, but will keep it for now (at least until merge done).
     }
 
+    // put output stream into standby mode
     if (!mStandby) {
         mOutput->stream->common.standby(&mOutput->stream->common);
     }
@@ -2194,12 +2217,12 @@
 
 // prepareTracks_l() must be called with ThreadBase::mLock held
 AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
-        const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
+        Vector< sp<Track> > *tracksToRemove)
 {
 
     mixer_state mixerStatus = MIXER_IDLE;
     // find out which tracks need to be processed
-    size_t count = activeTracks.size();
+    size_t count = mActiveTracks.size();
     size_t mixedTracks = 0;
     size_t tracksWithEffect = 0;
 
@@ -2219,7 +2242,7 @@
     }
 
     for (size_t i=0 ; i<count ; i++) {
-        sp<Track> t = activeTracks[i].promote();
+        sp<Track> t = mActiveTracks[i].promote();
         if (t == 0) continue;
 
         // this const just means the local variable doesn't change
@@ -2706,13 +2729,20 @@
 
 bool AudioFlinger::DirectOutputThread::threadLoop()
 {
+    // MixerThread has Vector instead of single trackToRemove
     sp<Track> trackToRemove;
-    sp<Track> activeTrack;
+
     nsecs_t standbyTime = systemTime();
-    size_t mixBufferSize = mFrameCount*mFrameSize;
+    size_t mixBufferSize = mFrameCount * mFrameSize;
+
+    // MixerThread has relaxed timing: maxPeriod, lastWarning, longStandbyExit
+
     uint32_t activeSleepTime = activeSleepTimeUs();
     uint32_t idleSleepTime = idleSleepTimeUs();
     uint32_t sleepTime = idleSleepTime;
+
+    // MixerThread has sleepTimeShift and cpuStats
+
     // use shorter standby delay as on normal output to release
     // hardware resources as soon as possible
     nsecs_t standbyDelay = microseconds(activeSleepTime*2);
@@ -2721,20 +2751,30 @@
 
     while (!exitPending())
     {
+        // MixerThread has cpuStats.sample()
+
         bool rampVolume;
         uint16_t leftVol;
         uint16_t rightVol;
+
         Vector< sp<EffectChain> > effectChains;
 
         processConfigEvents();
 
+        // MixerThread does not have activeTrack here
+        sp<Track> activeTrack;
+
         mixer_state mixerStatus = MIXER_IDLE;
         { // scope for the mLock
 
             Mutex::Autolock _l(mLock);
 
             if (checkForNewParameters_l()) {
-                mixBufferSize = mFrameCount*mFrameSize;
+                mixBufferSize = mFrameCount * mFrameSize;
+
+                // different calculations here
+                standbyDelay = microseconds(activeSleepTime*2);
+
                 activeSleepTime = activeSleepTimeUs();
                 idleSleepTime = idleSleepTimeUs();
                 standbyDelay = microseconds(activeSleepTime*2);
@@ -2742,10 +2782,9 @@
 
             // put audio hardware into standby after short delay
             if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
-                        mSuspended)) {
-                // wait until we have something to do...
+                        mSuspended > 0)) {
                 if (!mStandby) {
-                    ALOGV("Audio hardware entering standby, mixer %p, mSuspended %d", this, mSuspended);
+                    ALOGV("Audio hardware entering standby, mixer %p, suspend count %u", this, mSuspended);
                     mOutput->stream->common.standby(&mOutput->stream->common);
                     mStandby = true;
                     mBytesWritten = 0;
@@ -2758,19 +2797,27 @@
                     if (exitPending()) break;
 
                     releaseWakeLock_l();
+                    // wait until we have something to do...
                     ALOGV("Thread %p type %d TID %d going to sleep", this, mType, gettid());
                     mWaitWorkCV.wait(mLock);
                     ALOGV("Thread %p type %d TID %d waking up", this, mType, gettid());
                     acquireWakeLock_l();
 
+                    // MixerThread has "mPrevMixerStatus = MIXER_IDLE"
                     checkSilentMode_l();
 
+                    // MixerThread has different standbyDelay
                     standbyTime = systemTime() + standbyDelay;
                     sleepTime = idleSleepTime;
+                    // MixerThread has "sleepTimeShift = 0"
                     continue;
                 }
             }
 
+            // MixerThread has "mixerStatus = prepareTracks_l(...)"
+
+            // equivalent to MixerThread's lockEffectChains_l, but without the lock
+            // FIXME - is it OK to omit the lock here?
             effectChains = mEffectChains;
 
             // find out which tracks need to be processed
@@ -2901,6 +2948,7 @@
             lockEffectChains_l(effectChains);
        }
 
+        // For DirectOutputThread, this test is equivalent to "activeTrack != 0"
         if (CC_LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
             AudioBufferProvider::Buffer buffer;
             size_t frameCount = mFrameCount;
@@ -2933,15 +2981,18 @@
             }
         }
 
-        if (mSuspended) {
+        if (mSuspended > 0) {
             sleepTime = suspendSleepTimeUs();
         }
 
         // only process effects if we're going to write
         if (sleepTime == 0) {
+
+            // MixerThread does not have applyVolume
             if (mixerStatus == MIXER_TRACKS_READY) {
                 applyVolume(leftVol, rightVol, rampVolume);
             }
+
             for (size_t i = 0; i < effectChains.size(); i ++) {
                 effectChains[i]->process_l();
             }
@@ -2959,12 +3010,15 @@
             if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
             mNumWrites++;
             mInWrite = false;
+
+            // MixerThread has write blocked detection here
+
             mStandby = false;
         } else {
             usleep(sleepTime);
         }
 
-        // finally let go of removed track, without the lock held
+        // finally let go of removed track(s), without the lock held
         // since we can't guarantee the destructors won't acquire that
         // same lock.
         trackToRemove.clear();
@@ -2973,8 +3027,12 @@
         // Effect chains will be actually deleted here if they were removed from
         // mEffectChains list during mixing or effects processing
         effectChains.clear();
+
+        // FIXME Note that the above .clear() is no longer necessary since effectChains
+        // is now local to this block, but will keep it for now (at least until merge done).
     }
 
+    // put output stream into standby mode
     if (!mStandby) {
         mOutput->stream->common.standby(&mOutput->stream->common);
     }
@@ -3099,18 +3157,24 @@
 {
     Vector< sp<Track> > tracksToRemove;
     nsecs_t standbyTime = systemTime();
-    size_t mixBufferSize = mFrameCount*mFrameSize;
+    size_t mixBufferSize = mFrameCount * mFrameSize;
+
+    // Only in DuplicatingThread
     SortedVector< sp<OutputTrack> > outputTracks;
     uint32_t writeFrames = 0;
+
     uint32_t activeSleepTime = activeSleepTimeUs();
     uint32_t idleSleepTime = idleSleepTimeUs();
     uint32_t sleepTime = idleSleepTime;
-    Vector< sp<EffectChain> > effectChains;
 
     acquireWakeLock();
 
     while (!exitPending())
     {
+        // MixerThread has cpuStats.sample
+
+        Vector< sp<EffectChain> > effectChains;
+
         processConfigEvents();
 
         mixer_state mixerStatus = MIXER_IDLE;
@@ -3119,22 +3183,25 @@
             Mutex::Autolock _l(mLock);
 
             if (checkForNewParameters_l()) {
-                mixBufferSize = mFrameCount*mFrameSize;
+                mixBufferSize = mFrameCount * mFrameSize;
+
+                // Only in DuplicatingThread
                 updateWaitTime();
+
                 activeSleepTime = activeSleepTimeUs();
                 idleSleepTime = idleSleepTimeUs();
             }
 
-            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
-
+            // Only in DuplicatingThread
             for (size_t i = 0; i < mOutputTracks.size(); i++) {
                 outputTracks.add(mOutputTracks[i]);
             }
 
             // put audio hardware into standby after short delay
-            if (CC_UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
-                         mSuspended)) {
+            if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
+                         mSuspended > 0)) {
                 if (!mStandby) {
+                    // DuplicatingThread implements standby by stopping all tracks
                     for (size_t i = 0; i < outputTracks.size(); i++) {
                         outputTracks[i]->stop();
                     }
@@ -3142,7 +3209,7 @@
                     mBytesWritten = 0;
                 }
 
-                if (!activeTracks.size() && mConfigEvents.isEmpty()) {
+                if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
                     // we're about to wait, flush the binder command buffer
                     IPCThreadState::self()->flushCommands();
                     outputTracks.clear();
@@ -3156,15 +3223,17 @@
                     ALOGV("Thread %p type %d TID %d waking up", this, mType, gettid());
                     acquireWakeLock_l();
 
+                    // MixerThread has "mPrevMixerStatus = MIXER_IDLE"
                     checkSilentMode_l();
 
                     standbyTime = systemTime() + mStandbyTimeInNsecs;
                     sleepTime = idleSleepTime;
+                    // MixerThread has sleepTimeShift
                     continue;
                 }
             }
 
-            mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
+            mixerStatus = prepareTracks_l(&tracksToRemove);
 
             // prevent any changes in effect chain list and in each effect chain
             // during mixing and effect process as the audio buffers could be deleted
@@ -3172,6 +3241,7 @@
             lockEffectChains_l(effectChains);
         }
 
+        // Duplicating Thread is completely different here
         if (CC_LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
             // mix buffers...
             if (outputsReady(outputTracks)) {
@@ -3201,7 +3271,7 @@
             }
         }
 
-        if (mSuspended) {
+        if (mSuspended > 0) {
             sleepTime = suspendSleepTimeUs();
         }
 
@@ -3223,11 +3293,14 @@
             }
             mStandby = false;
             mBytesWritten += mixBufferSize;
+
+            // MixerThread has write blocked detection here
+
         } else {
             usleep(sleepTime);
         }
 
-        // finally let go of all our tracks, without the lock held
+        // finally let go of removed track(s), without the lock held
         // since we can't guarantee the destructors won't acquire that
         // same lock.
         tracksToRemove.clear();
@@ -3236,8 +3309,14 @@
         // Effect chains will be actually deleted here if they were removed from
         // mEffectChains list during mixing or effects processing
         effectChains.clear();
+
+        // FIXME Note that the above .clear() is no longer necessary since effectChains
+        // is now local to this block, but will keep it for now (at least until merge done).
     }
 
+    // MixerThread and DirectOutpuThread have standby here,
+    // but for DuplicatingThread this is handled by the outputTracks
+
     releaseWakeLock();
 
     ALOGV("Thread %p type %d exiting", this, mType);
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 457bd98..bdaf97c 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -455,9 +455,10 @@
         virtual     status_t addEffectChain_l(const sp<EffectChain>& chain) = 0;
                     // remove an effect chain from the chain list (mEffectChains)
         virtual     size_t removeEffectChain_l(const sp<EffectChain>& chain) = 0;
-                    // lock mall effect chains Mutexes. Must be called before releasing the
+                    // lock all effect chains Mutexes. Must be called before releasing the
                     // ThreadBase mutex before processing the mixer and effects. This guarantees the
                     // integrity of the chains during the process.
+                    // Also sets the parameter 'effectChains' to current value of mEffectChains.
                     void lockEffectChains_l(Vector<sp <EffectChain> >& effectChains);
                     // unlock effect chains after process
                     void unlockEffectChains(const Vector<sp<EffectChain> >& effectChains);
@@ -575,9 +576,11 @@
     public:
 
         enum mixer_state {
-            MIXER_IDLE,
-            MIXER_TRACKS_ENABLED,
-            MIXER_TRACKS_READY
+            MIXER_IDLE,             // no active tracks
+            MIXER_TRACKS_ENABLED,   // at least one active track, but no track has any data ready
+            MIXER_TRACKS_READY      // at least one active track, and at least one track has data
+            // standby mode does not have an enum value
+            // suspend by audio policy manager is orthogonal to mixer state
         };
 
         // playback track
@@ -821,8 +824,8 @@
                     virtual audio_stream_t* stream();
 
                     void        suspend() { mSuspended++; }
-                    void        restore() { if (mSuspended) mSuspended--; }
-                    bool        isSuspended() const { return (mSuspended != 0); }
+                    void        restore() { if (mSuspended > 0) mSuspended--; }
+                    bool        isSuspended() const { return (mSuspended > 0); }
         virtual     String8     getParameters(const String8& keys);
         virtual     void        audioConfigChanged_l(int event, int param = 0);
         virtual     status_t    getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
@@ -843,7 +846,7 @@
 
     protected:
         int16_t*                        mMixBuffer;
-        int                             mSuspended;
+        uint32_t                        mSuspended;     // suspend count, > 0 means suspended
         int                             mBytesWritten;
     private:
         // mMasterMute is in both PlaybackThread and in AudioFlinger.  When a
@@ -913,8 +916,11 @@
         virtual     status_t    dumpInternals(int fd, const Vector<String16>& args);
 
     protected:
-                    mixer_state prepareTracks_l(const SortedVector< wp<Track> >& activeTracks,
-                                                Vector< sp<Track> > *tracksToRemove);
+                    // prepareTracks_l reads and writes mActiveTracks, and also returns the
+                    // pending set of tracks to remove via Vector 'tracksToRemove'.  The caller is
+                    // responsible for clearing or destroying this Vector later on, when it
+                    // is safe to do so. That will drop the final ref count and destroy the tracks.
+                    mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
         virtual     int         getTrackName_l();
         virtual     void        deleteTrackName_l(int name);
         virtual     uint32_t    idleSleepTimeUs();