Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb039c3f authored by Avichal Rakesh's avatar Avichal Rakesh
Browse files

ImageWriter: remove mCloseLock guard from queue and dequeue operations

mCloseLock currently guards #queueInputImage, #dequeueInputImage, and
#postEventFromNative. However, there have been cases reported where a
contention between #postEventFromNative and #queueInputImage would lead
to a deadlock. This CL removes the mCloseLock guard from #queueInputImage
and #dequeInputImage as the native implementations are already
synchronized on `this` and there are no reported bugs from race
conditions in those two functions.

It also drops the mCloseLock guard from #postEventFromNative and moves
the responsibility of ensuring ImageWriter is valid to the
ListenerHandler. This ensures that mCloseLock is never in contention
in the JNI thread that calls #postEventFromNative.

#close() is still protected by mCloseLock to prevent multiple
simultaneous closes.

Bug: 263395157
Test: Existing ImageWriter tests pass
      Ran the sequence that led to deadlock 30 times without a single
      deadlock.
Change-Id: I5b0d367cce7df9401386e5a53c5e9b539d8c1f40
parent da209b10
Loading
Loading
Loading
Loading
+52 −58
Original line number Diff line number Diff line
@@ -452,7 +452,6 @@ public class ImageWriter implements AutoCloseable {
     * @see Image#close
     */
    public Image dequeueInputImage() {
        synchronized (mCloseLock) {
        if (mDequeuedImages.size() >= mMaxImages) {
            throw new IllegalStateException(
                    "Already dequeued max number of Images " + mMaxImages);
@@ -463,7 +462,6 @@ public class ImageWriter implements AutoCloseable {
        newImage.mIsImageValid = true;
        return newImage;
    }
    }

    /**
     * <p>
@@ -521,7 +519,6 @@ public class ImageWriter implements AutoCloseable {
            throw new IllegalArgumentException("image shouldn't be null");
        }

        synchronized (mCloseLock) {
        boolean ownedByMe = isImageOwnedByMe(image);
        if (ownedByMe && !(((WriterSurfaceImage) image).mIsImageValid)) {
            throw new IllegalStateException("Image from ImageWriter is invalid");
@@ -568,7 +565,6 @@ public class ImageWriter implements AutoCloseable {
            wi.mIsImageValid = false;
        }
    }
    }

    /**
     * Get the ImageWriter format.
@@ -702,11 +698,11 @@ public class ImageWriter implements AutoCloseable {
     */
    @Override
    public void close() {
        setOnImageReleasedListener(null, null);
        synchronized (mCloseLock) {
            if (!mIsWriterValid) {
                return;
            }
            setOnImageReleasedListener(null, null);
            for (Image image : mDequeuedImages) {
                image.close();
            }
@@ -836,14 +832,12 @@ public class ImageWriter implements AutoCloseable {
        }

        final Handler handler;
        final boolean isWriterValid;
        synchronized (iw.mListenerLock) {
            handler = iw.mListenerHandler;
        }
        synchronized (iw.mCloseLock) {
            isWriterValid = iw.mIsWriterValid;
        }
        if (handler != null && isWriterValid) {

        if (handler != null) {
            // The ListenerHandler will take care of ensuring that the parent ImageWriter is valid
            handler.sendEmptyMessage(0);
        }
    }