Merge 24Q3 (ab/11976889) to aosp-main-future

Bug: 347831320
Merged-In: I9183c2f8b1cae60b705016804cb36780513be854
Change-Id: Ifc0af2d7b44642d06e3696a35ff7c64eb1bbc785
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
index 821b11f..dc99339 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SuppressLint;
 import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraExtensionCharacteristics;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.util.Pair;
@@ -230,6 +231,13 @@
      *
      * <p>For example, an extension may limit the zoom ratio range. In this case, an OEM can return
      * a new zoom ratio range for the key {@link CameraCharacteristics#CONTROL_ZOOM_RATIO_RANGE}.
+     *
+     * <p> Currently, the only synthetic keys supported for override are
+     * {@link CameraCharacteristics#REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES} and
+     * {@link CameraCharacteristics#REQUEST_AVAILABLE_COLOR_SPACE_PROFILES}. To enable them, an OEM
+     * should override the respective native keys
+     * {@link CameraCharacteristics#REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP} and
+     *  {@link CameraCharacteristics#REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP}.
      * @since 1.5
      */
     List<Pair<CameraCharacteristics.Key, Object>> getAvailableCharacteristicsKeyValues();
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AutoAdvancedExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AutoAdvancedExtenderImpl.java
index 06c8c44..c818386 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AutoAdvancedExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AutoAdvancedExtenderImpl.java
@@ -33,6 +33,8 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -62,6 +64,39 @@
                 AWB_MODE_DAYLIGHT);
     }
 
+    @Override
+    public boolean isPostviewAvailable() {
+        return true;
+    }
+
+    @Override
+    public Map<Integer, List<Size>> getSupportedPostviewResolutions(Size captureSize) {
+        Map<Integer, List<Size>> res =  new HashMap<>();
+        Map<Integer, List<Size>> captureSupportedResolutions =
+                getSupportedCaptureOutputResolutions(mCameraId);
+        float targetAr = ((float) captureSize.getWidth()) / captureSize.getHeight();
+
+        List<Size> currFormatSizes = captureSupportedResolutions.get(ImageFormat.YUV_420_888);
+        if (currFormatSizes != null) {
+            List<Size> postviewSizes = new ArrayList<>();
+
+            for (Size s : currFormatSizes) {
+                if ((s.equals(captureSize)) || (s.getWidth() > captureSize.getWidth())
+                        || (s.getHeight() > captureSize.getHeight())) continue;
+                float currentAr = ((float) s.getWidth()) / s.getHeight();
+                if (Math.abs(targetAr - currentAr) < 0.01) {
+                    postviewSizes.add(s);
+                }
+            }
+
+            if (!postviewSizes.isEmpty()) {
+                res.put(ImageFormat.YUV_420_888, postviewSizes);
+            }
+        }
+
+        return res;
+    }
+
     public class AutoAdvancedSessionProcessor extends BaseAdvancedSessionProcessor {
 
         public AutoAdvancedSessionProcessor() {
@@ -78,6 +113,11 @@
             RequestBuilder build = new RequestBuilder(mCaptureOutputConfig.getId(),
                     CameraDevice.TEMPLATE_STILL_CAPTURE, DEFAULT_CAPTURE_ID);
             build.setParameters(CaptureRequest.CONTROL_AWB_MODE, AWB_MODE_DAYLIGHT);
+
+            if (mPostviewOutputSurfaceConfig.getSurface() != null) {
+                build.addTargetOutputConfigIds(mPostviewOutputConfig.getId());
+            }
+
             applyParameters(build);
 
             requestList.add(build.build());
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/BaseAdvancedExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/BaseAdvancedExtenderImpl.java
index b97fdbd..1b61d93 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/BaseAdvancedExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/BaseAdvancedExtenderImpl.java
@@ -23,14 +23,18 @@
 
 import android.annotation.SuppressLint;
 import android.content.Context;
+import android.graphics.ColorSpace;
 import android.graphics.ImageFormat;
 import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraCharacteristics.Key;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CaptureFailure;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.params.ColorSpaceProfiles;
+import android.hardware.camera2.params.DynamicRangeProfiles;
 import android.hardware.camera2.params.StreamConfigurationMap;
 import android.hardware.DataSpace;
 import android.media.Image;
@@ -57,6 +61,7 @@
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 @SuppressLint("UnknownNullness")
 public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
@@ -70,6 +75,12 @@
     }
 
     protected CameraCharacteristics mCameraCharacteristics;
+    protected String mCameraId;
+
+    protected static final Key REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP =
+            new Key<long[]>("android.request.availableDynamicRangeProfilesMap", long[].class);
+    protected static final Key REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP =
+            new Key<long[]>("android.request.availableColorSpaceProfilesMap", long[].class);
 
     public BaseAdvancedExtenderImpl() {
     }
@@ -82,6 +93,7 @@
     public void init(String cameraId,
             Map<String, CameraCharacteristics> characteristicsMap) {
         mCameraCharacteristics = characteristicsMap.get(cameraId);
+        mCameraId = cameraId;
     }
 
     @Override
@@ -115,12 +127,12 @@
     @Override
     public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(String cameraId) {
         return filterOutputResolutions(Arrays.asList(ImageFormat.JPEG, ImageFormat.YUV_420_888,
-                ImageFormat.JPEG_R));
+                ImageFormat.JPEG_R, ImageFormat.YCBCR_P010));
     }
 
     @Override
     public Map<Integer, List<Size>> getSupportedPostviewResolutions(Size captureSize) {
-        return new HashMap<>();
+        return new HashMap<Integer, List<Size>>();
     }
 
     @Override
@@ -138,22 +150,31 @@
 
         protected Camera2OutputConfigImpl mPreviewOutputConfig;
         protected Camera2OutputConfigImpl mCaptureOutputConfig;
+        protected Camera2OutputConfigImpl mPostviewOutputConfig;
 
         protected OutputSurfaceImpl mPreviewOutputSurfaceConfig;
         protected OutputSurfaceImpl mCaptureOutputSurfaceConfig;
+        protected OutputSurfaceImpl mPostviewOutputSurfaceConfig;
 
         protected final Object mLock = new Object();
         @GuardedBy("mLock")
         protected Map<CaptureRequest.Key<?>, Object> mParameters = new LinkedHashMap<>();
 
-        protected final Object mLockCaptureSurfaceImageWriter = new Object();
-        @GuardedBy("mLockCaptureSurfaceImageWriter")
+        protected final Object mLockImageWriter = new Object();
+        @GuardedBy("mLockImageWriter")
         protected ImageWriter mCaptureSurfaceImageWriter;
 
+        @GuardedBy("mLockImageWriter")
+        protected ImageWriter mPostviewSurfaceImageWriter;
+
         protected CaptureResultImageMatcher mImageCaptureCaptureResultImageMatcher =
                 new CaptureResultImageMatcher();
+        protected CaptureResultImageMatcher mPostviewCaptureCaptureResultImageMatcher =
+                new CaptureResultImageMatcher();
         protected HashMap<Integer, Pair<ImageReferenceImpl, TotalCaptureResult>> mCaptureResults =
                 new HashMap<>();
+        protected HashMap<Integer, Pair<ImageReferenceImpl, TotalCaptureResult>> mPostviewResults =
+                new HashMap<>();
         protected RequestProcessorImpl mRequestProcessor;
 
         protected List<Integer> mCaptureIdList = List.of(DEFAULT_CAPTURE_ID);
@@ -177,6 +198,7 @@
 
             mPreviewOutputSurfaceConfig = surfaceConfigs.getPreviewOutputSurface();
             mCaptureOutputSurfaceConfig = surfaceConfigs.getImageCaptureOutputSurface();
+            mPostviewOutputSurfaceConfig = surfaceConfigs.getPostviewOutputSurface();
 
             Camera2SessionConfigImplBuilder builder =
                     new Camera2SessionConfigImplBuilder()
@@ -190,6 +212,9 @@
                         Camera2OutputConfigImplBuilder.newSurfaceConfig(
                             mPreviewOutputSurfaceConfig.getSurface());
 
+                previewOutputConfigBuilder.setDynamicRangeProfile(
+                        mPreviewOutputSurfaceConfig.getDynamicRangeProfile());
+
                 mPreviewOutputConfig = previewOutputConfigBuilder.build();
 
                 builder.addOutputConfig(mPreviewOutputConfig);
@@ -198,7 +223,7 @@
             // Image Capture
             if (mCaptureOutputSurfaceConfig.getSurface() != null) {
 
-                // For this sample, JPEG_R will not be processed
+                // For this sample, JPEG_R or YCBCR_P010 will not be processed
                 if (isJpegR(mCaptureOutputSurfaceConfig)) {
                     Camera2OutputConfigImplBuilder captureOutputConfigBuilder;
 
@@ -210,6 +235,20 @@
 
                     builder.addOutputConfig(mCaptureOutputConfig);
                     mProcessCapture = false;
+                } else if (mCaptureOutputSurfaceConfig.getImageFormat() == ImageFormat.YCBCR_P010) {
+                    Camera2OutputConfigImplBuilder captureOutputConfigBuilder;
+
+                    captureOutputConfigBuilder =
+                            Camera2OutputConfigImplBuilder.newSurfaceConfig(
+                                        mCaptureOutputSurfaceConfig.getSurface());
+
+                    captureOutputConfigBuilder.setDynamicRangeProfile(
+                                mCaptureOutputSurfaceConfig.getDynamicRangeProfile());
+
+                    mCaptureOutputConfig = captureOutputConfigBuilder.build();
+
+                    builder.addOutputConfig(mCaptureOutputConfig);
+                    mProcessCapture = false;
                 } else {
                     Camera2OutputConfigImplBuilder captureOutputConfigBuilder;
 
@@ -226,6 +265,23 @@
                 }
             }
 
+            // Postview
+            if (mPostviewOutputSurfaceConfig.getSurface() != null) {
+                Camera2OutputConfigImplBuilder postviewOutputConfigBuilder;
+
+                postviewOutputConfigBuilder =
+                        Camera2OutputConfigImplBuilder.newImageReaderConfig(
+                                mPostviewOutputSurfaceConfig.getSize(),
+                                ImageFormat.YUV_420_888,
+                                BASIC_CAPTURE_PROCESS_MAX_IMAGES,
+                                mPostviewOutputSurfaceConfig.getUsage());
+
+                mPostviewOutputConfig = postviewOutputConfigBuilder.build();
+
+                builder.addOutputConfig(mPostviewOutputConfig);
+            }
+
+            builder.setColorSpace(surfaceConfigs.getColorSpace());
             addSessionParameter(builder);
 
             return builder.build();
@@ -255,11 +311,16 @@
 
         @Override
         public void deInitSession() {
-            synchronized (mLockCaptureSurfaceImageWriter) {
+            synchronized (mLockImageWriter) {
                 if (mCaptureSurfaceImageWriter != null) {
                     mCaptureSurfaceImageWriter.close();
                     mCaptureSurfaceImageWriter = null;
                 }
+
+                if (mPostviewSurfaceImageWriter != null) {
+                    mPostviewSurfaceImageWriter.close();
+                    mPostviewSurfaceImageWriter = null;
+                }
             }
         }
 
@@ -373,30 +434,39 @@
             mRequestProcessor = requestProcessor;
 
             if (mCaptureOutputSurfaceConfig.getSurface() != null) {
-                synchronized (mLockCaptureSurfaceImageWriter) {
-                    if (isJpegR(mCaptureOutputSurfaceConfig)) {
-                        return;
+                synchronized (mLockImageWriter) {
+                    if (mProcessCapture) {
+                        if (isJpeg(mCaptureOutputSurfaceConfig)) {
+                            mCaptureSurfaceImageWriter = new ImageWriter
+                                    .Builder(mCaptureOutputSurfaceConfig.getSurface())
+                                    .setImageFormat(ImageFormat.JPEG)
+                                    .setMaxImages(MAX_NUM_IMAGES)
+                                    // For JPEG format, width x height should be set to (w*h) x 1
+                                    // since the JPEG image is returned as a 1D byte array
+                                    .setWidthAndHeight(
+                                            mCaptureOutputSurfaceConfig.getSize().getWidth()
+                                            * mCaptureOutputSurfaceConfig.getSize().getHeight(),
+                                            1)
+                                    .build();
+                        } else {
+                            mCaptureSurfaceImageWriter = new ImageWriter
+                                    .Builder(mCaptureOutputSurfaceConfig.getSurface())
+                                    .setImageFormat(mCaptureOutputSurfaceConfig.getImageFormat())
+                                    .setMaxImages(MAX_NUM_IMAGES)
+                                    .build();
+                        }
                     }
+                }
+            }
 
-                    if (isJpeg(mCaptureOutputSurfaceConfig)) {
-                        mCaptureSurfaceImageWriter = new ImageWriter
-                                .Builder(mCaptureOutputSurfaceConfig.getSurface())
-                                .setImageFormat(ImageFormat.JPEG)
-                                .setMaxImages(MAX_NUM_IMAGES)
-                                // For JPEG format, width x height should be set to (w*h) x 1
-                                // since the JPEG image is returned as a 1D byte array
-                                .setWidthAndHeight(
-                                        mCaptureOutputSurfaceConfig.getSize().getWidth()
-                                        * mCaptureOutputSurfaceConfig.getSize().getHeight(),
-                                        1)
-                                .build();
-                    } else {
-                        mCaptureSurfaceImageWriter = new ImageWriter
-                                .Builder(mCaptureOutputSurfaceConfig.getSurface())
-                                .setImageFormat(mCaptureOutputSurfaceConfig.getImageFormat())
-                                .setMaxImages(MAX_NUM_IMAGES)
-                                .build();
-                    }
+            if (mPostviewOutputSurfaceConfig != null
+                    && mPostviewOutputSurfaceConfig.getSurface() != null) {
+                synchronized (mLockImageWriter) {
+                    mPostviewSurfaceImageWriter = new ImageWriter
+                            .Builder(mPostviewOutputSurfaceConfig.getSurface())
+                            .setImageFormat(mPostviewOutputSurfaceConfig.getImageFormat())
+                            .setMaxImages(MAX_NUM_IMAGES)
+                            .build();
                 }
             }
         }
@@ -405,6 +475,7 @@
         public void onCaptureSessionEnd() {
             synchronized (this) {
                 mImageCaptureCaptureResultImageMatcher.clear();
+                mPostviewCaptureCaptureResultImageMatcher.clear();
             }
 
             mRequestProcessor = null;
@@ -498,6 +569,7 @@
 
         @Override
         public int startCaptureWithPostview(@NonNull CaptureCallback captureCallback) {
+            Log.d(TAG, "startCaptureWithPostview");
             return startCapture(captureCallback);
         }
 
@@ -529,6 +601,12 @@
 
                     addCaptureResultKeys(seqId, totalCaptureResult, captureCallback);
 
+                    if (mPostviewOutputSurfaceConfig != null) {
+                        mPostviewCaptureCaptureResultImageMatcher.setCameraCaptureCallback(
+                            totalCaptureResult,
+                            requestProcessorRequest.getCaptureStageId());
+                    }
+
                     if (!mProcessCapture) {
                         captureCallback.onCaptureProcessStarted(seqId);
                     } else {
@@ -566,6 +644,33 @@
 
             mRequestProcessor.submit(requestList, callback);
 
+            if (mPostviewOutputSurfaceConfig != null &&
+                    mPostviewOutputSurfaceConfig.getSurface() != null) {
+                mRequestProcessor.setImageProcessor(mPostviewOutputConfig.getId(),
+                        new ImageProcessorImpl() {
+                                @Override
+                                public void onNextImageAvailable(int outputStreamId,
+                                        long timestampNs,
+                                        @NonNull ImageReferenceImpl imgReferenceImpl,
+                                        @Nullable String physicalCameraId) {
+                                    mPostviewCaptureCaptureResultImageMatcher
+                                            .setInputImage(imgReferenceImpl);
+                                }
+                });
+
+                mPostviewCaptureCaptureResultImageMatcher.setImageReferenceListener(
+                        new CaptureResultImageMatcher.ImageReferenceListener() {
+                                    @Override
+                                    public void onImageReferenceIncoming(
+                                            @NonNull ImageReferenceImpl imageReferenceImpl,
+                                            @NonNull TotalCaptureResult totalCaptureResult,
+                                            int captureId) {
+                                        processImageCapture(imageReferenceImpl, totalCaptureResult,
+                                                captureId, true /*isPostview*/);
+                                    }
+                });
+            }
+
             if (mCaptureOutputSurfaceConfig.getSurface() != null && mProcessCapture) {
                 mRequestProcessor.setImageProcessor(mCaptureOutputConfig.getId(),
                         new ImageProcessorImpl() {
@@ -588,7 +693,7 @@
                                             int captureId) {
                                         captureCallback.onCaptureProcessStarted(seqId);
                                         processImageCapture(imageReferenceImpl, totalCaptureResult,
-                                                captureId);
+                                                captureId, false /*isPostview*/);
                                     }
                 });
             }
@@ -597,20 +702,25 @@
         }
 
         protected void processImageCapture(@NonNull ImageReferenceImpl imageReferenceImpl,
-                @NonNull TotalCaptureResult totalCaptureResult,
-                int captureId) {
+                @NonNull TotalCaptureResult totalCaptureResult, int captureId,
+                boolean isPostview) {
 
-            mCaptureResults.put(captureId, new Pair<>(imageReferenceImpl, totalCaptureResult));
+            HashMap<Integer, Pair<ImageReferenceImpl, TotalCaptureResult>> captureResults =
+                    isPostview ? mPostviewResults : mCaptureResults;
+            ImageWriter imageWriter = isPostview ? mPostviewSurfaceImageWriter :
+                    mCaptureSurfaceImageWriter;
 
-            if (mCaptureResults.keySet().containsAll(mCaptureIdList)) {
+            captureResults.put(captureId, new Pair<>(imageReferenceImpl, totalCaptureResult));
+
+            if (captureResults.keySet().containsAll(mCaptureIdList)) {
                 List<Pair<ImageReferenceImpl, TotalCaptureResult>> imageDataPairs =
-                        new ArrayList<>(mCaptureResults.values());
+                        new ArrayList<>(captureResults.values());
 
                 Image resultImage = null;
                 int captureSurfaceWriterImageFormat = ImageFormat.UNKNOWN;
-                synchronized (mLockCaptureSurfaceImageWriter) {
-                    resultImage = mCaptureSurfaceImageWriter.dequeueInputImage();
-                    captureSurfaceWriterImageFormat = mCaptureSurfaceImageWriter.getFormat();
+                synchronized (mLockImageWriter) {
+                    resultImage = imageWriter.dequeueInputImage();
+                    captureSurfaceWriterImageFormat = imageWriter.getFormat();
                 }
 
                 if (captureSurfaceWriterImageFormat == ImageFormat.JPEG) {
@@ -648,11 +758,11 @@
                                 DEFAULT_CAPTURE_ID).first.get().getTimestamp());
                 }
 
-                synchronized (mLockCaptureSurfaceImageWriter) {
-                    mCaptureSurfaceImageWriter.queueInputImage(resultImage);
+                synchronized (mLockImageWriter) {
+                    imageWriter.queueInputImage(resultImage);
                 }
 
-                for (Pair<ImageReferenceImpl, TotalCaptureResult> val : mCaptureResults.values()) {
+                for (Pair<ImageReferenceImpl, TotalCaptureResult> val : captureResults.values()) {
                     val.first.decrement();
                 }
             } else {
@@ -742,18 +852,62 @@
 
     @Override
     public List<Pair<CameraCharacteristics.Key, Object>> getAvailableCharacteristicsKeyValues() {
+        int[] caps = mCameraCharacteristics
+                .get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+
+        Set<Integer> unsupportedCapabilities = new HashSet<>(Arrays.asList(
+                CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT,
+                CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_RAW,
+                CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING,
+                CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING,
+                CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO,
+                CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_OFFLINE_PROCESSING,
+                CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_REMOSAIC_REPROCESSING,
+                CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME,
+                CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_SECURE_IMAGE_DATA,
+                CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_SYSTEM_CAMERA,
+                CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_ULTRA_HIGH_RESOLUTION_SENSOR
+        ));
+
+        List<Integer> filtered = new ArrayList<>();
+        for (int c : caps) {
+            if (unsupportedCapabilities.contains(c)) {
+                continue;
+            }
+            filtered.add(c);
+        }
+        int[] extensionsCaps = new int[filtered.size()];
+        for (int i = 0; i < filtered.size(); i++) {
+                extensionsCaps[i] = filtered.get(i);
+        }
+
+        long[] dynamicRangeProfileArray = new long[]{
+                DynamicRangeProfiles.HLG10,
+                DynamicRangeProfiles.HLG10 | DynamicRangeProfiles.STANDARD,
+                0L};
+        long[] colorSpacesProfileArray = new long[]{
+                ColorSpace.Named.BT2020_HLG.ordinal(),
+                ImageFormat.YCBCR_P010,
+                DynamicRangeProfiles.HLG10};
+
         Range<Float> zoomRange = mCameraCharacteristics
                     .get(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE);
         float zoomRangeLower = Math.max(1f, zoomRange.getLower());
         float zoomRangeUpper = Math.min(10f, zoomRange.getUpper());
         return Arrays.asList(
+                Pair.create(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES,
+                        extensionsCaps),
                 Pair.create(CameraCharacteristics.CONTROL_ZOOM_RATIO_RANGE,
                         Range.create(zoomRangeLower, zoomRangeUpper)),
                 Pair.create(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES,
                         new int[]{
                                 CameraMetadata.CONTROL_AF_MODE_OFF,
                                 CameraMetadata.CONTROL_AF_MODE_AUTO
-                        })
+                        }),
+                Pair.create(REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP,
+                        dynamicRangeProfileArray),
+                Pair.create(REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP,
+                        colorSpacesProfileArray)
         );
     }
 }
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImpl.java
index 68de01b..fe0cddf 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImpl.java
@@ -17,6 +17,7 @@
 package androidx.camera.extensions.impl.advanced;
 
 import android.annotation.SuppressLint;
+import android.hardware.camera2.params.DynamicRangeProfiles;
 
 import java.util.List;
 
@@ -44,6 +45,15 @@
     String getPhysicalCameraId();
 
     /**
+     * Gets the dynamic range profile.
+     *
+     * @since 1.5
+     */
+    default long getDynamicRangeProfile() {
+        return DynamicRangeProfiles.STANDARD;
+    }
+
+    /**
      * If non-null, enable surface sharing and add the surface constructed by the return
      * Camera2OutputConfig.
      */
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java
index 9ae5f83..95cd48d 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java
@@ -17,6 +17,7 @@
 package androidx.camera.extensions.impl.advanced;
 
 import android.annotation.SuppressLint;
+import android.hardware.camera2.params.DynamicRangeProfiles;
 import android.hardware.camera2.params.OutputConfiguration;
 import android.util.Size;
 import android.view.Surface;
@@ -35,6 +36,7 @@
     private int mSurfaceGroupId = OutputConfiguration.SURFACE_GROUP_ID_NONE;
     private String mPhysicalCameraId;
     private List<Camera2OutputConfigImpl> mSurfaceSharingConfigs;
+    private long mDynamicRangeProfile = DynamicRangeProfiles.STANDARD;
 
     private Camera2OutputConfigImplBuilder(OutputConfigImplImpl outputConfig) {
         mOutputConfig = outputConfig;
@@ -93,6 +95,14 @@
     }
 
     /**
+     * Set dynamic range profile.
+     */
+    public Camera2OutputConfigImplBuilder setDynamicRangeProfile(long dynamicRangeProfile) {
+        mDynamicRangeProfile = dynamicRangeProfile;
+        return this;
+    }
+
+    /**
      * Sets surface group id.
      */
     public Camera2OutputConfigImplBuilder setSurfaceGroupId(int surfaceGroupId) {
@@ -108,6 +118,7 @@
         mOutputConfig.setPhysicalCameraId(mPhysicalCameraId);
         mOutputConfig.setSurfaceGroup(mSurfaceGroupId);
         mOutputConfig.setSurfaceSharingConfigs(mSurfaceSharingConfigs);
+        mOutputConfig.setDynamicRangeProfile(mDynamicRangeProfile);
         return mOutputConfig;
     }
 
@@ -115,6 +126,7 @@
         private int mId;
         private int mSurfaceGroup;
         private String mPhysicalCameraId;
+        private long mDynamicRangeProfile;
         private List<Camera2OutputConfigImpl> mSurfaceSharingConfigs;
 
         OutputConfigImplImpl() {
@@ -122,6 +134,7 @@
             mSurfaceGroup = 0;
             mPhysicalCameraId = null;
             mSurfaceSharingConfigs = null;
+            mDynamicRangeProfile = DynamicRangeProfiles.STANDARD;
         }
 
         @Override
@@ -140,6 +153,11 @@
         }
 
         @Override
+        public long getDynamicRangeProfile() {
+            return mDynamicRangeProfile;
+        }
+
+        @Override
         public List<Camera2OutputConfigImpl> getSurfaceSharingOutputConfigs() {
             return mSurfaceSharingConfigs;
         }
@@ -156,6 +174,10 @@
             mPhysicalCameraId = physicalCameraId;
         }
 
+        public void setDynamicRangeProfile(long dynamicRangeProfile) {
+            mDynamicRangeProfile = dynamicRangeProfile;
+        }
+
         public void setSurfaceSharingConfigs(
                 List<Camera2OutputConfigImpl> surfaceSharingConfigs) {
             mSurfaceSharingConfigs = surfaceSharingConfigs;
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImpl.java
index 6fb45bc..0b7d59b 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImpl.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SuppressLint;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.params.ColorSpaceProfiles;
 
 import java.util.List;
 import java.util.Map;
@@ -54,4 +55,14 @@
      * will be configured to use the default regular type.
      */
     int getSessionType();
+
+    /**
+     * Gets the color space.
+     *
+     * @since 1.5
+     * @return {@link android.graphics#ColorSpace.Named} set for session configuration
+     */
+    default int getColorSpace() {
+        return ColorSpaceProfiles.UNSPECIFIED;
+    }
 }
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImplBuilder.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImplBuilder.java
index dc1fecc..e745624 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImplBuilder.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImplBuilder.java
@@ -20,6 +20,7 @@
 import android.annotation.SuppressLint;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.params.ColorSpaceProfiles;
 import android.hardware.camera2.params.SessionConfiguration;
 
 import java.util.ArrayList;
@@ -33,6 +34,7 @@
 @SuppressLint("UnknownNullness")
 public class Camera2SessionConfigImplBuilder {
     private int mSessionTemplateId = CameraDevice.TEMPLATE_PREVIEW;
+    private int mColorSpace = ColorSpaceProfiles.UNSPECIFIED;
     private int mSessionType = SessionConfiguration.SESSION_REGULAR;
     Map<CaptureRequest.Key<?>, Object> mSessionParameters = new HashMap<>();
     List<Camera2OutputConfigImpl> mCamera2OutputConfigs = new ArrayList<>();
@@ -67,6 +69,21 @@
     }
 
     /**
+     * Sets the color space.
+     */
+    public Camera2SessionConfigImplBuilder setColorSpace(int colorSpace) {
+        mColorSpace = colorSpace;
+        return this;
+    }
+
+    /**
+     * Gets the color space.
+     */
+    public int getColorSpace() {
+        return mColorSpace;
+    }
+
+    /**
      * Gets the session template id.
      */
     public int getSessionTemplateId() {
@@ -105,12 +122,14 @@
             Camera2SessionConfigImpl {
         int mSessionTemplateId;
         int mSessionType;
+        int mColorSpace = ColorSpaceProfiles.UNSPECIFIED;
         Map<CaptureRequest.Key<?>, Object> mSessionParameters;
         List<Camera2OutputConfigImpl> mCamera2OutputConfigs;
 
         Camera2SessionConfigImplImpl(Camera2SessionConfigImplBuilder builder) {
             mSessionTemplateId = builder.getSessionTemplateId();
             mSessionParameters = builder.getSessionParameters();
+            mColorSpace = builder.getColorSpace();
             mCamera2OutputConfigs = builder.getCamera2OutputConfigs();
             mSessionType = builder.getSessionType();
         }
@@ -134,6 +153,11 @@
         public int getSessionType() {
             return mSessionType;
         }
+
+        @Override
+        public int getColorSpace() {
+            return mColorSpace;
+        }
     }
 }
 
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java
index 68a84b7..1a3a099 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/HdrAdvancedExtenderImpl.java
@@ -247,7 +247,7 @@
 
                 Image resultImage = null;
                 int captureSurfaceWriterImageFormat = ImageFormat.UNKNOWN;
-                synchronized (mLockCaptureSurfaceImageWriter) {
+                synchronized (mLockImageWriter) {
                     resultImage = mCaptureSurfaceImageWriter.dequeueInputImage();
                     captureSurfaceWriterImageFormat = mCaptureSurfaceImageWriter.getFormat();
                 }
@@ -290,7 +290,7 @@
                         UNDER_EXPOSED_CAPTURE_ID).first.get().getTimestamp());
                 }
 
