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

Commit 66108274 authored by Avichal Rakesh's avatar Avichal Rakesh
Browse files

camera2: Move getSessionCharacteristics to CameraDeviceSetup

getSessionCharacteristics is currently a part of CameraDevice
which forces apps to call openCamera before being able to query
session characteristics. However, there is no technical reason
for this query to need an open CameraDevice.

To let apps query session characteristics without paying the
latency cost associated with openCamera, this CL moves
getSessionCharacteristics call to CameraDeviceSetup which can
be created trivially.

Bug: 320741775
Test: atest CtsCameraTestCases:CameraDeviceTest passes.
Test: atest CtsCameraTestCases:FeatureCombinationTest passes.
Test: atest CtsCameraTestCases:CameraDeviceSetupTest passes.
Change-Id: Idccea17c685c59afbdd649c8f329c7c42acc70a2
parent b785b9d5
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -19226,7 +19226,6 @@ package android.hardware.camera2 {
    method @Deprecated public abstract void createReprocessableCaptureSessionByConfigurations(@NonNull android.hardware.camera2.params.InputConfiguration, @NonNull java.util.List<android.hardware.camera2.params.OutputConfiguration>, @NonNull android.hardware.camera2.CameraCaptureSession.StateCallback, @Nullable android.os.Handler) throws android.hardware.camera2.CameraAccessException;
    method public int getCameraAudioRestriction() throws android.hardware.camera2.CameraAccessException;
    method @NonNull public abstract String getId();
    method @FlaggedApi("com.android.internal.camera.flags.feature_combination_query") @NonNull public android.hardware.camera2.CameraCharacteristics getSessionCharacteristics(@NonNull android.hardware.camera2.params.SessionConfiguration) throws android.hardware.camera2.CameraAccessException;
    method public boolean isSessionConfigurationSupported(@NonNull android.hardware.camera2.params.SessionConfiguration) throws android.hardware.camera2.CameraAccessException;
    method public void setCameraAudioRestriction(int) throws android.hardware.camera2.CameraAccessException;
    field public static final int AUDIO_RESTRICTION_NONE = 0; // 0x0
@@ -19243,6 +19242,7 @@ package android.hardware.camera2 {
  @FlaggedApi("com.android.internal.camera.flags.camera_device_setup") public abstract static class CameraDevice.CameraDeviceSetup {
    method @FlaggedApi("com.android.internal.camera.flags.camera_device_setup") @NonNull public abstract android.hardware.camera2.CaptureRequest.Builder createCaptureRequest(int) throws android.hardware.camera2.CameraAccessException;
    method @FlaggedApi("com.android.internal.camera.flags.camera_device_setup") @NonNull public abstract String getId();
    method @FlaggedApi("com.android.internal.camera.flags.camera_device_setup") @NonNull public abstract android.hardware.camera2.CameraCharacteristics getSessionCharacteristics(@NonNull android.hardware.camera2.params.SessionConfiguration) throws android.hardware.camera2.CameraAccessException;
    method @FlaggedApi("com.android.internal.camera.flags.camera_device_setup") public abstract boolean isSessionConfigurationSupported(@NonNull android.hardware.camera2.params.SessionConfiguration) throws android.hardware.camera2.CameraAccessException;
    method @FlaggedApi("com.android.internal.camera.flags.camera_device_setup") @RequiresPermission(android.Manifest.permission.CAMERA) public abstract void openCamera(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.camera2.CameraDevice.StateCallback) throws android.hardware.camera2.CameraAccessException;
  }
+28 −29
Original line number Diff line number Diff line
@@ -1420,34 +1420,6 @@ public abstract class CameraDevice implements AutoCloseable {
        throw new UnsupportedOperationException("Subclasses must override this method");
    }

  /**
   * <p>Get camera characteristics for a particular session configuration by the camera device.</p>
   *
   * <p>The camera characteristics returned here is typically more limited than the characteristics
   * returned from {@link CameraManager#getCameraCharacteristics}. The keys that have more limited
   * values are listed in
   * {@link CameraCharacteristics#getAvailableSessionCharacteristicsKeys}. </p>
   *
   * <p>Other than that, the characteristics returned here can be used in the same way as those
   * returned from {@link CameraManager#getCameraCharacteristics}.</p>
   *
   * @param sessionConfig : The session configuration for which characteristics are fetched.
   * @return CameraCharacteristics specific to a given session configuration.
   * @throws UnsupportedOperationException if the query operation is not supported by the camera
   *                                       device
   * @throws IllegalArgumentException if the session configuration is invalid
   * @throws CameraAccessException if the camera device is no longer connected or has
   *                               encountered a fatal error
   * @throws IllegalStateException if the camera device has been closed
   * @see android.hardware.camera2.CameraCharacteristics#getAvailableSessionCharacteristicsKeys
   */
    @NonNull
    @FlaggedApi(Flags.FLAG_FEATURE_COMBINATION_QUERY)
    public CameraCharacteristics getSessionCharacteristics(
            @NonNull SessionConfiguration sessionConfig) throws CameraAccessException {
        throw new UnsupportedOperationException("Subclasses must override this method");
    }

    /**
     * A callback objects for receiving updates about the state of a camera device.
     *
@@ -1733,6 +1705,33 @@ public abstract class CameraDevice implements AutoCloseable {
        public abstract boolean isSessionConfigurationSupported(
                @NonNull SessionConfiguration config) throws CameraAccessException;

        /**
         * <p>Get camera characteristics for a particular session configuration for this camera
         * device</p>
         *
         * <p>The camera characteristics returned by this method are different from those returned
         * from {@link CameraManager#getCameraCharacteristics}. The characteristics returned here
         * reflect device capabilities more accurately if the device were to be configured with
         * {@code sessionConfig}. The keys that may get updated are listed in
         * {@link CameraCharacteristics#getAvailableSessionCharacteristicsKeys}.</p>
         *
         * <p>Other than that, the characteristics returned here can be used in the same way as
         * those returned from {@link CameraManager#getCameraCharacteristics}.</p>
         *
         * @param sessionConfig : The session configuration for which characteristics are fetched.
         * @return CameraCharacteristics specific to a given session configuration.
         *
         * @throws IllegalArgumentException      if the session configuration is invalid
         * @throws CameraAccessException         if the camera device is no longer connected or has
         *                                       encountered a fatal error
         *
         * @see CameraCharacteristics#getAvailableSessionCharacteristicsKeys
         */
        @NonNull
        @FlaggedApi(Flags.FLAG_CAMERA_DEVICE_SETUP)
        public abstract CameraCharacteristics getSessionCharacteristics(
                @NonNull SessionConfiguration sessionConfig) throws CameraAccessException;

        /**
         * Utility function to forward the call to
         * {@link CameraManager#openCamera(String, Executor, StateCallback)}. This function simply
+1 −2
Original line number Diff line number Diff line
@@ -772,8 +772,7 @@ public final class CameraManager {
                    "CameraDeviceSetup is not supported for Camera ID: " + cameraId);
        }

        return new CameraDeviceSetupImpl(cameraId, /*cameraManager=*/ this,
                mContext.getApplicationInfo().targetSdkVersion);
        return new CameraDeviceSetupImpl(cameraId, /*cameraManager=*/ this, mContext);
    }

    /**
+0 −12
Original line number Diff line number Diff line
@@ -811,18 +811,6 @@ public class CameraDeviceImpl extends CameraDevice
        }
    }

    @Override
    public CameraCharacteristics getSessionCharacteristics(
            @NonNull SessionConfiguration sessionConfig) throws CameraAccessException,
            UnsupportedOperationException, IllegalArgumentException {
        synchronized (mInterfaceLock) {
            checkIfCameraClosedOrInError();
            CameraMetadataNative info = mRemoteDevice.getSessionCharacteristics(sessionConfig);

            return new CameraCharacteristics(info);
        }
    }

    /**
     * For use by backwards-compatibility code only.
     */
