// Copyright 2016 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "camera3_test/camera3_module_fixture.h"

#include <algorithm>
#include <string>

#include <base/at_exit.h>
#include <base/bind.h>
#include <base/command_line.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/macros.h>
#include <base/no_destructor.h>
#include <base/stl_util.h>
#include <base/strings/string_split.h>
#include <base/strings/stringprintf.h>
#include <base/sys_info.h>

#include "camera3_test/camera3_perf_log.h"
#include "camera3_test/camera3_test_data_forwarder.h"
#include "common/utils/camera_hal_enumerator.h"

namespace camera3_test {

static camera_module_t* g_cam_module = NULL;

// TODO(shik): Objects with static storage duration are forbidden unless they
// are trivially destructible. CameraThread is trivially not trivially
// destructible.
static cros::CameraThread g_module_thread("Camera3 Test Module Thread");

std::vector<std::tuple<int, int32_t, int32_t, float>> ParseRecordingParams() {
  // This parameter would be generated and passed by the camera_HAL3 autotest.
  if (!base::CommandLine::ForCurrentProcess()->HasSwitch("recording_params")) {
    LOGF(ERROR) << "Missing recording parameters in the test command";
    // Return invalid parameters to fail the test
    return {{-1, 0, 0, 0.0}};
  }
  std::vector<std::tuple<int, int32_t, int32_t, float>> params;
  std::string params_str =
      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          "recording_params");
  // Expected video recording parameters in the format
  // "camera_id:width:height:frame_rate". For example:
  // "0:1280:720:30,0:1920:1080:30,1:1280:720:30" means camcorder profiles
  // contains 1280x720 and 1920x1080 for camera 0 and just 1280x720 for camera
  // 1.
  const size_t kNumParamsInProfile = 4;
  enum { CAMERA_ID_IDX, WIDTH_IDX, HEIGHT_IDX, FRAME_RATE_IDX };
  for (const auto& it : base::SplitString(
           params_str, ",", base::WhitespaceHandling::TRIM_WHITESPACE,
           base::SplitResult::SPLIT_WANT_ALL)) {
    auto profile =
        base::SplitString(it, ":", base::WhitespaceHandling::TRIM_WHITESPACE,
                          base::SplitResult::SPLIT_WANT_ALL);
    if (profile.size() != kNumParamsInProfile) {
      ADD_FAILURE() << "Failed to parse video recording parameters (" << it
                    << ")";
      continue;
    }
    params.emplace_back(
        std::stoi(profile[CAMERA_ID_IDX]), std::stoi(profile[WIDTH_IDX]),
        std::stoi(profile[HEIGHT_IDX]), std::stof(profile[FRAME_RATE_IDX]));
  }

  std::set<int> param_ids;
  for (const auto& param : params) {
    param_ids.insert(std::get<CAMERA_ID_IDX>(param));
  }

  // We are going to enable usb camera hal on all boards, so there will be more
  // than one hals on many platforms just like today's nautilus.  The
  // recording_params is now generated from media_profiles.xml, where the camera
  // ids are already translated by SuperHAL.  But cros_camera_test is used to
  // test only one camera hal directly without going through the hal_adapter,
  // therefore we have to remap the ids here.
  //
  // TODO(shik): This is a temporary workaround for SuperHAL camera ids mapping
  // until we have better ground truth config file.  Here we exploit the fact
  // that there are at most one back and at most one front internal cameras for
  // now, and all cameras are sorted by facing in SuperHAL.  I feel bad when
  // implementing the following hack (sigh).
  std::vector<std::tuple<int, int32_t, int32_t, float>> result;
  Camera3Module module;
  if (module.GetCameraIds().size() < param_ids.size()) {
    // SuperHAL case
    for (const auto& cam_id : module.GetTestCameraIds()) {
      camera_info info;
      EXPECT_EQ(0, Camera3Module().GetCameraInfo(cam_id, &info));
      bool found_matching_param = false;
      for (auto param : params) {
        if (std::get<CAMERA_ID_IDX>(param) == info.facing) {
          found_matching_param = true;
          std::get<CAMERA_ID_IDX>(param) = cam_id;
          result.emplace_back(param);
        }
      }
      EXPECT_TRUE(found_matching_param);
    }
  } else {
    // Single HAL case
    for (const auto& cam_id : module.GetTestCameraIds()) {
      if (std::find_if(
              params.begin(), params.end(),
              [&](const std::tuple<int, int32_t, int32_t, float>& item) {
                return std::get<CAMERA_ID_IDX>(item) == cam_id;
              }) == params.end()) {
        ADD_FAILURE() << "Missing video recording parameters for camera "
                      << cam_id;
      }
    }
    result = std::move(params);
  }

  LOGF(INFO) << "The parameters will be used for recording test:";
  for (const auto& param : result) {
    LOGF(INFO) << base::StringPrintf(
        "camera id = %d, size = %dx%d, fps = %g",
        std::get<CAMERA_ID_IDX>(param), std::get<WIDTH_IDX>(param),
        std::get<HEIGHT_IDX>(param), std::get<FRAME_RATE_IDX>(param));
  }

  return result;
}

// static
void CameraModuleCallbacksHandler::camera_device_status_change(
    const camera_module_callbacks_t* callbacks, int camera_id, int new_status) {
  auto* aux = static_cast<const CameraModuleCallbacksAux*>(callbacks);
  aux->handler->CameraDeviceStatusChange(
      camera_id, static_cast<camera_device_status_t>(new_status));
}

// static
void CameraModuleCallbacksHandler::torch_mode_status_change(
    const camera_module_callbacks_t* callbacks,
    const char* camera_id,
    int new_status) {
  auto* aux = static_cast<const CameraModuleCallbacksAux*>(callbacks);
  aux->handler->TorchModeStatusChange(
      atoi(camera_id), static_cast<torch_mode_status_t>(new_status));
}

// static
CameraModuleCallbacksHandler* CameraModuleCallbacksHandler::GetInstance() {
  static auto* instance = new CameraModuleCallbacksHandler();
  return instance;
}

bool CameraModuleCallbacksHandler::IsExternalCameraPresent(int camera_id) {
  base::AutoLock l(lock_);
  auto it = device_status_.find(camera_id);
  return it != device_status_.end() &&
         it->second == CAMERA_DEVICE_STATUS_PRESENT;
}

