Merge "Precautionary logging to identify  a potential infinite loop." into jb-dev
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
index 8735503..5bf052a 100644
--- a/media/libeffects/downmix/EffectDownmix.c
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -822,9 +822,9 @@
     if (accumulate) {
         while (numFrames) {
             // FL + RL
-            pDst[0] = clamp16(pDst[0] + pSrc[0] + pSrc[2]);
+            pDst[0] = clamp16(pDst[0] + ((pSrc[0] + pSrc[2]) >> 1));
             // FR + RR
-            pDst[1] = clamp16(pDst[1] + pSrc[1] + pSrc[3]);
+            pDst[1] = clamp16(pDst[1] + ((pSrc[1] + pSrc[3]) >> 1));
             pSrc += 4;
             pDst += 2;
             numFrames--;
@@ -832,9 +832,9 @@
     } else { // same code as above but without adding and clamping pDst[i] to itself
         while (numFrames) {
             // FL + RL
-            pDst[0] = clamp16(pSrc[0] + pSrc[2]);
+            pDst[0] = clamp16((pSrc[0] + pSrc[2]) >> 1);
             // FR + RR
-            pDst[1] = clamp16(pSrc[1] + pSrc[3]);
+            pDst[1] = clamp16((pSrc[1] + pSrc[3]) >> 1);
             pSrc += 4;
             pDst += 2;
             numFrames--;
@@ -877,8 +877,8 @@
             // FR + centerPlusRearContrib
             rt = (pSrc[1] << 12) + centerPlusRearContrib;
             // accumulate in destination
-            pDst[0] = clamp16(pDst[0] + (lt >> 12));
-            pDst[1] = clamp16(pDst[1] + (rt >> 12));
+            pDst[0] = clamp16(pDst[0] + (lt >> 13));
+            pDst[1] = clamp16(pDst[1] + (rt >> 13));
             pSrc += 4;
             pDst += 2;
             numFrames--;
@@ -892,8 +892,8 @@
             // FR + centerPlusRearContrib
             rt = (pSrc[1] << 12) + centerPlusRearContrib;
             // store in destination
-            pDst[0] = clamp16(lt >> 12); // differs from when accumulate is true above
-            pDst[1] = clamp16(rt >> 12); // differs from when accumulate is true above
+            pDst[0] = clamp16(lt >> 13); // differs from when accumulate is true above
+            pDst[1] = clamp16(rt >> 13); // differs from when accumulate is true above
             pSrc += 4;
             pDst += 2;
             numFrames--;
@@ -939,8 +939,8 @@
             // FR + centerPlusLfeContrib + RR
             rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[5] << 12);
             // accumulate in destination
-            pDst[0] = clamp16(pDst[0] + (lt >> 12));
-            pDst[1] = clamp16(pDst[1] + (rt >> 12));
+            pDst[0] = clamp16(pDst[0] + (lt >> 13));
+            pDst[1] = clamp16(pDst[1] + (rt >> 13));
             pSrc += 6;
             pDst += 2;
             numFrames--;
@@ -955,8 +955,8 @@
             // FR + centerPlusLfeContrib + RR
             rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[5] << 12);
             // store in destination
-            pDst[0] = clamp16(lt >> 12); // differs from when accumulate is true above
-            pDst[1] = clamp16(rt >> 12); // differs from when accumulate is true above
+            pDst[0] = clamp16(lt >> 13); // differs from when accumulate is true above
+            pDst[1] = clamp16(rt >> 13); // differs from when accumulate is true above
             pSrc += 6;
             pDst += 2;
             numFrames--;
@@ -1004,8 +1004,8 @@
             // FR + centerPlusLfeContrib + SR + RR
             rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[7] << 12) + (pSrc[5] << 12);
             //accumulate in destination
-            pDst[0] = clamp16(pDst[0] + (lt >> 12));
-            pDst[1] = clamp16(pDst[1] + (rt >> 12));
+            pDst[0] = clamp16(pDst[0] + (lt >> 13));
+            pDst[1] = clamp16(pDst[1] + (rt >> 13));
             pSrc += 8;
             pDst += 2;
             numFrames--;
@@ -1020,8 +1020,8 @@
             // FR + centerPlusLfeContrib + SR + RR
             rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[7] << 12) + (pSrc[5] << 12);
             // store in destination
