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

Commit 77bb682e authored by Shuzhen Wang's avatar Shuzhen Wang
Browse files

Camera: Refactor API for session configration query

- Modify OutputConfiguration class so that it can be created without
  output surfaces for SurfaceView, SurfaceTexture, MediaRecorder,
  MediaCodec, and ImageReader. This makes it possible to do feature
  combination query with minimum latency. The application can then call
  OutputConfiguration#addSurface before creating capture session.
- Enhance SessionConfiguration class for CameraDeviceSetup operations.

Test: atest CtsCameraTestCases
Bug: 298033056
Bug: 309627704
Change-Id: Ic943c225d07f1553efe22b7125642673d659c2a2
parent 4972f329
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -20138,9 +20138,14 @@ package android.hardware.camera2.params {
    ctor public OutputConfiguration(@NonNull android.view.Surface);
    ctor public OutputConfiguration(int, @NonNull android.view.Surface);
    ctor public <T> OutputConfiguration(@NonNull android.util.Size, @NonNull Class<T>);
    ctor @FlaggedApi("com.android.internal.camera.flags.camera_device_setup") public OutputConfiguration(int, @NonNull android.util.Size);
    ctor @FlaggedApi("com.android.internal.camera.flags.camera_device_setup") public OutputConfiguration(int, int, @NonNull android.util.Size);
    ctor @FlaggedApi("com.android.internal.camera.flags.camera_device_setup") public OutputConfiguration(int, @NonNull android.util.Size, long);
    ctor @FlaggedApi("com.android.internal.camera.flags.camera_device_setup") public OutputConfiguration(int, int, @NonNull android.util.Size, long);
    method public void addSensorPixelModeUsed(int);
    method public void addSurface(@NonNull android.view.Surface);
    method @NonNull public static java.util.Collection<android.hardware.camera2.params.OutputConfiguration> createInstancesForMultiResolutionOutput(@NonNull android.hardware.camera2.MultiResolutionImageReader);
    method @FlaggedApi("com.android.internal.camera.flags.camera_device_setup") @NonNull public static java.util.List<android.hardware.camera2.params.OutputConfiguration> createInstancesForMultiResolutionOutput(@NonNull java.util.Collection<android.hardware.camera2.params.MultiResolutionStreamInfo>, int);
    method public int describeContents();
    method public void enableSurfaceSharing();
    method public long getDynamicRangeProfile();
@@ -20159,6 +20164,7 @@ package android.hardware.camera2.params {
    method public void setPhysicalCameraId(@Nullable String);
    method public void setReadoutTimestampEnabled(boolean);
    method public void setStreamUseCase(long);
    method @FlaggedApi("com.android.internal.camera.flags.camera_device_setup") public static void setSurfacesForMultiResolutionOutput(@NonNull java.util.Collection<android.hardware.camera2.params.OutputConfiguration>, @NonNull android.hardware.camera2.MultiResolutionImageReader);
    method public void setTimestampBase(int);
    method public void writeToParcel(android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.camera2.params.OutputConfiguration> CREATOR;
@@ -20220,6 +20226,7 @@ package android.hardware.camera2.params {
  public final class SessionConfiguration implements android.os.Parcelable {
    ctor public SessionConfiguration(int, @NonNull java.util.List<android.hardware.camera2.params.OutputConfiguration>, @NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraCaptureSession.StateCallback);
    ctor @FlaggedApi("com.android.internal.camera.flags.camera_device_setup") public SessionConfiguration(int, @NonNull java.util.List<android.hardware.camera2.params.OutputConfiguration>);
    method public void clearColorSpace();
    method public int describeContents();
    method @Nullable public android.graphics.ColorSpace getColorSpace();
@@ -20229,6 +20236,7 @@ package android.hardware.camera2.params {
    method public android.hardware.camera2.CaptureRequest getSessionParameters();
    method public int getSessionType();
    method public android.hardware.camera2.CameraCaptureSession.StateCallback getStateCallback();
    method @FlaggedApi("com.android.internal.camera.flags.camera_device_setup") public void setCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraCaptureSession.StateCallback);
    method public void setColorSpace(@NonNull android.graphics.ColorSpace.Named);
    method public void setInputConfiguration(@NonNull android.hardware.camera2.params.InputConfiguration);
    method public void setSessionParameters(android.hardware.camera2.CaptureRequest);
+48 −12
Original line number Diff line number Diff line
@@ -585,6 +585,11 @@ public abstract class CameraDevice implements AutoCloseable {
     * <p>Configuring a session with an empty or null list will close the current session, if
     * any. This can be used to release the current session's target surfaces for another use.</p>
     *
     * <p>This function throws an {@code IllegalArgumentException} if called with a
     * SessionConfiguration lacking state callbacks or valid output surfaces. The only exceptions
     * are deferred SurfaceView or SurfaceTexture outputs. See {@link
     * OutputConfiguration#OutputConfiguration(Size, Class)} for details.</p>
     *
     * <h3>Regular capture</h3>
     *
     * <p>While any of the sizes from {@link StreamConfigurationMap#getOutputSizes} can be used when
@@ -1675,19 +1680,32 @@ public abstract class CameraDevice implements AutoCloseable {
         *
         * <p><b>IMPORTANT:</b></p>
         * <ul>
         * <li>If a feature support can be queried via
         * <li>If feature support can be queried via
         * {@link CameraCharacteristics#SCALER_MANDATORY_STREAM_COMBINATIONS} or
         * {@link CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP}, applications should
         * directly use it rather than calling this function as: (1) using
         * {@code CameraCharacteristics} is more efficient, and (2) calling this function with on
         * non-supported devices will throw a {@link UnsupportedOperationException}.
         *
         * <li>To minimize latency of {@link SessionConfiguration} creation, applications can
         * use deferred surfaces for SurfaceView and SurfaceTexture to avoid waiting for UI
         * creation before setting up the camera. For {@link android.media.MediaRecorder} and
         * {@link android.media.MediaCodec} uses, applications can use {@code ImageReader} with
         * {@link android.hardware.HardwareBuffer#USAGE_VIDEO_ENCODE}. The lightweight nature of
         * {@code ImageReader} helps minimize the latency cost.
         * directly use that route rather than calling this function as: (1) using
         * {@code CameraCharacteristics} is more efficient, and (2) calling this function with
         * certain non-supported features will throw a {@link IllegalArgumentException}.</li>
         *
         * <li>To minimize {@link SessionConfiguration} creation latency due to its dependency on
         * output surfaces, the application can call this method before acquiring valid
         * {@link android.view.SurfaceView}, {@link android.graphics.SurfaceTexture},
         * {@link android.media.MediaRecorder}, {@link android.media.MediaCodec}, or {@link
         * android.media.ImageReader} surfaces. For {@link android.view.SurfaceView},
         * {@link android.graphics.SurfaceTexture}, {@link android.media.MediaRecorder}, and
         * {@link android.media.MediaCodec}, the application can call
         * {@link OutputConfiguration#OutputConfiguration(Size, Class)}. For {@link
         * android.media.ImageReader}, the application can call {@link
         * OutputConfiguration#OutputConfiguration(int, Size)}, {@link
         * OutputConfiguration#OutputConfiguration(int, int, Size)}, {@link
         * OutputConfiguration#OutputConfiguration(int, Size, long)}, or {@link
         * OutputConfiguration#OutputConfiguration(int, int, Size, long)}. The {@link
         * SessionConfiguration} can then be created using the OutputConfiguration objects and
         * be used to query whether it's supported by the camera device. To create the
         * CameraCaptureSession, the application still needs to make sure all output surfaces
         * are added via {@link OutputConfiguration#addSurfaces} with the exception of deferred
         * surfaces for {@link android.view.SurfaceView} and
         * {@link android.graphics.SurfaceTexture}.</li>
         * </ul>
         *
         * @return {@code true} if the given session configuration is supported by the camera
@@ -1706,8 +1724,8 @@ public abstract class CameraDevice implements AutoCloseable {
                @NonNull SessionConfiguration config) throws CameraAccessException;

        /**
         * <p>Get camera characteristics for a particular session configuration for this camera
         * device</p>
         * Get camera characteristics for a particular session configuration for this camera
         * device.
         *
         * <p>The camera characteristics returned by this method are different from those returned
         * from {@link CameraManager#getCameraCharacteristics}. The characteristics returned here
@@ -1718,6 +1736,24 @@ public abstract class CameraDevice implements AutoCloseable {
         * <p>Other than that, the characteristics returned here can be used in the same way as
         * those returned from {@link CameraManager#getCameraCharacteristics}.</p>
         *
         * <p>To optimize latency, the application can call this method before acquiring valid
         * {@link android.view.SurfaceView}, {@link android.graphics.SurfaceTexture},
         * {@link android.media.MediaRecorder}, {@link android.media.MediaCodec}, or {@link
         * android.media.ImageReader} surfaces. For {@link android.view.SurfaceView},
         * {@link android.graphics.SurfaceTexture}, {@link android.media.MediaRecorder}, and
         * {@link android.media.MediaCodec}, the application can call
         * {@link OutputConfiguration#OutputConfiguration(Size, Class)}. For {@link
         * android.media.ImageReader}, the application can call {@link
         * OutputConfiguration#OutputConfiguration(int, Size)}, {@link
         * OutputConfiguration#OutputConfiguration(int, int, Size)}, {@link
         * OutputConfiguration#OutputConfiguration(int, Size, long)}, or {@link
         * OutputConfiguration#OutputConfiguration(int, int, Size, long)}. The {@link
         * SessionConfiguration} can then be created using the OutputConfiguration objects and
         * be used for this function. To create the CameraCaptureSession, the application still
         * needs to make sure all output surfaces are added via {@link
         * OutputConfiguration#addSurfaces} with the exception of deferred surfaces for {@link
         * android.view.SurfaceView} and {@link android.graphics.SurfaceTexture}.</p>
         *
         * @param sessionConfig The session configuration for which characteristics are fetched.
         * @return CameraCharacteristics specific to a given session configuration.
         *
+50 −7
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.hardware.camera2;

import static com.android.internal.util.Preconditions.checkNotNull;

import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntRange;
@@ -26,20 +28,15 @@ import android.graphics.ImageFormat;
import android.graphics.ImageFormat.Format;
import android.hardware.HardwareBuffer;
import android.hardware.HardwareBuffer.Usage;
import android.hardware.camera2.params.MultiResolutionStreamInfo;
import android.media.Image;
import android.media.ImageReader;
import android.hardware.camera2.params.MultiResolutionStreamInfo;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.util.Size;
import android.view.Surface;

import com.android.internal.camera.flags.Flags;

import java.nio.NioUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Executor;

/**
@@ -350,6 +347,52 @@ public class MultiResolutionImageReader implements AutoCloseable {
        return mReaders;
    }

    /**
     * Get the internal ImageReader surface based on configured size and physical camera Id.
     *
     * <p>The {@code configuredSize} and {@code physicalCameraId} parameters must match one of the
     * MultiResolutionStreamInfo used to create this {@link MultiResolutionImageReader}.</p>
     *
     * <p>The Surface returned from this function isn't meant to be used directly as part of a
     * {@link CaptureRequest}. It should instead be used for creating an OutputConfiguration
     * before session creation. See {@link OutputConfiguration#setSurfacesForMultiResolutionOutput}
     * for details. For {@link CaptureRequest}, use {@link #getSurface()} instead.</p>
     *
     * <p>Please note that holding on to the Surface objects returned by this method is not enough
     * to keep their parent MultiResolutionImageReaders from being reclaimed. In that sense, a
     * Surface acts like a {@link java.lang.ref.WeakReference weak reference} to the
     * MultiResolutionImageReader that provides it.</p>
     *
     * @param configuredSize The configured size corresponding to one of the internal ImageReader.
     * @param physicalCameraId The physical camera Id the internal ImageReader targets for. If
     *                         the ImageReader is not targeting a physical camera of a logical
     *                         multi-camera, this parameter is set to "".
     *
     * @return The {@link Surface} of the internal ImageReader corresponding to the provided
     *         configured size and physical camera Id.
     *
     * @throws IllegalArgumentException If {@code configuredSize} is {@code null}, or the ({@code
     *                                  configuredSize} and {@code physicalCameraId}) combo is not
     *                                  part of this {@code MultiResolutionImageReader}.
     * @hide
     */
    @FlaggedApi(Flags.FLAG_CAMERA_DEVICE_SETUP)
    public @NonNull Surface getSurface(@NonNull Size configuredSize,
            @NonNull String physicalCameraId) {
        checkNotNull(configuredSize, "configuredSize must not be null");
        checkNotNull(physicalCameraId, "physicalCameraId must not be null");

        for (int i = 0; i < mStreamInfo.length; i++) {
            if (mStreamInfo[i].getWidth() == configuredSize.getWidth()
                    && mStreamInfo[i].getHeight() == configuredSize.getHeight()
                    && physicalCameraId.equals(mStreamInfo[i].getPhysicalCameraId())) {
                return mReaders[i].getSurface();
            }
        }
        throw new IllegalArgumentException("configuredSize and physicalCameraId don't match with "
                + "this MultiResolutionImageReader");
    }

    /**
     * Get the surface that is used as a target for {@link CaptureRequest}
     *
+0 −1
Original line number Diff line number Diff line
@@ -90,7 +90,6 @@ public class CameraDeviceSetupImpl extends CameraDevice.CameraDeviceSetup {
    @Override
    public boolean isSessionConfigurationSupported(@NonNull SessionConfiguration config)
            throws CameraAccessException {
        // TODO(b/298033056): restructure the OutputConfiguration API for better usability
        synchronized (mInterfaceLock) {
            if (mCameraManager.isCameraServiceDisabled()) {
                throw new IllegalArgumentException("No cameras available on device");
+411 −51

File changed.

Preview size limit exceeded, changes collapsed.

Loading