// TODO(shik): Run tests on external cameras as well if detected.  We need to
// relax the requirements for them just like what CTS did.
void CameraModuleCallbacksHandler::CameraDeviceStatusChange(
    int camera_id, camera_device_status_t new_status) {
  base::AutoLock l(lock_);
  LOGF(INFO) << "camera_id = " << camera_id << ", new status = " << new_status;
  device_status_[camera_id] = new_status;
}

void CameraModuleCallbacksHandler::TorchModeStatusChange(
    int camera_id, torch_mode_status_t new_status) {
  LOGF(INFO) << "camera_id = " << camera_id << ", new status = " << new_status;
}

int32_t ResolutionInfo::Width() const {
  return width_;
}

int32_t ResolutionInfo::Height() const {
  return height_;
}

int32_t ResolutionInfo::Area() const {
  return width_ * height_;
}

bool ResolutionInfo::operator==(const ResolutionInfo& resolution) const {
  return (width_ == resolution.Width()) && (height_ == resolution.Height());
}

bool ResolutionInfo::operator<(const ResolutionInfo& resolution) const {
  // Compare by area it covers, if the areas are same, then compare the widths.
  return (Area() < resolution.Area()) ||
         (Area() == resolution.Area() && width_ < resolution.Width());
}

std::ostream& operator<<(std::ostream& out, const ResolutionInfo& info) {
  out << info.width_ << 'x' << info.height_;
  return out;
}

static std::vector<int> GetCmdLineTestCameraIds() {
  auto id_str =
      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII("camera_ids");
  std::vector<int> ids;
  if (!id_str.empty()) {
    auto id_strs = base::SplitString(id_str, ",",
                                     base::WhitespaceHandling::TRIM_WHITESPACE,
                                     base::SplitResult::SPLIT_WANT_ALL);
    for (const auto& id : id_strs) {
      ids.push_back(stoi(id));
    }
  }
  return ids;
}

static void InitCameraModuleOnThread(camera_module_t* cam_module) {
  static CameraModuleCallbacksAux* callbacks = []() {
    auto* aux = new CameraModuleCallbacksAux();
    aux->camera_device_status_change =
        &CameraModuleCallbacksHandler::camera_device_status_change;
    aux->torch_mode_status_change =
        &CameraModuleCallbacksHandler::torch_mode_status_change;
    aux->handler = CameraModuleCallbacksHandler::GetInstance();
    return aux;
  }();

  if (cam_module->init) {
    ASSERT_EQ(0, cam_module->init());
  }
  int num_builtin_cameras = cam_module->get_number_of_cameras();
  VLOGF(1) << "num_builtin_cameras = " << num_builtin_cameras;
  ASSERT_EQ(0, cam_module->set_callbacks(callbacks));
}

// On successfully Initialized, |cam_module_| will pointed to valid
// camera_module_t. We cannot dlclose |cam_hal_handle| until the lifetime
// conflict in b/119926433 is resolved.
static void InitCameraModule(const base::FilePath& camera_hal_path,
                             void** cam_hal_handle,
                             camera_module_t** cam_module) {
  *cam_hal_handle = dlopen(camera_hal_path.value().c_str(), RTLD_NOW);
  ASSERT_NE(nullptr, *cam_hal_handle) << "Failed to dlopen: " << dlerror();

  camera_module_t* module = static_cast<camera_module_t*>(
      dlsym(*cam_hal_handle, HAL_MODULE_INFO_SYM_AS_STR));
  ASSERT_NE(nullptr, module) << "Camera module is invalid";
  ASSERT_NE(nullptr, module->get_number_of_cameras)
      << "get_number_of_cameras is not implemented";
  ASSERT_NE(nullptr, module->get_camera_info)
      << "get_camera_info is not implemented";
  ASSERT_NE(nullptr, module->common.methods->open) << "open() is unimplemented";
  for (int id : GetCmdLineTestCameraIds()) {
    ASSERT_GT(module->get_number_of_cameras(), id)
        << "No such test camera id in HAL";
  }
  ASSERT_EQ(0, g_module_thread.PostTaskSync(
                   FROM_HERE, base::Bind(&InitCameraModuleOnThread, module)));
  *cam_module = module;
}

static void InitCameraModuleByHalPath(const base::FilePath& camera_hal_path,
                                      void** cam_hal_handle) {
  InitCameraModule(camera_hal_path, cam_hal_handle, &g_cam_module);
}

static void InitCameraModuleByFacing(int facing, void** cam_hal_handle) {
  // Do cleanup when exit from ASSERT_XX
  struct CleanupModule {
    void operator()(void** cam_hal_handle) {
      if (*cam_hal_handle) {
        g_cam_module = NULL;
        *cam_hal_handle = NULL;
      }
    }
  };
  for (const auto& hal_path : cros::GetCameraHalPaths()) {
    InitCameraModule(hal_path, cam_hal_handle, &g_cam_module);
    std::unique_ptr<void*, CleanupModule> cleanup_ptr(cam_hal_handle);
    if (g_cam_module != NULL) {
      Camera3Module camera_module;
      for (int i = 0; i < camera_module.GetNumberOfCameras(); i++) {
        camera_info info;
        ASSERT_EQ(0, camera_module.GetCameraInfo(i, &info));
        if (info.facing == facing) {
          base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
              "camera_ids", std::to_string(i));
          cleanup_ptr.release();
          return;
        }
      }
    }
  }
  FAIL() << "Cannot find camera with facing=" << facing;
}

static void InitPerfLog() {
  // GetNumberOfCameras() returns the number of internal cameras, so here we
  // should not see any external cameras (facing = 2).
  const std::string facing_names[] = {"back", "front"};
  camera3_test::Camera3Module camera_module;
  int num_cameras = camera_module.GetNumberOfCameras();
  std::map<int, std::string> name_map;
  for (int i = 0; i < num_cameras; i++) {
    camera_info info;
    ASSERT_EQ(0, camera_module.GetCameraInfo(i, &info));
    ASSERT_LE(0, info.facing);
    ASSERT_LT(info.facing, arraysize(facing_names));
    name_map[i] = facing_names[info.facing];
  }
  camera3_test::Camera3PerfLog::GetInstance()->SetCameraNameMap(name_map);
}

static camera_module_t* GetCameraModule() {
  return g_cam_module;
}

// Camera module

