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

Commit 05adabb3 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
Bug: 285886910
Test: Camera CTS
Change-Id: I3a78fa566cfe72dbfa1bc5721854823243e03f23
parent 3e866e7e
Loading
Loading
Loading
Loading
+69 −59
Original line number Diff line number Diff line
@@ -716,7 +716,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {

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

            try {
                mPreviewExtender.onDeInit();
@@ -1252,6 +1252,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
        @Override
        public void onImageAvailable(ImageReader reader) {
            Image img;
            synchronized (mInterfaceLock) {
                try {
                    img = reader.acquireNextImage();
                } catch (IllegalStateException e) {
@@ -1266,7 +1267,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 {
@@ -1274,13 +1276,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) {
@@ -1300,10 +1304,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) {
@@ -1319,9 +1326,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();
@@ -1336,6 +1345,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
                mImageListenerMap.clear();
            }
        }
    }

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