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

Commit ecfbb0a1 authored by Eino-Ville Talvala's avatar Eino-Ville Talvala Committed by Android (Google) Code Review
Browse files

Merge "Camera: Add proper buffer drop errors to LEGACY mode" into nyc-dev

parents 23c60f67 385f9e21
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ public class CameraDeviceState {
     * CameraDeviceStateListener callbacks to be called after state transitions.
     */
    public interface CameraDeviceStateListener {
        void onError(int errorCode, RequestHolder holder);
        void onError(int errorCode, Object errorArg, RequestHolder holder);
        void onConfiguring();
        void onIdle();
        void onBusy();
@@ -162,11 +162,12 @@ 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}.
     * @param captureErrorArg An argument for some error captureError codes.
     * @return {@code false} if an error has occurred.
     */
    public synchronized boolean setCaptureResult(final RequestHolder request,
            final CameraMetadataNative result,
                                             final int captureError) {
            final int captureError, final Object captureErrorArg) {
        if (mCurrentState != STATE_CAPTURING) {
            Log.e(TAG, "Cannot receive result while in state: " + mCurrentState);
            mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
@@ -179,7 +180,7 @@ public class CameraDeviceState {
                mCurrentHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        mCurrentListener.onError(captureError, request);
                        mCurrentListener.onError(captureError, captureErrorArg, request);
                    }
                });
            } else {
@@ -194,6 +195,11 @@ public class CameraDeviceState {
        return mCurrentError == NO_CAPTURE_ERROR;
    }

    public synchronized boolean setCaptureResult(final RequestHolder request,
            final CameraMetadataNative result) {
        return setCaptureResult(request, result, NO_CAPTURE_ERROR, /*errorArg*/null);
    }

    /**
     * Set the listener for state transition callbacks.
     *
@@ -239,7 +245,7 @@ public class CameraDeviceState {
                    mCurrentHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mCurrentListener.onError(mCurrentError, mCurrentRequest);
                            mCurrentListener.onError(mCurrentError, /*errorArg*/null, mCurrentRequest);
                        }
                    });
                }
