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

Commit 7875a886 authored by Eino-Ville Talvala's avatar Eino-Ville Talvala
Browse files

Camera2: Fix null-listener capture for CameraCaptureSession

Correctly allow null listener/handler when invoked on a thread with no
looper; otherwise all capture/repeating requests will fail even if listener
is null.

Change-Id: I4c64c81ad7f14b5cb309b4f92822cb50dbd74ba6
parent 6720be4e
Loading
Loading
Loading
Loading
+12 −9
Original line number Diff line number Diff line
@@ -141,7 +141,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
        checkNotClosed();
        checkLegalToCapture();

        handler = checkHandler(handler);
        handler = checkHandler(handler, listener);

        if (VERBOSE) {
            Log.v(TAG, "capture - request " + request + ", listener " + listener + " handler" +
@@ -164,7 +164,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
        checkNotClosed();
        checkLegalToCapture();

        handler = checkHandler(handler);
        handler = checkHandler(handler, listener);

        if (VERBOSE) {
            CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
@@ -186,7 +186,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
        checkNotClosed();
        checkLegalToCapture();

        handler = checkHandler(handler);
        handler = checkHandler(handler, listener);

        if (VERBOSE) {
            Log.v(TAG, "setRepeatingRequest - request " + request + ", listener " + listener +
@@ -209,7 +209,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
        checkNotClosed();
        checkLegalToCapture();

        handler = checkHandler(handler);
        handler = checkHandler(handler, listener);

        if (VERBOSE) {
            CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
@@ -379,15 +379,18 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
         * - then forward the call to a handler
         * - then finally invoke the destination method on the session listener object
         */
        Dispatchable<CaptureListener> userListenerSink;
        if (listener == null) { // OK: API allows the user to not specify a listener
            userListenerSink = new NullDispatcher<>();
        } else {
            userListenerSink = new InvokeDispatcher<>(listener);
        if (listener == null) {
            // OK: API allows the user to not specify a listener, and the handler may
            // also be null in that case. Collapse whole dispatch chain to only call the local
            // listener
            return localListener;
        }

        InvokeDispatcher<CameraDevice.CaptureListener> localSink =
                new InvokeDispatcher<>(localListener);

        InvokeDispatcher<CaptureListener> userListenerSink =
                new InvokeDispatcher<>(listener);
        HandlerDispatcher<CaptureListener> handlerPassthrough =
                new HandlerDispatcher<>(userListenerSink, handler);
        DuckTypingDispatcher<CameraDevice.CaptureListener, CaptureListener> duckToSession
+13 −3
Original line number Diff line number Diff line
@@ -543,9 +543,7 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {

        // Need a valid handler, or current thread needs to have a looper, if
        // listener is valid
        if (listener != null) {
            handler = checkHandler(handler);
        }
        handler = checkHandler(handler, listener);

        // Make sure that there all requests have at least 1 surface; all surfaces are non-null
        for (CaptureRequest request : requestList) {
@@ -1155,6 +1153,18 @@ public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
        return handler;
    }

    /**
     * Default handler management, conditional on there being a listener.
     *
     * <p>If the listener isn't null, check the handler, otherwise pass it through.</p>
     */
    static <T> Handler checkHandler(Handler handler, T listener) {
        if (listener != null) {
            return checkHandler(handler);
        }
        return handler;
    }

    private void checkIfCameraClosedOrInError() throws CameraAccessException {
        if (mInError) {
            throw new CameraAccessException(CameraAccessException.CAMERA_ERROR,