Camera: Add device 3.8 and HDR10 native APIs

Initial set of native API extensions to support 10-bit
output capable device:
- Identification
- Configuration
- Data plumbing

Bug: 195946346
Test: adb shell
/data/nativetest64/VtsHalCameraProviderV2_4TargetTest/VtsHalCameraProviderV2_4TargetTest
--gtest_filter=PerInstance/CameraHidlTest.process10BitDynamicRangeRequest/0_internal_0

Change-Id: I526120944232ce211259cbd215935db7e445a6c5
diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp
index 7fcf523..fbe8686 100644
--- a/camera/common/1.0/default/HandleImporter.cpp
+++ b/camera/common/1.0/default/HandleImporter.cpp
@@ -30,6 +30,7 @@
 using aidl::android::hardware::graphics::common::PlaneLayout;
 using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
 using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
+using MetadataType = android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
 using MapperErrorV2 = android::hardware::graphics::mapper::V2_0::Error;
 using MapperErrorV3 = android::hardware::graphics::mapper::V3_0::Error;
 using MapperErrorV4 = android::hardware::graphics::mapper::V4_0::Error;
@@ -123,6 +124,21 @@
     return layout;
 }
 
+bool isMetadataPesent(const sp<IMapperV4> mapper, const buffer_handle_t& buf,
+        MetadataType metadataType) {
+    auto buffer = const_cast<native_handle_t*>(buf);
+    mapper->get(buffer, metadataType, [] (const auto& tmpError,
+                const auto& tmpMetadata) {
+                    if (tmpError == MapperErrorV4::NONE) {
+                        return tmpMetadata.size() > 0;
+                    } else {
+                        ALOGE("%s: failed to get metadata %d!", __FUNCTION__, tmpError);
+                        return false;
+                    }});
+
+    return false;
+}
+
 std::vector<PlaneLayout> getPlaneLayouts(const sp<IMapperV4> mapper, buffer_handle_t& buf) {
     auto buffer = const_cast<native_handle_t*>(buf);
     std::vector<PlaneLayout> planeLayouts;
@@ -449,6 +465,55 @@
     return -1;
 }
 
+bool HandleImporter::isSmpte2086Present(const buffer_handle_t& buf) {
+    Mutex::Autolock lock(mLock);
+
+    if (!mInitialized) {
+        initializeLocked();
+    }
+
+    if (mMapperV4 != nullptr) {
+        return isMetadataPesent(mMapperV4, buf, gralloc4::MetadataType_Smpte2086);
+    } else {
+        ALOGE("%s: mMapperV4 is null! Query not supported!", __FUNCTION__);
+    }
+
+    return false;
+}
+
+bool HandleImporter::isSmpte2094_10Present(const buffer_handle_t& buf) {
+    Mutex::Autolock lock(mLock);
+
+    if (!mInitialized) {
+        initializeLocked();
+    }
+
+    if (mMapperV4 != nullptr) {
+        return isMetadataPesent(mMapperV4, buf, gralloc4::MetadataType_Smpte2094_10);
+    } else {
+        ALOGE("%s: mMapperV4 is null! Query not supported!", __FUNCTION__);
+    }
+
+    return false;
+}
+
+bool HandleImporter::isSmpte2094_40Present(const buffer_handle_t& buf) {
+    Mutex::Autolock lock(mLock);
+
+    if (!mInitialized) {
+        initializeLocked();
+    }
+
+    if (mMapperV4 != nullptr) {
+        return isMetadataPesent(mMapperV4, buf, gralloc4::MetadataType_Smpte2094_40);
+    } else {
+        ALOGE("%s: mMapperV4 is null! Query not supported!", __FUNCTION__);
+    }
+
+    return false;
+}
+
+
 } // namespace helper
 } // namespace V1_0
 } // namespace common
diff --git a/camera/common/1.0/default/include/HandleImporter.h b/camera/common/1.0/default/include/HandleImporter.h
index e404439..83fa755 100644
--- a/camera/common/1.0/default/include/HandleImporter.h
+++ b/camera/common/1.0/default/include/HandleImporter.h
@@ -61,6 +61,11 @@
 
     int unlock(buffer_handle_t& buf); // returns release fence
 
+    // Query Gralloc4 metadata
+    bool isSmpte2086Present(const buffer_handle_t& buf);
+    bool isSmpte2094_10Present(const buffer_handle_t& buf);
+    bool isSmpte2094_40Present(const buffer_handle_t& buf);
+
 private:
     void initializeLocked();
     void cleanup();