-            pDst[0] = clamp16(lt >> 12); // differs from when accumulate is true above
-            pDst[1] = clamp16(rt >> 12); // differs from when accumulate is true above
+            pDst[0] = clamp16(lt >> 13); // differs from when accumulate is true above
+            pDst[1] = clamp16(rt >> 13); // differs from when accumulate is true above
             pSrc += 8;
             pDst += 2;
             numFrames--;
@@ -1130,8 +1130,8 @@
             lt += centersLfeContrib;
             rt += centersLfeContrib;
             // accumulate in destination
-            pDst[0] = clamp16(pDst[0] + (lt >> 12));
-            pDst[1] = clamp16(pDst[1] + (rt >> 12));
+            pDst[0] = clamp16(pDst[0] + (lt >> 13));
+            pDst[1] = clamp16(pDst[1] + (rt >> 13));
             pSrc += numChan;
             pDst += 2;
             numFrames--;
@@ -1159,8 +1159,8 @@
             lt += centersLfeContrib;
             rt += centersLfeContrib;
             // store in destination
-            pDst[0] = clamp16(lt >> 12); // differs from when accumulate is true above
-            pDst[1] = clamp16(rt >> 12); // differs from when accumulate is true above
+            pDst[0] = clamp16(lt >> 13); // differs from when accumulate is true above
+            pDst[1] = clamp16(rt >> 13); // differs from when accumulate is true above
             pSrc += numChan;
             pDst += 2;
             numFrames--;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index b2f1746..c4743a1 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -3472,11 +3472,14 @@
 
                     mCodec->signalError(OMX_ErrorUndefined, err);
 
-                    // This is technically not correct, since we were unable
-                    // to allocate output buffers and therefore the output port
-                    // remains disabled. It is necessary however to allow us
-                    // to shutdown the codec properly.
-                    mCodec->changeState(mCodec->mExecutingState);
+                    // This is technically not correct, but appears to be
+                    // the only way to free the component instance.
+                    // Controlled transitioning from excecuting->idle
+                    // and idle->loaded seem impossible probably because
+                    // the output port never finishes re-enabling.
+                    mCodec->mShutdownInProgress = true;
+                    mCodec->mKeepComponentAllocated = false;
+                    mCodec->changeState(mCodec->mLoadedState);
                 }
 
                 return true;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 85fbcdf..755b502 100755
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -2811,8 +2811,8 @@
     mOwner->beginBox("stsz");
     mOwner->writeInt32(0);  // version=0, flags=0
     if (mSamplesHaveSameSize) {
-        List<uint32_t *>::iterator it = mSampleSizes.begin();
-        mOwner->writeInt32((*it)[0]);  // default sample size
+        CHECK(mCurrentSampleSizeArr != 0);
+        mOwner->write(mCurrentSampleSizeArr, 4, 1);  // default sample size
     } else {
         mOwner->writeInt32(0);
     }
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 66111dc..baabd37 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -2475,7 +2475,12 @@
                 } else {
                     err = allocateBuffersOnPort(portIndex);
                     if (err != OK) {
-                        CODEC_LOGE("allocateBuffersOnPort failed (err = %d)", err);
+                        CODEC_LOGE("allocateBuffersOnPort (%s) failed "
+                                   "(err = %d)",
+                                   portIndex == kPortIndexInput
+                                        ? "input" : "output",
+                                   err);
+
                         setState(ERROR);
                     }
                 }
