Merge "audiopolicy: Update flag enum tables for the new flags" into mnc-dev
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index c6e45af..7452e4b 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -5242,6 +5242,7 @@
         if (err == OK) {
             info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
         } else {
+            ALOGE("queueBuffer failed in onOutputBufferDrained: %d", err);
             mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
             info->mStatus = BufferInfo::OWNED_BY_US;
             // keeping read fence as write fence to avoid clobbering
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index b576cd9..69f44ed 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2528,7 +2528,25 @@
         err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
         if (err == BAD_VALUE) {
             ALOGI("native window already connected. Assuming no change of surface");
-        } else if (err != OK) {
+        } else if (err == OK) {
+            // Require a fresh set of buffers after each connect by using a unique generation
+            // number. Rely on the fact that max supported process id by Linux is 2^22.
+            // PID is never 0 so we don't have to worry that we use the default generation of 0.
+            // TODO: come up with a unique scheme if other producers also set the generation number.
+            static uint32_t mSurfaceGeneration = 0;
+            uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1));
+            surface->setGenerationNumber(generation);
+            ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation);
+
+            // HACK: clear any free buffers. Remove when connect will automatically do this.
+            // This is needed as the consumer may be holding onto stale frames that it can reattach
+            // to this surface after disconnect/connect, and those free frames would inherit the new
+            // generation number. Disconnecting after setting a unique generation prevents this.
+            native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+            err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
+        }
+
+        if (err != OK) {
             ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
         }
     }
@@ -2538,6 +2556,8 @@
 status_t MediaCodec::disconnectFromSurface() {
     status_t err = OK;
     if (mSurface != NULL) {
+        // Resetting generation is not technically needed, but there is no need to keep it either
+        mSurface->setGenerationNumber(0);
         err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
         if (err != OK) {
             ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err);
diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp
index b402e48..52077a7 100644
--- a/media/libstagefright/MediaSync.cpp
+++ b/media/libstagefright/MediaSync.cpp
@@ -558,7 +558,6 @@
             return;
         }
     }
-    ++mNumOutstandingBuffers;
 
     // Acquire and detach the buffer from the input.
     BufferItem bufferItem;
@@ -567,6 +566,7 @@
         ALOGE("acquiring buffer from input failed (%d)", status);
         return;
     }
+    ++mNumOutstandingBuffers;
 
     ALOGV("acquired buffer %#llx from input", (long long)bufferItem.mGraphicBuffer->getId());
 
@@ -608,6 +608,7 @@
 
     // Attach and queue the buffer to the output.
     int slot;
+    mOutput->setGenerationNumber(bufferItem.mGraphicBuffer->getGenerationNumber());
     status_t status = mOutput->attachBuffer(&slot, bufferItem.mGraphicBuffer);
     ALOGE_IF(status != NO_ERROR, "attaching buffer to output failed (%d)", status);
     if (status == NO_ERROR) {
@@ -695,16 +696,13 @@
         ALOGE_IF(status != NO_ERROR, "releasing buffer to input failed (%d)", status);
     }
 
-    if (status != NO_ERROR) {
-        // TODO: do we need to try to return this buffer later?
-        return;
-    }
-
-    ALOGV("released buffer %#llx to input", (long long)oldBuffer->getId());
-
     // Notify any waiting onFrameAvailable calls.
     --mNumOutstandingBuffers;
     mReleaseCondition.signal();
+
+    if (status == NO_ERROR) {
+        ALOGV("released buffer %#llx to input", (long long)oldBuffer->getId());
+    }
 }
 
 void MediaSync::onAbandoned_l(bool isInput) {
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 19f0a37..1a7dc9d 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -111,6 +111,7 @@
         uint32_t bufferWidth,
         uint32_t bufferHeight,
         uint32_t bufferCount,
+        uint32_t consumerUsage,
         const sp<IGraphicBufferConsumer> &consumer) :
     mInitCheck(UNKNOWN_ERROR),
     mNodeInstance(nodeInstance),
@@ -154,16 +155,10 @@
         BufferQueue::createBufferQueue(&mProducer, &mConsumer);
         mConsumer->setConsumerName(name);
 
-        // query consumer usage bits from encoder, but always add HW_VIDEO_ENCODER
+        // use consumer usage bits queried from encoder, but always add HW_VIDEO_ENCODER
         // for backward compatibility.