diff --git a/camera/device/3.8/Android.bp b/camera/device/3.8/Android.bp
index 2a1f215..c3c2941 100644
--- a/camera/device/3.8/Android.bp
+++ b/camera/device/3.8/Android.bp
@@ -9,7 +9,6 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-
 hidl_interface {
     name: "android.hardware.camera.device@3.8",
     root: "android.hardware",
@@ -17,6 +16,7 @@
         "types.hal",
         "ICameraDevice.hal",
         "ICameraDeviceCallback.hal",
+        "ICameraDeviceSession.hal",
     ],
     interfaces: [
         "android.hardware.camera.common@1.0",
@@ -31,6 +31,7 @@
         "android.hardware.camera.metadata@3.4",
         "android.hardware.camera.metadata@3.5",
         "android.hardware.camera.metadata@3.6",
+        "android.hardware.camera.metadata@3.8",
         "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
diff --git a/camera/device/3.8/ICameraDevice.hal b/camera/device/3.8/ICameraDevice.hal
index 1101819..8832c68 100644
--- a/camera/device/3.8/ICameraDevice.hal
+++ b/camera/device/3.8/ICameraDevice.hal
@@ -26,8 +26,8 @@
  * API at LIMITED or better hardware level.
  *
  * ICameraDevice.open() must return @3.2::ICameraDeviceSession,
- * @3.5::ICameraDeviceSession, @3.6::ICameraDeviceSession, or
- * @3.7::ICameraDeviceSession.
+ * @3.5::ICameraDeviceSession, @3.6::ICameraDeviceSession,
+ * @3.7::ICameraDeviceSession, or @3.8::ICameraDeviceSession.
  */
 interface ICameraDevice extends @3.7::ICameraDevice {
     /**
@@ -107,4 +107,15 @@
      *
      */
     getTorchStrengthLevel() generates (Status status, int32_t torchStrength);
+
+     /**
+     * isStreamCombinationSupported_3_8:
+     *
+     * Identical to @3.7::ICameraDevice.isStreamCombinationSupported, except
+     * that it takes a @3.8::StreamConfiguration parameter, which could contain
+     * additional information about a specific 10-bit dynamic range profile.
+     *
+     */
+    isStreamCombinationSupported_3_8(StreamConfiguration streams)
+            generates (Status status, bool queryStatus);
 };
diff --git a/camera/device/3.8/ICameraDeviceSession.hal b/camera/device/3.8/ICameraDeviceSession.hal
new file mode 100644
index 0000000..88e4338
--- /dev/null
+++ b/camera/device/3.8/ICameraDeviceSession.hal
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package android.hardware.camera.device@3.8;
+
+import android.hardware.camera.common@1.0::Status;
+import @3.5::StreamConfiguration;
+import @3.7::ICameraDeviceSession;
+import @3.6::HalStreamConfiguration;
+
+/**
+ * Camera device active session interface.
+ *
+ * Obtained via ICameraDevice::open(), this interface contains the methods to
+ * configure and request captures from an active camera device.
+ */
+interface ICameraDeviceSession extends @3.7::ICameraDeviceSession {
+    /**
+     * configureStreams_3_8:
+     *
+     * Identical to @3.7::ICameraDeviceSession.configureStreams_3_7, except that:
+     *
+     * - The requestedConfiguration allows the camera framework to configure
+     *   10-bit dynamic range profile.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On successful stream configuration.
+     *     INTERNAL_ERROR:
+     *         If there has been a fatal error and the device is no longer
+     *         operational. Only close() can be called successfully by the
+     *         framework after this error is returned.
+     *     ILLEGAL_ARGUMENT:
+     *         If the requested stream configuration is invalid. Some examples
+     *         of invalid stream configurations include:
+     *           - Including more than 1 INPUT stream
+     *           - Not including any OUTPUT streams
+     *           - Including streams with unsupported formats, or an unsupported
+     *             size for that format.
+     *           - Including too many output streams of a certain format.
+     *           - Unsupported rotation configuration
+     *           - Stream sizes/formats don't satisfy the
+     *             StreamConfigurationMode requirements
+     *             for non-NORMAL mode, or the requested operation_mode is not
+     *             supported by the HAL.
+     *           - Unsupported usage flag
+     *           - Unsupported stream groupIds, or unsupported multi-resolution
+     *             input stream.
+     *           - Invalid combination between a 10-bit dynamic range profile
+     *             and none impl. defined 8-bit format for a particular stream.
+     *         The camera service cannot filter out all possible illegal stream
+     *         configurations, since some devices may support more simultaneous
+     *         streams or larger stream resolutions than the minimum required
+     *         for a given camera device hardware level. The HAL must return an
+     *         ILLEGAL_ARGUMENT for any unsupported stream set, and then be
+     *         ready to accept a future valid stream configuration in a later
+     *         configureStreams call.
+     * @return halConfiguration The stream parameters desired by the HAL for
+     *     each stream, including maximum buffers, the usage flags, and the
+     *     override format and dataspace.
+     */
+    configureStreams_3_8(StreamConfiguration requestedConfiguration)
+        generates (Status status, @3.6::HalStreamConfiguration halConfiguration);
+
+    /**
+     * repeatingRequestEnd:
+     *
+     * Notification about the last frame number in a repeating request along with the
+     * ids of all streams included in the repeating request.
+     *
+     * This can be called at any point after 'processCaptureRequest' in response
+     * to camera clients disabling an active repeating request.
+     *
+     * Performance requirements:
+     * The call must not be blocked for extensive periods and should be extremely lightweight. There
+     * must be no frame rate degradation or frame jitter introduced.
+     *
+     * This method must always succeed, even if the device has encountered a
+     * serious error.
+     */
+    repeatingRequestEnd(uint32_t frameNumber, vec<int32_t> streamIds);
+};
diff --git a/camera/device/3.8/types.hal b/camera/device/3.8/types.hal
index 843d050..9d1ac22 100644
--- a/camera/device/3.8/types.hal
+++ b/camera/device/3.8/types.hal
@@ -19,6 +19,11 @@
 import @3.2::ErrorMsg;
 import @3.2::MsgType;
 import @3.2::ShutterMsg;
+import @3.2::CameraMetadata;
+import @3.2::StreamConfigurationMode;
+import @3.7::Stream;
+
+import android.hardware.camera.metadata@3.8::CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap;
 
 /**
  * ShutterMsg:
@@ -67,3 +72,75 @@
         ShutterMsg shutter;
     } msg;
 };
+
+/**
+ * Stream:
+ *
+ * A descriptor for a single camera input or output stream. A stream is defined
+ * by the framework by its buffer resolution and format, and additionally by the
+ * HAL with the gralloc usage flags and the maximum in-flight buffer count.
+ *
+ * This version extends the @3.7 Stream with the dynamic range profile field.
+ */
+struct Stream {
+    /**
+     * The definition of Stream from the prior version.
+     */
+    @3.7::Stream v3_7;
+
+    /**
+     * The dynamic range profile for this stream.
+     *
+     * This field is valid and must only be considered for streams with format
+     * android.hardware.graphics.common.PixelFormat.YCBCR_P010 or
+     * android.hardware.graphics.common.PixelFormat.IMPLEMENTATION_DEFINED on devices supporting the
+     * ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_10_BIT capability.
+     *
+     */
+    CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap dynamicRangeProfile;
+};
+
+/**
+ * StreamConfiguration:
+ *
+ * Identical to @3.7::StreamConfiguration, except that the streams
+ * vector contains @3.8::Stream.
+ */
+struct StreamConfiguration {
+    /**
+     * An array of camera stream pointers, defining the input/output
+     * configuration for the camera HAL device.
+     */
+    vec<Stream> streams;
+
+    /**
+     * The definition of operation mode from prior version.
+     *
+     */
+    @3.2::StreamConfigurationMode operationMode;
+
+    /**
+     * The definition of session parameters from prior version.
+     */
+    @3.2::CameraMetadata sessionParams;
+
+    /**
+     * The definition of stream configuration counter from prior version.
+     */
+    uint32_t streamConfigCounter;
+
+    /**
+     * If an input stream is configured, whether the input stream is expected to
+     * receive variable resolution images.
+     *
+     * This flag can only be set to true if the camera device supports
+     * multi-resolution input streams by advertising input stream configurations in
+     * physicalCameraMultiResolutionStreamConfigurations in its physical cameras'
+     * characteristics.
+     *
+     * When this flag is set to true, the input stream's width and height can be
+     * any one of the supported multi-resolution input stream sizes.
+     */
+    bool multiResolutionInputImage;
+};
+
diff --git a/camera/metadata/3.8/types.hal b/camera/metadata/3.8/types.hal
index 11360da..4c70eb9 100644
--- a/camera/metadata/3.8/types.hal
+++ b/camera/metadata/3.8/types.hal
@@ -53,6 +53,21 @@
 
     ANDROID_FLASH_INFO_END_3_8,
 
+    /** android.request.availableDynamicRangeProfilesMap [static, enum[], ndk_public]
+     *
+     * <p>A map of all available 10-bit dynamic range profiles along with their
+     * capture request constraints.</p>
+     */
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_REQUEST_END_3_4,
+
+    /** android.request.recommendedTenBitDynamicRangeProfile [static, int32, java_public]
+     *
+     * <p>Recommended 10-bit dynamic range profile.</p>
+     */
+    ANDROID_REQUEST_RECOMMENDED_TEN_BIT_DYNAMIC_RANGE_PROFILE,
+
+    ANDROID_REQUEST_END_3_8,
+
 };
 
 /*
@@ -66,3 +81,51 @@
         @3.2::CameraMetadataEnumAndroidControlVideoStabilizationMode {
     ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION,
 };
+
+/** android.request.availableCapabilities enumeration values added since v3.6
+ * @see ANDROID_REQUEST_AVAILABLE_CAPABILITIES
+ */
+enum CameraMetadataEnumAndroidRequestAvailableCapabilities :
+        @3.6::CameraMetadataEnumAndroidRequestAvailableCapabilities {
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT,
+};
+
+/** android.request.availableDynamicRangeProfilesMap enumeration values
+ * @see ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP
+ */
+enum CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap : uint32_t {
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD
+                                                                 = 0x1,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10  = 0x2,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10  = 0x4,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS
+                                                                 = 0x8,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF
+                                                                 = 0x10,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO
+                                                                 = 0x20,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM
+                                                                 = 0x40,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO
+                                                                 = 0x80,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF
+                                                                 = 0x100,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO
+                                                                 = 0x200,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM
+                                                                 = 0x400,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO
+                                                                 = 0x800,
+    ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_MAX    = 0x1000,
+};
+
+/** android.scaler.availableRecommendedStreamConfigurations enumeration values added since v3.4
+ * @see ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS
+ */
+enum CameraMetadataEnumAndroidScalerAvailableRecommendedStreamConfigurations :
+        @3.4::CameraMetadataEnumAndroidScalerAvailableRecommendedStreamConfigurations {
+    ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_10BIT_OUTPUT
+                                                                 = 0x8,
+    ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END_3_8
+                                                                 = 0x9,
+};
diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp
index 2c141ee..0e62265 100644
--- a/camera/provider/2.4/vts/functional/Android.bp
+++ b/camera/provider/2.4/vts/functional/Android.bp
@@ -51,11 +51,15 @@
         "android.hardware.camera.device@3.7",
         "android.hardware.camera.device@3.8",
         "android.hardware.camera.metadata@3.4",