@@ -3643,7 +3648,7 @@
 }
 
 status_t OMXCodec::stop() {
-    CODEC_LOGV("stop mState=%d", mState);
+    CODEC_LOGI("stop mState=%d", mState);
 
     Mutex::Autolock autoLock(mLock);
 
@@ -3658,14 +3663,33 @@
 
         case ERROR:
         {
-            OMX_STATETYPE state = OMX_StateInvalid;
-            status_t err = mOMX->getState(mNode, &state);
-            CHECK_EQ(err, (status_t)OK);
-
-            if (state != OMX_StateExecuting) {
+            if (mPortStatus[kPortIndexOutput] == ENABLING) {
+                // Codec is in a wedged state (technical term)
+                // We've seen an output port settings change from the codec,
+                // We've disabled the output port, then freed the output
+                // buffers, initiated re-enabling the output port but
+                // failed to reallocate the output buffers.
+                // There doesn't seem to be a way to orderly transition
+                // from executing->idle and idle->loaded now that the
+                // output port hasn't been reenabled yet...
+                // Simply free as many resources as we can and pretend
+                // that we're in LOADED state so that the destructor
+                // will free the component instance without asserting.
+                freeBuffersOnPort(kPortIndexInput, true /* onlyThoseWeOwn */);
+                freeBuffersOnPort(kPortIndexOutput, true /* onlyThoseWeOwn */);
+                setState(LOADED);
                 break;
+            } else {
+                OMX_STATETYPE state = OMX_StateInvalid;
+                status_t err = mOMX->getState(mNode, &state);
+                CHECK_EQ(err, (status_t)OK);
+
+                if (state != OMX_StateExecuting) {
+                    break;
+                }
+                // else fall through to the idling code
             }
-            // else fall through to the idling code
+
             isError = true;
         }
 
@@ -3724,9 +3748,10 @@
         mLeftOverBuffer = NULL;
     }
 
+    CODEC_LOGI("stopping in state %d", mState);
     mSource->stop();
 
-    CODEC_LOGV("stopped in state %d", mState);
+    CODEC_LOGI("stopped in state %d", mState);
 
     return OK;
 }
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 68be7a7..57d7089 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -474,19 +474,15 @@
 
         ALOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
         if (sessionId != NULL && *sessionId != AUDIO_SESSION_OUTPUT_MIX) {
+            // check if an effect chain with the same session ID is present on another
+            // output thread and move it here.
             for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
                 sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
                 if (mPlaybackThreads.keyAt(i) != output) {
-                    // prevent same audio session on different output threads
                     uint32_t sessions = t->hasAudioSession(*sessionId);
-                    if (sessions & PlaybackThread::TRACK_SESSION) {
-                        ALOGE("createTrack() session ID %d already in use", *sessionId);
-                        lStatus = BAD_VALUE;
-                        goto Exit;
-                    }
-                    // check if an effect with same session ID is waiting for a track to be created
                     if (sessions & PlaybackThread::EFFECT_SESSION) {
                         effectThread = t.get();
+                        break;
                     }
                 }
             }
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 92d1223..bf07f8b 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -410,6 +410,7 @@
 status_t CameraService::Client::lock() {
     int callingPid = getCallingPid();
     LOG1("lock (pid %d)", callingPid);
+    Mutex::Autolock ilock(mICameraLock);
     Mutex::Autolock lock(mLock);
 
     // lock camera to this client if the the camera is unlocked
@@ -425,6 +426,7 @@
 status_t CameraService::Client::unlock() {
     int callingPid = getCallingPid();
     LOG1("unlock (pid %d)", callingPid);
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
 
     // allow anyone to use camera (after they lock the camera)
@@ -447,6 +449,7 @@
 status_t CameraService::Client::connect(const sp<ICameraClient>& client) {
     int callingPid = getCallingPid();
     LOG1("connect E (pid %d)", callingPid);
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
 
     if (mClientPid != 0 && checkPid() != NO_ERROR) {
@@ -482,6 +485,7 @@
 void CameraService::Client::disconnect() {
     int callingPid = getCallingPid();
     LOG1("disconnect E (pid %d)", callingPid);
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
 
     if (checkPid() != NO_ERROR) {
@@ -526,6 +530,7 @@
 
 status_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder,
         const sp<ANativeWindow>& window) {
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
     status_t result = checkPidAndHardware();
     if (result != NO_ERROR) return result;
@@ -597,6 +602,7 @@
 // preview are handled.
 void CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
     LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
     if (checkPidAndHardware() != NO_ERROR) return;
 
@@ -623,6 +629,7 @@
 // start preview or recording
 status_t CameraService::Client::startCameraMode(camera_mode mode) {
     LOG1("startCameraMode(%d)", mode);
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
     status_t result = checkPidAndHardware();
     if (result != NO_ERROR) return result;
@@ -696,6 +703,7 @@
 // stop preview mode
 void CameraService::Client::stopPreview() {
     LOG1("stopPreview (pid %d)", getCallingPid());
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
     if (checkPidAndHardware() != NO_ERROR) return;
 
@@ -709,6 +717,7 @@
 // stop recording mode
 void CameraService::Client::stopRecording() {
     LOG1("stopRecording (pid %d)", getCallingPid());
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
     if (checkPidAndHardware() != NO_ERROR) return;
 
@@ -721,6 +730,7 @@
 
 // release a recording frame
 void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
     if (checkPidAndHardware() != NO_ERROR) return;
     mHardware->releaseRecordingFrame(mem);
@@ -729,6 +739,7 @@
 status_t CameraService::Client::storeMetaDataInBuffers(bool enabled)
 {
     LOG1("storeMetaDataInBuffers: %s", enabled? "true": "false");
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
     if (checkPidAndHardware() != NO_ERROR) {
         return UNKNOWN_ERROR;
@@ -739,6 +750,7 @@
 bool CameraService::Client::previewEnabled() {
     LOG1("previewEnabled (pid %d)", getCallingPid());
 
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
     if (checkPidAndHardware() != NO_ERROR) return false;
     return mHardware->previewEnabled();
@@ -747,6 +759,7 @@
 bool CameraService::Client::recordingEnabled() {
     LOG1("recordingEnabled (pid %d)", getCallingPid());
 
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
     if (checkPidAndHardware() != NO_ERROR) return false;
     return mHardware->recordingEnabled();
@@ -755,6 +768,7 @@
 status_t CameraService::Client::autoFocus() {
     LOG1("autoFocus (pid %d)", getCallingPid());
 
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
     status_t result = checkPidAndHardware();
     if (result != NO_ERROR) return result;
@@ -765,6 +779,7 @@
 status_t CameraService::Client::cancelAutoFocus() {
     LOG1("cancelAutoFocus (pid %d)", getCallingPid());
 
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
     status_t result = checkPidAndHardware();
     if (result != NO_ERROR) return result;
@@ -776,26 +791,30 @@
 status_t CameraService::Client::takePicture(int msgType) {
     LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType);
 
-    Mutex::Autolock lock(mLock);
-    status_t result = checkPidAndHardware();
-    if (result != NO_ERROR) return result;
+    Mutex::Autolock iLock(mICameraLock);
+    int picMsgType = 0;
+    { // scope for lock
+        Mutex::Autolock lock(mLock);
+        status_t result = checkPidAndHardware();
+        if (result != NO_ERROR) return result;
 
-    if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
-        (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
-        ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
-                " cannot be both enabled");
-        return BAD_VALUE;
+        if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
+                (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
+            ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
+                    " cannot be both enabled");
+            return BAD_VALUE;
+        }
+
+        // We only accept picture related message types
+        // and ignore other types of messages for takePicture().
+        picMsgType = msgType
+                & (CAMERA_MSG_SHUTTER |
+                        CAMERA_MSG_POSTVIEW_FRAME |
+                        CAMERA_MSG_RAW_IMAGE |
+                        CAMERA_MSG_RAW_IMAGE_NOTIFY |
+                        CAMERA_MSG_COMPRESSED_IMAGE);
+
     }
-
-    // We only accept picture related message types
-    // and ignore other types of messages for takePicture().
-    int picMsgType = msgType
-                        & (CAMERA_MSG_SHUTTER |
-                           CAMERA_MSG_POSTVIEW_FRAME |
-                           CAMERA_MSG_RAW_IMAGE |
-                           CAMERA_MSG_RAW_IMAGE_NOTIFY |
-                           CAMERA_MSG_COMPRESSED_IMAGE);
-
     enableMsgType(picMsgType);
 
     return mHardware->takePicture();
@@ -805,6 +824,7 @@
 status_t CameraService::Client::setParameters(const String8& params) {
     LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());
 
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
     status_t result = checkPidAndHardware();
     if (result != NO_ERROR) return result;
@@ -815,6 +835,7 @@
 
 // get preview/capture parameters - key/value pairs
 String8 CameraService::Client::getParameters() const {
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
     if (checkPidAndHardware() != NO_ERROR) return String8();
 
@@ -855,6 +876,7 @@
 status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
     LOG1("sendCommand (pid %d)", getCallingPid());
     int orientation;
+    Mutex::Autolock iLock(mICameraLock);
     Mutex::Autolock lock(mLock);
     status_t result = checkPidAndHardware();
     if (result != NO_ERROR) return result;
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 5b63399..95ac197 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -190,6 +190,11 @@
 
         // Ensures atomicity among the public methods
         mutable Mutex                   mLock;
+        // A lock to synchronize access through the ICamera binder
+        // interface. The entire binder call should be done with mICameraLock
+        // locked, to serialize ICamera access, even when mLock is disabled for
+        // calls to the HAL.
+        mutable Mutex                   mICameraLock;
         // This is a binder of Surface or SurfaceTexture.
         sp<IBinder>                     mSurface;
         sp<ANativeWindow>               mPreviewWindow;