Simple dump for Virtual Caemra device

Bug: 301023410
Test: atest VirtualCameraDeviceTest#dump
Change-Id: I917c73c587ea246aeb44f8d6ca0ba03ca43f87dc
diff --git a/services/camera/virtualcamera/VirtualCameraDevice.cc b/services/camera/virtualcamera/VirtualCameraDevice.cc
index d4c6423..fe9e0ed 100644
--- a/services/camera/virtualcamera/VirtualCameraDevice.cc
+++ b/services/camera/virtualcamera/VirtualCameraDevice.cc
@@ -28,6 +28,7 @@
 #include <string>
 #include <vector>
 
+#include "VirtualCameraService.h"
 #include "VirtualCameraSession.h"
 #include "aidl/android/companion/virtualcamera/SupportedStreamConfiguration.h"
 #include "aidl/android/companion/virtualcamera/VirtualCameraConfiguration.h"
@@ -575,12 +576,18 @@
   return cameraStatus(Status::OPERATION_NOT_SUPPORTED);
 }
 
-binder_status_t VirtualCameraDevice::dump(int fd, const char** args,
-                                          uint32_t numArgs) {
-  // TODO(b/301023410) Implement.
-  (void)fd;
-  (void)args;
-  (void)numArgs;
+binder_status_t VirtualCameraDevice::dump(int fd, const char**, uint32_t) {
+  ALOGD("Dumping virtual camera %d", mCameraId);
+  const char* indent = "  ";
+  const char* doubleIndent = "    ";
+  dprintf(fd, "%svirtual_camera %d belongs to virtual device %d\n", indent,
+          mCameraId,
+          getDeviceId(mCameraCharacteristics)
+              .value_or(VirtualCameraService::kDefaultDeviceId));
+  dprintf(fd, "%sSupportedStreamConfiguration:\n", indent);
+  for (auto& config : mSupportedInputConfigurations) {
+    dprintf(fd, "%s%s", doubleIndent, config.toString().c_str());
+  }
   return STATUS_OK;
 }
 
diff --git a/services/camera/virtualcamera/VirtualCameraService.cc b/services/camera/virtualcamera/VirtualCameraService.cc
index 48b4410..b5b07f0 100644
--- a/services/camera/virtualcamera/VirtualCameraService.cc
+++ b/services/camera/virtualcamera/VirtualCameraService.cc
@@ -64,7 +64,6 @@
 constexpr int kVgaWidth = 640;
 constexpr int kVgaHeight = 480;
 constexpr int kMaxFps = 60;
-constexpr int kDefaultDeviceId = 0;
 constexpr char kEnableTestCameraCmd[] = "enable_test_camera";
 constexpr char kDisableTestCameraCmd[] = "disable_test_camera";
 constexpr char kHelp[] = "help";
diff --git a/services/camera/virtualcamera/VirtualCameraService.h b/services/camera/virtualcamera/VirtualCameraService.h
index 2121d64..f04acb5 100644
--- a/services/camera/virtualcamera/VirtualCameraService.h
+++ b/services/camera/virtualcamera/VirtualCameraService.h
@@ -75,6 +75,9 @@
     mVerifyEglExtensions = false;
   }
 
+  // Default virtual device id (the host device id)
+  static constexpr int kDefaultDeviceId = 0;
+
  private:
   // Create and enable test camera instance if there's none.
   binder_status_t enableTestCameraCmd(
diff --git a/services/camera/virtualcamera/tests/VirtualCameraDeviceTest.cc b/services/camera/virtualcamera/tests/VirtualCameraDeviceTest.cc
index 5c9b3b9..3fe7c11 100644
--- a/services/camera/virtualcamera/tests/VirtualCameraDeviceTest.cc
+++ b/services/camera/virtualcamera/tests/VirtualCameraDeviceTest.cc
@@ -363,6 +363,33 @@
               ElementsAre(Resolution(0, 0), Resolution(240, 180)));
 }
 
+TEST_F(VirtualCameraDeviceTest, dump) {
+  std::string expected = R"(  virtual_camera 42 belongs to virtual device 0
+  SupportedStreamConfiguration:
+    SupportedStreamConfiguration{width: 640, height: 480, pixelFormat: YUV_420_888, maxFps: 30})";
+  int expectedSize = expected.size() * sizeof(char);
+  char buffer[expectedSize];
+
+  // Create an in memory fd
+  int fd = memfd_create("tmpFile", 0);
+  mCamera->dump(fd, {}, 0);
+
+  // Check that we wrote the expected size
+  int dumpSize = lseek(fd, 0, SEEK_END);
+
+  // Rewind and read from the fd
+  lseek(fd, 0, SEEK_SET);
+  read(fd, buffer, expectedSize);
+  close(fd);
+
+  // Check the content of the dump
+  std::string name = std::string(buffer, expectedSize);
+  ASSERT_EQ(expected, name);
+  // Check the size after the content to display the string mismatch when a
+  // failure occurs
+  ASSERT_EQ(expectedSize, dumpSize);
+}
+
 }  // namespace
 }  // namespace virtualcamera
 }  // namespace companion
diff --git a/services/camera/virtualcamera/util/MetadataUtil.cc b/services/camera/virtualcamera/util/MetadataUtil.cc
index d8f6125..31a8776 100644
--- a/services/camera/virtualcamera/util/MetadataUtil.cc
+++ b/services/camera/virtualcamera/util/MetadataUtil.cc
@@ -947,6 +947,20 @@
       entry.data.u8[0]);
 }
 
+std::optional<int32_t> getDeviceId(
+    const aidl::android::hardware::camera::device::CameraMetadata& cameraMetadata) {
+  auto metadata =
+      reinterpret_cast<const camera_metadata_t*>(cameraMetadata.metadata.data());
+
+  camera_metadata_ro_entry_t entry;
+  if (find_camera_metadata_ro_entry(metadata, ANDROID_INFO_DEVICE_ID, &entry) !=
+      OK) {
+    return std::nullopt;
+  }
+
+  return static_cast<int32_t>(entry.data.i32[0]);
+}
+
 }  // namespace virtualcamera
 }  // namespace companion
 }  // namespace android
diff --git a/services/camera/virtualcamera/util/MetadataUtil.h b/services/camera/virtualcamera/util/MetadataUtil.h
index d0af0c1..ca6f332 100644
--- a/services/camera/virtualcamera/util/MetadataUtil.h
+++ b/services/camera/virtualcamera/util/MetadataUtil.h
@@ -484,6 +484,10 @@
 getPrecaptureTrigger(
     const aidl::android::hardware::camera::device::CameraMetadata& cameraMetadata);
 
+// Returns the virtual device id. This is not the camera id.
+std::optional<int32_t> getDeviceId(
+    const aidl::android::hardware::camera::device::CameraMetadata& cameraMetadata);
+
 }  // namespace virtualcamera
 }  // namespace companion
 }  // namespace android