@@ -299,7 +305,7 @@ public class CameraDeviceState {
                        mCurrentHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                mCurrentListener.onError(error, mCurrentRequest);
                                mCurrentListener.onError(error, /*errorArg*/null, mCurrentRequest);
                            }
                        });
                    } else {
+3 −7
Original line number Diff line number Diff line
@@ -480,19 +480,15 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
        }

        ArrayList<Surface> surfaces = null;
        SparseArray<Surface> surfaces = null;
        synchronized(mConfigureLock) {
            if (!mConfiguring) {
                String err = "Cannot end configure, no configuration change in progress.";
                Log.e(TAG, err);
                throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
            }
            int numSurfaces = mSurfaces.size();
            if (numSurfaces > 0) {
                surfaces = new ArrayList<>();
                for (int i = 0; i < numSurfaces; ++i) {
                    surfaces.add(mSurfaces.valueAt(i));
                }
            if (mSurfaces != null) {
                surfaces = mSurfaces.clone();
            }
            mConfiguring = false;
        }
+23 −17
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ import android.hardware.camera2.impl.CameraDeviceImpl;
import android.util.Log;
import android.util.MutableLong;
import android.util.Pair;

import android.view.Surface;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.TreeSet;
@@ -95,22 +95,28 @@ public class CaptureCollector {
                    } else {
                        // Send buffer dropped errors for each pending buffer if the request has
                        // started.
                        if (mFailedPreview) {
                            Log.w(TAG, "Preview buffers dropped for request: " +
                                    mRequest.getRequestId());
                            for (int i = 0; i < mRequest.numPreviewTargets(); i++) {
                        for (Surface targetSurface : mRequest.getRequest().getTargets() ) {
                            try {
                                if (mRequest.jpegType(targetSurface)) {
                                    if (mFailedJpeg) {
                                        CaptureCollector.this.mDeviceState.setCaptureResult(mRequest,
                                                /*result*/null,
                                        CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_BUFFER);
                            }
                                                CameraDeviceImpl.CameraDeviceCallbacks.
                                                        ERROR_CAMERA_BUFFER,
                                                targetSurface);
                                    }
                        if (mFailedJpeg) {
                            Log.w(TAG, "Jpeg buffers dropped for request: " +
                                    mRequest.getRequestId());
                            for (int i = 0; i < mRequest.numJpegTargets(); i++) {
                                } else {
                                    // preview buffer
                                    if (mFailedPreview) {
                                        CaptureCollector.this.mDeviceState.setCaptureResult(mRequest,
                                                /*result*/null,
                                        CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_BUFFER);
                                                CameraDeviceImpl.CameraDeviceCallbacks.
                                                        ERROR_CAMERA_BUFFER,
                                                targetSurface);
                                    }
                                }
                            } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
                                Log.e(TAG, "Unexpected exception when querying Surface: " + e);
                            }
                        }
                    }
+46 −9
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.os.ServiceSpecificException;
import android.util.Log;
import android.util.Pair;
import android.util.Size;
import android.util.SparseArray;
import android.view.Surface;

import java.util.ArrayList;
@@ -64,7 +65,7 @@ public class LegacyCameraDevice implements AutoCloseable {
    private final CameraCharacteristics mStaticCharacteristics;
    private final ICameraDeviceCallbacks mDeviceCallbacks;
    private final CameraDeviceState mDeviceState = new CameraDeviceState();
    private List<Surface> mConfiguredSurfaces;
    private SparseArray<Surface> mConfiguredSurfaces;
    private boolean mClosed = false;

    private final ConditionVariable mIdle = new ConditionVariable(/*open*/true);
@@ -89,13 +90,29 @@ public class LegacyCameraDevice implements AutoCloseable {
    public static final int NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW = 1;

    private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) {
        return getExtrasFromRequest(holder,
                /*errorCode*/CameraDeviceState.NO_CAPTURE_ERROR, /*errorArg*/null);
    }

    private CaptureResultExtras getExtrasFromRequest(RequestHolder holder,
            int errorCode, Object errorArg) {
        int errorStreamId = -1;
        if (errorCode == CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_BUFFER) {
            Surface errorTarget = (Surface) errorArg;
            int indexOfTarget = mConfiguredSurfaces.indexOfValue(errorTarget);
            if (indexOfTarget < 0) {
                Log.e(TAG, "Buffer drop error reported for unknown Surface");
            } else {
                errorStreamId = mConfiguredSurfaces.keyAt(indexOfTarget);
            }
        }
        if (holder == null) {
            return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE,
                    ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE);
        }
        return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(),
                /*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber(),
                /*partialResultCount*/1, /*errorStreamId*/-1);
                /*partialResultCount*/1, errorStreamId);
    }

    /**
@@ -105,9 +122,9 @@ public class LegacyCameraDevice implements AutoCloseable {
    private final CameraDeviceState.CameraDeviceStateListener mStateListener =
            new CameraDeviceState.CameraDeviceStateListener() {
        @Override
        public void onError(final int errorCode, final RequestHolder holder) {
        public void onError(final int errorCode, final Object errorArg, final RequestHolder holder) {
            if (DEBUG) {
                Log.d(TAG, "onError called, errorCode = " + errorCode);
                Log.d(TAG, "onError called, errorCode = " + errorCode + ", errorArg = " + errorArg);
            }
            switch (errorCode) {
                /*
@@ -125,7 +142,7 @@ public class LegacyCameraDevice implements AutoCloseable {
                }
            }

            final CaptureResultExtras extras = getExtrasFromRequest(holder);
            final CaptureResultExtras extras = getExtrasFromRequest(holder, errorCode, errorArg);
            mResultHandler.post(new Runnable() {
                @Override
                public void run() {
@@ -281,14 +298,17 @@ public class LegacyCameraDevice implements AutoCloseable {
     *
     * <p>Every surface in {@code outputs} must be non-{@code null}.</p>
     *
     * @param outputs a list of surfaces to set.
     * @param outputs a list of surfaces to set. LegacyCameraDevice will take ownership of this
     *          list; it must not be modified by the caller once it's passed in.
     * @return an error code for this binder operation, or {@link NO_ERROR}
     *          on success.
     */
    public int configureOutputs(List<Surface> outputs) {
    public int configureOutputs(SparseArray<Surface> outputs) {
        List<Pair<Surface, Size>> sizedSurfaces = new ArrayList<>();
        if (outputs != null) {
            for (Surface output : outputs) {
            int count = outputs.size();
            for (int i = 0; i < count; i++)  {
                Surface output = outputs.valueAt(i);
                if (output == null) {
                    Log.e(TAG, "configureOutputs - null outputs are not allowed");
                    return BAD_VALUE;
@@ -353,7 +373,7 @@ public class LegacyCameraDevice implements AutoCloseable {
        }

        if (success) {
            mConfiguredSurfaces = outputs != null ? new ArrayList<>(outputs) : null;
            mConfiguredSurfaces = outputs;
        } else {
            return LegacyExceptionUtils.INVALID_OPERATION;
        }
@@ -659,6 +679,23 @@ public class LegacyCameraDevice implements AutoCloseable {
        return nativeGetSurfaceId(surface);
    }

    static List<Long> getSurfaceIds(SparseArray<Surface> surfaces) {
        if (surfaces == null) {
            throw new NullPointerException("Null argument surfaces");
        }
        List<Long> surfaceIds = new ArrayList<>();
        int count = surfaces.size();
        for (int i = 0; i < count; i++) {
            long id = getSurfaceId(surfaces.valueAt(i));
            if (id == 0) {
                throw new IllegalStateException(
                        "Configured surface had null native GraphicBufferProducer pointer!");
            }
            surfaceIds.add(id);
        }
        return surfaceIds;
    }

    static List<Long> getSurfaceIds(Collection<Surface> surfaces) {
        if (surfaces == null) {
            throw new NullPointerException("Null argument surfaces");
+16 −2
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@ public class RequestHolder {
    private final int mNumPreviewTargets;
    private volatile boolean mFailed = false;

    private final Collection<Long> mJpegSurfaceIds;

    /**
     * A builder class for {@link RequestHolder} objects.
     *
@@ -150,13 +152,13 @@ public class RequestHolder {
         */
        public RequestHolder build(long frameNumber) {
            return new RequestHolder(mRequestId, mSubsequenceId, mRequest, mRepeating, frameNumber,
                    mNumJpegTargets, mNumPreviewTargets);
                    mNumJpegTargets, mNumPreviewTargets, mJpegSurfaceIds);
        }
    }

    private RequestHolder(int requestId, int subsequenceId, CaptureRequest request,
                          boolean repeating, long frameNumber, int numJpegTargets,
                          int numPreviewTargets) {
                          int numPreviewTargets, Collection<Long> jpegSurfaceIds) {
        mRepeating = repeating;
        mRequest = request;
        mRequestId = requestId;
@@ -164,6 +166,7 @@ public class RequestHolder {
        mFrameNumber = frameNumber;
        mNumJpegTargets = numJpegTargets;
        mNumPreviewTargets = numPreviewTargets;
        mJpegSurfaceIds = jpegSurfaceIds;
    }

    /**
@@ -237,6 +240,17 @@ public class RequestHolder {
        return mNumPreviewTargets;
    }

    /**
     * Returns true if the given surface requires jpeg buffers.
     *
     * @param s a {@link android.view.Surface} to check.
     * @return true if the surface requires a jpeg buffer.
     */
    public boolean jpegType(Surface s)
            throws LegacyExceptionUtils.BufferQueueAbandonedException {
        return LegacyCameraDevice.containsSurfaceId(s, mJpegSurfaceIds);
    }

    /**
     * Mark this request as failed.
     */
Loading