+        "android.hardware.camera.metadata@3.8",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.provider@2.5",
         "android.hardware.camera.provider@2.6",
         "android.hardware.camera.provider@2.7",
         "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@4.0",
         "android.hidl.allocator@1.0",
         "libgrallocusage",
         "libhidlmemory",
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index d39850d..dd45b0d 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -30,6 +30,7 @@
 
 #include <CameraMetadata.h>
 #include <CameraParameters.h>
+#include <HandleImporter.h>
 #include <android/hardware/camera/device/1.0/ICameraDevice.h>
 #include <android/hardware/camera/device/3.2/ICameraDevice.h>
 #include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
@@ -45,7 +46,9 @@
 #include <android/hardware/camera/device/3.7/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
 #include <android/hardware/camera/device/3.8/ICameraDeviceCallback.h>
+#include <android/hardware/camera/device/3.8/ICameraDeviceSession.h>
 #include <android/hardware/camera/metadata/3.4/types.h>
+#include <android/hardware/camera/metadata/3.8/types.h>
 #include <android/hardware/camera/provider/2.4/ICameraProvider.h>
 #include <android/hardware/camera/provider/2.5/ICameraProvider.h>
 #include <android/hardware/camera/provider/2.6/ICameraProvider.h>
@@ -97,6 +100,7 @@
 using ::android::hardware::camera::common::V1_0::TorchMode;
 using ::android::hardware::camera::common::V1_0::TorchModeStatus;
 using ::android::hardware::camera::common::V1_0::helper::CameraParameters;
+using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
 using ::android::hardware::camera::common::V1_0::helper::Size;
 using ::android::hardware::camera::device::V1_0::CameraFacing;
 using ::android::hardware::camera::device::V1_0::CameraFrameMetadata;
@@ -129,6 +133,8 @@
         CameraMetadataEnumAndroidSensorInfoColorFilterArrangement;
 using ::android::hardware::camera::metadata::V3_4::CameraMetadataTag;
 using ::android::hardware::camera::metadata::V3_6::CameraMetadataEnumAndroidSensorPixelMode;
+using ::android::hardware::camera::metadata::V3_8::
+        CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap;
 using ::android::hardware::camera::provider::V2_4::ICameraProvider;
 using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
 using ::android::hardware::camera::provider::V2_6::CameraIdAndStreamCombination;
@@ -136,7 +142,6 @@
 using ::android::hardware::graphics::common::V1_0::Dataspace;
 using ::android::hardware::graphics::common::V1_0::PixelFormat;
 using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMapper;
 using ::android::hidl::memory::V1_0::IMemory;
 using ResultMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
 using ::android::hidl::manager::V1_0::IServiceManager;
@@ -781,13 +786,15 @@
             sp<device::V3_4::ICameraDeviceSession> *session3_4 /*out*/,
             sp<device::V3_5::ICameraDeviceSession> *session3_5 /*out*/,
             sp<device::V3_6::ICameraDeviceSession> *session3_6 /*out*/,
-            sp<device::V3_7::ICameraDeviceSession> *session3_7 /*out*/);
+            sp<device::V3_7::ICameraDeviceSession> *session3_7 /*out*/,
+            sp<device::V3_8::ICameraDeviceSession> *session3_8 /*out*/);
     void castInjectionSession(
             const sp<ICameraDeviceSession>& session,
             sp<device::V3_7::ICameraInjectionSession>* injectionSession3_7 /*out*/);
     void castDevice(const sp<device::V3_2::ICameraDevice>& device, int32_t deviceVersion,
                     sp<device::V3_5::ICameraDevice>* device3_5 /*out*/,
-                    sp<device::V3_7::ICameraDevice>* device3_7 /*out*/);
+                    sp<device::V3_7::ICameraDevice>* device3_7 /*out*/,
+                    sp<device::V3_8::ICameraDevice>* device3_8 /*out*/);
     void createStreamConfiguration(
             const ::android::hardware::hidl_vec<V3_2::Stream>& streams3_2,
             StreamConfigurationMode configMode,
@@ -817,6 +824,16 @@
                              uint32_t* partialResultCount /*out*/, bool* useHalBufManager /*out*/,
                              sp<DeviceCb>* outCb /*out*/, uint32_t streamConfigCounter,
                              bool maxResolution);
