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

Commit e79449ae authored by Chien-Yu Chen's avatar Chien-Yu Chen Committed by Android (Google) Code Review
Browse files

Merge "camera2: validate reprocess request's session"

parents 43149717 7a316f6b
Loading
Loading
Loading
Loading
+14 −5
Original line number Diff line number Diff line
@@ -64,6 +64,12 @@ import java.util.List;
 */
public abstract class CameraCaptureSession implements AutoCloseable {

    /**
     * Used to identify invalid session ID.
     * @hide
     */
    public static final int SESSION_ID_NONE = -1;

    /**
     * Get the camera device that this session is created for.
     */
@@ -168,10 +174,11 @@ public abstract class CameraCaptureSession implements AutoCloseable {
     * @throws IllegalArgumentException if the request targets no Surfaces or Surfaces that are not
     *                                  configured as outputs for this session; or a reprocess
     *                                  capture request is submitted in a non-reprocessible capture
     *                                  session; or the capture targets a Surface in the middle
     *                                  of being {@link #prepare prepared}; or the handler is
     *                                  null, the listener is not null, and the calling thread has
     *                                  no looper.
     *                                  session; or the reprocess capture request was created with
     *                                  a {@link TotalCaptureResult} from a different session; or
     *                                  the capture targets a Surface in the middle of being
     *                                  {@link #prepare prepared}; or the handler is null, the
     *                                  listener is not null, and the calling thread has no looper.
     *
     * @see #captureBurst
     * @see #setRepeatingRequest
@@ -226,7 +233,9 @@ public abstract class CameraCaptureSession implements AutoCloseable {
     *                                  capture request is submitted in a non-reprocessible capture
     *                                  session; or the list of requests contains both requests to
     *                                  capture images from the camera and reprocess capture
     *                                  requests; or one of the captures targets a Surface in the
     *                                  requests; or one of the reprocess capture requests was
     *                                  created with a {@link TotalCaptureResult} from a different
     *                                  session; or one of the captures targets a Surface in the
     *                                  middle of being {@link #prepare prepared}; or if the handler
     *                                  is null, the listener is not null, and the calling thread
     *                                  has no looper.
+66 −4
Original line number Diff line number Diff line
@@ -158,6 +158,9 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
    private final HashSet<Surface> mSurfaceSet;
    private final CameraMetadataNative mSettings;
    private boolean mIsReprocess;
    // Each reprocess request must be tied to a reprocessible session ID.
    // Valid only for reprocess requests (mIsReprocess == true).
    private int mReprocessibleSessionId;

    private Object mUserTag;

@@ -170,6 +173,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
        mSettings = new CameraMetadataNative();
        mSurfaceSet = new HashSet<Surface>();
        mIsReprocess = false;
        mReprocessibleSessionId = CameraCaptureSession.SESSION_ID_NONE;
    }

    /**
@@ -182,6 +186,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
        mSettings = new CameraMetadataNative(source.mSettings);
        mSurfaceSet = (HashSet<Surface>) source.mSurfaceSet.clone();
        mIsReprocess = source.mIsReprocess;
        mReprocessibleSessionId = source.mReprocessibleSessionId;
        mUserTag = source.mUserTag;
    }

@@ -189,11 +194,36 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
     * Take ownership of passed-in settings.
     *
     * Used by the Builder to create a mutable CaptureRequest.
     *
     * @param settings Settings for this capture request.
     * @param isReprocess Indicates whether to create a reprocess capture request. {@code true}
     *                    to create a reprocess capture request. {@code false} to create a regular
     *                    capture request.
     * @param reprocessibleSessionId The ID of the camera capture session this capture is created
     *                               for. This is used to validate if the application submits a
     *                               reprocess capture request to the same session where
     *                               the {@link TotalCaptureResult}, used to create the reprocess
     *                               capture, came from.
     *
     * @throws IllegalArgumentException If creating a reprocess capture request with an invalid
     *                                  reprocessibleSessionId.
     *
     * @see CameraDevice#createReprocessCaptureRequest
     */
    private CaptureRequest(CameraMetadataNative settings, boolean isReprocess) {
    private CaptureRequest(CameraMetadataNative settings, boolean isReprocess,
            int reprocessibleSessionId) {
        mSettings = CameraMetadataNative.move(settings);
        mSurfaceSet = new HashSet<Surface>();
        mIsReprocess = isReprocess;
        if (isReprocess) {
            if (reprocessibleSessionId == CameraCaptureSession.SESSION_ID_NONE) {
                throw new IllegalArgumentException("Create a reprocess capture request with an " +
                        "invalid session ID: " + reprocessibleSessionId);
            }
            mReprocessibleSessionId = reprocessibleSessionId;
        } else {
            mReprocessibleSessionId = CameraCaptureSession.SESSION_ID_NONE;
        }
    }

    /**
@@ -276,6 +306,23 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
        return mIsReprocess;
    }

    /**
     * Get the reprocessible session ID this reprocess capture request is associated with.
     *
     * @return the reprocessible session ID this reprocess capture request is associated with
     *
     * @throws IllegalStateException if this capture request is not a reprocess capture request.
     * @hide
     */
    public int getReprocessibleSessionId() {
        if (mIsReprocess == false ||
                mReprocessibleSessionId == CameraCaptureSession.SESSION_ID_NONE) {
            throw new IllegalStateException("Getting the reprocessible session ID for a "+
                    "non-reprocess capture request is illegal.");
        }
        return mReprocessibleSessionId;
    }

    /**
     * Determine whether this CaptureRequest is equal to another CaptureRequest.
     *
@@ -298,7 +345,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
                && Objects.equals(mUserTag, other.mUserTag)
                && mSurfaceSet.equals(other.mSurfaceSet)
                && mSettings.equals(other.mSettings)
                && mIsReprocess == other.mIsReprocess;
                && mIsReprocess == other.mIsReprocess
                && mReprocessibleSessionId == other.mReprocessibleSessionId;
    }

    @Override
@@ -347,6 +395,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
        }

        mIsReprocess = (in.readInt() == 0) ? false : true;
        mReprocessibleSessionId = CameraCaptureSession.SESSION_ID_NONE;
    }

    @Override
@@ -397,10 +446,23 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
         * Initialize the builder using the template; the request takes
         * ownership of the template.
         *
         * @param template Template settings for this capture request.
         * @param reprocess Indicates whether to create a reprocess capture request. {@code true}
         *                  to create a reprocess capture request. {@code false} to create a regular
         *                  capture request.
         * @param reprocessibleSessionId The ID of the camera capture session this capture is
         *                               created for. This is used to validate if the application
         *                               submits a reprocess capture request to the same session
         *                               where the {@link TotalCaptureResult}, used to create the
         *                               reprocess capture, came from.
         *
         * @throws IllegalArgumentException If creating a reprocess capture request with an invalid
         *                                  reprocessibleSessionId.
         * @hide
         */
        public Builder(CameraMetadataNative template, boolean reprocess) {
            mRequest = new CaptureRequest(template, reprocess);
        public Builder(CameraMetadataNative template, boolean reprocess,
                int reprocessibleSessionId) {
            mRequest = new CaptureRequest(template, reprocess, reprocessibleSessionId);
        }

        /**
+15 −1
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import java.util.List;
public final class TotalCaptureResult extends CaptureResult {

    private final List<CaptureResult> mPartialResults;
    private final int mSessionId;

    /**
     * Takes ownership of the passed-in camera metadata and the partial results
@@ -58,7 +59,7 @@ public final class TotalCaptureResult extends CaptureResult {
     * @hide
     */
    public TotalCaptureResult(CameraMetadataNative results, CaptureRequest parent,
            CaptureResultExtras extras, List<CaptureResult> partials) {
            CaptureResultExtras extras, List<CaptureResult> partials, int sessionId) {
        super(results, parent, extras);

        if (partials == null) {
@@ -66,6 +67,8 @@ public final class TotalCaptureResult extends CaptureResult {
        } else {
            mPartialResults = partials;
        }

        mSessionId = sessionId;
    }

    /**
@@ -78,6 +81,7 @@ public final class TotalCaptureResult extends CaptureResult {
        super(results, sequenceId);

        mPartialResults = new ArrayList<>();
        mSessionId = CameraCaptureSession.SESSION_ID_NONE;
    }

    /**
@@ -95,4 +99,14 @@ public final class TotalCaptureResult extends CaptureResult {
    public List<CaptureResult> getPartialResults() {
        return Collections.unmodifiableList(mPartialResults);
    }

    /**
     * Get the ID of the session where the capture request of this result was submitted.
     *
     * @return The session ID
     * @hide
     */
    public int getSessionId() {
        return mSessionId;
    }
}
+7 −1
Original line number Diff line number Diff line
@@ -156,9 +156,10 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
        } else if (request.isReprocess() && !isReprocessible()) {
            throw new IllegalArgumentException("this capture session cannot handle reprocess " +
                    "requests");
        } else if (request.isReprocess() && request.getReprocessibleSessionId() != mId) {
            throw new IllegalArgumentException("capture request was created for another session");
        }


        checkNotClosed();

        handler = checkHandler(handler, callback);
@@ -185,12 +186,17 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
        if (reprocess && !isReprocessible()) {
            throw new IllegalArgumentException("this capture session cannot handle reprocess " +
                    "requests");
        } else if (reprocess && requests.get(0).getReprocessibleSessionId() != mId) {
            throw new IllegalArgumentException("capture request was created for another session");
        }

        for (int i = 1; i < requests.size(); i++) {
            if (requests.get(i).isReprocess() != reprocess) {
                throw new IllegalArgumentException("cannot mix regular and reprocess capture " +
                        " requests");
            } else if (reprocess && requests.get(i).getReprocessibleSessionId() != mId) {
                throw new IllegalArgumentException("capture request was created for another " +
                    "session");
            }
        }

+16 −8
Original line number Diff line number Diff line
@@ -585,8 +585,8 @@ public class CameraDeviceImpl extends CameraDevice {
                return null;
            }

            CaptureRequest.Builder builder =
                    new CaptureRequest.Builder(templatedRequest, /*reprocess*/false);
            CaptureRequest.Builder builder = new CaptureRequest.Builder(
                    templatedRequest, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);

            return builder;
        }
@@ -601,7 +601,8 @@ public class CameraDeviceImpl extends CameraDevice {
            CameraMetadataNative resultMetadata = new
                    CameraMetadataNative(inputResult.getNativeCopy());

            return new CaptureRequest.Builder(resultMetadata, /*reprocess*/true);
            return new CaptureRequest.Builder(resultMetadata, /*reprocess*/true,
                    inputResult.getSessionId());
        }
    }

@@ -763,7 +764,7 @@ public class CameraDeviceImpl extends CameraDevice {

            if (callback != null) {
                mCaptureCallbackMap.put(requestId, new CaptureCallbackHolder(callback,
                        requestList, handler, repeating));
                        requestList, handler, repeating, mNextSessionId - 1));
            } else {
                if (DEBUG) {
                    Log.d(TAG, "Listen for request " + requestId + " is null");
@@ -1095,9 +1096,10 @@ public class CameraDeviceImpl extends CameraDevice {
        private final CaptureCallback mCallback;
        private final List<CaptureRequest> mRequestList;
        private final Handler mHandler;
        private final int mSessionId;

        CaptureCallbackHolder(CaptureCallback callback, List<CaptureRequest> requestList,
                Handler handler, boolean repeating) {
                Handler handler, boolean repeating, int sessionId) {
            if (callback == null || handler == null) {
                throw new UnsupportedOperationException(
                    "Must have a valid handler and a valid callback");
@@ -1106,6 +1108,7 @@ public class CameraDeviceImpl extends CameraDevice {
            mHandler = handler;
            mRequestList = new ArrayList<CaptureRequest>(requestList);
            mCallback = callback;
            mSessionId = sessionId;
        }

        public boolean isRepeating() {
@@ -1140,6 +1143,10 @@ public class CameraDeviceImpl extends CameraDevice {
            return mHandler;
        }

        public int getSessionId() {
            return mSessionId;
        }

    }

    /**
@@ -1643,8 +1650,8 @@ public class CameraDeviceImpl extends CameraDevice {
                    List<CaptureResult> partialResults =
                            mFrameNumberTracker.popPartialResults(frameNumber);

                    final TotalCaptureResult resultAsCapture =
                            new TotalCaptureResult(result, request, resultExtras, partialResults);
                    final TotalCaptureResult resultAsCapture = new TotalCaptureResult(result,
                            request, resultExtras, partialResults, holder.getSessionId());

                    // Final capture result
                    resultDispatch = new Runnable() {
@@ -1665,7 +1672,8 @@ public class CameraDeviceImpl extends CameraDevice {
                holder.getHandler().post(resultDispatch);

                // Collect the partials for a total result; or mark the frame as totally completed
                mFrameNumberTracker.updateTracker(frameNumber, finalResult, isPartialResult, isReprocess);
                mFrameNumberTracker.updateTracker(frameNumber, finalResult, isPartialResult,
                        isReprocess);

                // Fire onCaptureSequenceCompleted
                if (!isPartialResult) {
Loading