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

Commit 9e8348b8 authored by Emilian Peev's avatar Emilian Peev
Browse files

Camera: Quit extension handler thread during release

The extension framework logic assumes that there will be
no further handler loop processing after the release
method quits the corresponding thread.
The current approach does allow pending messages to be
handled which depending on timing can result in data
races.
To avoid potential data races ensure that the handler
thread quits regardless of any queued messages.
Additionally synchronize access to 'mImageListenerMap'
in 'CameraOutputImageCallback'.

Bug: 278160240
Test: Camera CTS
Change-Id: I3a78fa566cfe72dbfa1bc5721854823243e03f23
parent 6cca48d2
Loading
Loading
Loading
Loading
+69 −59
Original line number Diff line number Diff line
@@ -828,7 +828,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {

        synchronized (mInterfaceLock) {
            mInternalRepeatingRequestEnabled = false;
            mHandlerThread.quitSafely();
            mHandlerThread.quit();

            try {
                mPreviewExtender.onDeInit();
@@ -1368,6 +1368,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
        @Override
        public void onImageAvailable(ImageReader reader) {
            Image img;
            synchronized (mInterfaceLock) {
                try {
                    img = reader.acquireNextImage();
                } catch (IllegalStateException e) {
@@ -1382,7 +1383,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {

                Long timestamp = img.getTimestamp();
                if (mImageListenerMap.containsKey(timestamp)) {
                Pair<Image, OnImageAvailableListener> entry = mImageListenerMap.remove(timestamp);
                    Pair<Image, OnImageAvailableListener> entry = mImageListenerMap.remove(
                            timestamp);
                    if (entry.second != null) {
                        entry.second.onImageAvailable(reader, img);
                    } else {
@@ -1390,13 +1392,15 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
                        img.close();
                    }
                } else {
                mImageListenerMap.put(img.getTimestamp(), new Pair<>(img, null));
                    mImageListenerMap.put(timestamp, new Pair<>(img, null));
                }

                notifyDroppedImages(timestamp);
            }
        }

        private void notifyDroppedImages(long timestamp) {
            synchronized (mInterfaceLock) {
                Set<Long> timestamps = mImageListenerMap.keySet();
                ArrayList<Long> removedTs = new ArrayList<>();
                for (long ts : timestamps) {
@@ -1416,10 +1420,13 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
                    mImageListenerMap.remove(ts);
                }
            }
        }

        public void registerListener(Long timestamp, OnImageAvailableListener listener) {
            synchronized (mInterfaceLock) {
                if (mImageListenerMap.containsKey(timestamp)) {
                Pair<Image, OnImageAvailableListener> entry = mImageListenerMap.remove(timestamp);
                    Pair<Image, OnImageAvailableListener> entry = mImageListenerMap.remove(
                            timestamp);
                    if (entry.first != null) {
                        listener.onImageAvailable(mImageReader, entry.first);
                        if (mOutOfBuffers) {
@@ -1435,9 +1442,11 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
                    mImageListenerMap.put(timestamp, new Pair<>(null, listener));
                }
            }
        }

        @Override
        public void close() {
            synchronized (mInterfaceLock) {
                for (Pair<Image, OnImageAvailableListener> entry : mImageListenerMap.values()) {
                    if (entry.first != null) {
                        entry.first.close();
@@ -1452,6 +1461,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
                mImageListenerMap.clear();
            }
        }
    }

    private class CloseRequestHandler extends CameraCaptureSession.CaptureCallback {
        private final CameraOutputImageCallback mImageCallback;