-                synchronized (mLockCaptureSurfaceImageWriter) {
+                synchronized (mLockImageWriter) {
                     mCaptureSurfaceImageWriter.queueInputImage(resultImage);
                 }
 
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java
index ba4ea4c..86ea363 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/NightAdvancedExtenderImpl.java
@@ -27,6 +27,7 @@
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.params.DynamicRangeProfiles;
 import android.media.Image;
 import android.media.Image.Plane;
 import android.media.ImageWriter;
@@ -39,6 +40,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -70,6 +72,8 @@
 
     public class NightAdvancedSessionProcessor extends BaseAdvancedSessionProcessor {
 
+        protected boolean mProcessPreview = true;
+
         public NightAdvancedSessionProcessor() {
             appendTag("::Night");
         }
@@ -101,12 +105,23 @@
             if (mPreviewOutputSurfaceConfig.getSurface() != null) {
                 Camera2OutputConfigImplBuilder previewOutputConfigBuilder;
 
-                previewOutputConfigBuilder =
-                        Camera2OutputConfigImplBuilder.newImageReaderConfig(
-                                mPreviewOutputSurfaceConfig.getSize(),
-                                ImageFormat.YUV_420_888,
-                                BASIC_CAPTURE_PROCESS_MAX_IMAGES,
-                                mPreviewOutputSurfaceConfig.getUsage());
+                if (mPreviewOutputSurfaceConfig.getDynamicRangeProfile() ==
+                        DynamicRangeProfiles.STANDARD) {
+                    previewOutputConfigBuilder =
+                    Camera2OutputConfigImplBuilder.newImageReaderConfig(
+                            mPreviewOutputSurfaceConfig.getSize(),
+                            ImageFormat.YUV_420_888,
+                            BASIC_CAPTURE_PROCESS_MAX_IMAGES,
+                            mPreviewOutputSurfaceConfig.getUsage());
+                } else {
+                    previewOutputConfigBuilder =
+                    Camera2OutputConfigImplBuilder.newSurfaceConfig(
+                        mPreviewOutputSurfaceConfig.getSurface());
+                    previewOutputConfigBuilder.setDynamicRangeProfile(
+                            mPreviewOutputSurfaceConfig.getDynamicRangeProfile());
+
+                    mProcessPreview = false;
+                }
 
                 mPreviewOutputConfig = previewOutputConfigBuilder.build();
 
@@ -116,7 +131,7 @@
             // Image Capture
             if (mCaptureOutputSurfaceConfig.getSurface() != null) {
 
-                // For this sample, JPEG_R will not be processed
+                // For this sample, JPEG_R or YCBCR_P010 will not be processed
                 if (isJpegR(mCaptureOutputSurfaceConfig)) {
                     Camera2OutputConfigImplBuilder captureOutputConfigBuilder;
 
@@ -128,6 +143,20 @@
 
                     builder.addOutputConfig(mCaptureOutputConfig);
                     mProcessCapture = false;
+                } else if (mCaptureOutputSurfaceConfig.getImageFormat() == ImageFormat.YCBCR_P010) {
+                    Camera2OutputConfigImplBuilder captureOutputConfigBuilder;
+
+                    captureOutputConfigBuilder =
+                            Camera2OutputConfigImplBuilder.newSurfaceConfig(
+                                        mCaptureOutputSurfaceConfig.getSurface());
+
+                    captureOutputConfigBuilder.setDynamicRangeProfile(
+                            mCaptureOutputSurfaceConfig.getDynamicRangeProfile());
+
+                    mCaptureOutputConfig = captureOutputConfigBuilder.build();
+
+                    builder.addOutputConfig(mCaptureOutputConfig);
+                    mProcessCapture = false;
                 } else {
                     Camera2OutputConfigImplBuilder captureOutputConfigBuilder;
 
@@ -144,6 +173,7 @@
                 }
             }
 
+            builder.setColorSpace(surfaceConfigs.getColorSpace());
             addSessionParameter(builder);
 
             return builder.build();
@@ -170,6 +200,10 @@
         public void onCaptureSessionStart(@NonNull RequestProcessorImpl requestProcessor) {
             super.onCaptureSessionStart(requestProcessor);
 
+            if (!mProcessPreview) {
+                return;
+            }
+
             if (mPreviewOutputSurfaceConfig.getSurface() != null) {
                 synchronized (mLockPreviewSurfaceImageWriter) {
                     mPreviewSurfaceImageWriter = new ImageWriter
@@ -246,8 +280,10 @@
 
                     addCaptureResultKeys(seqId, totalCaptureResult, captureCallback);
 
-                    mCaptureResultImageMatcher.setCameraCaptureCallback(
-                                totalCaptureResult);
+                    if (mProcessPreview) {
+                        mCaptureResultImageMatcher.setCameraCaptureCallback(
+                            totalCaptureResult);
+                    }
 
                     captureCallback.onCaptureProcessStarted(seqId);
                 }
@@ -295,4 +331,22 @@
     public SessionProcessorImpl createSessionProcessor() {
         return new NightAdvancedSessionProcessor();
     }
+
+    @Override
+    public List<CaptureRequest.Key> getAvailableCaptureRequestKeys() {
+        final CaptureRequest.Key [] CAPTURE_REQUEST_SET = {CaptureRequest.CONTROL_ZOOM_RATIO,
+            CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_REGIONS,
+            CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.JPEG_QUALITY,
+            CaptureRequest.JPEG_ORIENTATION};
+        return Arrays.asList(CAPTURE_REQUEST_SET);
+    }
+
+    @Override
+    public List<CaptureResult.Key> getAvailableCaptureResultKeys() {
+        final CaptureResult.Key [] CAPTURE_RESULT_SET = {CaptureResult.CONTROL_ZOOM_RATIO,
+            CaptureResult.CONTROL_AF_MODE, CaptureResult.CONTROL_AF_REGIONS,
+            CaptureResult.CONTROL_AF_TRIGGER, CaptureResult.CONTROL_AF_STATE,
+            CaptureResult.JPEG_QUALITY, CaptureResult.JPEG_ORIENTATION};
+        return Arrays.asList(CAPTURE_RESULT_SET);
+    }
 }
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceConfigurationImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceConfigurationImpl.java
index ca3832e..8fe3514 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceConfigurationImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceConfigurationImpl.java
@@ -17,6 +17,7 @@
 package androidx.camera.extensions.impl.advanced;
 
 import android.annotation.SuppressLint;
+import android.hardware.camera2.params.ColorSpaceProfiles;
 
 /**
  * For specifying the output surface configurations for the extension.
@@ -32,4 +33,13 @@
     public OutputSurfaceImpl getImageAnalysisOutputSurface();
 
     public OutputSurfaceImpl getPostviewOutputSurface();
+
+    /*
+     * Gets the color space.
+     *
+     * @since 1.5
+     */
+    default int getColorSpace() {
+        return ColorSpaceProfiles.UNSPECIFIED;
+    }
 }
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java
index f173c1b..33759b0 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java
@@ -17,6 +17,7 @@
 package androidx.camera.extensions.impl.advanced;
 
 import android.annotation.SuppressLint;
+import android.hardware.camera2.params.DynamicRangeProfiles;
 import android.util.Size;
 import android.view.Surface;
 
@@ -49,4 +50,13 @@
      * Get the surface usage bits.
      */
     long getUsage();
+
+    /**
+     * Gets the dynamic range profile.
+     *
+     * @since 1.5
+     */
+    default long getDynamicRangeProfile() {
+        return DynamicRangeProfiles.STANDARD;
+    }
 }
diff --git a/camera2/extensions/eyesFreeVidSample/Android.bp b/camera2/extensions/eyesFreeVidSample/Android.bp
index 3d9567e..d555190 100644
--- a/camera2/extensions/eyesFreeVidSample/Android.bp
+++ b/camera2/extensions/eyesFreeVidSample/Android.bp
@@ -20,8 +20,19 @@
     name: "EyesFreeVidService",
     srcs: ["src/**/*.java"],
     static_libs: [
-        "androidx.annotation_annotation"
+        "androidx.annotation_annotation",
     ],
     platform_apis: true,
-    system_ext_specific: true
+    system_ext_specific: true,
+    required: ["privapp-permissions-efv.xml"],
+    privileged: true,
+    certificate: "platform",
+}
+
+prebuilt_etc {
+    name: "privapp-permissions-efv.xml",
+    system_ext_specific: true,
+    sub_dir: "permissions",
+    src: "privapp-permissions-efv.xml",
+    filename_from_src: true,
 }
diff --git a/camera2/extensions/eyesFreeVidSample/AndroidManifest.xml b/camera2/extensions/eyesFreeVidSample/AndroidManifest.xml
index 1e53b09..6cf1d91 100644
--- a/camera2/extensions/eyesFreeVidSample/AndroidManifest.xml
+++ b/camera2/extensions/eyesFreeVidSample/AndroidManifest.xml
@@ -2,6 +2,9 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="android.camera.extensions.impl.service">
 
+    <uses-permission android:name="android.permission.SYSTEM_CAMERA" />
+    <uses-permission android:name="android.permission.CAMERA" />
+
     <application
         android:defaultToDeviceProtectedStorage="true"
         android:forceQueryable="true"
diff --git a/camera2/extensions/eyesFreeVidSample/privapp-permissions-efv.xml b/camera2/extensions/eyesFreeVidSample/privapp-permissions-efv.xml
new file mode 100644
index 0000000..87a5bd6
--- /dev/null
+++ b/camera2/extensions/eyesFreeVidSample/privapp-permissions-efv.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<!--
+This XML file declares which signature|privileged permissions should be granted to privileged
+applications that come with the platform
+-->
+<permissions>
+    <privapp-permissions package="android.camera.extensions.impl.service">
+        <permission name="android.permission.SYSTEM_CAMERA"/>
+    </privapp-permissions>
+</permissions>
\ No newline at end of file
diff --git a/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidService.java b/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidService.java
index d175c1a..496ead1 100644
--- a/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidService.java
+++ b/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidService.java
@@ -25,8 +25,10 @@
 import java.util.Set;
 
 import android.annotation.FlaggedApi;
+import android.graphics.ColorSpace;
 import android.graphics.ImageFormat;
 import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraCharacteristics.Key;
 import android.hardware.camera2.CameraExtensionCharacteristics;
 import android.hardware.camera2.CameraManager;
 import android.hardware.camera2.CameraMetadata;
@@ -38,6 +40,8 @@
 import android.hardware.camera2.extension.CameraExtensionService;
 import android.hardware.camera2.extension.CharacteristicsMap;
 import android.hardware.camera2.extension.SessionProcessor;
+import android.hardware.camera2.params.ColorSpaceProfiles;
+import android.hardware.camera2.params.DynamicRangeProfiles;
 import android.hardware.camera2.params.StreamConfiguration;
 import android.hardware.camera2.params.StreamConfigurationDuration;
 import android.hardware.camera2.params.StreamConfigurationMap;
@@ -50,7 +54,7 @@
 
 import com.android.internal.camera.flags.Flags;
 
-@FlaggedApi(Flags.FLAG_CONCERT_MODE)
+@FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
 public class EyesFreeVidService extends CameraExtensionService {
 
     private static final String TAG = "EyesFreeVidService";
@@ -60,7 +64,12 @@
     private final Set<IBinder> mAttachedClients = new HashSet<>();
     CameraManager mCameraManager;
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    protected static final Key REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP =
+            new Key<long[]>("android.request.availableDynamicRangeProfilesMap", long[].class);
+    protected static final Key REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP =
+            new Key<long[]>("android.request.availableColorSpaceProfilesMap", long[].class);
+
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     @Override
     public boolean onRegisterClient(IBinder token) {
         synchronized (mLock) {
@@ -72,7 +81,7 @@
         }
     }
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     @Override
     public void onUnregisterClient(IBinder token) {
         synchronized (mLock) {
@@ -80,7 +89,7 @@
         }
     }
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     @Override
     public AdvancedExtender onInitializeAdvancedExtension(int extensionType) {
         mCameraManager = getSystemService(CameraManager.class);
@@ -93,29 +102,29 @@
         }
     }
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     public static class AdvancedExtenderEyesFreeImpl extends AdvancedExtender {
         private CameraCharacteristics mCameraCharacteristics;
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         public AdvancedExtenderEyesFreeImpl(@NonNull CameraManager cameraManager) {
             super(cameraManager);
         }
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         @Override
         public boolean isExtensionAvailable(String cameraId,
                 CharacteristicsMap charsMap) {
             return true;
         }
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         @Override
         public void initialize(String cameraId, CharacteristicsMap map) {
             mCameraCharacteristics = map.get(cameraId);
         }
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         @Override
         public Map<Integer, List<Size>> getSupportedPreviewOutputResolutions(
                 String cameraId) {
@@ -144,21 +153,21 @@
             return mCameraCharacteristics;
         }
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         @Override
         public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(
                 String cameraId) {
             return filterOutputResolutions(Arrays.asList(ImageFormat.YUV_420_888,
-                    ImageFormat.JPEG));
+                    ImageFormat.JPEG, ImageFormat.JPEG_R, ImageFormat.YCBCR_P010));
         }
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         @Override
         public SessionProcessor getSessionProcessor() {
             return new EyesFreeVidSessionProcessor(this);
         }
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         @Override
         public List<CaptureRequest.Key> getAvailableCaptureRequestKeys(
                 String cameraId) {
@@ -174,7 +183,7 @@
             return Arrays.asList(CAPTURE_REQUEST_SET);
         }
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         @Override
         public List<CaptureResult.Key> getAvailableCaptureResultKeys(
                 String cameraId) {
@@ -272,6 +281,15 @@
                     new StreamConfigurationDuration[tmpStallDurations.size()];
             filteredStallDurations = tmpStallDurations.toArray(filteredStallDurations);
 
+            long[] dynamicRangeProfileArray = new long[]{
+                    DynamicRangeProfiles.HLG10,
+                    DynamicRangeProfiles.HLG10 | DynamicRangeProfiles.STANDARD,
+                    0L};
+            long[] colorSpacesProfileArray = new long[]{
+                    ColorSpace.Named.BT2020_HLG.ordinal(),
+                    ImageFormat.YCBCR_P010,
+                    DynamicRangeProfiles.HLG10};
+
             return Arrays.asList(
                     Pair.create(CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
                             filteredConfigurations),
@@ -293,33 +311,37 @@
                                     .CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION
                             }),
                     Pair.create(CameraExtensionCharacteristics.EFV_PADDING_ZOOM_FACTOR_RANGE,
-                            new Range<Float>(1.0f, 2.0f))
+                            new Range<Float>(1.0f, 2.0f)),
+                    Pair.create(REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP,
+                            dynamicRangeProfileArray),
+                    Pair.create(REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP,
+                            colorSpacesProfileArray)
             );
         }
     }
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     public static class AdvancedExtenderImpl extends AdvancedExtender {
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         public AdvancedExtenderImpl(@NonNull CameraManager cameraManager) {
             super(cameraManager);
         }
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         @Override
         public boolean isExtensionAvailable(String cameraId,
                 CharacteristicsMap charsMap) {
             return false;
         }
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         @Override
         public void initialize(String cameraId, CharacteristicsMap map) {
             throw new RuntimeException("Extension not supported");
         }
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         @Override
         public Map<Integer, List<Size>> getSupportedPreviewOutputResolutions(
                 String cameraId) {
@@ -334,20 +356,20 @@
             throw new RuntimeException("Extension not supported");
         }
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         @Override
         public Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(
                 String cameraId) {
             throw new RuntimeException("Extension not supported");
         }
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         @Override
         public SessionProcessor getSessionProcessor() {
             throw new RuntimeException("Extension not supported");
         }
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         @Override
         public List<CaptureRequest.Key> getAvailableCaptureRequestKeys(
                 String cameraId) {
@@ -355,7 +377,7 @@
 
         }
 
-        @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+        @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
         @Override
         public List<CaptureResult.Key> getAvailableCaptureResultKeys(
                 String cameraId) {
diff --git a/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidSessionProcessor.java b/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidSessionProcessor.java
index 92f371f..9158792 100644
--- a/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidSessionProcessor.java
+++ b/camera2/extensions/eyesFreeVidSample/src/android/camera/extensions/impl/service/EyesFreeVidSessionProcessor.java
@@ -28,6 +28,7 @@
 import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.camera.extensions.impl.service.EyesFreeVidService.AdvancedExtenderEyesFreeImpl;
+import android.graphics.ImageFormat;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.hardware.camera2.CameraAccessException;
@@ -61,7 +62,7 @@
 import java.util.concurrent.atomic.AtomicBoolean;
 
 
-@FlaggedApi(Flags.FLAG_CONCERT_MODE)
+@FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
 public class EyesFreeVidSessionProcessor extends SessionProcessor {
 
     private static final String TAG = "EyesFreeVidSessionProcessor";
@@ -93,12 +94,12 @@
 
     protected AtomicBoolean mOnCaptureSessionEndStarted = new AtomicBoolean(false);
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     protected EyesFreeVidSessionProcessor(AdvancedExtenderEyesFreeImpl advancedExtender) {
         mAdvancedExtender = advancedExtender;
     }
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     public ExtensionConfiguration initSession(@NonNull IBinder token,
             @NonNull String cameraId, @NonNull CharacteristicsMap map,
             @NonNull CameraOutputSurface previewSurface,
@@ -126,9 +127,10 @@
                     previewSurface.getSize().getHeight(), previewSurface.getImageFormat(),
                     MAX_NUM_IMAGES, SurfaceUtils.getSurfaceUsage(previewSurface.getSurface()));
 
-            List<CameraOutputSurface> previewList = new ArrayList<>(List.of(
-                    new CameraOutputSurface(mPreviewImageReader.getSurface(),
-                    previewSurface.getSize())));
+            CameraOutputSurface previewOutputSurface = new CameraOutputSurface(
+                    mPreviewImageReader.getSurface(), previewSurface.getSize());
+            previewOutputSurface.setDynamicRangeProfile(previewSurface.getDynamicRangeProfile());
+            List<CameraOutputSurface> previewList = new ArrayList<>(List.of(previewOutputSurface));
 
             ExtensionOutputConfiguration previewConfig = new ExtensionOutputConfiguration(
                     previewList, PREVIEW_OUTPUT_ID, null, -1);
@@ -138,10 +140,15 @@
         ExtensionConfiguration res = new ExtensionConfiguration(0 /*session type*/,
                 CameraDevice.TEMPLATE_PREVIEW, outputs, null);
 
+        if (imageCaptureSurface != null
+                && imageCaptureSurface.getImageFormat() == ImageFormat.YCBCR_P010) {
+            res.setColorSpace(imageCaptureSurface.getColorSpace());
+        }
+
         return res;
     }
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     @Override
     public void deInitSession(@NonNull IBinder token) {
         if (mPreviewImageReader != null) {
@@ -163,7 +170,7 @@
         }
     }
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     @Override
     public void onCaptureSessionStart(@NonNull RequestProcessor requestProcessor,
             @NonNull String statsKey) {
@@ -188,7 +195,7 @@
         mPreviewImageReader.setOnImageAvailableListener(new ImageListener(), mHandler);
     }
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     @Override
     public void onCaptureSessionEnd() {
         mOnCaptureSessionEndStarted.set(true);
@@ -200,7 +207,7 @@
         mRequestProcessor = null;
     }
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     @Override
     public int startRepeating(@NonNull Executor executor,
             @NonNull CaptureCallback captureCallback) {
@@ -375,13 +382,13 @@
         return mParametersList;
     }
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     @Override
     public void stopRepeating() {
         mRequestProcessor.stopRepeating();
     }
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     @Override
     public int startMultiFrameCapture(@NonNull Executor executor,
             @NonNull CaptureCallback captureCallback) {
@@ -446,7 +453,7 @@
         return seqId;
     }
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     @Override
     public int startTrigger(@NonNull CaptureRequest captureRequest,
             @NonNull Executor executor, @NonNull CaptureCallback captureCallback) {
@@ -526,7 +533,7 @@
         return parameters;
     }
 
-    @FlaggedApi(Flags.FLAG_CONCERT_MODE)
+    @FlaggedApi(Flags.FLAG_CONCERT_MODE_API)
     @Override
     public void setParameters(@NonNull CaptureRequest captureRequest) {
         synchronized (mParametersLock) {
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
index abf8d45..4386b5e 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
@@ -233,6 +233,13 @@
      * {@link CameraCharacteristics#CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION} and
      * {@link CameraCharacteristics#CONTROL_VIDEO_STABILIZATION_MODE_OFF} for the key
      * {@link CameraCharacteristics#CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES}.
+     *
+     * <p> Currently, the only synthetic keys supported for override are
+     * {@link CameraCharacteristics#REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES} and
+     * {@link CameraCharacteristics#REQUEST_AVAILABLE_COLOR_SPACE_PROFILES}. To enable them, an OEM
+     * should override the respective native keys
+     * {@link CameraCharacteristics#REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP} and
+     *  {@link CameraCharacteristics#REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP}.
      * @since 1.5
      */
     List<Pair<CameraCharacteristics.Key, Object>> getAvailableCharacteristicsKeyValues();
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImpl.java
index 68de01b..fe0cddf 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImpl.java
@@ -17,6 +17,7 @@
 package androidx.camera.extensions.impl.advanced;
 
 import android.annotation.SuppressLint;
+import android.hardware.camera2.params.DynamicRangeProfiles;
 
 import java.util.List;
 
@@ -44,6 +45,15 @@
     String getPhysicalCameraId();
 
     /**
+     * Gets the dynamic range profile.
+     *
+     * @since 1.5
+     */
+    default long getDynamicRangeProfile() {
+        return DynamicRangeProfiles.STANDARD;
+    }
+
+    /**
      * If non-null, enable surface sharing and add the surface constructed by the return
      * Camera2OutputConfig.
      */
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java
index 365abc3..541ade6 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2OutputConfigImplBuilder.java
@@ -17,6 +17,7 @@
 package androidx.camera.extensions.impl.advanced;
 
 import android.annotation.SuppressLint;
+import android.hardware.camera2.params.DynamicRangeProfiles;
 import android.hardware.camera2.params.OutputConfiguration;
 import android.util.Size;
 import android.view.Surface;
@@ -35,6 +36,7 @@
     private int mSurfaceGroupId = OutputConfiguration.SURFACE_GROUP_ID_NONE;
     private String mPhysicalCameraId;
     private List<Camera2OutputConfigImpl> mSurfaceSharingConfigs;
+    private long mDynamicRangeProfile = DynamicRangeProfiles.STANDARD;
 
     private Camera2OutputConfigImplBuilder(OutputConfigImplImpl outputConfig) {
         mOutputConfig = outputConfig;
@@ -93,6 +95,14 @@
     }
 
     /**
+     * Set dynamic range profile.
+     */
+    public Camera2OutputConfigImplBuilder setDynamicRangeProfile(long dynamicRangeProfile) {
+        mDynamicRangeProfile = dynamicRangeProfile;
+        return this;
+    }
+
+    /**
      * Sets surface group id.
      */
     public Camera2OutputConfigImplBuilder setSurfaceGroupId(int surfaceGroupId) {
@@ -108,6 +118,7 @@
         mOutputConfig.setPhysicalCameraId(mPhysicalCameraId);
         mOutputConfig.setSurfaceGroup(mSurfaceGroupId);
         mOutputConfig.setSurfaceSharingConfigs(mSurfaceSharingConfigs);
+        mOutputConfig.setDynamicRangeProfile(mDynamicRangeProfile);
         return mOutputConfig;
     }
 
@@ -115,6 +126,7 @@
         private int mId;
         private int mSurfaceGroup;
         private String mPhysicalCameraId;
+        private long mDynamicRangeProfile;
         private List<Camera2OutputConfigImpl> mSurfaceSharingConfigs;
 
         OutputConfigImplImpl() {
@@ -122,6 +134,7 @@
             mSurfaceGroup = 0;
             mPhysicalCameraId = null;
             mSurfaceSharingConfigs = null;
+            mDynamicRangeProfile = DynamicRangeProfiles.STANDARD;
         }
 
         @Override
@@ -140,6 +153,11 @@
         }
 
         @Override
+        public long getDynamicRangeProfile() {
+            return mDynamicRangeProfile;
+        }
+
+        @Override
         public List<Camera2OutputConfigImpl> getSurfaceSharingOutputConfigs() {
             return mSurfaceSharingConfigs;
         }
@@ -156,6 +174,10 @@
             mPhysicalCameraId = physicalCameraId;
         }
 
+        public void setDynamicRangeProfile(long dynamicRangeProfile) {
+            mDynamicRangeProfile = dynamicRangeProfile;
+        }
+
         public void setSurfaceSharingConfigs(
                 List<Camera2OutputConfigImpl> surfaceSharingConfigs) {
             mSurfaceSharingConfigs = surfaceSharingConfigs;
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImpl.java
index 850f0e1..5d4444f 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImpl.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SuppressLint;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.params.ColorSpaceProfiles;
 
 import java.util.List;
 import java.util.Map;
@@ -55,4 +56,14 @@
      * will be configured to use the default regular type.
      */
     int getSessionType();
+
+    /**
+     * Gets the color space.
+     *
+     * @since 1.5
+     * @return {@link android.graphics#ColorSpace.Named} set for session configuration
+     */
+    default int getColorSpace() {
+        return ColorSpaceProfiles.UNSPECIFIED;
+    }
 }
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImplBuilder.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImplBuilder.java
index dc1fecc..e745624 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImplBuilder.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/Camera2SessionConfigImplBuilder.java
@@ -20,6 +20,7 @@
 import android.annotation.SuppressLint;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.params.ColorSpaceProfiles;
 import android.hardware.camera2.params.SessionConfiguration;
 
 import java.util.ArrayList;
@@ -33,6 +34,7 @@
 @SuppressLint("UnknownNullness")
 public class Camera2SessionConfigImplBuilder {
     private int mSessionTemplateId = CameraDevice.TEMPLATE_PREVIEW;
+    private int mColorSpace = ColorSpaceProfiles.UNSPECIFIED;
     private int mSessionType = SessionConfiguration.SESSION_REGULAR;
     Map<CaptureRequest.Key<?>, Object> mSessionParameters = new HashMap<>();
     List<Camera2OutputConfigImpl> mCamera2OutputConfigs = new ArrayList<>();
@@ -67,6 +69,21 @@
     }
 
     /**
+     * Sets the color space.
+     */
+    public Camera2SessionConfigImplBuilder setColorSpace(int colorSpace) {
+        mColorSpace = colorSpace;
+        return this;
+    }
+
+    /**
+     * Gets the color space.
+     */
+    public int getColorSpace() {
+        return mColorSpace;
+    }
+
+    /**
      * Gets the session template id.
      */
     public int getSessionTemplateId() {
@@ -105,12 +122,14 @@
             Camera2SessionConfigImpl {
         int mSessionTemplateId;
         int mSessionType;
+        int mColorSpace = ColorSpaceProfiles.UNSPECIFIED;
         Map<CaptureRequest.Key<?>, Object> mSessionParameters;
         List<Camera2OutputConfigImpl> mCamera2OutputConfigs;
 
         Camera2SessionConfigImplImpl(Camera2SessionConfigImplBuilder builder) {
             mSessionTemplateId = builder.getSessionTemplateId();
             mSessionParameters = builder.getSessionParameters();
+            mColorSpace = builder.getColorSpace();
             mCamera2OutputConfigs = builder.getCamera2OutputConfigs();
             mSessionType = builder.getSessionType();
         }
@@ -134,6 +153,11 @@
         public int getSessionType() {
             return mSessionType;
         }
+
+        @Override
+        public int getColorSpace() {
+            return mColorSpace;
+        }
     }
 }
 
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceConfigurationImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceConfigurationImpl.java
index 723f0f4..217887b 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceConfigurationImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceConfigurationImpl.java
@@ -17,6 +17,7 @@
 package androidx.camera.extensions.impl.advanced;
 
 import android.annotation.SuppressLint;
+import android.hardware.camera2.params.ColorSpaceProfiles;
 
 /**
  * For specifying the output surface configurations for the extension.
@@ -32,4 +33,13 @@
     public OutputSurfaceImpl getImageAnalysisOutputSurface();
 
     public OutputSurfaceImpl getPostviewOutputSurface();
+
+    /*
+     * Gets the color space.
+     *
+     * @since 1.5
+     */
+    default int getColorSpace() {
+        return ColorSpaceProfiles.UNSPECIFIED;
+    }
 }
diff --git a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java
index 7bf8df2..72bc4ab 100644
--- a/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java
+++ b/camera2/extensions/stub/src/main/java/androidx/camera/extensions/impl/advanced/OutputSurfaceImpl.java
@@ -17,6 +17,7 @@
 package androidx.camera.extensions.impl.advanced;
 
 import android.annotation.SuppressLint;
+import android.hardware.camera2.params.DynamicRangeProfiles;
 import android.util.Size;
 import android.view.Surface;
 
@@ -49,4 +50,13 @@
     * Gets the surface usage bits.
     */
     long getUsage();
+
+    /**
+     * Gets the dynamic range profile.
+     *
+     * @since 1.5
+     */
+    default long getDynamicRangeProfile() {
+        return DynamicRangeProfiles.STANDARD;
+    }
 }