Camera3Module::Camera3Module()
    : cam_module_(GetCameraModule()),
      test_camera_ids_(GetCmdLineTestCameraIds()),
      hal_thread_(&g_module_thread),
      dev_thread_("Camera3 Test Device Thread") {
  dev_thread_.Start();
}

int Camera3Module::Initialize() {
  return cam_module_ ? 0 : -ENODEV;
}

int Camera3Module::GetNumberOfCameras() {
  if (!cam_module_) {
    return -ENODEV;
  }
  int result = -EINVAL;
  hal_thread_->PostTaskSync(
      FROM_HERE, base::Bind(&Camera3Module::GetNumberOfCamerasOnHalThread,
                            base::Unretained(this), &result));
  return result;
}

std::vector<int> Camera3Module::GetCameraIds() {
  if (!cam_module_) {
    return std::vector<int>();
  }

  int num_cams = GetNumberOfCameras();
  std::vector<int> ids(num_cams);
  for (int i = 0; i < num_cams; i++) {
    ids[i] = i;
  }

  return ids;
}

std::vector<int> Camera3Module::GetTestCameraIds() {
  return test_camera_ids_.empty() ? GetCameraIds() : test_camera_ids_;
}

void Camera3Module::GetStreamConfigEntry(int cam_id,
                                         int32_t key,
                                         camera_metadata_ro_entry_t* entry) {
  entry->count = 0;

  camera_info info;
  ASSERT_EQ(0, GetCameraInfo(cam_id, &info))
      << "Can't get camera info for" << cam_id;

  camera_metadata_ro_entry_t local_entry = {};
  ASSERT_EQ(
      0, find_camera_metadata_ro_entry(
             const_cast<camera_metadata_t*>(info.static_camera_characteristics),
             key, &local_entry))
      << "Fail to find metadata key " << get_camera_metadata_tag_name(key);
  ASSERT_NE(0u, local_entry.count) << "Camera stream configuration is empty";
  ASSERT_EQ(0u, local_entry.count % kNumOfElementsInStreamConfigEntry)
      << "Camera stream configuration parsing error";
  *entry = local_entry;
}

bool Camera3Module::IsFormatAvailable(int cam_id, int format) {
  if (!cam_module_) {
    return false;
  }

  camera_metadata_ro_entry_t available_config = {};
  GetStreamConfigEntry(cam_id, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
                       &available_config);

  for (uint32_t i = 0; i < available_config.count;
       i += kNumOfElementsInStreamConfigEntry) {
    if (available_config.data.i32[i + STREAM_CONFIG_FORMAT_INDEX] == format) {
      return true;
    }
  }

  return false;
}

camera3_device* Camera3Module::OpenDevice(int cam_id) {
  if (!cam_module_) {
    return NULL;
  }
  camera3_device_t* cam_device = nullptr;
  hal_thread_->PostTaskSync(
      FROM_HERE, base::Bind(&Camera3Module::OpenDeviceOnHalThread,
                            base::Unretained(this), cam_id, &cam_device));
  return cam_device;
}

int Camera3Module::CloseDevice(camera3_device* cam_device) {
  VLOGF_ENTER();
  if (!cam_module_) {
    return -ENODEV;
  }
  int result = -ENODEV;
  dev_thread_.PostTaskSync(
      FROM_HERE, base::Bind(&Camera3Module::CloseDeviceOnDevThread,
                            base::Unretained(this), cam_device, &result));
  return result;
}

int Camera3Module::GetCameraInfo(int cam_id, camera_info* info) {
  if (!cam_module_) {
    return -ENODEV;
  }
  int result = -ENODEV;
  hal_thread_->PostTaskSync(
      FROM_HERE, base::Bind(&Camera3Module::GetCameraInfoOnHalThread,
                            base::Unretained(this), cam_id, info, &result));
  return result;
}

std::vector<int32_t> Camera3Module::GetOutputFormats(int cam_id) {
  if (!cam_module_) {
    return std::vector<int32_t>();
  }

  camera_metadata_ro_entry_t available_config = {};
  GetStreamConfigEntry(cam_id, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
                       &available_config);

  std::set<int32_t> available_formats;
  for (uint32_t i = 0; i < available_config.count;
       i += kNumOfElementsInStreamConfigEntry) {
    if (available_config.data.i32[i + STREAM_CONFIG_DIRECTION_INDEX] ==
        ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT) {
      available_formats.insert(
          available_config.data.i32[i + STREAM_CONFIG_FORMAT_INDEX]);
    }
  }

  return std::vector<int32_t>(available_formats.begin(),
                              available_formats.end());
}

std::vector<ResolutionInfo> Camera3Module::GetSortedOutputResolutions(
    int cam_id, int32_t format) {
  if (!cam_module_) {
    return std::vector<ResolutionInfo>();
  }

  camera_metadata_ro_entry_t available_config = {};
  GetStreamConfigEntry(cam_id, ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
                       &available_config);

  std::vector<ResolutionInfo> available_resolutions;
  for (uint32_t i = 0; i < available_config.count;
       i += kNumOfElementsInStreamConfigEntry) {
    int32_t fmt = available_config.data.i32[i + STREAM_CONFIG_FORMAT_INDEX];
    int32_t width = available_config.data.i32[i + STREAM_CONFIG_WIDTH_INDEX];
    int32_t height = available_config.data.i32[i + STREAM_CONFIG_HEIGHT_INDEX];
    int32_t in_or_out =
        available_config.data.i32[i + STREAM_CONFIG_DIRECTION_INDEX];
    if ((fmt == format) &&
        (in_or_out == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT)) {
      available_resolutions.emplace_back(width, height);
    }
  }
  std::sort(available_resolutions.begin(), available_resolutions.end());
  return available_resolutions;
}

int64_t Camera3Module::GetOutputKeyParameterI64(
    int cam_id,
    int32_t format,
    const ResolutionInfo& resolution,
    int32_t key,
    int32_t index) {
  if (!cam_module_) {
    return -EINVAL;
  }

  camera_metadata_ro_entry_t available_config = {};
  GetStreamConfigEntry(cam_id, key, &available_config);

  for (uint32_t i = 0; i < available_config.count;
       i += kNumOfElementsInStreamConfigEntry) {
    int64_t fmt = available_config.data.i64[i + STREAM_CONFIG_FORMAT_INDEX];
    int64_t width = available_config.data.i64[i + STREAM_CONFIG_WIDTH_INDEX];
    int64_t height = available_config.data.i64[i + STREAM_CONFIG_HEIGHT_INDEX];
    if (fmt == format && width == resolution.Width() &&
        height == resolution.Height()) {
      return available_config.data.i64[i + index];
    }
  }

  return -ENODATA;
}