-        uint32_t usageBits;
-        status_t err = mNodeInstance->getParameter(
-                (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, &usageBits, sizeof(usageBits));
-        if (err != OK) {
-            usageBits = 0;
-        }
-        usageBits |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
-        mConsumer->setConsumerUsageBits(usageBits);
+        consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
+        mConsumer->setConsumerUsageBits(consumerUsage);
 
         mInitCheck = mConsumer->setMaxAcquiredBufferCount(bufferCount);
         if (mInitCheck != NO_ERROR) {
@@ -848,13 +843,15 @@
         mConsumer->detachBuffer(id);
         mBufferSlot[id] = NULL;
 
-        mConsumer->attachBuffer(&id, buffer);
-        mConsumer->releaseBuffer(
-                id, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
+        if (mConsumer->attachBuffer(&id, buffer) == OK) {
+            mConsumer->releaseBuffer(
+                    id, 0, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
+        }
     } else {
         mConsumer->releaseBuffer(
                 id, frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, fence);
     }
+    id = -1; // invalidate id
     mNumBufferAcquired--;
 }
 
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index 3f64088..2f929d9 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -55,6 +55,7 @@
             uint32_t bufferWidth,
             uint32_t bufferHeight,
             uint32_t bufferCount,
+            uint32_t consumerUsage,
             const sp<IGraphicBufferConsumer> &consumer = NULL
     );
 
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 95549a4..9f1c5d8 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -834,7 +834,8 @@
     }
 
     CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x := %p",
-            portString(portIndex), portIndex, buffer, graphicBuffer->handle);
+            portString(portIndex), portIndex, buffer,
+            graphicBuffer == NULL ? NULL : graphicBuffer->handle);
     return OK;
 }
 
@@ -885,10 +886,18 @@
         return INVALID_OPERATION;
     }
 
+    uint32_t usageBits;
+    oerr = OMX_GetParameter(
+            mHandle, (OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits, &usageBits);
+    if (oerr != OMX_ErrorNone) {
+        usageBits = 0;
+    }
+
     sp<GraphicBufferSource> bufferSource = new GraphicBufferSource(this,
             def.format.video.nFrameWidth,
             def.format.video.nFrameHeight,
             def.nBufferCountActual,
+            usageBits,
             bufferConsumer);
 
     if ((err = bufferSource->initCheck()) != OK) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 4b55dad..9e73b5c 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -164,9 +164,17 @@
         return res;
     }
 
-    /** Start up request queue thread */
+    bool aeLockAvailable = false;
+    camera_metadata_ro_entry aeLockAvailableEntry;
+    res = find_camera_metadata_ro_entry(info.static_camera_characteristics,
+            ANDROID_CONTROL_AE_LOCK_AVAILABLE, &aeLockAvailableEntry);
+    if (res == OK && aeLockAvailableEntry.count > 0) {
+        aeLockAvailable = (aeLockAvailableEntry.data.u8[0] ==
+                ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE);
+    }
 
-    mRequestThread = new RequestThread(this, mStatusTracker, device);
+    /** Start up request queue thread */
+    mRequestThread = new RequestThread(this, mStatusTracker, device, aeLockAvailable);
     res = mRequestThread->run(String8::format("C3Dev-%d-ReqQueue", mId).string());
     if (res != OK) {
         SET_ERR_L("Unable to start request queue thread: %s (%d)",
@@ -2472,7 +2480,8 @@
 
 Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
         sp<StatusTracker> statusTracker,
-        camera3_device_t *hal3Device) :
+        camera3_device_t *hal3Device,
+        bool aeLockAvailable) :
         Thread(/*canCallJava*/false),
         mParent(parent),
         mStatusTracker(statusTracker),
@@ -2485,19 +2494,9 @@
         mLatestRequestId(NAME_NOT_FOUND),
         mCurrentAfTriggerId(0),
         mCurrentPreCaptureTriggerId(0),
-        mRepeatingLastFrameNumber(NO_IN_FLIGHT_REPEATING_FRAMES) {
+        mRepeatingLastFrameNumber(NO_IN_FLIGHT_REPEATING_FRAMES),
+        mAeLockAvailable(aeLockAvailable) {
     mStatusId = statusTracker->addComponent();
-
-    mAeLockAvailable = false;
-    sp<Camera3Device> p = parent.promote();
-    if (p != NULL) {
-        camera_metadata_ro_entry aeLockAvailable =
-                p->info().find(ANDROID_CONTROL_AE_LOCK_AVAILABLE);
-        if (aeLockAvailable.count > 0) {
-            mAeLockAvailable = (aeLockAvailable.data.u8[0] ==
-                    ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE);
-        }
-    }
 }
 
 void Camera3Device::RequestThread::setNotificationListener(
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index bb4bcc4..31b6132 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -389,7 +389,8 @@
 
         RequestThread(wp<Camera3Device> parent,
                 sp<camera3::StatusTracker> statusTracker,
-                camera3_device_t *hal3Device);
+                camera3_device_t *hal3Device,
+                bool aeLockAvailable);
 
         void     setNotificationListener(NotificationListener *listener);