+42 −2
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package android.hardware.camera2.impl;

import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.content.Context;
import android.hardware.ICameraService;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
@@ -40,15 +41,17 @@ import java.util.concurrent.Executor;
public class CameraDeviceSetupImpl extends CameraDevice.CameraDeviceSetup {
    private final String mCameraId;
    private final CameraManager mCameraManager;
    private final Context mContext;
    private final int mTargetSdkVersion;

    private final Object mInterfaceLock = new Object();

    public CameraDeviceSetupImpl(@NonNull String cameraId, @NonNull CameraManager cameraManager,
            int targetSdkVersion) {
            @NonNull Context context) {
        mCameraId = cameraId;
        mCameraManager = cameraManager;
        mTargetSdkVersion = targetSdkVersion;
        mContext = context;
        mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
    }

    @NonNull
@@ -110,6 +113,43 @@ public class CameraDeviceSetupImpl extends CameraDevice.CameraDeviceSetup {
        }
    }

    @NonNull
    @Override
    public CameraCharacteristics getSessionCharacteristics(
            @NonNull SessionConfiguration sessionConfig) throws CameraAccessException {
        synchronized (mInterfaceLock) {
            if (mCameraManager.isCameraServiceDisabled()) {
                throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
                        "Camera service is currently disabled");
            }

            ICameraService cameraService = mCameraManager.getCameraService();
            if (cameraService == null) {
                throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
                        "Camera service is currently unavailable");
            }

            try {
                CameraMetadataNative metadataNative = cameraService.getSessionCharacteristics(
                        mCameraId, mTargetSdkVersion,
                        CameraManager.shouldOverrideToPortrait(mContext), sessionConfig);

                return new CameraCharacteristics(metadataNative);
            } catch (ServiceSpecificException e) {
                switch (e.errorCode) {
                    case ICameraService.ERROR_INVALID_OPERATION ->
                            throw new UnsupportedOperationException(
                                    "Session Characteristics Query not supported by device.");
                    case ICameraService.ERROR_ILLEGAL_ARGUMENT ->
                            throw new IllegalArgumentException("Invalid Session Configuration");
                    default -> throw ExceptionUtils.throwAsPublicException(e);
                }
            } catch (RemoteException e) {
                throw ExceptionUtils.throwAsPublicException(e);
            }
        }
    }

    @Override
    public void openCamera(@NonNull @CallbackExecutor Executor executor,
            @NonNull CameraDevice.StateCallback callback) throws CameraAccessException {
Loading