int64_t Camera3Module::GetOutputStallDuration(
    int cam_id, int32_t format, const ResolutionInfo& resolution) {
  int64_t value = GetOutputKeyParameterI64(
      cam_id, format, resolution, ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
      STREAM_CONFIG_STALL_DURATION_INDEX);
  return (value != -ENODATA)
             ? value
             : 0;  // Default duration is '0' (unsupported/no extra stall)
}

int64_t Camera3Module::GetOutputMinFrameDuration(
    int cam_id, int32_t format, const ResolutionInfo& resolution) {
  return GetOutputKeyParameterI64(cam_id, format, resolution,
                                  ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
                                  STREAM_CONFIG_MIN_DURATION_INDEX);
}

void Camera3Module::GetNumberOfCamerasOnHalThread(int* result) {
  *result = cam_module_->get_number_of_cameras();
}

void Camera3Module::GetCameraInfoOnHalThread(int cam_id,
                                             camera_info* info,
                                             int* result) {
  *result = cam_module_->get_camera_info(cam_id, info);
}

void Camera3Module::OpenDeviceOnHalThread(int cam_id,
                                          camera3_device_t** cam_device) {
  *cam_device = nullptr;
  hw_device_t* device = nullptr;
  char cam_id_name[3];
  snprintf(cam_id_name, sizeof(cam_id_name), "%d", cam_id);
  if (cam_module_->common.methods->open((const hw_module_t*)cam_module_,
                                        cam_id_name, &device) == 0) {
    *cam_device = reinterpret_cast<camera3_device_t*>(device);
  }
}

void Camera3Module::CloseDeviceOnDevThread(camera3_device_t* cam_device,
                                           int* result) {
  VLOGF_ENTER();
  ASSERT_NE(nullptr, cam_device->common.close)
      << "Camera close() is not implemented";
  *result = cam_device->common.close(&cam_device->common);
}

// Test fixture

void Camera3ModuleFixture::SetUp() {
  ASSERT_EQ(0, cam_module_.Initialize())
      << "Camera module initialization fails";
}

// Test cases

TEST_F(Camera3ModuleFixture, NumberOfCameras) {
  ASSERT_GT(cam_module_.GetNumberOfCameras(), 0) << "No cameras found";
  ASSERT_LE(cam_module_.GetNumberOfCameras(), kMaxNumCameras)
      << "Too many cameras found";
}

TEST_F(Camera3ModuleFixture, OpenDeviceOfBadIndices) {
  auto* callbacks_handler = CameraModuleCallbacksHandler::GetInstance();
  std::vector<int> bad_ids = {-1};
  for (int id = cam_module_.GetNumberOfCameras(); bad_ids.size() < 3; id++) {
    if (callbacks_handler->IsExternalCameraPresent(id)) {
      LOG(INFO) << "Camera " << id << " is an external camera, skip it";
      continue;
    }
    bad_ids.push_back(id);
  }
  // Possible TOCTOU race here if the external camera is plugged after
  // |IsExternalCameraPresent()|, but before |OpenDevice()|.
  for (int id : bad_ids) {
    ASSERT_EQ(nullptr, cam_module_.OpenDevice(id))
        << "Open camera device of bad id " << id;
  }
}

TEST_F(Camera3ModuleFixture, IsActiveArraySizeSubsetOfPixelArraySize) {
  for (int cam_id = 0; cam_id < cam_module_.GetNumberOfCameras(); cam_id++) {
    camera_info info;
    ASSERT_EQ(0, cam_module_.GetCameraInfo(cam_id, &info))
        << "Can't get camera info for " << cam_id;

    camera_metadata_ro_entry_t entry;
    ASSERT_EQ(
        0,
        find_camera_metadata_ro_entry(
            const_cast<camera_metadata_t*>(info.static_camera_characteristics),
            ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, &entry))
        << "Can't find the sensor pixel array size.";
    int pixel_array_w = entry.data.i32[0];
    int pixel_array_h = entry.data.i32[1];

    ASSERT_EQ(
        0,
        find_camera_metadata_ro_entry(
            const_cast<camera_metadata_t*>(info.static_camera_characteristics),
            ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, &entry))
        << "Can't find the sensor active array size.";
    int active_array_w = entry.data.i32[0];
    int active_array_h = entry.data.i32[1];

    ASSERT_LE(active_array_h, pixel_array_h);
    ASSERT_LE(active_array_w, pixel_array_w);
  }
}

TEST_F(Camera3ModuleFixture, OpenDevice) {
  for (int cam_id = 0; cam_id < cam_module_.GetNumberOfCameras(); cam_id++) {
    camera3_device* cam_dev = cam_module_.OpenDevice(cam_id);
    ASSERT_NE(nullptr, cam_dev) << "Camera open() returned a NULL device";
    cam_module_.CloseDevice(cam_dev);
  }
}

TEST_F(Camera3ModuleFixture, OpenDeviceTwice) {
  for (int cam_id = 0; cam_id < cam_module_.GetNumberOfCameras(); cam_id++) {
    camera3_device* cam_dev = cam_module_.OpenDevice(cam_id);
    ASSERT_NE(nullptr, cam_dev) << "Camera open() returned a NULL device";
    // Open the device again
    camera3_device* cam_bad_dev = cam_module_.OpenDevice(cam_id);
    ASSERT_EQ(nullptr, cam_bad_dev)
        << "Opening camera device " << cam_id << " should have failed";
    cam_module_.CloseDevice(cam_dev);
  }
}