+    void configureStreams3_8(const std::string& name, int32_t deviceVersion,
+                             sp<ICameraProvider> provider, PixelFormat format,
+                             sp<device::V3_8::ICameraDeviceSession>* session3_8 /*out*/,
+                             V3_2::Stream* previewStream /*out*/,
+                             device::V3_6::HalStreamConfiguration* halStreamConfig /*out*/,
+                             bool* supportsPartialResults /*out*/,
+                             uint32_t* partialResultCount /*out*/, bool* useHalBufManager /*out*/,
+                             sp<DeviceCb>* outCb /*out*/, uint32_t streamConfigCounter,
+                             bool maxResolution,
+                             CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap prof);
 
     void configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion,
             sp<ICameraProvider> provider,
@@ -896,6 +913,9 @@
     static bool isDepthOnly(const camera_metadata_t* staticMeta);
 
     static bool isUltraHighResolution(const camera_metadata_t* staticMeta);
+    static void get10BitDynamicRangeProfiles(const camera_metadata_t* staticMeta,
+        std::vector<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap> *profiles);
+    static bool is10BitDynamicRangeCapable(const camera_metadata_t* staticMeta);
 
     static Status getAvailableOutputStreams(const camera_metadata_t* staticMeta,
                                             std::vector<AvailableStream>& outputStreams,
@@ -1077,6 +1097,10 @@
                 expectedPhysicalResults(extraPhysicalResult) {}
     };
 
+    static void verify10BitMetadata(HandleImporter& importer,
+            const InFlightRequest& request,
+            CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap profile);
+
     // Map from frame number to the in-flight request state
     typedef ::android::KeyedVector<uint32_t, InFlightRequest*> InFlightMap;
 
@@ -1105,6 +1129,8 @@
 
     // Camera provider type.
     std::string mProviderType;
+
+    HandleImporter mHandleImporter;
 };
 
 Return<void> CameraHidlTest::Camera1DeviceCb::notifyCallback(
@@ -3342,10 +3368,13 @@
                 sp<device::V3_5::ICameraDeviceSession> sessionV3_5;
                 sp<device::V3_6::ICameraDeviceSession> sessionV3_6;
                 sp<device::V3_7::ICameraDeviceSession> sessionV3_7;
+                sp<device::V3_8::ICameraDeviceSession> sessionV3_8;
                 castSession(session, deviceVersion, &sessionV3_3,
                         &sessionV3_4, &sessionV3_5, &sessionV3_6,
-                        &sessionV3_7);
-                if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_7) {
+                        &sessionV3_7, &sessionV3_8);
+                if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_8) {
+                    ASSERT_TRUE(sessionV3_8.get() != nullptr);
+                } else if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_7) {
                     ASSERT_TRUE(sessionV3_7.get() != nullptr);
                 } else if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_6) {
                     ASSERT_TRUE(sessionV3_6.get() != nullptr);
@@ -3513,14 +3542,17 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         sp<device::V3_2::ICameraDevice> cameraDevice;
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
         openEmptyDeviceSession(name, mProvider,
                 &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-                &session3_6, &session3_7);
-        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+                &session3_6, &session3_7, &session3_8);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7,
+                &cameraDevice3_8);
 
         outputStreams.clear();
         ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
@@ -3616,9 +3648,11 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         sp<device::V3_2::ICameraDevice> cameraDevice;
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
         ::android::hardware::camera::device::V3_7::StreamConfiguration config3_7;
         ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5;
         ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
@@ -3655,8 +3689,9 @@
             openEmptyDeviceSession(name, mProvider2_6, &cti.session /*out*/,
                                    &cti.staticMeta /*out*/, &cti.cameraDevice /*out*/);
             castSession(cti.session, deviceVersion, &cti.session3_3, &cti.session3_4,
-                        &cti.session3_5, &cti.session3_6, &cti.session3_7);
-            castDevice(cti.cameraDevice, deviceVersion, &cti.cameraDevice3_5, &cti.cameraDevice3_7);
+                        &cti.session3_5, &cti.session3_6, &cti.session3_7, &cti.session3_8);
+            castDevice(cti.cameraDevice, deviceVersion, &cti.cameraDevice3_5, &cti.cameraDevice3_7,
+                    &cti.cameraDevice3_8);
 
             outputStreams.clear();
             ASSERT_EQ(Status::OK, getMandatoryConcurrentStreams(cti.staticMeta, &outputStreams));
@@ -3785,14 +3820,17 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         sp<device::V3_2::ICameraDevice> cameraDevice;
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
         openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
                 &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-                &session3_6, &session3_7);
-        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+                &session3_6, &session3_7, &session3_8);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7,
+                &cameraDevice3_8);
 
         outputStreams.clear();
         ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
@@ -3998,14 +4036,17 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         sp<device::V3_2::ICameraDevice> cameraDevice;
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
         openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
                 &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-                &session3_6, &session3_7);
-        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+                &session3_6, &session3_7, &session3_8);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7,
+                &cameraDevice3_8);
 
         Status rc = isZSLModeAvailable(staticMeta);
         if (Status::METHOD_NOT_SUPPORTED == rc) {
@@ -4184,9 +4225,10 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMetaBuffer /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-                &session3_6, &session3_7);
+                &session3_6, &session3_7, &session3_8);
         if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_4) {
             ASSERT_NE(session3_4, nullptr);
         } else {
@@ -4325,14 +4367,17 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         sp<device::V3_2::ICameraDevice> cameraDevice;
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
         openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
                 &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-                &session3_6, &session3_7);
-        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+                &session3_6, &session3_7, &session3_8);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7,
+                &cameraDevice3_8);
 
         // Check if camera support depth only
         if (isDepthOnly(staticMeta)) {
@@ -4459,14 +4504,17 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         sp<device::V3_2::ICameraDevice> cameraDevice;
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
         openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
                 &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-                &session3_6, &session3_7);
-        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+                &session3_6, &session3_7, &session3_8);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7,
+                &cameraDevice3_8);
 
         Status rc = isConstrainedModeAvailable(staticMeta);
         if (Status::METHOD_NOT_SUPPORTED == rc) {
@@ -4706,14 +4754,17 @@
         sp<device::V3_5::ICameraDeviceSession> session3_5;
         sp<device::V3_6::ICameraDeviceSession> session3_6;
         sp<device::V3_7::ICameraDeviceSession> session3_7;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
         sp<device::V3_2::ICameraDevice> cameraDevice;
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
         openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
                 &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-                &session3_6, &session3_7);
