Merge "ImageWriter: always detach the origially attached buffer" into rvc-dev am: baa0a1faa3

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11988333

Change-Id: If6b4abe5ca7397c01f1108b12c249795c26d915e
This commit is contained in:
TreeHugger Robot
2020-06-26 16:21:22 +00:00
committed by Automerger Merge Worker

View File

@@ -86,6 +86,14 @@ public:
void setBufferHeight(int height) { mHeight = height; } void setBufferHeight(int height) { mHeight = height; }
int getBufferHeight() { return mHeight; } int getBufferHeight() { return mHeight; }
void queueAttachedFlag(bool isAttached) {
Mutex::Autolock l(mAttachedFlagQueueLock);
mAttachedFlagQueue.push_back(isAttached);
}
void dequeueAttachedFlag() {
Mutex::Autolock l(mAttachedFlagQueueLock);
mAttachedFlagQueue.pop_back();
}
private: private:
static JNIEnv* getJNIEnv(bool* needsDetach); static JNIEnv* getJNIEnv(bool* needsDetach);
static void detachJNI(); static void detachJNI();
@@ -136,6 +144,11 @@ private:
}; };
static BufferDetacher sBufferDetacher; static BufferDetacher sBufferDetacher;
// Buffer queue guarantees both producer and consumer side buffer flows are
// in order. See b/19977520. As a result, we can use a queue here.
Mutex mAttachedFlagQueueLock;
std::deque<bool> mAttachedFlagQueue;
}; };
JNIImageWriterContext::BufferDetacher JNIImageWriterContext::sBufferDetacher; JNIImageWriterContext::BufferDetacher JNIImageWriterContext::sBufferDetacher;
@@ -265,11 +278,23 @@ void JNIImageWriterContext::onBufferReleased() {
ALOGV("%s: buffer released", __FUNCTION__); ALOGV("%s: buffer released", __FUNCTION__);
bool needsDetach = false; bool needsDetach = false;
JNIEnv* env = getJNIEnv(&needsDetach); JNIEnv* env = getJNIEnv(&needsDetach);
bool bufferIsAttached = false;
{
Mutex::Autolock l(mAttachedFlagQueueLock);
if (!mAttachedFlagQueue.empty()) {
bufferIsAttached = mAttachedFlagQueue.front();
mAttachedFlagQueue.pop_front();
} else {
ALOGW("onBufferReleased called with no attached flag queued");
}
}
if (env != NULL) { if (env != NULL) {
// Detach the buffer every time when a buffer consumption is done, // Detach the buffer every time when a buffer consumption is done,
// need let this callback give a BufferItem, then only detach if it was attached to this // need let this callback give a BufferItem, then only detach if it was attached to this
// Writer. Do the detach unconditionally for opaque format now. see b/19977520 // Writer. see b/19977520
if (mFormat == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) { if (mFormat == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED || bufferIsAttached) {
sBufferDetacher.detach(mProducer); sBufferDetacher.detach(mProducer);
} }
@@ -622,10 +647,16 @@ static void ImageWriter_queueImage(JNIEnv* env, jobject thiz, jlong nativeCtx, j
return; return;
} }
// Finally, queue input buffer // Finally, queue input buffer.
//
// Because onBufferReleased may be called before queueBuffer() returns,
// queue the "attached" flag before calling queueBuffer. In case
// queueBuffer() fails, remove it from the queue.
ctx->queueAttachedFlag(false);
res = anw->queueBuffer(anw.get(), buffer, fenceFd); res = anw->queueBuffer(anw.get(), buffer, fenceFd);
if (res != OK) { if (res != OK) {
ALOGE("%s: Queue buffer failed: %s (%d)", __FUNCTION__, strerror(-res), res); ALOGE("%s: Queue buffer failed: %s (%d)", __FUNCTION__, strerror(-res), res);
ctx->dequeueAttachedFlag();
switch (res) { switch (res) {
case NO_INIT: case NO_INIT:
jniThrowException(env, "java/lang/IllegalStateException", jniThrowException(env, "java/lang/IllegalStateException",
@@ -720,10 +751,16 @@ static jint ImageWriter_attachAndQueueImage(JNIEnv* env, jobject thiz, jlong nat
} }
// Step 3. Queue Image. // Step 3. Queue Image.
//
// Because onBufferReleased may be called before queueBuffer() returns,
// queue the "attached" flag before calling queueBuffer. In case
// queueBuffer() fails, remove it from the queue.
ctx->queueAttachedFlag(true);
res = anw->queueBuffer(anw.get(), buffer->mGraphicBuffer.get(), /*fenceFd*/ res = anw->queueBuffer(anw.get(), buffer->mGraphicBuffer.get(), /*fenceFd*/
-1); -1);
if (res != OK) { if (res != OK) {
ALOGE("%s: Queue buffer failed: %s (%d)", __FUNCTION__, strerror(-res), res); ALOGE("%s: Queue buffer failed: %s (%d)", __FUNCTION__, strerror(-res), res);
ctx->dequeueAttachedFlag();
switch (res) { switch (res) {
case NO_INIT: case NO_INIT:
jniThrowException(env, "java/lang/IllegalStateException", jniThrowException(env, "java/lang/IllegalStateException",