TEST_F(Camera3ModuleFixture, RequiredFormats) {
  auto IsResolutionSupported =
      [](const std::vector<ResolutionInfo>& resolution_list,
         const ResolutionInfo& resolution) {
        return std::find(resolution_list.begin(), resolution_list.end(),
                         resolution) != resolution_list.end();
      };
  auto RemoveResolution = [](std::vector<ResolutionInfo>& resolution_list,
                             const ResolutionInfo& resolution) {
    auto it =
        std::find(resolution_list.begin(), resolution_list.end(), resolution);
    if (it != resolution_list.end()) {
      resolution_list.erase(it);
    }
  };
  auto GetMaxVideoResolution = [](int cam_id) {
    auto recording_params = ParseRecordingParams();
    int32_t width = 0;
    int32_t height = 0;
    for (const auto& it : recording_params) {
      int32_t area = std::get<1>(it) * std::get<2>(it);
      if (std::get<0>(it) == cam_id &&
          (width * height < area ||
           (width * height == area && width < std::get<1>(it)))) {
        width = std::get<1>(it);
        height = std::get<2>(it);
      }
    }
    return ResolutionInfo(width, height);
  };

  for (int cam_id = 0; cam_id < cam_module_.GetNumberOfCameras(); cam_id++) {
    ASSERT_TRUE(cam_module_.IsFormatAvailable(cam_id, HAL_PIXEL_FORMAT_BLOB))
        << "Camera stream configuration does not support JPEG";
    ASSERT_TRUE(
        cam_module_.IsFormatAvailable(cam_id, HAL_PIXEL_FORMAT_YCbCr_420_888))
        << "Camera stream configuration does not support flexible YUV";

    // Reference:
    // camera2/cts/ExtendedCameraCharacteristicsTest.java#testAvailableStreamConfigs
    camera_info info;
    ASSERT_EQ(0, cam_module_.GetCameraInfo(cam_id, &info))
        << "Can't get camera info for " << cam_id;

    std::vector<ResolutionInfo> jpeg_resolutions =
        cam_module_.GetSortedOutputResolutions(cam_id, HAL_PIXEL_FORMAT_BLOB);
    std::vector<ResolutionInfo> yuv_resolutions =
        cam_module_.GetSortedOutputResolutions(cam_id,
                                               HAL_PIXEL_FORMAT_YCbCr_420_888);
    std::vector<ResolutionInfo> private_resolutions =
        cam_module_.GetSortedOutputResolutions(
            cam_id, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);

    const ResolutionInfo full_hd(1920, 1080), full_hd_alt(1920, 1088),
        hd(1280, 720), vga(640, 480), qvga(320, 240);

    camera_metadata_ro_entry_t entry;
    ASSERT_EQ(
        0,
        find_camera_metadata_ro_entry(
            const_cast<camera_metadata_t*>(info.static_camera_characteristics),
            ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, &entry))
        << "Can't find the sensor active array size.";
    ResolutionInfo active_array(entry.data.i32[0], entry.data.i32[1]);
    if ((active_array.Width() >= full_hd.Width()) &&
        (active_array.Height() >= full_hd.Height())) {
      EXPECT_TRUE(IsResolutionSupported(jpeg_resolutions, full_hd) ||
                  IsResolutionSupported(jpeg_resolutions, full_hd_alt))
          << "Required FULLHD size not found for JPEG for camera " << cam_id;
    }
    if ((active_array.Width() >= hd.Width()) &&
        (active_array.Height() >= hd.Height())) {
      EXPECT_TRUE(IsResolutionSupported(jpeg_resolutions, hd))
          << "Required HD size not found for JPEG for camera " << cam_id;
    }
    if ((active_array.Width() >= vga.Width()) &&
        (active_array.Height() >= vga.Height())) {
      EXPECT_TRUE(IsResolutionSupported(jpeg_resolutions, vga))
          << "Required VGA size not found for JPEG for camera " << cam_id;
    }
    if ((active_array.Width() >= qvga.Width()) &&
        (active_array.Height() >= qvga.Height())) {
      EXPECT_TRUE(IsResolutionSupported(jpeg_resolutions, qvga))
          << "Required QVGA size not found for JPEG for camera " << cam_id;
    }

    ASSERT_EQ(
        0,
        find_camera_metadata_ro_entry(
            const_cast<camera_metadata_t*>(info.static_camera_characteristics),
            ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &entry))
        << "Cannot find the metadata ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL";
    int32_t hw_level = entry.data.i32[0];

    // Handle FullHD special case first
    if (IsResolutionSupported(jpeg_resolutions, full_hd)) {
      if (hw_level == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL) {
        EXPECT_TRUE(IsResolutionSupported(yuv_resolutions, full_hd) ||
                    IsResolutionSupported(yuv_resolutions, full_hd_alt))
            << "FullHD YUV size not found in Full device ";
        EXPECT_TRUE(IsResolutionSupported(private_resolutions, full_hd) ||
                    IsResolutionSupported(private_resolutions, full_hd_alt))
            << "FullHD private size not found in Full device ";
      }
      // Remove all FullHD or FullHD_Alt sizes for the remaining of the test
      RemoveResolution(jpeg_resolutions, full_hd);
      RemoveResolution(jpeg_resolutions, full_hd_alt);
    }

    // Check all sizes other than FullHD
    if (hw_level == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED) {
      // Remove all jpeg sizes larger than max video size
      auto max_video_resolution = GetMaxVideoResolution(cam_id);
      for (auto it = jpeg_resolutions.begin(); it != jpeg_resolutions.end();) {
        if (it->Width() >= max_video_resolution.Width() &&
            it->Height() >= max_video_resolution.Height()) {
          it = jpeg_resolutions.erase(it);
        } else {
          it++;
        }
      }
    }

    std::stringstream ss;
    auto PrintResolutions =
        [&](const std::vector<ResolutionInfo>& resolutions) {
          ss.str("");
          for (const auto& it : resolutions) {
            ss << (ss.str().empty() ? "" : ", ") << it.Width() << "x"
               << it.Height();
          }
          return ss.str().c_str();
        };
    if (hw_level == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL ||
        hw_level == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED) {
      std::vector<ResolutionInfo> diff;
      std::set_difference(jpeg_resolutions.begin(), jpeg_resolutions.end(),
                          yuv_resolutions.begin(), yuv_resolutions.end(),
                          std::inserter(diff, diff.begin()));
      EXPECT_TRUE(diff.empty())
          << "Sizes " << PrintResolutions(diff) << " not found in YUV format";
    }

    std::vector<ResolutionInfo> diff;
    std::set_difference(jpeg_resolutions.begin(), jpeg_resolutions.end(),
                        private_resolutions.begin(), private_resolutions.end(),
                        std::inserter(diff, diff.begin()));
    EXPECT_TRUE(diff.empty())
        << "Sizes " << PrintResolutions(diff) << " not found in private format";
  }
}

