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

Commit 67e4da3f authored by Igor Murashkin's avatar Igor Murashkin Committed by Android Git Automerger
Browse files

am d3edd1c2: am ba164dfb: Merge "camera2: Fix race conditions and deadlocks...

am d3edd1c2: am ba164dfb: Merge "camera2: Fix race conditions and deadlocks around configuration" into lmp-dev

* commit 'd3edd1c2f2c6c4c78d515a8f70273b9bc7f27e68':
  camera2: Fix race conditions and deadlocks around configuration
parents a552e984 e014f23e
Loading
Loading
Loading
Loading
+25 −18
Original line number Diff line number Diff line
@@ -633,6 +633,10 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
        @Override
        public void onDrained() {
            if (VERBOSE) Log.v(TAG, mIdString + "onIdleDrained");

            // Take device lock before session lock so that we can call back into device
            // without causing a deadlock
            synchronized (mDeviceImpl.mInterfaceLock) {
                synchronized (CameraCaptureSessionImpl.this) {
                /*
                 * The device is now IDLE, and has settled. It will not transition to
@@ -642,7 +646,8 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
                 *
                 * This operation is idempotent; a session will not be closed twice.
                 */
                if (VERBOSE) Log.v(TAG, mIdString + "Session drain complete, skip unconfigure: " +
                    if (VERBOSE)
                        Log.v(TAG, mIdString + "Session drain complete, skip unconfigure: " +
                                mSkipUnconfigure);

                    // Fast path: A new capture session has replaced this one; don't unconfigure.
@@ -655,7 +660,8 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {

                    try {
                        mUnconfigureDrainer.taskStarted();
                    mDeviceImpl.configureOutputsChecked(null); // begin transition to unconfigured
                        mDeviceImpl
                                .configureOutputsChecked(null); // begin transition to unconfigured
                    } catch (CameraAccessException e) {
                        // OK: do not throw checked exceptions.
                        Log.e(TAG, mIdString + "Exception while configuring outputs: ", e);
@@ -667,6 +673,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
                }
            }
        }
    }

    private class UnconfigureDrainListener implements TaskDrainer.DrainListener {
        @Override
+1 −1
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ public class CameraDeviceImpl extends CameraDevice {
    private ICameraDeviceUser mRemoteDevice;

    // Lock to synchronize cross-thread access to device public interface
    private final Object mInterfaceLock = new Object();
    final Object mInterfaceLock = new Object(); // access from this class and Session only!
    private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks();

    private final StateCallback mDeviceCallback;
+15 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ public class CameraDeviceState {
        void onError(int errorCode, RequestHolder holder);
        void onConfiguring();
        void onIdle();
        void onBusy();
        void onCaptureStarted(RequestHolder holder, long timestamp);
        void onCaptureResult(CameraMetadataNative result, RequestHolder holder);
    }
@@ -217,6 +218,20 @@ public class CameraDeviceState {
            }
            Log.i(TAG, "Legacy camera service transitioning to state " + stateName);
        }

        // If we transitioned into a non-IDLE/non-ERROR state then mark the device as busy
        if(newState != STATE_ERROR && newState != STATE_IDLE) {
            if (mCurrentState != newState && mCurrentHandler != null &&
                    mCurrentListener != null) {
                mCurrentHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mCurrentListener.onBusy();
                    }
                });
            }
        }

        switch(newState) {
            case STATE_ERROR:
                if (mCurrentState != STATE_ERROR && mCurrentHandler != null &&
+3 −0
Original line number Diff line number Diff line
@@ -113,6 +113,9 @@ public class GLThreadManager {
                    case MSG_ALLOW_FRAMES:
                        mDroppingFrames = false;
                        break;
                    case RequestHandlerThread.MSG_POKE_IDLE_HANDLER:
                        // OK: Ignore message.
                        break;
                    default:
                        Log.e(TAG, "Unhandled message " + msg.what + " on GLThread.");
                        break;
+33 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.impl.CameraDeviceImpl;
import android.hardware.camera2.impl.CaptureResultExtras;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.params.StreamConfiguration;
@@ -95,7 +96,25 @@ public class LegacyCameraDevice implements AutoCloseable {
            new CameraDeviceState.CameraDeviceStateListener() {
        @Override
        public void onError(final int errorCode, final RequestHolder holder) {
            if (DEBUG) {
                Log.d(TAG, "onError called, errorCode = " + errorCode);
            }
            switch (errorCode) {
                /*
                 * Only be considered idle if we hit a fatal error
                 * and no further requests can be processed.
                 */
                case CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DISCONNECTED:
                case CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_SERVICE:
                case CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE: {
                    mIdle.open();

                    if (DEBUG) {
                        Log.d(TAG, "onError - opening idle");
                    }
                }
            }

            final CaptureResultExtras extras = getExtrasFromRequest(holder);
            mResultHandler.post(new Runnable() {
                @Override
@@ -124,6 +143,10 @@ public class LegacyCameraDevice implements AutoCloseable {

        @Override
        public void onIdle() {
            if (DEBUG) {
                Log.d(TAG, "onIdle called");
            }

            mIdle.open();

            mResultHandler.post(new Runnable() {
@@ -142,6 +165,15 @@ public class LegacyCameraDevice implements AutoCloseable {
            });
        }

        @Override
        public void onBusy() {
            mIdle.close();

            if (DEBUG) {
                Log.d(TAG, "onBusy called");
            }
        }

        @Override
        public void onCaptureStarted(final RequestHolder holder, final long timestamp) {
            final CaptureResultExtras extras = getExtrasFromRequest(holder);
Loading