-        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+                &session3_6, &session3_7, &session3_8);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5, &cameraDevice3_7,
+                &cameraDevice3_8);
 
         // Check if camera support depth only
         if (isDepthOnly(staticMeta)) {
@@ -4997,6 +5048,20 @@
         ASSERT_EQ(Status::OK, status);
         ASSERT_EQ(numRequestProcessed, 1u);
 
+        if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_8) {
+            sp<device::V3_3::ICameraDeviceSession> session3_3;
+            sp<device::V3_4::ICameraDeviceSession> session3_4;
+            sp<device::V3_5::ICameraDeviceSession> session3_5;
+            sp<device::V3_6::ICameraDeviceSession> session3_6;
+            sp<device::V3_7::ICameraDeviceSession> session3_7;
+            sp<device::V3_8::ICameraDeviceSession> session3_8;
+            castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
+                    &session3_6, &session3_7, &session3_8);
+            ASSERT_TRUE(session3_8.get() != nullptr);
+            hidl_vec<int32_t> streamIds = { halStreamConfig.streams[0].id };
+            session3_8->repeatingRequestEnd(request.frameNumber, streamIds);
+        }
+
         {
             std::unique_lock<std::mutex> l(mLock);
             while (!inflightReq.errorCodeValid &&
@@ -5640,6 +5705,188 @@
     }
 }
 
+// Generate and verify 10-bit dynamic range request
+TEST_P(CameraHidlTest, process10BitDynamicRangeRequest) {
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    uint64_t bufferId = 1;
+    uint32_t frameNumber = 1;
+    ::android::hardware::hidl_vec<uint8_t> settings;
+
+    for (const auto& name : cameraDeviceNames) {
+        int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+        if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_8) {
+            continue;
+        }
+        std::string version, deviceId;
+        ASSERT_TRUE(::matchDeviceName(name, mProviderType, &version, &deviceId));
+        camera_metadata_t* staticMeta;
+        Return<void> ret;
+        sp<ICameraDeviceSession> session;
+        openEmptyDeviceSession(name, mProvider, &session, &staticMeta);
+        if (!is10BitDynamicRangeCapable(staticMeta)) {
+            free_camera_metadata(staticMeta);
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
+            continue;
+        }
+        std::vector<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap> profileList;
+        get10BitDynamicRangeProfiles(staticMeta, &profileList);
+        ASSERT_FALSE(profileList.empty());
+
+        android::hardware::camera::common::V1_0::helper::CameraMetadata defaultSettings;
+        ret = session->constructDefaultRequestSettings(
+                RequestTemplate::STILL_CAPTURE,
+                [&defaultSettings](auto status, const auto& req) mutable {
+                    ASSERT_EQ(Status::OK, status);
+
+                    const camera_metadata_t* metadata =
+                            reinterpret_cast<const camera_metadata_t*>(req.data());
+                    size_t expectedSize = req.size();
+                    int result = validate_camera_metadata_structure(metadata, &expectedSize);
+                    ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
+
+                    size_t entryCount = get_camera_metadata_entry_count(metadata);
+                    ASSERT_GT(entryCount, 0u);
+                    defaultSettings = metadata;
+                });
+        ASSERT_TRUE(ret.isOk());
+
+        const camera_metadata_t* settingsBuffer = defaultSettings.getAndLock();
+        settings.setToExternal(
+                reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(settingsBuffer)),
+                get_camera_metadata_size(settingsBuffer));
+        overrideRotateAndCrop(&settings);
+
+        free_camera_metadata(staticMeta);
+        ret = session->close();
+        ASSERT_TRUE(ret.isOk());
+        V3_6::HalStreamConfiguration halStreamConfig;
+        bool supportsPartialResults = false;
+        bool useHalBufManager = false;
+        uint32_t partialResultCount = 0;
+        V3_2::Stream previewStream;
+        sp<device::V3_8::ICameraDeviceSession> session3_8;
+        sp<DeviceCb> cb;
+        for (const auto& profile : profileList) {
+            configureStreams3_8(name, deviceVersion, mProvider, PixelFormat::IMPLEMENTATION_DEFINED,
+                                &session3_8, &previewStream, &halStreamConfig,
+                                &supportsPartialResults, &partialResultCount, &useHalBufManager,
+                                &cb, 0, /*maxResolution*/ false, profile);
+            ASSERT_NE(session3_8, nullptr);
+
+            std::shared_ptr<ResultMetadataQueue> resultQueue;
+            auto resultQueueRet = session3_8->getCaptureResultMetadataQueue(
+                    [&resultQueue](const auto& descriptor) {
+                        resultQueue = std::make_shared<ResultMetadataQueue>(descriptor);
+                        if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
+                            ALOGE("%s: HAL returns empty result metadata fmq,"
+                                  " not use it",
+                                  __func__);
+                            resultQueue = nullptr;
+                            // Don't use the queue onwards.
+                        }
+                    });
+            ASSERT_TRUE(resultQueueRet.isOk());
+
+            std::vector<hidl_handle> graphicBuffers;
+            graphicBuffers.reserve(halStreamConfig.streams.size());
+            ::android::hardware::hidl_vec<StreamBuffer> outputBuffers;
+            outputBuffers.resize(halStreamConfig.streams.size());
+            InFlightRequest inflightReq = {static_cast<ssize_t>(halStreamConfig.streams.size()),
+                                           false,
+                                           supportsPartialResults,
+                                           partialResultCount,
+                                           std::unordered_set<std::string>(),
+                                           resultQueue};
+
+            size_t k = 0;
+            for (const auto& halStream : halStreamConfig.streams) {
+                hidl_handle buffer_handle;
+                if (useHalBufManager) {
+                    outputBuffers[k] = {halStream.v3_4.v3_3.v3_2.id,
+                                        0,
+                                        buffer_handle,
+                                        BufferStatus::OK,
+                                        nullptr,
+                                        nullptr};
+                } else {
+                    allocateGraphicBuffer(
+                            previewStream.width, previewStream.height,
+                            android_convertGralloc1To0Usage(halStream.v3_4.v3_3.v3_2.producerUsage,
+                                                            halStream.v3_4.v3_3.v3_2.consumerUsage),
+                            halStream.v3_4.v3_3.v3_2.overrideFormat, &buffer_handle);
+
+                    graphicBuffers.push_back(buffer_handle);
+                    outputBuffers[k] = {halStream.v3_4.v3_3.v3_2.id,
+                                        bufferId,
+                                        buffer_handle,
+                                        BufferStatus::OK,
+                                        nullptr,
+                                        nullptr};
+                    bufferId++;
+                }
+                k++;
+            }
+
+            StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, nullptr};
+            V3_4::CaptureRequest request3_4;
+            request3_4.v3_2.frameNumber = frameNumber;
+            request3_4.v3_2.fmqSettingsSize = 0;
+            request3_4.v3_2.settings = settings;
+            request3_4.v3_2.inputBuffer = emptyInputBuffer;
+            request3_4.v3_2.outputBuffers = outputBuffers;
+            V3_7::CaptureRequest request3_7;
+            request3_7.v3_4 = request3_4;
+            request3_7.inputWidth = 0;
+            request3_7.inputHeight = 0;
+
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                mInflightMap.clear();
+                mInflightMap.add(frameNumber, &inflightReq);
+            }
+
+            Status stat = Status::INTERNAL_ERROR;
+            uint32_t numRequestProcessed = 0;
+            hidl_vec<BufferCache> cachesToRemove;
+            Return<void> returnStatus = session3_8->processCaptureRequest_3_7(
+                    {request3_7}, cachesToRemove,
+                    [&stat, &numRequestProcessed](auto s, uint32_t n) {
+                        stat = s;
+                        numRequestProcessed = n;
+                    });
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, stat);
+            ASSERT_EQ(numRequestProcessed, 1u);
+
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                while (!inflightReq.errorCodeValid &&
+                       ((0 < inflightReq.numBuffersLeft) || (!inflightReq.haveResultMetadata))) {
+                    auto timeout = std::chrono::system_clock::now() +
+                                   std::chrono::seconds(kStreamBufferTimeoutSec);
+                    ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
+                }
+
+                ASSERT_FALSE(inflightReq.errorCodeValid);
+                ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
+                verify10BitMetadata(mHandleImporter, inflightReq, profile);
+            }
+            if (useHalBufManager) {
+                hidl_vec<int32_t> streamIds(halStreamConfig.streams.size());
+                for (size_t i = 0; i < streamIds.size(); i++) {
+                    streamIds[i] = halStreamConfig.streams[i].v3_4.v3_3.v3_2.id;
+                }
+                session3_8->signalStreamFlush(streamIds, /*streamConfigCounter*/ 0);
+                cb->waitForBuffersReturned();
+            }
+
+            ret = session3_8->close();
+            ASSERT_TRUE(ret.isOk());
+        }
+    }
+}
+
 // Generate and verify a burst containing alternating sensor sensitivity values
 TEST_P(CameraHidlTest, processCaptureRequestBurstISO) {
     hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
@@ -7448,8 +7695,9 @@
     sp<device::V3_4::ICameraDeviceSession> session3_4;
     sp<device::V3_5::ICameraDeviceSession> session3_5;
     sp<device::V3_6::ICameraDeviceSession> session3_6;
+    sp<device::V3_8::ICameraDeviceSession> session3_8;
     castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6,
-                session3_7);
+                session3_7, &session3_8);
     ASSERT_NE(nullptr, (*session3_7).get());
 
     *useHalBufManager = false;