// TODO(hywu): test keys used by RAW, burst and reprocessing capabilities when
// full mode is supported

static bool AreAllCapabilitiesSupported(
    camera_metadata_t* characteristics,
    const std::vector<int32_t>& capabilities) {
  std::set<int32_t> supported_capabilities;
  camera_metadata_ro_entry_t entry;
  if (find_camera_metadata_ro_entry(characteristics,
                                    ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
                                    &entry) == 0) {
    for (size_t i = 0; i < entry.count; i++) {
      if ((entry.data.i32[i] >=
           ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) &&
          (entry.data.i32[i] <=
           ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO)) {  // NOLINT(whitespace/line_length)
        supported_capabilities.insert(entry.data.i32[i]);
      }
    }
  }

  for (const auto& it : capabilities) {
    if (supported_capabilities.find(it) == supported_capabilities.end()) {
      return false;
    }
  }
  return true;
}

static void ExpectKeyAvailable(camera_metadata_t* characteristics,
                               int32_t key,
                               int32_t hw_level,
                               const std::vector<int32_t>& capabilities) {
  camera_metadata_ro_entry_t entry;
  ASSERT_EQ(0,
            find_camera_metadata_ro_entry(
                characteristics, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &entry))
      << "Cannot find the metadata ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL";
  int32_t actual_hw_level = entry.data.i32[0];

  // For LIMITED-level targeted keys, rely on capability check, not level
  if (actual_hw_level >= hw_level &&
      hw_level != ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED) {
    ASSERT_EQ(0, find_camera_metadata_ro_entry(characteristics, key, &entry))
        << "Key " << get_camera_metadata_tag_name(key)
        << " must be in characteristics for this hardware level ";
  } else if (AreAllCapabilitiesSupported(characteristics, capabilities)) {
    if (!(hw_level == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED &&
          actual_hw_level < hw_level)) {
      // Don't enforce LIMITED-starting keys on LEGACY level, even if cap is
      // defined
      std::stringstream ss;
      auto PrintCapabilities = [&]() {
        for (const auto& it : capabilities) {
          ss << (ss.str().empty() ? "" : ", ");
          switch (it) {
            case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE:
              ss << "BACKWARD_COMPATIBLE";
              break;
            case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR:
              ss << "MANUAL_SENSOR";
              break;
            case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING:
              ss << "MANUAL_POST_PROCESSING";
              break;
            case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW:
              ss << "RAW";
              break;
            case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING:
              ss << "PRIVATE_PROCESSING";
              break;
            case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS:
              ss << "READ_SENSOR_SETTINGS";
              break;
            case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE:
              ss << "BURST_CAPTURE";
              break;
            case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING:
              ss << "YUV_REPROCESSING";
              break;
            case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT:
              ss << "DEPTH_OUTPUT";
              break;
            case ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO:  // NOLINT(whitespace/line_length)
              ss << "HIGHT_SPEED_VIDEO";
              break;
            default:
              ss << "unknown(" << it << ")";
          }
        }
        return ss.str().c_str();
      };
      ASSERT_EQ(0, find_camera_metadata_ro_entry(characteristics, key, &entry))
          << "Key " << get_camera_metadata_tag_name(key)
          << " must be in characteristics for capabilities "
          << PrintCapabilities();
    }
  }
}

static void ExpectKeyAvailable(camera_metadata_t* c,
                               int32_t key,
                               int32_t hw_level,
                               int32_t capability) {
  return ExpectKeyAvailable(c, key, hw_level, std::vector<int>({capability}));
}

