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

Commit 524d16f7 authored by Ruben Brunk's avatar Ruben Brunk Committed by Android Git Automerger
Browse files

am 979c03a2: Merge "camera2: Avoid spurious IDLE transitions." into lmp-dev

* commit '979c03a21bc346ddbfbfcf5d1d4239e5cdf30302':
  camera2: Avoid spurious IDLE transitions.
parents a8b449b8 c90b5ebb
Loading
Loading
Loading
Loading
+21 −21
Original line number Diff line number Diff line
@@ -16,8 +16,8 @@

package android.hardware.camera2.legacy;

import android.hardware.camera2.impl.CameraDeviceImpl;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.utils.CameraBinderDecorator;
import android.os.Handler;
import android.util.Log;

@@ -53,7 +53,7 @@ public class CameraDeviceState {
            "CAPTURING"};

    private int mCurrentState = STATE_UNCONFIGURED;
    private int mCurrentError = CameraBinderDecorator.NO_ERROR;
    private int mCurrentError = NO_CAPTURE_ERROR;

    private RequestHolder mCurrentRequest = null;

@@ -87,7 +87,7 @@ public class CameraDeviceState {
     * </p>
     *
     * @param error the error to set.  Should be one of the error codes defined in
     *      {@link android.hardware.camera2.utils.CameraBinderDecorator}.
     *      {@link CameraDeviceImpl.CameraDeviceCallbacks}.
     */
    public synchronized void setError(int error) {
        mCurrentError = error;
@@ -102,11 +102,11 @@ public class CameraDeviceState {
     * {@link CameraDeviceStateListener#onConfiguring()} will be called.
     * </p>
     *
     * @return {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
     * @return {@code false} if an error has occurred.
     */
    public synchronized int setConfiguring() {
    public synchronized boolean setConfiguring() {
        doStateTransition(STATE_CONFIGURING);
        return mCurrentError;
        return mCurrentError == NO_CAPTURE_ERROR;
    }

    /**
@@ -117,11 +117,11 @@ public class CameraDeviceState {
     * {@link CameraDeviceStateListener#onIdle()} will be called.
     * </p>
     *
     * @return {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
     * @return {@code false} if an error has occurred.
     */
    public synchronized int setIdle() {
    public synchronized boolean setIdle() {
        doStateTransition(STATE_IDLE);
        return mCurrentError;
        return mCurrentError == NO_CAPTURE_ERROR;
    }

    /**
@@ -137,13 +137,13 @@ public class CameraDeviceState {
     * @param captureError Report a recoverable error for a single request using a valid
     *                     error code for {@code ICameraDeviceCallbacks}, or
     *                     {@link #NO_CAPTURE_ERROR}
     * @return {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
     * @return {@code false} if an error has occurred.
     */
    public synchronized int setCaptureStart(final RequestHolder request, long timestamp,
    public synchronized boolean setCaptureStart(final RequestHolder request, long timestamp,
                                            int captureError) {
        mCurrentRequest = request;
        doStateTransition(STATE_CAPTURING, timestamp, captureError);
        return mCurrentError;
        return mCurrentError == NO_CAPTURE_ERROR;
    }

    /**
@@ -161,16 +161,16 @@ public class CameraDeviceState {
     * @param captureError Report a recoverable error for a single buffer or result using a valid
     *                     error code for {@code ICameraDeviceCallbacks}, or
     *                     {@link #NO_CAPTURE_ERROR}.
     * @return {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
     * @return {@code false} if an error has occurred.
     */
    public synchronized int setCaptureResult(final RequestHolder request,
    public synchronized boolean setCaptureResult(final RequestHolder request,
                                             final CameraMetadataNative result,
                                             final int captureError) {
        if (mCurrentState != STATE_CAPTURING) {
            Log.e(TAG, "Cannot receive result while in state: " + mCurrentState);
            mCurrentError = CameraBinderDecorator.INVALID_OPERATION;
            mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
            doStateTransition(STATE_ERROR);
            return mCurrentError;
            return mCurrentError == NO_CAPTURE_ERROR;
        }

        if (mCurrentHandler != null && mCurrentListener != null) {
@@ -190,7 +190,7 @@ public class CameraDeviceState {
                });
            }
        }
        return mCurrentError;
        return mCurrentError == NO_CAPTURE_ERROR;
    }

    /**
@@ -206,7 +206,7 @@ public class CameraDeviceState {
    }

    private void doStateTransition(int newState) {
        doStateTransition(newState, /*timestamp*/0, CameraBinderDecorator.NO_ERROR);
        doStateTransition(newState, /*timestamp*/0, NO_CAPTURE_ERROR);
    }

    private void doStateTransition(int newState, final long timestamp, final int error) {
@@ -233,7 +233,7 @@ public class CameraDeviceState {
            case STATE_CONFIGURING:
                if (mCurrentState != STATE_UNCONFIGURED && mCurrentState != STATE_IDLE) {
                    Log.e(TAG, "Cannot call configure while in state: " + mCurrentState);
                    mCurrentError = CameraBinderDecorator.INVALID_OPERATION;
                    mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
                    doStateTransition(STATE_ERROR);
                    break;
                }
@@ -255,7 +255,7 @@ public class CameraDeviceState {

                if (mCurrentState != STATE_CONFIGURING && mCurrentState != STATE_CAPTURING) {
                    Log.e(TAG, "Cannot call idle while in state: " + mCurrentState);
                    mCurrentError = CameraBinderDecorator.INVALID_OPERATION;
                    mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
                    doStateTransition(STATE_ERROR);
                    break;
                }
@@ -274,7 +274,7 @@ public class CameraDeviceState {
            case STATE_CAPTURING:
                if (mCurrentState != STATE_IDLE && mCurrentState != STATE_CAPTURING) {
                    Log.e(TAG, "Cannot call capture while in state: " + mCurrentState);
                    mCurrentError = CameraBinderDecorator.INVALID_OPERATION;
                    mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
                    doStateTransition(STATE_ERROR);
                    break;
                }
+46 −36
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.hardware.camera2.legacy;

import android.graphics.SurfaceTexture;
import android.hardware.camera2.impl.CameraDeviceImpl;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.Message;
@@ -42,6 +43,8 @@ public class GLThreadManager {

    private CaptureCollector mCaptureCollector;

    private final CameraDeviceState mDeviceState;

    private final SurfaceTextureRenderer mTextureRenderer;

    private final RequestHandlerThread mGLHandlerThread;
@@ -76,6 +79,7 @@ public class GLThreadManager {
            if (mCleanup) {
                return true;
            }
            try {
                switch (msg.what) {
                    case MSG_NEW_CONFIGURATION:
                        ConfigureHolder configure = (ConfigureHolder) msg.obj;
@@ -113,6 +117,10 @@ public class GLThreadManager {
                        Log.e(TAG, "Unhandled message " + msg.what + " on GLThread.");
                        break;
                }
            } catch (Exception e) {
                Log.e(TAG, "Received exception on GL render thread: ", e);
                mDeviceState.setError(CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
            }
            return true;
        }
    };
@@ -122,11 +130,13 @@ public class GLThreadManager {
     *
     * @param cameraId the camera id for this thread.
     * @param facing direction the camera is facing.
     * @param state {@link CameraDeviceState} to use for error handling.
     */
    public GLThreadManager(int cameraId, int facing) {
    public GLThreadManager(int cameraId, int facing, CameraDeviceState state) {
        mTextureRenderer = new SurfaceTextureRenderer(facing);
        TAG = String.format("CameraDeviceGLThread-%d", cameraId);
        mGLHandlerThread = new RequestHandlerThread(TAG, mGLHandlerCb);
        mDeviceState = state;
    }

    /**
+8 −6
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.params.StreamConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.utils.ArrayUtils;
import android.hardware.camera2.utils.CameraBinderDecorator;
import android.hardware.camera2.utils.LongParcelable;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.utils.CameraRuntimeException;
@@ -288,17 +289,18 @@ public class LegacyCameraDevice implements AutoCloseable {
            }
        }

        int error = mDeviceState.setConfiguring();
        if (error == NO_ERROR) {
        boolean success = false;
        if (mDeviceState.setConfiguring()) {
            mRequestThreadManager.configure(outputs);
            error = mDeviceState.setIdle();
            success = mDeviceState.setIdle();
        }

        if (error == NO_ERROR) {
        if (success) {
            mConfiguredSurfaces = outputs != null ? new ArrayList<>(outputs) : null;
        } else {
            return CameraBinderDecorator.INVALID_OPERATION;
        }

        return error;
        return CameraBinderDecorator.NO_ERROR;
    }

    /**
+30 −6
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ public class RequestThreadManager {
    private SurfaceTexture mDummyTexture;
    private Surface mDummySurface;

    private final Object mIdleLock = new Object();
    private final FpsCounter mPrevCounter = new FpsCounter("Incoming Preview");
    private final FpsCounter mRequestCounter = new FpsCounter("Incoming Requests");

@@ -173,6 +174,14 @@ public class RequestThreadManager {
        }
    }

    private final Camera.ErrorCallback mErrorCallback = new Camera.ErrorCallback() {
        @Override
        public void onError(int i, Camera camera) {
            Log.e(TAG, "Received error " + i + " from the Camera1 ErrorCallback");
            mDeviceState.setError(CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
        }
    };

    private final ConditionVariable mReceivedJpeg = new ConditionVariable(false);

    private final Camera.PictureCallback mJpegCallback = new Camera.PictureCallback() {
@@ -405,7 +414,7 @@ public class RequestThreadManager {

        // TODO: Detect and optimize single-output paths here to skip stream teeing.
        if (mGLThreadManager == null) {
            mGLThreadManager = new GLThreadManager(mCameraId, facing);
            mGLThreadManager = new GLThreadManager(mCameraId, facing, mDeviceState);
            mGLThreadManager.start();
        }
        mGLThreadManager.waitUntilStarted();
@@ -617,9 +626,20 @@ public class RequestThreadManager {
                                    CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
                            break;
                        }

                        synchronized (mIdleLock) {
                            // Retry the the request queue.
                            nextBurst = mRequestQueue.getNext();

                            // If we still have no queued requests, go idle.
                            if (nextBurst == null) {
                                mDeviceState.setIdle();
                                break;
                    } else {
                            }
                        }
                    }

                    if (nextBurst != null) {
                        // Queue another capture if we did not get the last burst.
                        handler.sendEmptyMessage(MSG_SUBMIT_CAPTURE_REQUEST);
                    }
@@ -831,6 +851,7 @@ public class RequestThreadManager {
        mFaceDetectMapper = new LegacyFaceDetectMapper(mCamera, mCharacteristics);
        mCaptureCollector = new CaptureCollector(MAX_IN_FLIGHT_REQUESTS, mDeviceState);
        mRequestThread = new RequestHandlerThread(name, mRequestHandlerCb);
        mCamera.setErrorCallback(mErrorCallback);
    }

    /**
@@ -883,8 +904,11 @@ public class RequestThreadManager {
    public int submitCaptureRequests(List<CaptureRequest> requests, boolean repeating,
            /*out*/LongParcelable frameNumber) {
        Handler handler = mRequestThread.waitAndGetHandler();
        int ret = mRequestQueue.submit(requests, repeating, frameNumber);
        int ret;
        synchronized (mIdleLock) {
            ret = mRequestQueue.submit(requests, repeating, frameNumber);
            handler.sendEmptyMessage(MSG_SUBMIT_CAPTURE_REQUEST);
        }
        return ret;
    }