@@ -7497,7 +7745,8 @@
     ASSERT_TRUE(deviceVersion >= CAMERA_DEVICE_API_VERSION_3_7);
     sp<device::V3_5::ICameraDevice> cameraDevice3_5 = nullptr;
     sp<device::V3_7::ICameraDevice> cameraDevice3_7 = nullptr;
-    castDevice(device3_x, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+    sp<device::V3_8::ICameraDevice> cameraDevice3_8 = nullptr;
+    castDevice(device3_x, deviceVersion, &cameraDevice3_5, &cameraDevice3_7, &cameraDevice3_8);
     ASSERT_NE(cameraDevice3_7, nullptr);
     bool supported = false;
     ret = cameraDevice3_7->isStreamCombinationSupported_3_7(
@@ -7530,6 +7779,153 @@
     ASSERT_TRUE(ret.isOk());
 }
 
+// Configure streams
+void CameraHidlTest::configureStreams3_8(
+        const std::string& name, int32_t deviceVersion, sp<ICameraProvider> provider,
+        PixelFormat format, sp<device::V3_8::ICameraDeviceSession>* session3_8 /*out*/,
+        V3_2::Stream* previewStream /*out*/,
+        device::V3_6::HalStreamConfiguration* halStreamConfig /*out*/,
+        bool* supportsPartialResults /*out*/, uint32_t* partialResultCount /*out*/,
+        bool* useHalBufManager /*out*/, sp<DeviceCb>* outCb /*out*/, uint32_t streamConfigCounter,
+        bool maxResolution,
+        CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap prof) {
+    ASSERT_NE(nullptr, session3_8);
+    ASSERT_NE(nullptr, halStreamConfig);
+    ASSERT_NE(nullptr, previewStream);
+    ASSERT_NE(nullptr, supportsPartialResults);
+    ASSERT_NE(nullptr, partialResultCount);
+    ASSERT_NE(nullptr, useHalBufManager);
+    ASSERT_NE(nullptr, outCb);
+    ASSERT_TRUE(deviceVersion >= CAMERA_DEVICE_API_VERSION_3_8);
+
+    std::vector<AvailableStream> outputStreams;
+    ::android::sp<ICameraDevice> device3_x;
+    ALOGI("configureStreams: Testing camera device %s", name.c_str());
+    Return<void> ret;
+    ret = provider->getCameraDeviceInterface_V3_x(name, [&](auto status, const auto& device) {
+        ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+        ASSERT_EQ(Status::OK, status);
+        ASSERT_NE(device, nullptr);
+        device3_x = device;
+    });
+    ASSERT_TRUE(ret.isOk());
+
+    camera_metadata_t* staticMeta;
+    ret = device3_x->getCameraCharacteristics([&](Status s, CameraMetadata metadata) {
+        ASSERT_EQ(Status::OK, s);
+        staticMeta =
+                clone_camera_metadata(reinterpret_cast<const camera_metadata_t*>(metadata.data()));
+        ASSERT_NE(nullptr, staticMeta);
+    });
+    ASSERT_TRUE(ret.isOk());
+
+    camera_metadata_ro_entry entry;
+    auto status =
+            find_camera_metadata_ro_entry(staticMeta, ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &entry);
+    if ((0 == status) && (entry.count > 0)) {
+        *partialResultCount = entry.data.i32[0];
+        *supportsPartialResults = (*partialResultCount > 1);
+    }
+
+    sp<DeviceCb> cb = new DeviceCb(this, deviceVersion, staticMeta);
+    sp<ICameraDeviceSession> session;
+    ret = device3_x->open(cb, [&session](auto status, const auto& newSession) {
+        ALOGI("device::open returns status:%d", (int)status);
+        ASSERT_EQ(Status::OK, status);
+        ASSERT_NE(newSession, nullptr);
+        session = newSession;
+    });
+    ASSERT_TRUE(ret.isOk());
+    *outCb = cb;
+
+    sp<device::V3_3::ICameraDeviceSession> session3_3;
+    sp<device::V3_4::ICameraDeviceSession> session3_4;
+    sp<device::V3_5::ICameraDeviceSession> session3_5;
+    sp<device::V3_6::ICameraDeviceSession> session3_6;
+    sp<device::V3_7::ICameraDeviceSession> session3_7;
+    castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5, &session3_6,
+                &session3_7, session3_8);
+    ASSERT_NE(nullptr, (*session3_8).get());
+
+    *useHalBufManager = false;
+    status = find_camera_metadata_ro_entry(
+            staticMeta, ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION, &entry);
+    if ((0 == status) && (entry.count == 1)) {
+        *useHalBufManager = (entry.data.u8[0] ==
+                             ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+    }
+
+    outputStreams.clear();
+    Size maxSize;
+    auto rc = getMaxOutputSizeForFormat(staticMeta, format, &maxSize, maxResolution);
+    ASSERT_EQ(Status::OK, rc);
+    free_camera_metadata(staticMeta);
+
+    ::android::hardware::hidl_vec<V3_8::Stream> streams3_8(1);
+    streams3_8[0].v3_7.groupId = -1;
+    streams3_8[0].v3_7.sensorPixelModesUsed = {
+            CameraMetadataEnumAndroidSensorPixelMode::ANDROID_SENSOR_PIXEL_MODE_DEFAULT};
+    streams3_8[0].v3_7.v3_4.bufferSize = 0;
+    streams3_8[0].v3_7.v3_4.v3_2.id = 0;
+    streams3_8[0].v3_7.v3_4.v3_2.streamType = StreamType::OUTPUT;
+    streams3_8[0].v3_7.v3_4.v3_2.width = static_cast<uint32_t>(maxSize.width);
+    streams3_8[0].v3_7.v3_4.v3_2.height = static_cast<uint32_t>(maxSize.height);
+    streams3_8[0].v3_7.v3_4.v3_2.format = static_cast<PixelFormat>(format);
+    streams3_8[0].v3_7.v3_4.v3_2.usage = GRALLOC1_CONSUMER_USAGE_CPU_READ;
+    streams3_8[0].v3_7.v3_4.v3_2.dataSpace = 0;
+    streams3_8[0].v3_7.v3_4.v3_2.rotation = StreamRotation::ROTATION_0;
+    streams3_8[0].dynamicRangeProfile = prof;
+
+    ::android::hardware::camera::device::V3_8::StreamConfiguration config3_8;
+    config3_8.streams = streams3_8;
+    config3_8.operationMode = StreamConfigurationMode::NORMAL_MODE;
+    config3_8.streamConfigCounter = streamConfigCounter;
+    config3_8.multiResolutionInputImage = false;
+    RequestTemplate reqTemplate = RequestTemplate::STILL_CAPTURE;
+    ret = (*session3_8)
+                  ->constructDefaultRequestSettings(reqTemplate,
+                                                    [&config3_8](auto status, const auto& req) {
+                                                        ASSERT_EQ(Status::OK, status);
+                                                        config3_8.sessionParams = req;
+                                                    });
+    ASSERT_TRUE(ret.isOk());
+
+    sp<device::V3_5::ICameraDevice> cameraDevice3_5 = nullptr;
+    sp<device::V3_7::ICameraDevice> cameraDevice3_7 = nullptr;
+    sp<device::V3_8::ICameraDevice> cameraDevice3_8 = nullptr;
+    castDevice(device3_x, deviceVersion, &cameraDevice3_5, &cameraDevice3_7, &cameraDevice3_8);
+    ASSERT_NE(cameraDevice3_8, nullptr);
+    bool supported = false;
+    ret = cameraDevice3_8->isStreamCombinationSupported_3_8(
+            config3_8, [&supported](Status s, bool combStatus) {
+                ASSERT_TRUE((Status::OK == s) || (Status::METHOD_NOT_SUPPORTED == s));
+                if (Status::OK == s) {
+                    supported = combStatus;
+                }
+            });
+    ASSERT_TRUE(ret.isOk());
+    ASSERT_EQ(supported, true);
+
+    if (*session3_8 != nullptr) {
+        ret = (*session3_8)
+                      ->configureStreams_3_8(
+                              config3_8,
+                              [&](Status s, device::V3_6::HalStreamConfiguration halConfig) {
+                                  ASSERT_EQ(Status::OK, s);
+                                  *halStreamConfig = halConfig;
+                                  if (*useHalBufManager) {
+                                      hidl_vec<V3_4::Stream> streams(1);
+                                      hidl_vec<V3_2::HalStream> halStreams(1);
+                                      streams[0] = streams3_8[0].v3_7.v3_4;
+                                      halStreams[0] = halConfig.streams[0].v3_4.v3_3.v3_2;
+                                      cb->setCurrentStreamConfig(streams, halStreams);
+                                  }
+                              });
+    }
+    *previewStream = streams3_8[0].v3_7.v3_4.v3_2;
+    ASSERT_TRUE(ret.isOk());
+}
+
 // Configure multiple preview streams using different physical ids.
 void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion,
         sp<ICameraProvider> provider,
@@ -7604,8 +8000,9 @@
     sp<device::V3_3::ICameraDeviceSession> session3_3;
     sp<device::V3_6::ICameraDeviceSession> session3_6;
     sp<device::V3_7::ICameraDeviceSession> session3_7;
+    sp<device::V3_8::ICameraDeviceSession> session3_8;
     castSession(session, deviceVersion, &session3_3, session3_4, session3_5,
-            &session3_6, &session3_7);
+            &session3_6, &session3_7, &session3_8);
     ASSERT_NE(nullptr, (*session3_4).get());
 
     *useHalBufManager = false;
