camera: usb: Add quirk to report user space timestamps instead of V4L2

Some camera modules failed to provide monotonically increasing V4L2
timestamps for the captured frames, and caused "Captures are out of
order" CTS failures. Add a quirk for them to report user space
timestamps got from HAL to fix it.

BUG=b:158957477, b:161103422
TEST=CTS test case SurfaceViewPreviewTest#testSurfaceSet

Change-Id: I52c27e779b17877c253045e10aaf0fe460e74e5c
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2289810
Reviewed-by: Shik Chen <shik@chromium.org>
Tested-by: Ren-Pei Zeng <kamesan@chromium.org>
Commit-Queue: Ren-Pei Zeng <kamesan@chromium.org>
(cherry picked from commit 729cd5fdb1c9cebbe9f4f812b97ac45d1ff6ffb2)
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2298564
Reviewed-by: Ren-Pei Zeng <kamesan@chromium.org>
diff --git a/camera/hal/usb/camera_client.cc b/camera/hal/usb/camera_client.cc
index 357c746..00cce3f 100644
--- a/camera/hal/usb/camera_client.cc
+++ b/camera/hal/usb/camera_client.cc
@@ -889,8 +889,9 @@
 }
 
 uint64_t CameraClient::RequestHandler::CurrentBufferTimestamp() {
-  return IsExternalCamera() ? current_buffer_timestamp_in_user_
-                            : current_buffer_timestamp_in_v4l2_;
+  return device_info_.quirks & kQuirkUserSpaceTimestamp
+             ? current_buffer_timestamp_in_user_
+             : current_buffer_timestamp_in_v4l2_;
 }
 
 bool CameraClient::RequestHandler::ShouldEnableConstantFrameRate(
diff --git a/camera/hal/usb/camera_client.h b/camera/hal/usb/camera_client.h
index 3a80466..49e2393 100644
--- a/camera/hal/usb/camera_client.h
+++ b/camera/hal/usb/camera_client.h
@@ -202,10 +202,9 @@
     // Returns true if the connected device is an external camera.
     bool IsExternalCamera();
 
-    // Returns the current buffer timestamp.  For built-in camera, it uses
-    // hardware timestamp from v4l2 buffer; for external camera, it uses
-    // software timestamp from userspace, because the hardware timestamp is not
-    // reliable and sometimes even jump backwards.
+    // Returns the current buffer timestamp. It chooses hardware timestamp from
+    // v4l2 buffer or software timestamp from userspace based on the device
+    // specific quirks.
     uint64_t CurrentBufferTimestamp();
 
     // Check whether we should enable constant frame rate according to metadata.
diff --git a/camera/hal/usb/camera_hal.cc b/camera/hal/usb/camera_hal.cc
index 945ace0..8576f2d 100644
--- a/camera/hal/usb/camera_hal.cc
+++ b/camera/hal/usb/camera_hal.cc
@@ -427,6 +427,10 @@
       VLOGF(1) << "Use a new id " << info.camera_id << " for camera "
                << model_id;
     }
+
+    // Uses software timestamp from userspace for external cameras, because the
+    // hardware timestamp is not reliable and sometimes even jump backwards.
+    info.quirks |= kQuirkUserSpaceTimestamp;
   }
 
   android::CameraMetadata static_metadata, request_template;
diff --git a/camera/hal/usb/quirks.cc b/camera/hal/usb/quirks.cc
index e7f4985..8f78741 100644
--- a/camera/hal/usb/quirks.cc
+++ b/camera/hal/usb/quirks.cc
@@ -30,6 +30,8 @@
       {{"046d", "0876"}, kQuirkRestartOnTimeout},
       // IPEVO Ziggi-HD Plus
       {{"1778", "0225"}, kQuirkDisableFrameRateSetting},
+      // Chicony CNFFH37 (b/158957477)
+      {{"0c45", "6a05"}, kQuirkUserSpaceTimestamp},
   };
   return kQuirksMap;
 }
diff --git a/camera/hal/usb/quirks.h b/camera/hal/usb/quirks.h
index f37263c..6150726 100644
--- a/camera/hal/usb/quirks.h
+++ b/camera/hal/usb/quirks.h
@@ -22,6 +22,7 @@
   kQuirkReportLeastFpsRanges = 1 << 3,
   kQuirkDisableFrameRateSetting = 1 << 4,
   kQuirkV1Device = 1 << 5,
+  kQuirkUserSpaceTimestamp = 1 << 6,
 };
 
 uint32_t GetQuirks(const std::string& vid, const std::string& pid);