TEST_F(Camera3ModuleFixture, StaticKeysTest) {
// Reference:
// camera2/cts/ExtendedCameraCharacteristicsTest.java#testKeys
#define IGNORE_HARDWARE_LEVEL INT32_MAX
#define IGNORE_CAPABILITY -1
  for (int cam_id = 0; cam_id < cam_module_.GetNumberOfCameras(); cam_id++) {
    camera_info info;
    ASSERT_EQ(0, cam_module_.GetCameraInfo(cam_id, &info))
        << "Can't get camera info for " << cam_id;
    auto c = const_cast<camera_metadata_t*>(info.static_camera_characteristics);
    ExpectKeyAvailable(
        c, ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
        IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_CONTROL_AVAILABLE_MODES, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
        IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_CONTROL_AE_AVAILABLE_MODES, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
        IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_CONTROL_AE_COMPENSATION_RANGE, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_CONTROL_AE_COMPENSATION_STEP, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_CONTROL_AE_LOCK_AVAILABLE, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_CONTROL_AF_AVAILABLE_MODES, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_CONTROL_AVAILABLE_EFFECTS, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_CONTROL_AVAILABLE_SCENE_MODES, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
        IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_CONTROL_AWB_AVAILABLE_MODES, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_CONTROL_AWB_LOCK_AVAILABLE, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    // TODO(hywu): ANDROID_CONTROL_MAX_REGIONS_AE,
    //             ANDROID_CONTROL_MAX_REGIONS_AF,
    //             ANDROID_CONTROL_MAX_REGIONS_AWB
    ExpectKeyAvailable(c, ANDROID_EDGE_AVAILABLE_EDGE_MODES,
                       ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
                       IGNORE_CAPABILITY);
    ExpectKeyAvailable(
        c, ANDROID_FLASH_INFO_AVAILABLE, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(c, ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES,
                       IGNORE_HARDWARE_LEVEL,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
    ExpectKeyAvailable(
        c, ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_LENS_FACING, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(c, ANDROID_LENS_INFO_AVAILABLE_APERTURES,
                       ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
    ExpectKeyAvailable(c, ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
                       ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
    ExpectKeyAvailable(
        c, ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
        ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(c, ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
                       ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
    ExpectKeyAvailable(
        c, ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
        ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
        ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
        IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_REQUEST_AVAILABLE_CAPABILITIES, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, IGNORE_HARDWARE_LEVEL,
        std::vector<int32_t>(
            {ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING,
             ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING}));
    ExpectKeyAvailable(
        c, ANDROID_REQUEST_PARTIAL_RESULT_COUNT, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_REQUEST_PIPELINE_MAX_DEPTH, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_SCALER_CROPPING_TYPE, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_SENSOR_BLACK_LEVEL_PATTERN,
        ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
        std::vector<int32_t>(
            {ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR,
             ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW}));
    ExpectKeyAvailable(c, ANDROID_SENSOR_CALIBRATION_TRANSFORM1,
                       IGNORE_HARDWARE_LEVEL,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
    ExpectKeyAvailable(c, ANDROID_SENSOR_COLOR_TRANSFORM1,
                       IGNORE_HARDWARE_LEVEL,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
    ExpectKeyAvailable(c, ANDROID_SENSOR_FORWARD_MATRIX1, IGNORE_HARDWARE_LEVEL,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
    ExpectKeyAvailable(
        c, ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, IGNORE_HARDWARE_LEVEL,
        std::vector<int32_t>(
            {ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
             ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW}));
    ExpectKeyAvailable(c, ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
                       ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
    ExpectKeyAvailable(c, ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
                       ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
    ExpectKeyAvailable(c, ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
                       ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
    ExpectKeyAvailable(
        c, ANDROID_SENSOR_INFO_PHYSICAL_SIZE, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(c, ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
                       ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
    ExpectKeyAvailable(c, ANDROID_SENSOR_INFO_WHITE_LEVEL,
                       IGNORE_HARDWARE_LEVEL,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
    ExpectKeyAvailable(
        c, ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(c, ANDROID_SENSOR_MAX_ANALOG_SENSITIVITY,
                       ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR);
    ExpectKeyAvailable(
        c, ANDROID_SENSOR_ORIENTATION, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(c, ANDROID_SENSOR_REFERENCE_ILLUMINANT1,
                       IGNORE_HARDWARE_LEVEL,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
    ExpectKeyAvailable(
        c, ANDROID_SHADING_AVAILABLE_MODES,
        ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
        std::vector<int32_t>(
            {ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING,
             ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW}));
    ExpectKeyAvailable(
        c, ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
        IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(c, ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
                       IGNORE_HARDWARE_LEVEL,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
    ExpectKeyAvailable(c,
                       ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
                       ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
                       ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
    ExpectKeyAvailable(
        c, ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_SYNC_MAX_LATENCY, IGNORE_HARDWARE_LEVEL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
    ExpectKeyAvailable(
        c, ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES,
        ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING);
    ExpectKeyAvailable(
        c, ANDROID_TONEMAP_MAX_CURVE_POINTS,
        ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
        ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING);
    camera_metadata_ro_entry_t entry;
    if (find_camera_metadata_ro_entry(c, ANDROID_SENSOR_REFERENCE_ILLUMINANT2,
                                      &entry) == 0) {
      ExpectKeyAvailable(c, ANDROID_SENSOR_REFERENCE_ILLUMINANT2,
                         IGNORE_HARDWARE_LEVEL,
                         ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
      ExpectKeyAvailable(c, ANDROID_SENSOR_COLOR_TRANSFORM2,
                         IGNORE_HARDWARE_LEVEL,
                         ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
      ExpectKeyAvailable(c, ANDROID_SENSOR_CALIBRATION_TRANSFORM2,
                         IGNORE_HARDWARE_LEVEL,
                         ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
      ExpectKeyAvailable(c, ANDROID_SENSOR_FORWARD_MATRIX2,
                         IGNORE_HARDWARE_LEVEL,
                         ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW);
    }
  }
}

TEST_F(Camera3ModuleFixture, StreamConfigurationMapTest) {
  // Reference:
  // camera2/cts/ExtendedCameraCharacteristicsTest.java#testStreamConfigurationMap
  const int64_t kToleranceFactor = 2;
  for (int cam_id = 0; cam_id < cam_module_.GetNumberOfCameras(); cam_id++) {
    camera_info info;
    ASSERT_EQ(0, cam_module_.GetCameraInfo(cam_id, &info))
        << "Can't get camera info for " << cam_id;

    std::vector<int32_t> available_formats =
        cam_module_.GetOutputFormats(cam_id);
    for (const auto& format : available_formats) {
      std::vector<ResolutionInfo> available_resolutions =
          cam_module_.GetSortedOutputResolutions(cam_id, format);
      size_t resolution_count = available_resolutions.size();
      for (size_t i = 0; i < resolution_count; i++) {
        int64_t stall_duration = cam_module_.GetOutputStallDuration(
            cam_id, format, available_resolutions[i]);
        if (stall_duration >= 0) {
          if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
            EXPECT_EQ(0, stall_duration)
                << "YUV_420_888 may not have a non-zero stall duration";
          } else if (format == HAL_PIXEL_FORMAT_BLOB) {
            // Stall duration should be in a reasonable range: larger size
            // should normally have larger stall duration
            if (i > 0) {
              int64_t prev_duration = cam_module_.GetOutputStallDuration(
                  cam_id, format, available_resolutions[i - 1]);
              EXPECT_LE(prev_duration / kToleranceFactor, stall_duration)
                  << "Stall duration (format " << format << " and size "
                  << available_resolutions[i].Width() << "x"
                  << available_resolutions[i].Height()
                  << ") is not in the right range";
            }
          }
        } else {
          ADD_FAILURE() << "Negative stall duration for format " << format;
        }

        int64_t min_duration = cam_module_.GetOutputMinFrameDuration(
            cam_id, format, available_resolutions[i]);
        if (AreAllCapabilitiesSupported(
                const_cast<camera_metadata_t*>(
                    info.static_camera_characteristics),
                std::vector<int32_t>(
                    {ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR}))) {
          EXPECT_LT(0, min_duration)
              << "MANUAL_SENSOR capability, need positive min frame duration "
                 "for format "
              << format << " and size " << available_resolutions[i].Width()
              << "x" << available_resolutions[i].Height();
        } else {
          EXPECT_LE(0, min_duration)
              << "Need non-negative min frame duration for format " << format
              << " and size " << available_resolutions[i].Width() << "x"
              << available_resolutions[i].Height();
        }
      }
    }
  }
}

TEST_F(Camera3ModuleFixture, ChromeOSRequiredResolution) {
  const int required_formats[] = {HAL_PIXEL_FORMAT_BLOB,
                                  HAL_PIXEL_FORMAT_YCbCr_420_888,
                                  HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED};
  const ResolutionInfo required_resolutions[] = {ResolutionInfo(1600, 1200),
                                                 ResolutionInfo(1280, 960)};
  for (const auto& cam_id : cam_module_.GetCameraIds()) {
    camera_info info;
    ASSERT_EQ(0, cam_module_.GetCameraInfo(cam_id, &info))
        << "Can't get camera info for " << cam_id;
    camera_metadata_ro_entry_t entry;
    ASSERT_EQ(
        0,
        find_camera_metadata_ro_entry(
            const_cast<camera_metadata_t*>(info.static_camera_characteristics),
            ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, &entry))
        << "Can't find the sensor active array size.";
    ASSERT_GE(entry.count, 2);
    ResolutionInfo active_array(entry.data.i32[0], entry.data.i32[1]);
    for (const auto& resolution : required_resolutions) {
      if ((active_array.Width() >= resolution.Width()) &&
          (active_array.Height() >= resolution.Height())) {
        for (const auto& format : required_formats) {
          auto resolutions =
              cam_module_.GetSortedOutputResolutions(cam_id, format);
          EXPECT_NE(resolutions.end(), std::find(resolutions.begin(),
                                                 resolutions.end(), resolution))
              << "Required size " << resolution.Width() << "x"
              << resolution.Height() << " not found for format " << format
              << " for camera " << cam_id;
        }
      }
    }
  }
}

}  // namespace camera3_test

static void AddGtestFilterNegativePattern(std::string negative) {
  using ::testing::GTEST_FLAG(filter);

  GTEST_FLAG(filter)
      .append((GTEST_FLAG(filter).find('-') == std::string::npos) ? "-" : ":")
      .append(negative);
}

// Return -ENOENT for no facing specified, -EINVAL for invalid facing name.
static int GetCmdLineTestCameraFacing(const base::CommandLine& cmd_line) {
  const std::string facing_names[] = {"back", "front"};
  const auto& facing_name = cmd_line.GetSwitchValueASCII("camera_facing");
  if (facing_name.empty())
    return -ENOENT;
  int idx = std::distance(
      facing_names,
      std::find(facing_names, facing_names + arraysize(facing_names),
                facing_name));
  if (idx == arraysize(facing_names)) {
    ADD_FAILURE() << "Invalid facing name: " << facing_name;
    return -EINVAL;
  }
  return idx;
}

bool InitializeTest(int* argc, char*** argv, void** cam_hal_handle) {
  // Set up logging so we can enable VLOGs with -v / --vmodule.
  base::CommandLine::Init(*argc, *argv);
  logging::LoggingSettings settings;
  settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
  LOG_ASSERT(logging::InitLogging(settings));

  base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
  base::FilePath camera_hal_path =
      cmd_line->GetSwitchValuePath("camera_hal_path");
  int facing = GetCmdLineTestCameraFacing(*cmd_line);

  if (facing != -ENOENT) {
    if (facing == -EINVAL) {
      LOG(ERROR) << "Invalid camera facing name.";
      return false;
    } else if (!camera_hal_path.empty() ||
               !camera3_test::GetCmdLineTestCameraIds().empty()) {
      LOGF(ERROR) << "Cannot specify both --camera_hal_path/--camera_ids and "
                     "--camera_facing.";
      return false;
    }
  } else if (camera_hal_path.empty()) {
    std::vector<base::FilePath> camera_hal_paths = cros::GetCameraHalPaths();

    if (camera_hal_paths.size() == 1) {
      // TODO(shik): Ignore usb.so if there is no built-in USB camera, so we
      // have a better heuristic guess.

      camera_hal_path = camera_hal_paths[0];

      LOG(INFO) << "camera_hal_path unspecified, using "
                << camera_hal_path.value() << " as default. "
                << "You can override this behavior by the command line "
                << "argument `--camera_hal_path=`";
    } else {
      LOGF(ERROR) << "camera_hal_path unspecified. "
                  << "Since we cannot determine the suitable one, please add "
                  << "`--camera_hal_path=` into command line argument.";

      if (!camera_hal_paths.empty()) {
        LOGF(ERROR) << "List of possible paths:";
        for (const auto& path : camera_hal_paths) {
          LOGF(ERROR) << path.value();
        }
      }

      return false;
    }
  }

  // Open camera HAL and get module
  camera3_test::g_module_thread.Start();
  if (facing != -ENOENT) {
    camera3_test::InitCameraModuleByFacing(facing, cam_hal_handle);
  } else {
    camera3_test::InitCameraModuleByHalPath(camera_hal_path, cam_hal_handle);
  }

  camera3_test::InitPerfLog();

  // Initialize gtest
  ::testing::InitGoogleTest(argc, *argv);
  if (testing::Test::HasFailure()) {
    camera3_test::g_module_thread.Stop();
    return false;
  }

  if (camera_hal_path.value().find("usb") != std::string::npos) {
    // Skip 3A algorithm sandbox IPC tests for USB HAL
    AddGtestFilterNegativePattern("*Camera3AlgoSandboxIPCErrorTest*");
  }

  const std::vector<std::string> kIgnoreSensorOrientationTestBoards = {
      "nocturne",
      "scarlet",
  };
  std::string board = base::SysInfo::GetLsbReleaseBoard();
  if (base::ContainsValue(kIgnoreSensorOrientationTestBoards, board)) {
    VLOG(1) << "Ignore SensorOrientationTest on " << board;
    AddGtestFilterNegativePattern("*SensorOrientationTest/*");
  }

  return true;
}

#ifdef FUZZER

extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
  void* cam_hal_handle = NULL;
  if (!InitializeTest(argc, argv, &cam_hal_handle)) {
    exit(EXIT_FAILURE);
  }
  ::testing::TestEventListeners& listeners =
      ::testing::UnitTest::GetInstance()->listeners();
  delete listeners.Release(listeners.default_result_printer());
  return 0;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
  camera3_test::Camera3TestDataForwarder::GetInstance()->SetData(Data, Size);
  ignore_result(RUN_ALL_TESTS());
  return 0;
}

#else
int main(int argc, char** argv) {
  // We have to make it leaky until the lifetime conflict in b/119926433 is
  // resolved.
  base::NoDestructor<base::AtExitManager> leaky_at_exit_manager;
  int result = EXIT_FAILURE;
  void* cam_hal_handle = NULL;
  if (!InitializeTest(&argc, &argv, &cam_hal_handle)) {
    return result;
  } else {
    result = RUN_ALL_TESTS();
  }
  camera3_test::g_module_thread.Stop();

  return result;
}
#endif
