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

Commit 86c843e8 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Camera: Add support for client requests&results when using extension sessions"

parents fd04f04b 5b3d7a7c
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -17443,6 +17443,8 @@ package android.hardware.camera2 {
  }
  public final class CameraExtensionCharacteristics {
    method @NonNull public java.util.Set<android.hardware.camera2.CaptureRequest.Key> getAvailableCaptureRequestKeys(int);
    method @NonNull public java.util.Set<android.hardware.camera2.CaptureResult.Key> getAvailableCaptureResultKeys(int);
    method @Nullable public android.util.Range<java.lang.Long> getEstimatedCaptureLatencyRangeMillis(int, @NonNull android.util.Size, int);
    method @NonNull public <T> java.util.List<android.util.Size> getExtensionSupportedSizes(int, @NonNull Class<T>);
    method @NonNull public java.util.List<android.util.Size> getExtensionSupportedSizes(int, int);
@@ -17467,6 +17469,7 @@ package android.hardware.camera2 {
    ctor public CameraExtensionSession.ExtensionCaptureCallback();
    method public void onCaptureFailed(@NonNull android.hardware.camera2.CameraExtensionSession, @NonNull android.hardware.camera2.CaptureRequest);
    method public void onCaptureProcessStarted(@NonNull android.hardware.camera2.CameraExtensionSession, @NonNull android.hardware.camera2.CaptureRequest);
    method public void onCaptureResultAvailable(@NonNull android.hardware.camera2.CameraExtensionSession, @NonNull android.hardware.camera2.CaptureRequest, @NonNull android.hardware.camera2.TotalCaptureResult);
    method public void onCaptureSequenceAborted(@NonNull android.hardware.camera2.CameraExtensionSession, int);
    method public void onCaptureSequenceCompleted(@NonNull android.hardware.camera2.CameraExtensionSession, int);
    method public void onCaptureStarted(@NonNull android.hardware.camera2.CameraExtensionSession, @NonNull android.hardware.camera2.CaptureRequest, long);
+1 −1
Original line number Diff line number Diff line
@@ -657,7 +657,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
     *
     * @throws IllegalArgumentException if metadataClass is not a subclass of CameraMetadata
     */
    private <TKey> List<TKey>
    <TKey> List<TKey>
    getAvailableKeyList(Class<?> metadataClass, Class<TKey> keyClass, int[] filterTags,
            boolean includeSynthetic) {

+142 −2
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.hardware.camera2.extension.IInitializeSessionCallback;
import android.hardware.camera2.extension.IPreviewExtenderImpl;
import android.hardware.camera2.extension.LatencyRange;
import android.hardware.camera2.extension.SizeList;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.params.ExtensionSessionConfiguration;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.os.ConditionVariable;
@@ -49,6 +50,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -795,4 +797,142 @@ public final class CameraExtensionCharacteristics {

        return null;
    }

    /**
     * Returns the set of keys supported by a {@link CaptureRequest} submitted in a
     * {@link CameraExtensionSession} with a given extension type.
     *
     * <p>The set returned is not modifiable, so any attempts to modify it will throw
     * a {@code UnsupportedOperationException}.</p>
     *
     * @param extension the extension type
     *
     * @return non-modifiable set of capture keys supported by camera extension session initialized
     *         with the given extension type.
     * @throws IllegalArgumentException in case of unsupported extension.
     */
    @NonNull
    public Set<CaptureRequest.Key> getAvailableCaptureRequestKeys(@Extension int extension) {
        long clientId = registerClient(mContext);
        if (clientId < 0) {
            throw new IllegalArgumentException("Unsupported extensions");
        }

        HashSet<CaptureRequest.Key> ret = new HashSet<>();

        try {
            if (!isExtensionSupported(mCameraId, extension, mChars)) {
                throw new IllegalArgumentException("Unsupported extension");
            }
            Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
                    initializeExtension(extension);
            extenders.second.onInit(mCameraId, mChars.getNativeMetadata());
            extenders.second.init(mCameraId, mChars.getNativeMetadata());
            CameraMetadataNative captureRequestMeta =
                    extenders.second.getAvailableCaptureRequestKeys();

            if (captureRequestMeta != null) {
                int[] requestKeys = captureRequestMeta.get(
                        CameraCharacteristics.REQUEST_AVAILABLE_REQUEST_KEYS);
                if (requestKeys == null) {
                    throw new AssertionError("android.request.availableRequestKeys must be non-null"
                            + " in the characteristics");
                }
                CameraCharacteristics requestChars = new CameraCharacteristics(captureRequestMeta);

                Object crKey = CaptureRequest.Key.class;
                Class<CaptureRequest.Key<?>> crKeyTyped = (Class<CaptureRequest.Key<?>>)crKey;

                ret.addAll(requestChars.getAvailableKeyList(CaptureRequest.class, crKeyTyped,
                        requestKeys, /*includeSynthetic*/ false));
            }

            // Jpeg quality and orientation must always be supported
            if (!ret.contains(CaptureRequest.JPEG_QUALITY)) {
                ret.add(CaptureRequest.JPEG_QUALITY);
            }
            if (!ret.contains(CaptureRequest.JPEG_ORIENTATION)) {
                ret.add(CaptureRequest.JPEG_ORIENTATION);
            }
            extenders.second.onDeInit();
        } catch (RemoteException e) {
            throw new IllegalStateException("Failed to query the available capture request keys!");
        } finally {
            unregisterClient(clientId);
        }

        return Collections.unmodifiableSet(ret);
    }

    /**
     * Returns the set of keys supported by a {@link CaptureResult} passed as an argument to
     * {@link CameraExtensionSession.ExtensionCaptureCallback#onCaptureResultAvailable}.
     *
     * <p>The set returned is not modifiable, so any attempts to modify it will throw
     * a {@code UnsupportedOperationException}.</p>
     *
     * <p>In case the set is empty, then the extension is not able to support any capture results
     * and the {@link CameraExtensionSession.ExtensionCaptureCallback#onCaptureResultAvailable}
     * callback will not be fired.</p>
     *
     * @param extension the extension type
     *
     * @return non-modifiable set of capture result keys supported by camera extension session
     *         initialized with the given extension type.
     * @throws IllegalArgumentException in case of unsupported extension.
     */
    @NonNull
    public Set<CaptureResult.Key> getAvailableCaptureResultKeys(@Extension int extension) {
        long clientId = registerClient(mContext);
        if (clientId < 0) {
            throw new IllegalArgumentException("Unsupported extensions");
        }

        HashSet<CaptureResult.Key> ret = new HashSet<>();
        try {
            if (!isExtensionSupported(mCameraId, extension, mChars)) {
                throw new IllegalArgumentException("Unsupported extension");
            }

            Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
                    initializeExtension(extension);
            extenders.second.onInit(mCameraId, mChars.getNativeMetadata());
            extenders.second.init(mCameraId, mChars.getNativeMetadata());
            CameraMetadataNative captureResultMeta =
                    extenders.second.getAvailableCaptureResultKeys();

            if (captureResultMeta != null) {
                int[] resultKeys = captureResultMeta.get(
                        CameraCharacteristics.REQUEST_AVAILABLE_RESULT_KEYS);
                if (resultKeys == null) {
                    throw new AssertionError("android.request.availableResultKeys must be non-null "
                            + "in the characteristics");
                }
                CameraCharacteristics resultChars = new CameraCharacteristics(captureResultMeta);
                Object crKey = CaptureResult.Key.class;
                Class<CaptureResult.Key<?>> crKeyTyped = (Class<CaptureResult.Key<?>>)crKey;

                ret.addAll(resultChars.getAvailableKeyList(CaptureResult.class, crKeyTyped,
                        resultKeys, /*includeSynthetic*/ false));

                // Jpeg quality, orientation and sensor timestamp must always be supported
                if (!ret.contains(CaptureResult.JPEG_QUALITY)) {
                    ret.add(CaptureResult.JPEG_QUALITY);
                }
                if (!ret.contains(CaptureResult.JPEG_ORIENTATION)) {
                    ret.add(CaptureResult.JPEG_ORIENTATION);
                }
                if (!ret.contains(CaptureResult.SENSOR_TIMESTAMP)) {
                    ret.add(CaptureResult.SENSOR_TIMESTAMP);
                }
            }
            extenders.second.onDeInit();
        } catch (RemoteException e) {
            throw new IllegalStateException("Failed to query the available capture result keys!");
        } finally {
            unregisterClient(clientId);
        }

        return Collections.unmodifiableSet(ret);
    }
}
+26 −0
Original line number Diff line number Diff line
@@ -172,6 +172,32 @@ public abstract class CameraExtensionSession implements AutoCloseable {
                int sequenceId) {
            // default empty implementation
        }

        /**
         * This method is called when an image capture has fully completed and all the
         * result metadata is available.
         *
         * <p>This callback will only be called in case
         * {@link CameraExtensionCharacteristics#getAvailableCaptureResultKeys} returns a valid
         * non-empty list.</p>
         *
         * <p>The default implementation of this method does nothing.</p>
         *
         * @param session The session received during
         *                {@link StateCallback#onConfigured(CameraExtensionSession)}
         * @param request The request that was given to the CameraDevice
         * @param result The total output metadata from the capture, which only includes the
         * capture result keys advertised as supported in
         * {@link CameraExtensionCharacteristics#getAvailableCaptureResultKeys}.
         *
         * @see #capture
         * @see #setRepeatingRequest
         * @see CameraExtensionCharacteristics#getAvailableCaptureResultKeys
         */
        public void onCaptureResultAvailable(@NonNull CameraExtensionSession session,
                @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
            // default empty implementation
        }
    }

    /**
+2 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package android.hardware.camera2.extension;

import android.view.Surface;
import android.hardware.camera2.extension.CaptureBundle;
import android.hardware.camera2.extension.IProcessResultImpl;
import android.hardware.camera2.extension.Size;

/** @hide */
@@ -25,5 +26,5 @@ interface ICaptureProcessorImpl
    void onOutputSurface(in Surface surface, int imageFormat);
    void onResolutionUpdate(in Size size);
    void onImageFormatUpdate(int imageFormat);
    void process(in List<CaptureBundle> capturelist);
    void process(in List<CaptureBundle> capturelist, in IProcessResultImpl resultCallback);
}
Loading