Expose timestamp source & thumbnail sizes characteristic

... for virtual camera.

Also fix .setAvailableCharacteristicKeys so it takes effect once
the .build() is called so it's not order dependent.

Bug: 301023410
Bug: 322965201
Test: atest android.hardware.cts.CameraGLTest
Test: atest android.hardware.camera2.cts.ImageReaderTest
Test: presubmit
Change-Id: I1fac9c4561c910f128fa67b7ce11d8e4c6c31b09
diff --git a/services/camera/virtualcamera/util/MetadataBuilder.cc b/services/camera/virtualcamera/util/MetadataBuilder.cc
index bf4758f..b30f2b5 100644
--- a/services/camera/virtualcamera/util/MetadataBuilder.cc
+++ b/services/camera/virtualcamera/util/MetadataBuilder.cc
@@ -31,6 +31,7 @@
 #include "aidl/android/hardware/camera/device/CameraMetadata.h"
 #include "log/log.h"
 #include "system/camera_metadata.h"
+#include "util/Util.h"
 #include "utils/Errors.h"
 
 namespace android {
@@ -95,6 +96,14 @@
   return *this;
 }
 
+MetadataBuilder& MetadataBuilder::setSensorTimestampSource(
+    const camera_metadata_enum_android_sensor_info_timestamp_source_t
+        timestampSource) {
+  mEntryMap[ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE] =
+      std::vector<uint8_t>({static_cast<uint8_t>(timestampSource)});
+  return *this;
+}
+
 MetadataBuilder& MetadataBuilder::setSensorTimestamp(
     std::chrono::nanoseconds timestamp) {
   mEntryMap[ANDROID_SENSOR_TIMESTAMP] =
@@ -247,6 +256,18 @@
   return *this;
 }
 
+MetadataBuilder& MetadataBuilder::setJpegAvailableThumbnailSizes(
+    const std::vector<Resolution>& thumbnailSizes) {
+  std::vector<int32_t> sizes;
+  sizes.reserve(thumbnailSizes.size() * 2);
+  for (const Resolution& resolution : thumbnailSizes) {
+    sizes.push_back(resolution.width);
+    sizes.push_back(resolution.height);
+  }
+  mEntryMap[ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES] = sizes;
+  return *this;
+}
+
 MetadataBuilder& MetadataBuilder::setMaxNumberOutputStreams(
     const int32_t maxRawStreams, const int32_t maxProcessedStreams,
     const int32_t maxStallStreams) {
@@ -381,19 +402,23 @@
 }
 
 MetadataBuilder& MetadataBuilder::setAvailableCharacteristicKeys() {
-  std::vector<camera_metadata_tag_t> availableKeys;
-  availableKeys.reserve(mEntryMap.size());
-  for (const auto& [key, _] : mEntryMap) {
-    if (key != ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS) {
-      availableKeys.push_back(key);
-    }
-  }
-  setAvailableCharacteristicKeys(availableKeys);
+  mExtendWithAvailableCharacteristicsKeys = true;
   return *this;
 }
 
 std::unique_ptr<aidl::android::hardware::camera::device::CameraMetadata>
-MetadataBuilder::build() const {
+MetadataBuilder::build() {
+  if (mExtendWithAvailableCharacteristicsKeys) {
+    std::vector<camera_metadata_tag_t> availableKeys;
+    availableKeys.reserve(mEntryMap.size());
+    for (const auto& [key, _] : mEntryMap) {
+      if (key != ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS) {
+        availableKeys.push_back(key);
+      }
+    }
+    setAvailableCharacteristicKeys(availableKeys);
+  }
+
   CameraMetadata metadataHelper;
   for (const auto& entry : mEntryMap) {
     status_t ret = std::visit(
diff --git a/services/camera/virtualcamera/util/MetadataBuilder.h b/services/camera/virtualcamera/util/MetadataBuilder.h
index d35fa3d..71832d9 100644
--- a/services/camera/virtualcamera/util/MetadataBuilder.h
+++ b/services/camera/virtualcamera/util/MetadataBuilder.h
@@ -26,6 +26,7 @@
 
 #include "aidl/android/hardware/camera/device/CameraMetadata.h"
 #include "system/camera_metadata.h"
+#include "util/Util.h"
 
 namespace android {
 namespace companion {
@@ -91,6 +92,10 @@
   // See ANDROID_SENSOR_TIMESTAMP in CameraMetadataTag.aidl.
   MetadataBuilder& setSensorTimestamp(std::chrono::nanoseconds timestamp);
 
+  // See SENSOR_INFO_TIMESTAMP_SOURCE in CameraCharacteristic.java.
+  MetadataBuilder& setSensorTimestampSource(
+      camera_metadata_enum_android_sensor_info_timestamp_source_t timestampSource);
+
   // See ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE in CameraMetadataTag.aidl.
   MetadataBuilder& setSensorActiveArraySize(int x0, int y0, int x1, int y1);
 
@@ -183,6 +188,10 @@
   // See ANDROID_JPEG_SIZE in CameraMetadataTag.aidl.
   MetadataBuilder& setMaxJpegSize(int32_t size);
 
+  // See JPEG_AVAILABLE_THUMBNAIL_SIZES in CameraCharacteristic.java.
+  MetadataBuilder& setJpegAvailableThumbnailSizes(
+      const std::vector<Resolution>& thumbnailSizes);
+
   // The maximum numbers of different types of output streams
   // that can be configured and used simultaneously by a camera device.
   //
@@ -232,14 +241,14 @@
       const std::vector<camera_metadata_tag_t>& keys);
 
   // Extends metadata with ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS
-  // containing all previously set tags.
+  // containing all set tags.
   MetadataBuilder& setAvailableCharacteristicKeys();
 
   // Build CameraMetadata instance.
   //
   // Returns nullptr in case something went wrong.
   std::unique_ptr<::aidl::android::hardware::camera::device::CameraMetadata>
-  build() const;
+  build();
 
  private:
   // Maps metadata tags to vectors of values for the given tag.
@@ -248,6 +257,8 @@
                         std::vector<uint8_t>, std::vector<float>,
                         std::vector<camera_metadata_rational_t>>>
       mEntryMap;
+  // Extend metadata with ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS.
+  bool mExtendWithAvailableCharacteristicsKeys = false;
 };
 
 }  // namespace virtualcamera
diff --git a/services/camera/virtualcamera/util/Util.h b/services/camera/virtualcamera/util/Util.h
index e0a31c0..9f81bb1 100644
--- a/services/camera/virtualcamera/util/Util.h
+++ b/services/camera/virtualcamera/util/Util.h
@@ -52,6 +52,27 @@
     int width, int height,
     ::aidl::android::companion::virtualcamera::Format format, int maxFps);
 
+// Representation of resolution / size.
+struct Resolution {
+  Resolution(const int w, const int h) : width(w), height(h) {
+  }
+
+  // Order by increasing pixel count, and by width for same pixel count.
+  bool operator<(const Resolution& other) const {
+    const int pixCount = width * height;
+    const int otherPixCount = other.width * other.height;
+    return pixCount == otherPixCount ? width < other.width
+                                     : pixCount < otherPixCount;
+  }
+
+  bool operator==(const Resolution& other) const {
+    return width == other.width && height == other.height;
+  }
+
+  const int width;
+  const int height;
+};
+
 }  // namespace virtualcamera
 }  // namespace companion
 }  // namespace android