@@ -7650,7 +8047,8 @@
     if (allowUnsupport) {
         sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         sp<device::V3_7::ICameraDevice> cameraDevice3_7;
-        castDevice(device3_x, deviceVersion, &cameraDevice3_5, &cameraDevice3_7);
+        sp<device::V3_8::ICameraDevice> cameraDevice3_8;
+        castDevice(device3_x, deviceVersion, &cameraDevice3_5, &cameraDevice3_7, &cameraDevice3_8);
 
         bool supported = false;
         ret = cameraDevice3_5->isStreamCombinationSupported(config3_4,
@@ -7843,6 +8241,95 @@
     return false;
 }
 
+void CameraHidlTest::get10BitDynamicRangeProfiles(const camera_metadata_t* staticMeta,
+        std::vector<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap> *profiles) {
+    ASSERT_NE(nullptr, staticMeta);
+    ASSERT_NE(nullptr, profiles);
+    camera_metadata_ro_entry entry;
+    std::unordered_set<int32_t> entries;
+    int rc = find_camera_metadata_ro_entry(staticMeta,
+            ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP, &entry);
+    ASSERT_EQ(rc, 0);
+    ASSERT_TRUE(entry.count > 0);
+    ASSERT_EQ(entry.count % 2, 0);
+
+    for (uint32_t i = 0; i < entry.count; i += 2) {
+        ASSERT_NE(entry.data.i32[i],
+                ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD);
+        ASSERT_EQ(entries.find(entry.data.i32[i]), entries.end());
+        entries.insert(static_cast<int32_t>(entry.data.i32[i]));
+        profiles->emplace_back(
+                static_cast<CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap>
+                (entry.data.i32[i]));
+    }
+
+    if (!entries.empty()) {
+        ASSERT_NE(entries.find(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10),
+                entries.end());
+    }
+}
+
+bool CameraHidlTest::is10BitDynamicRangeCapable(const camera_metadata_t* staticMeta) {
+    camera_metadata_ro_entry scalarEntry;
+    int rc = find_camera_metadata_ro_entry(staticMeta, ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+                                           &scalarEntry);
+    if (rc == 0) {
+        for (uint32_t i = 0; i < scalarEntry.count; i++) {
+            if (scalarEntry.data.u8[i] ==
+                ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+void CameraHidlTest::verify10BitMetadata(HandleImporter& importer,
+        const InFlightRequest& request,
+        CameraMetadataEnumAndroidRequestAvailableDynamicRangeProfilesMap profile) {
+    for (const auto& b : request.resultOutputBuffers) {
+        bool smpte2086Present = importer.isSmpte2086Present(b.buffer.buffer.getNativeHandle());
+        bool smpte2094_10Present = importer.isSmpte2094_10Present(
+                b.buffer.buffer.getNativeHandle());
+        bool smpte2094_40Present = importer.isSmpte2094_40Present(
+                b.buffer.buffer.getNativeHandle());
+
+        switch (static_cast<uint32_t>(profile)) {
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10:
+                ASSERT_FALSE(smpte2086Present);
+                ASSERT_FALSE(smpte2094_10Present);
+                ASSERT_FALSE(smpte2094_40Present);
+                break;
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
+                ASSERT_TRUE(smpte2086Present);
+                ASSERT_FALSE(smpte2094_10Present);
+                ASSERT_FALSE(smpte2094_40Present);
+                break;
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
+                ASSERT_FALSE(smpte2086Present);
+                ASSERT_FALSE(smpte2094_10Present);
+                ASSERT_TRUE(smpte2094_40Present);
+                break;
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF:
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO:
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM:
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO:
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF:
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO:
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM:
+            case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO:
+                ASSERT_FALSE(smpte2086Present);
+                ASSERT_TRUE(smpte2094_10Present);
+                ASSERT_FALSE(smpte2094_40Present);
+                break;
+            default:
+                ALOGE("%s: Unexpected 10-bit dynamic range profile: %d",
+                        __FUNCTION__, profile);
+                ADD_FAILURE();
+        }
+    }
+}
+
 bool CameraHidlTest::isDepthOnly(const camera_metadata_t* staticMeta) {
     camera_metadata_ro_entry scalarEntry;
     camera_metadata_ro_entry depthEntry;
@@ -8006,8 +8493,9 @@
     sp<device::V3_5::ICameraDeviceSession> session3_5;
     sp<device::V3_6::ICameraDeviceSession> session3_6;
     sp<device::V3_7::ICameraDeviceSession> session3_7;
+    sp<device::V3_8::ICameraDeviceSession> session3_8;
     castSession(*session, deviceVersion, &session3_3, &session3_4, &session3_5,
-            &session3_6, &session3_7);
+            &session3_6, &session3_7, &session3_8);
 
     *useHalBufManager = false;
     status = find_camera_metadata_ro_entry(staticMeta,
@@ -8138,12 +8626,19 @@
 void CameraHidlTest::castDevice(const sp<device::V3_2::ICameraDevice>& device,
                                 int32_t deviceVersion,
                                 sp<device::V3_5::ICameraDevice>* device3_5 /*out*/,
-                                sp<device::V3_7::ICameraDevice>* device3_7 /*out*/) {
+                                sp<device::V3_7::ICameraDevice>* device3_7 /*out*/,
+                                sp<device::V3_8::ICameraDevice>* device3_8 /*out*/) {
     ASSERT_NE(nullptr, device3_5);
     ASSERT_NE(nullptr, device3_7);
+    ASSERT_NE(nullptr, device3_8);
 
     switch (deviceVersion) {
-        case CAMERA_DEVICE_API_VERSION_3_8:
+        case CAMERA_DEVICE_API_VERSION_3_8: {
+            auto castResult = device::V3_8::ICameraDevice::castFrom(device);
+            ASSERT_TRUE(castResult.isOk());
+            *device3_8 = castResult;
+        }
+            [[fallthrough]];
         case CAMERA_DEVICE_API_VERSION_3_7: {
             auto castResult = device::V3_7::ICameraDevice::castFrom(device);
             ASSERT_TRUE(castResult.isOk());
@@ -8192,15 +8687,22 @@
         sp<device::V3_4::ICameraDeviceSession> *session3_4 /*out*/,
         sp<device::V3_5::ICameraDeviceSession> *session3_5 /*out*/,
         sp<device::V3_6::ICameraDeviceSession> *session3_6 /*out*/,
-        sp<device::V3_7::ICameraDeviceSession> *session3_7 /*out*/) {
+        sp<device::V3_7::ICameraDeviceSession> *session3_7 /*out*/,
+        sp<device::V3_8::ICameraDeviceSession> *session3_8 /*out*/) {
     ASSERT_NE(nullptr, session3_3);
     ASSERT_NE(nullptr, session3_4);
     ASSERT_NE(nullptr, session3_5);
     ASSERT_NE(nullptr, session3_6);
     ASSERT_NE(nullptr, session3_7);
+    ASSERT_NE(nullptr, session3_8);
 
     switch (deviceVersion) {
-        case CAMERA_DEVICE_API_VERSION_3_8:
+        case CAMERA_DEVICE_API_VERSION_3_8: {
+            auto castResult = device::V3_8::ICameraDeviceSession::castFrom(session);
+            ASSERT_TRUE(castResult.isOk());
+            *session3_8 = castResult;
+        }
+        [[fallthrough]];
         case CAMERA_DEVICE_API_VERSION_3_7: {
             auto castResult = device::V3_7::ICameraDeviceSession::castFrom(session);
             ASSERT_TRUE(castResult.isOk());
@@ -9077,8 +9579,9 @@
     sp<device::V3_5::ICameraDeviceSession> session3_5;
     sp<device::V3_6::ICameraDeviceSession> session3_6;
     sp<device::V3_7::ICameraDeviceSession> session3_7;
+    sp<device::V3_8::ICameraDeviceSession> session3_8;
     castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5,
-            &session3_6, &session3_7);
+            &session3_6, &session3_7, &session3_8);
     ASSERT_NE(nullptr, session3_5.get());
 
     hidl_vec<int32_t> streamIds(1);
@@ -9320,7 +9823,7 @@
     size_t CONFIG_ENTRY_TYPE_OFFSET = 3;
     size_t CONFIG_ENTRY_BITFIELD_OFFSET = 4;
     uint32_t maxPublicUsecase =
-            ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END;
+            ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_PUBLIC_END_3_8;
     uint32_t vendorUsecaseStart =
             ANDROID_SCALER_AVAILABLE_RECOMMENDED_STREAM_CONFIGURATIONS_VENDOR_START;
     uint32_t usecaseMask = (1 << vendorUsecaseStart) - 1;