QCamera2: HAL3: Validate usage flags for configure_streams

If usage flag has combined bits from different consumers, fail
configure_streams if camera device doesn't support it.

Camera device take into consideration of below 3 factors:
- stream format
- stream dataspace, and
- HAL interface restriction

Test: Camera CTS
Bug: 33777818
Change-Id: Ie2b2ad44de74ad908269bc23c8ce8ce065153a8f
diff --git a/msm8998/QCamera2/HAL3/QCamera3HWI.cpp b/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
index 1a0ec8a..26de733 100644
--- a/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
@@ -1240,6 +1240,98 @@
     return rc;
 }
 
+/*===========================================================================
+ * FUNCTION   : validateUsageFlags
+ *
+ * DESCRIPTION: Check if the configuration usage flags map to same internal format.
+ *
+ * PARAMETERS :
+ *   @stream_list : streams to be configured
+ *
+ * RETURN     :
+ *   NO_ERROR if the usage flags are supported
+ *   error code if usage flags are not supported
+ *
+ *==========================================================================*/
+int QCamera3HardwareInterface::validateUsageFlags(
+        const camera3_stream_configuration_t* streamList)
+{
+    for (size_t j = 0; j < streamList->num_streams; j++) {
+        const camera3_stream_t *newStream = streamList->streams[j];
+
+        if (newStream->format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
+            (newStream->stream_type != CAMERA3_STREAM_OUTPUT &&
+             newStream->stream_type != CAMERA3_STREAM_BIDIRECTIONAL)) {
+            continue;
+        }
+
+        bool isVideo = IS_USAGE_VIDEO(newStream->usage);
+        bool isPreview = IS_USAGE_PREVIEW(newStream->usage);
+        bool isZSL = IS_USAGE_ZSL(newStream->usage);
+        bool forcePreviewUBWC = true;
+        if (isVideo && !QCameraCommon::isVideoUBWCEnabled()) {
+            forcePreviewUBWC = false;
+        }
+        cam_format_t videoFormat = QCamera3Channel::getStreamDefaultFormat(
+                CAM_STREAM_TYPE_VIDEO, newStream->width, newStream->height, forcePreviewUBWC);
+        cam_format_t previewFormat = QCamera3Channel::getStreamDefaultFormat(
+                CAM_STREAM_TYPE_PREVIEW, newStream->width, newStream->height, forcePreviewUBWC);
+        cam_format_t zslFormat = QCamera3Channel::getStreamDefaultFormat(
+                CAM_STREAM_TYPE_SNAPSHOT, newStream->width, newStream->height, forcePreviewUBWC);
+
+        // Color space for this camera device is guaranteed to be ITU_R_601_FR.
+        // So color spaces will always match.
+
+        // Check whether underlying formats of shared streams match.
+        if (isVideo && isPreview && videoFormat != previewFormat) {
+            LOGE("Combined video and preview usage flag is not supported");
+            return -EINVAL;
+        }
+        if (isPreview && isZSL && previewFormat != zslFormat) {
+            LOGE("Combined preview and zsl usage flag is not supported");
+            return -EINVAL;
+        }
+        if (isVideo && isZSL && videoFormat != zslFormat) {
+            LOGE("Combined video and zsl usage flag is not supported");
+            return -EINVAL;
+        }
+    }
+    return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION   : validateUsageFlagsForEis
+ *
+ * DESCRIPTION: Check if the configuration usage flags conflict with Eis
+ *
+ * PARAMETERS :
+ *   @stream_list : streams to be configured
+ *
+ * RETURN     :
+ *   NO_ERROR if the usage flags are supported
+ *   error code if usage flags are not supported
+ *
+ *==========================================================================*/
+int QCamera3HardwareInterface::validateUsageFlagsForEis(
+        const camera3_stream_configuration_t* streamList)
+{
+    for (size_t j = 0; j < streamList->num_streams; j++) {
+        const camera3_stream_t *newStream = streamList->streams[j];
+
+        bool isVideo = IS_USAGE_VIDEO(newStream->usage);
+        bool isPreview = IS_USAGE_PREVIEW(newStream->usage);
+
+        // Because EIS is "hard-coded" for certain use case, and current
+       // implementation doesn't support shared preview and video on the same
+        // stream, return failure if EIS is forced on.
+        if (isPreview && isVideo && m_bEisEnable && m_bEisSupportedSize) {
+            LOGE("Combined video and preview usage flag is not supported due to EIS");
+            return -EINVAL;
+        }
+    }
+    return NO_ERROR;
+}
+
 /*==============================================================================
  * FUNCTION   : isSupportChannelNeeded
  *
@@ -1554,6 +1646,11 @@
         return BAD_VALUE;
     }
 
+    rc = validateUsageFlags(streamList);
+    if (rc != NO_ERROR) {
+        return rc;
+    }
+
     mOpMode = streamList->operation_mode;
     LOGD("mOpMode: %d", mOpMode);
 
@@ -1619,6 +1716,7 @@
     m_bVideoHdrEnabled = false;
     bool isZsl = false;
     bool depthPresent = false;
+    bool isPreview = false;
     uint32_t videoWidth = 0U;
     uint32_t videoHeight = 0U;
     size_t rawStreamCnt = 0;
@@ -1700,6 +1798,11 @@
                 newStream->stream_type == CAMERA3_STREAM_INPUT){
             isZsl = true;
         }
+        if ((HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED == newStream->format) &&
+                IS_USAGE_PREVIEW(newStream->usage)) {
+            isPreview = true;
+        }
+
         if (newStream->stream_type == CAMERA3_STREAM_INPUT){
             inputStream = newStream;
         }
@@ -1731,6 +1834,7 @@
             }
             m_bEisSupportedSize = (newStream->width <= maxEisWidth) &&
                                   (newStream->height <= maxEisHeight);
+
         }
         if (newStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL ||
                 newStream->stream_type == CAMERA3_STREAM_OUTPUT) {
@@ -1810,6 +1914,11 @@
         m_bEisEnable = false;
     }
 
+    if (validateUsageFlagsForEis(streamList) != NO_ERROR) {
+        pthread_mutex_unlock(&mMutex);
+        return -EINVAL;
+    }
+
     uint8_t forceEnableTnr = 0;
     char tnr_prop[PROPERTY_VALUE_MAX];
     memset(tnr_prop, 0, sizeof(tnr_prop));
@@ -2253,6 +2362,7 @@
                 break;
             }
 
+            bool forcePreviewUBWC = true;
             if (newStream->stream_type == CAMERA3_STREAM_OUTPUT ||
                     newStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL) {
                 QCamera3ProcessingChannel *channel = NULL;
@@ -2315,13 +2425,12 @@
                         }
                         /* disable UBWC for preview, though supported,
                          * to take advantage of CPP duplication */
-                        if (m_bIsVideo && (!mCommon.isVideoUBWCEnabled()) &&
+                        if (m_bIsVideo && (!QCameraCommon::isVideoUBWCEnabled()) &&
                                 (previewSize.width == (int32_t)videoWidth)&&
                                 (previewSize.height == (int32_t)videoHeight)){
-                            channel->setUBWCEnabled(false);
-                        }else {
-                            channel->setUBWCEnabled(true);
+                            forcePreviewUBWC = false;
                         }
+                        channel->setUBWCEnabled(forcePreviewUBWC);
                         newStream->max_buffers = channel->getNumBuffers();
                         newStream->priv = channel;
                     }
@@ -2416,10 +2525,10 @@
             }
 
             QCamera3Channel *channel = (QCamera3Channel*) newStream->priv;
-            if (channel != NULL && channel->isUBWCEnabled()) {
-                cam_format_t fmt = channel->getStreamDefaultFormat(
+            if (channel != NULL && QCamera3Channel::isUBWCEnabled()) {
+                cam_format_t fmt = QCamera3Channel::getStreamDefaultFormat(
                         mStreamConfigInfo.type[mStreamConfigInfo.num_streams],
-                        newStream->width, newStream->height);
+                        newStream->width, newStream->height, forcePreviewUBWC);
                 if(fmt == CAM_FORMAT_YUV_420_NV12_UBWC) {
                     newStream->usage |= GRALLOC_USAGE_PRIVATE_ALLOC_UBWC;
                 }