/*
 * 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 "hal/usb/metadata_handler.h"

#include <algorithm>
#include <cmath>
#include <limits>
#include <map>
#include <set>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include <base/no_destructor.h>

#include <chromeos-config/libcros_config/cros_config.h>
#include "cros-camera/common.h"
#include "cros-camera/utils/camera_config.h"
#include "hal/usb/quirks.h"
#include "hal/usb/stream_format.h"
#include "hal/usb/v4l2_camera_device.h"
#include "hal/usb/vendor_tag.h"
#include "mojo/cros_camera_enum.mojom.h"

namespace cros {

namespace {

constexpr int32_t kMinFps = 1;
constexpr float kDefaultAvailableFocalLength = 1.6f;
constexpr float kDefaultMinimumFocusDistance = 0.3f;
constexpr float kDefaultLensFocusDistance = 0.5f;

const cros::AwbModeToTemperatureMap& GetAwbModeTemperatureMap() {
  // https://source.android.com/devices/camera/camera3_3Amodes#auto-wb
  static const base::NoDestructor<cros::AwbModeToTemperatureMap>
      kAwbModeTemperatureMap({
          {ANDROID_CONTROL_AWB_MODE_INCANDESCENT, 2700},
          {ANDROID_CONTROL_AWB_MODE_FLUORESCENT, 5000},
          {ANDROID_CONTROL_AWB_MODE_WARM_FLUORESCENT, 3000},
          {ANDROID_CONTROL_AWB_MODE_DAYLIGHT, 5500},
          {ANDROID_CONTROL_AWB_MODE_CLOUDY_DAYLIGHT, 6500},
          {ANDROID_CONTROL_AWB_MODE_TWILIGHT, 15000},
          {ANDROID_CONTROL_AWB_MODE_SHADE, 7500},
      });
  return *kAwbModeTemperatureMap;
}

uint32_t GetAwbTemperatureByMode(
    const cros::ControlRange& range,
    camera_metadata_enum_android_control_awb_mode mode) {
  const cros::AwbModeToTemperatureMap& map = GetAwbModeTemperatureMap();

  if (mode == ANDROID_CONTROL_AWB_MODE_AUTO)
    return 0;

  auto it = map.find(mode);
  if (it == map.end()) {
    LOGF(ERROR) << "Can't find mode " << mode;
    return 0;
  }

  // Get acceptable temperature by minimum and step. in case the step is
  // too large.
  uint32_t temperature =
      range.minimum + range.step * ((it->second - range.minimum) / range.step);

  if (temperature < range.minimum || temperature > range.maximum)
    return 0;

  return temperature;
}

std::vector<float> GetPhysicalSize(float horiz_fov,
                                   float vert_fov,
                                   float focal_length,
                                   float array_aspect,
                                   float still_aspect) {
  float angle_to_rad_ratio = M_PI / 180.f;
  float crop_factor = still_aspect / array_aspect;
  float horiz_crop_factor = std::min(1.f, crop_factor);
  float vert_crop_factor = std::min(1.f, 1.f / crop_factor);
  return {2.f * focal_length * std::tan(horiz_fov * angle_to_rad_ratio / 2.f) /
              horiz_crop_factor,
          2.f * focal_length * std::tan(vert_fov * angle_to_rad_ratio / 2.f) /
              vert_crop_factor};
}

// The unit of ANDROID_LENS_FOCUS_DISTANCE is diopters (1/meter), but the unit
// of V4L2_CID_FOCUS_ABSOLUTE is undefined. We map the V4L2 value to diopters by
// (value - minimum) / normalize_factor where |value| is in [minimum, maximum].
// We calculate a proper |normalize_factor| by assuming the minimum focus
// distance of USB cameras is >= 1cm (tested on real webcams), i.e. max diopter
// is <= 100, and only use power of 10s for readability.
// For example, V4L2 range [0, 250] will map to Android range [0, 25], where the
// minimum focus distance is 1m/25=4cm. This function takes |v4l2_range|
// (== maximum - minimum) and returns |normalize_factor|.
uint32_t GetNormalizeFactorForV4l2FocusRange(float v4l2_range) {
  uint32_t normalize_factor = 1;

  while (v4l2_range / normalize_factor > 100.0)
    normalize_factor *= 10;

  return normalize_factor;
}

class MetadataUpdater {
 public:
  explicit MetadataUpdater(android::CameraMetadata* metadata)
      : metadata_(metadata), ok_(true) {}

  bool ok() { return ok_; }

  template <typename T>
  void operator()(int tag, const std::vector<T>& data) {
    if (!ok_) {
      return;
    }
    if (metadata_->update(tag, data) != 0) {
      ok_ = false;
      LOGF(ERROR) << "Update metadata with tag " << std::hex << std::showbase
                  << tag << " failed" << std::dec;
    }
  }

  template <typename T>
  std::enable_if_t<std::is_enum<T>::value> operator()(int tag, const T& data) {
    static const std::set<int> kInt32EnumTags = {
        ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
        ANDROID_SCALER_AVAILABLE_FORMATS,
        ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
        ANDROID_SENSOR_TEST_PATTERN_MODE,
        ANDROID_SYNC_MAX_LATENCY,
    };
    if (kInt32EnumTags.find(tag) != kInt32EnumTags.end()) {
      operator()(tag, std::vector<int32_t>{static_cast<int32_t>(data)});
    } else {
      operator()(tag, std::vector<uint8_t>{base::checked_cast<uint8_t>(data)});
    }
  }

  template <typename T>
  std::enable_if_t<!std::is_enum<T>::value> operator()(int tag, const T& data) {
    operator()(tag, std::vector<T>{data});
  }

 private:
  android::CameraMetadata* metadata_;
  bool ok_;
};

// Checks if a fps range can be filled into aeAvailableTargetFpsRanges given a
// list of supported formats.
// Android metadata only reports min frame duration for each format/resolution.
// CTS assumes a fps range is supported if the min frame duration (1/max_fps)
// covers the range. Thus we need to check if the USB camera actually supports
// some fps in the range.
bool IsFpsRangeSupported(const SupportedFormats& supported_formats,
                         int32_t fps_range_min,
                         int32_t fps_range_max) {
  for (const auto& format : supported_formats) {
    const int32_t max_fps = static_cast<int32_t>(*std::max_element(
        format.frame_rates.begin(), format.frame_rates.end()));
    if (max_fps >= fps_range_max) {
      const bool has_fps_in_range = std::any_of(
          format.frame_rates.begin(), format.frame_rates.end(), [&](float x) {
            const int32_t fps = static_cast<int32_t>(x);
            return fps_range_min <= fps && fps <= fps_range_max;
          });
      if (!has_fps_in_range)
        return false;
    }
  }
  return true;
}

Size GetMaxDimensions(const SupportedFormats& formats) {
  uint32_t max_width = 0;
  uint32_t max_height = 0;
  for (const SupportedFormat& format : formats) {
    max_width = std::max(max_width, format.width);
    max_height = std::max(max_height, format.height);
  }
  return Size(max_width, max_height);
}

}  // namespace

MetadataHandler::MetadataHandler(const camera_metadata_t& static_metadata,
                                 const camera_metadata_t& request_template,
                                 const DeviceInfo& device_info,
                                 V4L2CameraDevice* device,
                                 const SupportedFormats& supported_formats)
    : device_info_(device_info),
      device_(device),
      af_trigger_(false),
      focus_distance_normalize_factor_(0) {
  // MetadataBase::operator= will make a copy of camera_metadata_t.
  static_metadata_ = &static_metadata;
  request_template_ = &request_template;

  max_supported_fps_ = 0;
  for (const auto& format : supported_formats) {
    for (const float& frame_rate : format.frame_rates) {
      // Since the |frame_rate| is a float, we need to round here.
      int fps = std::round(frame_rate);
      if (fps > max_supported_fps_) {
        max_supported_fps_ = fps;
      }
    }
  }

  // camera3_request_template_t starts at 1.
  for (int i = 1; i < CAMERA3_TEMPLATE_COUNT; i++) {
    template_settings_[i] = CreateDefaultRequestSettings(i);
  }

  sensor_handler_ = SensorHandler::Create(device_info, supported_formats);

  is_awb_control_supported_ = V4L2CameraDevice::IsControlSupported(
      device_info_.device_path, kControlWhiteBalanceTemperature);
  awb_temperature_ = GetAvailableAwbTemperatures(device_info);

  is_brightness_control_supported_ = V4L2CameraDevice::IsControlSupported(
      device_info.device_path, kControlBrightness);
  is_contrast_control_supported_ = V4L2CameraDevice::IsControlSupported(
      device_info.device_path, kControlContrast);
  is_pan_control_supported_ = V4L2CameraDevice::IsControlSupported(
      device_info.device_path, kControlPan);
  is_saturation_control_supported_ = V4L2CameraDevice::IsControlSupported(
      device_info.device_path, kControlSaturation);
  is_sharpness_control_supported_ = V4L2CameraDevice::IsControlSupported(
      device_info.device_path, kControlSharpness);
  is_tilt_control_supported_ = V4L2CameraDevice::IsControlSupported(
      device_info.device_path, kControlTilt);
  is_zoom_control_supported_ = V4L2CameraDevice::IsControlSupported(
      device_info.device_path, kControlZoom);

  if (V4L2CameraDevice::IsFocusDistanceSupported(device_info.device_path,
                                                 &focus_distance_range_)) {
    float full_range =
        focus_distance_range_.maximum - focus_distance_range_.minimum;
    focus_distance_normalize_factor_ =
        GetNormalizeFactorForV4l2FocusRange(full_range);
  }

  thread_checker_.DetachFromThread();
}

MetadataHandler::~MetadataHandler() {}

int MetadataHandler::FillDefaultMetadata(
    android::CameraMetadata* static_metadata,
    android::CameraMetadata* request_metadata) {
  MetadataUpdater update_static(static_metadata);
  MetadataUpdater update_request(request_metadata);

  // android.colorCorrection
  update_static(ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
                std::vector<uint8_t>{
                    ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST,
                    ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY});
  update_request(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
                 ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST);

  // android.control
  // We don't support AE compensation.
  update_static(ANDROID_CONTROL_AE_COMPENSATION_RANGE,
                std::vector<int32_t>{0, 0});

  update_static(ANDROID_CONTROL_AE_COMPENSATION_STEP,
                camera_metadata_rational_t{0, 1});

  update_static(ANDROID_CONTROL_MAX_REGIONS,
                std::vector<int32_t>{/*AE*/ 0, /*AWB*/ 0, /*AF*/ 0});

  update_static(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
                ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF);
  update_request(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
                 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF);

  update_static(ANDROID_CONTROL_AWB_AVAILABLE_MODES,
                ANDROID_CONTROL_AWB_MODE_AUTO);
  update_request(ANDROID_CONTROL_AWB_MODE, ANDROID_CONTROL_AWB_MODE_AUTO);

  update_static(ANDROID_CONTROL_AE_AVAILABLE_MODES, ANDROID_CONTROL_AE_MODE_ON);
  // ON means auto-exposure is active with no flash control.
  update_request(ANDROID_CONTROL_AE_MODE, ANDROID_CONTROL_AE_MODE_ON);

  update_request(ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, int32_t{0});

  update_request(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
                 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);

  update_request(ANDROID_CONTROL_AF_TRIGGER, ANDROID_CONTROL_AF_TRIGGER_IDLE);

  update_static(ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
                ANDROID_CONTROL_SCENE_MODE_DISABLED);
  update_request(ANDROID_CONTROL_SCENE_MODE,
                 ANDROID_CONTROL_SCENE_MODE_DISABLED);

  update_static(ANDROID_CONTROL_AVAILABLE_EFFECTS,
                ANDROID_CONTROL_EFFECT_MODE_OFF);
  update_request(ANDROID_CONTROL_EFFECT_MODE, ANDROID_CONTROL_EFFECT_MODE_OFF);

  update_static(ANDROID_CONTROL_AE_LOCK_AVAILABLE,
                ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE);

  update_static(ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
                ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE);

  update_static(ANDROID_CONTROL_AVAILABLE_MODES,
                std::vector<uint8_t>{ANDROID_CONTROL_MODE_OFF,
                                     ANDROID_CONTROL_MODE_AUTO});

  // android.flash
  update_static(ANDROID_FLASH_INFO_AVAILABLE,
                ANDROID_FLASH_INFO_AVAILABLE_FALSE);
  update_request(ANDROID_FLASH_STATE, ANDROID_FLASH_STATE_UNAVAILABLE);
  update_request(ANDROID_FLASH_MODE, ANDROID_FLASH_MODE_OFF);

  // android.jpeg
  update_static(ANDROID_JPEG_MAX_SIZE, int32_t{13 << 20});
  update_request(ANDROID_JPEG_QUALITY, uint8_t{90});
  update_request(ANDROID_JPEG_THUMBNAIL_QUALITY, uint8_t{90});
  update_request(ANDROID_JPEG_ORIENTATION, int32_t{0});

  // android.lens
  // This should not be needed.
  update_static(ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE, 0.0f);
  update_static(ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
                ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF);
  update_request(ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
                 ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF);

  // android.noiseReduction
  update_static(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
                ANDROID_NOISE_REDUCTION_MODE_OFF);
  update_request(ANDROID_NOISE_REDUCTION_MODE,
                 ANDROID_NOISE_REDUCTION_MODE_OFF);

  // android.request
  update_static(ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
                ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE);
  update_static(ANDROID_REQUEST_PARTIAL_RESULT_COUNT, int32_t{1});

  // This means pipeline latency of X frame intervals. The maximum number is 4.
  update_static(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, uint8_t{4});
  update_request(ANDROID_REQUEST_PIPELINE_DEPTH, uint8_t{4});

  // Three numbers represent the maximum numbers of different types of output
  // streams simultaneously. The types are raw sensor, processed (but not
  // stalling), and processed (but stalling). For usb limited mode, raw sensor
  // is not supported. Stalling stream is JPEG. Non-stalling streams are
  // YUV_420_888, NV21, or YV12.
  update_static(ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
                std::vector<int32_t>{0, 2, 1});

  // Limited mode doesn't support reprocessing.
  update_static(ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS, int32_t{0});

  // android.scaler
  update_static(ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, 1.0f);

  update_static(ANDROID_SCALER_CROPPING_TYPE,
                ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY);

  update_static(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
                std::vector<int32_t>{
                    ANDROID_SENSOR_TEST_PATTERN_MODE_OFF,
                    ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY});
  update_request(ANDROID_SENSOR_TEST_PATTERN_MODE,
                 ANDROID_SENSOR_TEST_PATTERN_MODE_OFF);

  uint8_t timestamp_source;
  if (V4L2CameraDevice::GetUvcClock() == CLOCK_BOOTTIME) {
    timestamp_source = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME;
  } else {
    timestamp_source = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
  }
  update_static(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, timestamp_source);

  // android.shading
  update_static(ANDROID_SHADING_AVAILABLE_MODES, ANDROID_SHADING_MODE_FAST);

  // android.statistics
  update_static(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
                ANDROID_STATISTICS_FACE_DETECT_MODE_OFF);
  update_request(ANDROID_STATISTICS_FACE_DETECT_MODE,
                 ANDROID_STATISTICS_FACE_DETECT_MODE_OFF);

  update_static(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, int32_t{0});

  update_static(ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
                ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF);
  update_request(ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
                 ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF);

  update_static(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
                ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF);

  // android.sync
  update_static(ANDROID_SYNC_MAX_LATENCY, ANDROID_SYNC_MAX_LATENCY_UNKNOWN);

  return update_static.ok() && update_request.ok() ? 0 : -EINVAL;
}

int MetadataHandler::FillMetadataFromSupportedFormats(
    const SupportedFormats& supported_formats,
    const DeviceInfo& device_info,
    android::CameraMetadata* static_metadata,
    android::CameraMetadata* request_metadata) {
  bool is_external = device_info.lens_facing == LensFacing::kExternal;
  bool is_builtin = !is_external;
  bool is_v1_builtin = device_info.quirks & kQuirkV1Device;

  if (supported_formats.empty()) {
    return -EINVAL;
  }
  std::vector<int32_t> stream_configurations;
  std::vector<int64_t> min_frame_durations;
  std::vector<int64_t> stall_durations;

  // The min fps <= 15 must be supported in CTS.
  const int64_t kOneSecOfNanoUnit = 1000000000LL;
  int32_t max_fps = std::numeric_limits<int32_t>::min();
  int64_t max_frame_duration = kOneSecOfNanoUnit / kMinFps;
  std::set<int32_t> supported_fps;

  std::vector<int> hal_formats{HAL_PIXEL_FORMAT_BLOB,
                               HAL_PIXEL_FORMAT_YCbCr_420_888,
                               HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED};

  std::unordered_map<int, int> max_hal_width_by_format;
  std::unordered_map<int, int> max_hal_height_by_format;
  std::unique_ptr<CameraConfig> camera_config =
      CameraConfig::Create(constants::kCrosCameraConfigPathString);
  max_hal_width_by_format[HAL_PIXEL_FORMAT_BLOB] = camera_config->GetInteger(
      constants::kCrosMaxBlobWidth, std::numeric_limits<int>::max());
  max_hal_width_by_format[HAL_PIXEL_FORMAT_YCbCr_420_888] =
      camera_config->GetInteger(constants::kCrosMaxYuvWidth,
                                std::numeric_limits<int>::max());
  max_hal_width_by_format[HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED] =
      camera_config->GetInteger(constants::kCrosMaxPrivateWidth,
                                std::numeric_limits<int>::max());

  max_hal_height_by_format[HAL_PIXEL_FORMAT_BLOB] = camera_config->GetInteger(
      constants::kCrosMaxBlobHeight, std::numeric_limits<int>::max());
  max_hal_height_by_format[HAL_PIXEL_FORMAT_YCbCr_420_888] =
      camera_config->GetInteger(constants::kCrosMaxYuvHeight,
                                std::numeric_limits<int>::max());
  max_hal_height_by_format[HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED] =
      camera_config->GetInteger(constants::kCrosMaxPrivateHeight,
                                std::numeric_limits<int>::max());

  for (const auto& supported_format : supported_formats) {
    int64_t min_frame_duration = std::numeric_limits<int64_t>::max();
    int32_t per_format_max_fps = std::numeric_limits<int32_t>::min();
    for (const auto& frame_rate : supported_format.frame_rates) {
      // To prevent floating point precision problem we cast the floating point
      // to double here.
      int64_t frame_duration =
          kOneSecOfNanoUnit / static_cast<double>(frame_rate);
      if (frame_duration < min_frame_duration) {
        min_frame_duration = frame_duration;
      }
      if (frame_duration > max_frame_duration) {
        max_frame_duration = frame_duration;
      }
      if (per_format_max_fps < static_cast<int32_t>(frame_rate)) {
        per_format_max_fps = static_cast<int32_t>(frame_rate);
      }
      supported_fps.insert(frame_rate);
    }
    if (per_format_max_fps > max_fps) {
      max_fps = per_format_max_fps;
    }

    for (const auto& format : hal_formats) {
      if (is_builtin) {
        if (supported_format.width > max_hal_width_by_format[format]) {
          LOGF(INFO) << "Filter Format: 0x" << std::hex << format << std::dec
                     << "-width " << supported_format.width << ". max is "
                     << max_hal_width_by_format[format];
          continue;
        }
        if (supported_format.height > max_hal_height_by_format[format]) {
          LOGF(INFO) << "Filter Format: 0x" << std::hex << format << std::dec
                     << "-height " << supported_format.height << ". max is "
                     << max_hal_height_by_format[format];
          continue;
        }
        if (format != HAL_PIXEL_FORMAT_BLOB && per_format_max_fps < 30) {
          continue;
        }
      }

      stream_configurations.push_back(format);
      stream_configurations.push_back(supported_format.width);
      stream_configurations.push_back(supported_format.height);
      stream_configurations.push_back(
          ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT);

      min_frame_durations.push_back(format);
      min_frame_durations.push_back(supported_format.width);
      min_frame_durations.push_back(supported_format.height);
      min_frame_durations.push_back(min_frame_duration);
    }

    // The stall duration is 0 for non-jpeg formats. For JPEG format, stall
    // duration can be 0 if JPEG is small. 5MP JPEG takes 700ms to decode
    // and encode. Here we choose 1 sec for JPEG.
    for (const auto& format : hal_formats) {
      // For non-jpeg formats, the camera orientation workaround crops,
      // rotates, and scales the frames. Theoretically the stall duration of
      // huge resolution may be bigger than 0. Set it to 0 for now.
      int64_t stall_duration =
          (format == HAL_PIXEL_FORMAT_BLOB) ? 1000000000 : 0;
      stall_durations.push_back(format);
      stall_durations.push_back(supported_format.width);
      stall_durations.push_back(supported_format.height);
      stall_durations.push_back(stall_duration);
    }
  }

  MetadataUpdater update_static(static_metadata);
  MetadataUpdater update_request(request_metadata);

  // The document in aeAvailableTargetFpsRanges section says the min fps should
  // not be larger than 15.
  // We enumerate all possible fps and put (min, fps) as available fps range. If
  // the device support constant frame rate, put (fps, fps) into the list as
  // well.
  // TODO(wtlee): Handle non-integer fps when setting controls.
  bool support_constant_framerate = !device_info.constant_framerate_unsupported;
  std::vector<int32_t> available_fps_ranges;

  // For devices that cannot actually meet the fps ranges they report, only
  // report (min, max) and optional (max, max) if they support constant frame
  // rate.
  if (device_info.quirks & kQuirkReportLeastFpsRanges) {
    available_fps_ranges.push_back(kMinFps);
    available_fps_ranges.push_back(max_fps);

    if (support_constant_framerate) {
      available_fps_ranges.push_back(max_fps);
      available_fps_ranges.push_back(max_fps);
    }
  } else {
    for (auto fps : supported_fps) {
      // The IsFpsRangeSupported() filter should only apply on built-in
      // cameras, otherwise some webcams with fps combinations that cannot be
      // represented in HALv3 API would stop working (b/171845790).
      if (is_external || IsFpsRangeSupported(supported_formats, kMinFps, fps)) {
        available_fps_ranges.push_back(kMinFps);
        available_fps_ranges.push_back(fps);
      }

      if (support_constant_framerate &&
          (is_external || IsFpsRangeSupported(supported_formats, fps, fps))) {
        available_fps_ranges.push_back(fps);
        available_fps_ranges.push_back(fps);
      }
    }
  }
  update_static(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
                available_fps_ranges);
  update_static(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
                stream_configurations);
  update_static(ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
                min_frame_durations);
  update_static(ANDROID_SCALER_AVAILABLE_STALL_DURATIONS, stall_durations);

  std::vector<int32_t> jpeg_available_thumbnail_sizes =
      GetJpegAvailableThumbnailSizes(supported_formats);
  update_static(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
                jpeg_available_thumbnail_sizes);
  update_request(ANDROID_JPEG_THUMBNAIL_SIZE,
                 std::vector<int32_t>(jpeg_available_thumbnail_sizes.end() - 2,
                                      jpeg_available_thumbnail_sizes.end()));
  update_static(ANDROID_SENSOR_INFO_MAX_FRAME_DURATION, max_frame_duration);

  const Size max_dimensions = GetMaxDimensions(supported_formats);
  std::vector<int32_t> active_array_size(4);
  if (device_info.sensor_info_active_array_size.is_valid()) {
    const Rect<int32_t>& rect = device_info.sensor_info_active_array_size;
    if (rect.width() < max_dimensions.width ||
        rect.height() < max_dimensions.height) {
      LOGF(ERROR) << "Sensor active array size (" << rect.width() << "x"
                  << rect.height()
                  << ") is smaller than max supported format dimensions ("
                  << max_dimensions.width << "x" << max_dimensions.height
                  << ")";
      return -EINVAL;
    }
    active_array_size[0] = rect.left;
    active_array_size[1] = rect.top;
    active_array_size[2] = rect.right;
    active_array_size[3] = rect.bottom;
  } else {
    active_array_size[0] = 0;
    active_array_size[1] = 0;
    active_array_size[2] = static_cast<int32_t>(max_dimensions.width);
    active_array_size[3] = static_cast<int32_t>(max_dimensions.height);
  }
  update_static(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
                active_array_size);
  update_static(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE, active_array_size);

  if (is_v1_builtin) {
    if (FillSensorInfo(device_info, static_metadata,
                       static_cast<int32_t>(max_dimensions.width),
                       static_cast<int32_t>(max_dimensions.height)) != 0) {
      LOGF(ERROR) << "Failed to fill sensor info for v1 built-in camera";
      return -EINVAL;
    }
  } else if (is_external) {
    // It's a sensible value for external camera, since it's required on all
    // devices per spec. For built-in camera, this would be filled in
    // FillMetadataFromDeviceInfo() or FillSensorInfo() using the value from the
    // configuration file.
    //
    // The official document for this field:
    // https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#SENSOR_INFO_PIXEL_ARRAY_SIZE
    update_static(
        ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
        std::vector<int32_t>{static_cast<int32_t>(max_dimensions.width),
                             static_cast<int32_t>(max_dimensions.height)});
  }

  return update_static.ok() && update_request.ok() ? 0 : -EINVAL;
}

// static
AwbModeToTemperatureMap MetadataHandler::GetAvailableAwbTemperatures(
    const DeviceInfo& device_info) {
  AwbModeToTemperatureMap available_awb_temperatures;

  available_awb_temperatures[ANDROID_CONTROL_AWB_MODE_AUTO] =
      kColorTemperatureAuto;

  if (!V4L2CameraDevice::IsControlSupported(device_info.device_path,
                                            kControlAutoWhiteBalance))
    return available_awb_temperatures;

  ControlInfo info;
  if (V4L2CameraDevice::QueryControl(
          device_info.device_path, kControlWhiteBalanceTemperature, &info) != 0)
    return available_awb_temperatures;

  for (auto& mode_temperature : GetAwbModeTemperatureMap()) {
    uint32_t temperature =
        GetAwbTemperatureByMode(info.range, mode_temperature.first);
    if (!temperature)
      continue;
    available_awb_temperatures[mode_temperature.first] = temperature;
  }

  return available_awb_temperatures;
}

// static
int MetadataHandler::FillMetadataFromDeviceInfo(
    const DeviceInfo& device_info,
    android::CameraMetadata* static_metadata,
    android::CameraMetadata* request_metadata) {
  MetadataUpdater update_static(static_metadata);
  MetadataUpdater update_request(request_metadata);

  bool is_external = device_info.lens_facing == LensFacing::kExternal;
  bool is_builtin = !is_external;
  bool is_v1_builtin = device_info.quirks & kQuirkV1Device;
  bool is_v3_builtin = is_builtin && !is_v1_builtin;

  std::vector<int32_t> available_request_keys = {
      ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
      ANDROID_CONTROL_AE_ANTIBANDING_MODE,
      ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
      ANDROID_CONTROL_AE_LOCK,
      ANDROID_CONTROL_AE_MODE,
      ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
      ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
      ANDROID_CONTROL_AF_MODE,
      ANDROID_CONTROL_AF_TRIGGER,
      ANDROID_CONTROL_AWB_LOCK,
      ANDROID_CONTROL_AWB_MODE,
      ANDROID_CONTROL_CAPTURE_INTENT,
      ANDROID_CONTROL_EFFECT_MODE,
      ANDROID_CONTROL_MODE,
      ANDROID_CONTROL_SCENE_MODE,
      ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
      ANDROID_FLASH_MODE,
      ANDROID_JPEG_ORIENTATION,
      ANDROID_JPEG_QUALITY,
      ANDROID_JPEG_THUMBNAIL_QUALITY,
      ANDROID_JPEG_THUMBNAIL_SIZE,
      ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
      ANDROID_NOISE_REDUCTION_MODE,
      ANDROID_SCALER_CROP_REGION,
      ANDROID_SENSOR_TEST_PATTERN_MODE,
      ANDROID_STATISTICS_FACE_DETECT_MODE,
      ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
  };
  if (is_builtin) {
    available_request_keys.insert(available_request_keys.end(),
                                  {
                                      ANDROID_LENS_APERTURE,
                                      ANDROID_LENS_FOCAL_LENGTH,
                                      ANDROID_LENS_FOCUS_DISTANCE,
                                  });
  }

  // TODO(shik): All properties listed for capture requests can also be queried
  // on the capture result, to determine the final values used for capture. We
  // shuold build this list from |available_request_keys|.
  // ref:
  // https://developer.android.com/reference/android/hardware/camera2/CaptureResult
  std::vector<int32_t> available_result_keys = {
      ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
      ANDROID_CONTROL_AE_ANTIBANDING_MODE,
      ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
      ANDROID_CONTROL_AE_LOCK,
      ANDROID_CONTROL_AE_MODE,
      ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
      ANDROID_CONTROL_AE_STATE,
      ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
      ANDROID_CONTROL_AF_MODE,
      ANDROID_CONTROL_AF_STATE,
      ANDROID_CONTROL_AF_TRIGGER,
      ANDROID_CONTROL_AWB_LOCK,
      ANDROID_CONTROL_AWB_MODE,
      ANDROID_CONTROL_AWB_STATE,
      ANDROID_CONTROL_CAPTURE_INTENT,
      ANDROID_CONTROL_EFFECT_MODE,
      ANDROID_CONTROL_MODE,
      ANDROID_CONTROL_SCENE_MODE,
      ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
      ANDROID_FLASH_MODE,
      ANDROID_FLASH_STATE,
      ANDROID_JPEG_ORIENTATION,
      ANDROID_JPEG_QUALITY,
      ANDROID_JPEG_THUMBNAIL_QUALITY,
      ANDROID_JPEG_THUMBNAIL_SIZE,
      ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
      ANDROID_LENS_STATE,
      ANDROID_NOISE_REDUCTION_MODE,
      ANDROID_REQUEST_PIPELINE_DEPTH,
      ANDROID_SCALER_CROP_REGION,
      ANDROID_SENSOR_EXPOSURE_TIME,
      ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,
      ANDROID_SENSOR_TEST_PATTERN_MODE,
      ANDROID_SENSOR_TIMESTAMP,
      ANDROID_STATISTICS_FACE_DETECT_MODE,
      ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
      ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
      ANDROID_STATISTICS_SCENE_FLICKER,
  };
  if (is_builtin) {
    available_result_keys.insert(available_result_keys.end(),
                                 {
                                     ANDROID_LENS_APERTURE,
                                     ANDROID_LENS_FOCAL_LENGTH,
                                     ANDROID_LENS_FOCUS_DISTANCE,
                                 });
  }

  // TODO(shik): The HAL must not have any tags in its static info that are not
  // listed either here or in the vendor tag list.  Some request/result metadata
  // entries are also presented in the static info now, and we should fix it.
  // ref:
  // https://android.googlesource.com/platform/system/media/+/a8cff157ff0ed02fa7e29438f4889a9933c37768/camera/docs/docs.html#16298
  std::vector<int32_t> available_characteristics_keys = {
      ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
      ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
      ANDROID_CONTROL_AE_AVAILABLE_MODES,
      ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
      ANDROID_CONTROL_AE_COMPENSATION_RANGE,
      ANDROID_CONTROL_AE_COMPENSATION_STEP,
      ANDROID_CONTROL_AE_LOCK_AVAILABLE,
      ANDROID_CONTROL_AF_AVAILABLE_MODES,
      ANDROID_CONTROL_AVAILABLE_EFFECTS,
      ANDROID_CONTROL_AVAILABLE_MODES,
      ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
      ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
      ANDROID_CONTROL_AWB_AVAILABLE_MODES,
      ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
      ANDROID_CONTROL_MAX_REGIONS,
      ANDROID_FLASH_INFO_AVAILABLE,
      ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
      ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
      ANDROID_JPEG_MAX_SIZE,
      ANDROID_LENS_FACING,
      ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
      ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
      ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
      ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
      ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
      ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
      ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
      ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
      ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
      ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
      ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
      ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
      ANDROID_SCALER_CROPPING_TYPE,
      ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
      ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE,
      ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
      ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
      ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
      ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
      ANDROID_SENSOR_ORIENTATION,
      ANDROID_SHADING_AVAILABLE_MODES,
      ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
      ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
      ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
      ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
      ANDROID_SYNC_MAX_LATENCY,
  };
  if (is_builtin) {
    if (!device_info.lens_info_available_apertures.empty()) {
      // This field is optional. Only list it if it presents in the
      // configuration.
      available_characteristics_keys.insert(
          available_characteristics_keys.end(),
          {
              ANDROID_LENS_INFO_AVAILABLE_APERTURES,
          });
    }
    available_characteristics_keys.insert(
        available_characteristics_keys.end(),
        {
            ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
            ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
        });
  }

  update_static(ANDROID_SENSOR_ORIENTATION, device_info.sensor_orientation);
  update_static(ANDROID_LENS_FACING,
                static_cast<uint8_t>(device_info.lens_facing));

  if (is_v3_builtin) {
    update_static(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
                  ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED);

    update_static(ANDROID_LENS_INFO_AVAILABLE_APERTURES,
                  device_info.lens_info_available_apertures);

    update_request(ANDROID_LENS_APERTURE,
                   device_info.lens_info_available_apertures[0]);

    update_static(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
                  device_info.lens_info_available_focal_lengths);

    update_request(ANDROID_LENS_FOCAL_LENGTH,
                   device_info.lens_info_available_focal_lengths[0]);

    update_static(
        ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
        std::vector<float>{device_info.sensor_info_physical_size_width,
                           device_info.sensor_info_physical_size_height});
    update_static(
        ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
        std::vector<int32_t>{device_info.sensor_info_pixel_array_size_width,
                             device_info.sensor_info_pixel_array_size_height});
  } else if (is_v1_builtin) {
    update_static(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
                  ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL);

    if (device_info.lens_info_available_apertures.size() > 0) {
      update_static(ANDROID_LENS_INFO_AVAILABLE_APERTURES,
                    device_info.lens_info_available_apertures);
      update_request(ANDROID_LENS_APERTURE,
                     device_info.lens_info_available_apertures[0]);
    }

    if (device_info.lens_info_available_focal_lengths.size() > 0) {
      update_static(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
                    device_info.lens_info_available_focal_lengths);
      update_request(ANDROID_LENS_FOCAL_LENGTH,
                     device_info.lens_info_available_focal_lengths[0]);
    } else {
      update_static(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
                    kDefaultAvailableFocalLength);
      update_request(ANDROID_LENS_FOCAL_LENGTH, kDefaultAvailableFocalLength);
    }

    if (device_info.sensor_info_pixel_array_size_width > 0 &&
        device_info.sensor_info_pixel_array_size_height > 0) {
      update_static(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
                    std::vector<int32_t>{
                        device_info.sensor_info_pixel_array_size_width,
                        device_info.sensor_info_pixel_array_size_height});
    }
    // For |sensor_info_physical_size|, fill them later with supported formats
    // information.
  } else {
    update_static(ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
                  ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL);
  }

  update_static(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
                ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO);
  update_request(ANDROID_CONTROL_AE_ANTIBANDING_MODE,
                 ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO);

  // Set vendor tags for specified boards.
  if (device_info.quirks & kQuirkMonocle) {
    int32_t timestamp_sync =
        static_cast<int32_t>(mojom::CameraSensorSyncTimestamp::NEAREST);
    update_static(kVendorTagTimestampSync, timestamp_sync);
  }

  ControlInfo info;

  if (V4L2CameraDevice::QueryControl(device_info.device_path,
                                     kControlBrightness, &info) == 0) {
    update_static(kVendorTagControlBrightnessRange,
                  std::vector<int32_t>{info.range.minimum, info.range.maximum,
                                       info.range.step});
  }

  if (V4L2CameraDevice::QueryControl(device_info.device_path, kControlContrast,
                                     &info) == 0) {
    update_static(kVendorTagControlContrastRange,
                  std::vector<int32_t>{info.range.minimum, info.range.maximum,
                                       info.range.step});
  }

  if (V4L2CameraDevice::QueryControl(device_info.device_path, kControlPan,
                                     &info) == 0) {
    update_static(kVendorTagControlPanRange,
                  std::vector<int32_t>{info.range.minimum, info.range.maximum,
                                       info.range.step});
  }

  if (V4L2CameraDevice::QueryControl(device_info.device_path,
                                     kControlSaturation, &info) == 0) {
    update_static(kVendorTagControlSaturationRange,
                  std::vector<int32_t>{info.range.minimum, info.range.maximum,
                                       info.range.step});
  }

  if (V4L2CameraDevice::QueryControl(device_info.device_path, kControlSharpness,
                                     &info) == 0) {
    update_static(kVendorTagControlSharpnessRange,
                  std::vector<int32_t>{info.range.minimum, info.range.maximum,
                                       info.range.step});
  }

  if (V4L2CameraDevice::QueryControl(device_info.device_path, kControlTilt,
                                     &info) == 0) {
    update_static(kVendorTagControlTiltRange,
                  std::vector<int32_t>{info.range.minimum, info.range.maximum,
                                       info.range.step});
  }

  if (V4L2CameraDevice::QueryControl(device_info.device_path, kControlZoom,
                                     &info) == 0) {
    update_static(kVendorTagControlZoomRange,
                  std::vector<int32_t>{info.range.minimum, info.range.maximum,
                                       info.range.step});
  }

  std::vector<uint8_t> available_awb_modes;
  for (auto const& it : GetAvailableAwbTemperatures(device_info))
    available_awb_modes.push_back(it.first);

  update_static(ANDROID_CONTROL_AWB_AVAILABLE_MODES, available_awb_modes);

  // Check if device supports manual exposure control.
  ControlRange range;
  if (V4L2CameraDevice::IsManualExposureTimeSupported(device_info.device_path,
                                                      &range)) {
    update_static(ANDROID_CONTROL_AE_AVAILABLE_MODES,
                  std::vector<uint8_t>{ANDROID_CONTROL_AE_MODE_OFF,
                                       ANDROID_CONTROL_AE_MODE_ON});
    // The unit of the range is 100 us.
    update_static(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
                  std::vector<int64_t>{
                      range.minimum * 100 * 1000 /* ns */,
                      range.maximum * 100 * 1000 /* ns */
                  });
    // CtsCameraTestCases needs it. This control is only effective if
    // android.control.aeMode is set to OFF.
    update_request(
        ANDROID_SENSOR_EXPOSURE_TIME,
        static_cast<int64_t>(range.default_value) * 100 * 1000 /* ns */);
    available_characteristics_keys.push_back(
        ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE);
    available_request_keys.push_back(ANDROID_SENSOR_EXPOSURE_TIME);
  }

  // The unit of V4L2 focus distance is undefined, so set it to uncalibrated.
  update_static(ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
                ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED);
  if (V4L2CameraDevice::IsControlSupported(device_info.device_path,
                                           kControlFocusAuto)) {
    update_static(ANDROID_CONTROL_AF_AVAILABLE_MODES,
                  std::vector<uint8_t>{ANDROID_CONTROL_AF_MODE_OFF,
                                       ANDROID_CONTROL_AF_MODE_AUTO});
    update_request(ANDROID_CONTROL_AF_MODE, ANDROID_CONTROL_AF_MODE_AUTO);
    update_request(ANDROID_LENS_FOCUS_DISTANCE, 0.0f);
    if (V4L2CameraDevice::IsFocusDistanceSupported(device_info.device_path,
                                                   &range)) {
      float full_range = range.maximum - range.minimum;
      uint32_t factor = GetNormalizeFactorForV4l2FocusRange(full_range);
      update_static(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
                    full_range / factor);
    } else {
      if (device_info.lens_info_minimum_focus_distance > 0) {
        update_static(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
                      1.0f / device_info.lens_info_minimum_focus_distance);
      } else {
        update_static(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
                      1.0f / kDefaultMinimumFocusDistance);
      }
    }
  } else {
    update_static(ANDROID_CONTROL_AF_AVAILABLE_MODES,
                  ANDROID_CONTROL_AF_MODE_OFF);
    update_request(ANDROID_CONTROL_AF_MODE, ANDROID_CONTROL_AF_MODE_OFF);
    update_static(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE, 0.0f);
  }

  update_static(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
                available_characteristics_keys);
  update_static(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, available_request_keys);
  update_static(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, available_result_keys);
  return update_static.ok() && update_request.ok() ? 0 : -EINVAL;
}

int MetadataHandler::FillSensorInfo(const DeviceInfo& device_info,
                                    android::CameraMetadata* metadata,
                                    int32_t array_width,
                                    int32_t array_height) {
  MetadataUpdater update_static(metadata);

  if (device_info.sensor_info_pixel_array_size_width <= 0 ||
      device_info.sensor_info_pixel_array_size_height <= 0) {
    update_static(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
                  std::vector<int32_t>{array_width, array_height});
  }

  float focal_length = device_info.lens_info_available_focal_lengths.size() > 0
                           ? device_info.lens_info_available_focal_lengths[0]
                           : kDefaultAvailableFocalLength;

  float aspect_ratio = 1.f * array_width / array_height;
  bool is_closer_to_16_9 = std::fabs(aspect_ratio - 16.f / 9.f) <
                           std::fabs(aspect_ratio - 4.f / 3.f);
  bool has_fov_info_16_9 = device_info.horizontal_view_angle_16_9 > 0.f &&
                           device_info.vertical_view_angle_16_9 > 0.f;
  bool has_fov_info_4_3 = device_info.horizontal_view_angle_4_3 > 0.f &&
                          device_info.vertical_view_angle_4_3 > 0.f;

  // Use the FOV information (16:9 or 4:3) whose aspect ratio is closer to the
  // ratio of sensor array size to calculate the sensor physical size.
  if (has_fov_info_16_9 && (is_closer_to_16_9 || !has_fov_info_4_3)) {
    update_static(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
                  GetPhysicalSize(device_info.horizontal_view_angle_16_9,
                                  device_info.vertical_view_angle_16_9,
                                  focal_length, aspect_ratio, 16.f / 9.f));
  } else if (has_fov_info_4_3) {
    update_static(ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
                  GetPhysicalSize(device_info.horizontal_view_angle_4_3,
                                  device_info.vertical_view_angle_4_3,
                                  focal_length, aspect_ratio, 4.f / 3.f));
  } else if (device_info.sensor_info_physical_size_width > 0.f &&
             device_info.sensor_info_physical_size_height > 0.f) {
    // Since the sensor physical size might be incorrect, only use these values
    // when there are no view angle information.
    update_static(
        ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
        std::vector<float>{device_info.sensor_info_physical_size_width,
                           device_info.sensor_info_physical_size_height});
  } else {
    LOGF(ERROR)
        << "Neither sensor physical size nor view angle information is found";
    return -EINVAL;
  }
  return update_static.ok() ? 0 : -EINVAL;
}

const camera_metadata_t* MetadataHandler::GetDefaultRequestSettings(
    int template_type) {
  if (!IsValidTemplateType(template_type)) {
    LOGF(ERROR) << "Invalid template request type: " << template_type;
    return nullptr;
  }
  return template_settings_[template_type].get();
}

bool MetadataHandler::ShouldEnableConstantFrameRate(
    const android::CameraMetadata* metadata) const {
  if (device_info_.constant_framerate_unsupported) {
    return false;
  }

  // TODO(shik): Add a helper function to do the exists() and find() combo, so
  // it's less likely to have typos in the tag name.

  if (metadata->exists(ANDROID_CONTROL_AE_TARGET_FPS_RANGE)) {
    camera_metadata_ro_entry entry =
        metadata->find(ANDROID_CONTROL_AE_TARGET_FPS_RANGE);
    if (entry.data.i32[0] == entry.data.i32[1]) {
      return true;
    }
  }

  if (metadata->exists(ANDROID_CONTROL_CAPTURE_INTENT)) {
    camera_metadata_ro_entry entry =
        metadata->find(ANDROID_CONTROL_CAPTURE_INTENT);
    switch (entry.data.u8[0]) {
      case ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD:
      case ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT:
        return true;
    }
  }

  return false;
}

int MetadataHandler::PreHandleRequest(int frame_number,
                                      const Size& resolution,
                                      android::CameraMetadata* metadata) {
  DCHECK(thread_checker_.CalledOnValidThread());
  MetadataUpdater update_request(metadata);

  if (!device_info_.constant_framerate_unsupported) {
    bool enable = ShouldEnableConstantFrameRate(metadata);
    if (device_->SetControlValue(kControlExposureAutoPriority,
                                 enable ? 0 : 1) != 0) {
      LOGF(WARNING) << "Failed to set constant frame rate to " << std::boolalpha
                    << enable;
    }
  }

  if (metadata->exists(ANDROID_CONTROL_AF_TRIGGER)) {
    camera_metadata_entry entry = metadata->find(ANDROID_CONTROL_AF_TRIGGER);
    if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_START) {
      af_trigger_ = true;
    } else if (entry.data.u8[0] == ANDROID_CONTROL_AF_TRIGGER_CANCEL) {
      af_trigger_ = false;
    }
  }

  if (metadata->exists(ANDROID_CONTROL_AF_MODE)) {
    camera_metadata_entry entry = metadata->find(ANDROID_CONTROL_AF_MODE);
    if (entry.data.u8[0] == ANDROID_CONTROL_AF_MODE_OFF) {
      if (metadata->exists(ANDROID_LENS_FOCUS_DISTANCE) &&
          focus_distance_normalize_factor_ > 0) {
        entry = metadata->find(ANDROID_LENS_FOCUS_DISTANCE);
        int32_t distance =
            static_cast<int32_t>(entry.data.f[0] *
                                 focus_distance_normalize_factor_) +
            focus_distance_range_.minimum;
        distance = std::min(distance, focus_distance_range_.maximum);
        device_->SetAutoFocus(false);
        device_->SetFocusDistance(distance);
        int32_t focus_distance;
        device_->GetControlValue(kControlFocusDistance, &focus_distance);
        float simulate_diopters =
            static_cast<float>(focus_distance - focus_distance_range_.minimum) /
            focus_distance_normalize_factor_;
        update_request(ANDROID_LENS_FOCUS_DISTANCE, simulate_diopters);
      } else {
        device_->SetAutoFocus(false);
      }
    } else if (entry.data.u8[0] == ANDROID_CONTROL_AF_MODE_AUTO) {
      device_->SetAutoFocus(true);
      float diopters;
      if (device_info_.lens_info_optimal_focus_distance > 0) {
        diopters = 1.0 / device_info_.lens_info_optimal_focus_distance;
      } else {
        diopters = 1.0 / kDefaultLensFocusDistance;
      }
      update_request(ANDROID_LENS_FOCUS_DISTANCE, diopters);
    }
  }

  if (is_awb_control_supported_ && metadata->exists(ANDROID_CONTROL_AWB_MODE)) {
    camera_metadata_entry entry = metadata->find(ANDROID_CONTROL_AWB_MODE);
    auto mode = static_cast<camera_metadata_enum_android_control_awb_mode>(
        entry.data.u8[0]);
    if (awb_temperature_.count(mode))
      device_->SetColorTemperature(awb_temperature_[mode]);
    else
      LOGF(WARNING) << "Unsupported AWB mode:" << mode;
  }

  const int64_t rolling_shutter_skew =
      sensor_handler_->GetRollingShutterSkew(resolution);
  update_request(ANDROID_SENSOR_ROLLING_SHUTTER_SKEW, rolling_shutter_skew);

  if (metadata->exists(kVendorTagControlBrightness)) {
    camera_metadata_entry entry = metadata->find(kVendorTagControlBrightness);
    device_->SetControlValue(kControlBrightness, entry.data.i32[0]);
  }

  if (metadata->exists(kVendorTagControlContrast)) {
    camera_metadata_entry entry = metadata->find(kVendorTagControlContrast);
    device_->SetControlValue(kControlContrast, entry.data.i32[0]);
  }

  if (metadata->exists(kVendorTagControlPan)) {
    camera_metadata_entry entry = metadata->find(kVendorTagControlPan);
    device_->SetControlValue(kControlPan, entry.data.i32[0]);
  }

  if (metadata->exists(kVendorTagControlSaturation)) {
    camera_metadata_entry entry = metadata->find(kVendorTagControlSaturation);
    device_->SetControlValue(kControlSaturation, entry.data.i32[0]);
  }

  if (metadata->exists(kVendorTagControlSharpness)) {
    camera_metadata_entry entry = metadata->find(kVendorTagControlSharpness);
    device_->SetControlValue(kControlSharpness, entry.data.i32[0]);
  }

  if (metadata->exists(kVendorTagControlTilt)) {
    camera_metadata_entry entry = metadata->find(kVendorTagControlTilt);
    device_->SetControlValue(kControlTilt, entry.data.i32[0]);
  }

  if (metadata->exists(kVendorTagControlZoom)) {
    camera_metadata_entry entry = metadata->find(kVendorTagControlZoom);
    device_->SetControlValue(kControlZoom, entry.data.i32[0]);
  }

  if (metadata->exists(ANDROID_CONTROL_AE_MODE)) {
    camera_metadata_entry entry = metadata->find(ANDROID_CONTROL_AE_MODE);
    int32_t exposure_time;
    switch (entry.data.u8[0]) {
      case ANDROID_CONTROL_AE_MODE_ON:
        device_->SetExposureTimeHundredUs(kExposureTimeAuto);
        update_request(ANDROID_SENSOR_EXPOSURE_TIME,
                       sensor_handler_->GetExposureTime(resolution));
        break;

      case ANDROID_CONTROL_AE_MODE_OFF:
        if (metadata->exists(ANDROID_SENSOR_EXPOSURE_TIME)) {
          entry = metadata->find(ANDROID_SENSOR_EXPOSURE_TIME);
          exposure_time =
              static_cast<int32_t>(entry.data.i64[0] / (100 * 1000));  // ns
          device_->SetExposureTimeHundredUs(exposure_time);
          device_->GetControlValue(kControlExposureTime, &exposure_time);
          update_request(
              ANDROID_SENSOR_EXPOSURE_TIME,
              base::strict_cast<int64_t>(exposure_time) * 100 * 1000);  // ns
        } else {
          LOGF(WARNING) << "There is no ANDROID_SENSOR_EXPOSURE_TIME metadata";
        }
        break;

      default:
        LOGF(WARNING) << "Unsupport AE mode " << entry.data.u8[0];
        break;
    }
  }

  current_frame_number_ = frame_number;
  return 0;
}

int MetadataHandler::PostHandleRequest(int frame_number,
                                       int64_t timestamp,
                                       android::CameraMetadata* metadata) {
  DCHECK(thread_checker_.CalledOnValidThread());
  if (current_frame_number_ != frame_number) {
    LOGF(ERROR)
        << "Frame number mismatch in PreHandleRequest and PostHandleRequest";
    return -EINVAL;
  }

  MetadataUpdater update_request(metadata);
  // android.control
  // For USB camera, we don't know the AE state. Set the state to converged to
  // indicate the frame should be good to use. Then apps don't have to wait the
  // AE state.
  update_request(ANDROID_CONTROL_AE_STATE, ANDROID_CONTROL_AE_STATE_CONVERGED);
  update_request(ANDROID_CONTROL_AE_LOCK, ANDROID_CONTROL_AE_LOCK_OFF);

  // For USB camera, the USB camera handles everything and we don't have control
  // over AF. We only simply fake the AF metadata based on the request
  // received here.
  uint8_t af_state;
  if (af_trigger_) {
    af_state = ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED;
  } else {
    af_state = ANDROID_CONTROL_AF_STATE_INACTIVE;
  }
  update_request(ANDROID_CONTROL_AF_STATE, af_state);

  // Set AWB state to converged to indicate the frame should be good to use.
  update_request(ANDROID_CONTROL_AWB_STATE,
                 ANDROID_CONTROL_AWB_STATE_CONVERGED);

  update_request(ANDROID_CONTROL_AWB_LOCK, ANDROID_CONTROL_AWB_LOCK_OFF);

  camera_metadata_entry active_array_size =
      static_metadata_.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);

  if (active_array_size.count == 0) {
    LOGF(ERROR) << "Active array size is not found.";
    return -EINVAL;
  }

  // android.lens
  // Since android.lens.focalLength, android.lens.focusDistance and
  // android.lens.aperture are all fixed. And we don't support
  // android.lens.filterDensity so we can set the state to stationary.
  update_request(ANDROID_LENS_STATE, ANDROID_LENS_STATE_STATIONARY);

  // android.scaler
  update_request(ANDROID_SCALER_CROP_REGION, std::vector<int32_t>{
                                                 active_array_size.data.i32[0],
                                                 active_array_size.data.i32[1],
                                                 active_array_size.data.i32[2],
                                                 active_array_size.data.i32[3],
                                             });

  // android.sensor
  update_request(ANDROID_SENSOR_TIMESTAMP, timestamp);

  // android.statistics
  update_request(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
                 ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF);

  update_request(ANDROID_STATISTICS_SCENE_FLICKER,
                 ANDROID_STATISTICS_SCENE_FLICKER_NONE);

  int32_t value;
  if (is_brightness_control_supported_ &&
      device_->GetControlValue(kControlBrightness, &value) == 0)
    update_request(kVendorTagControlBrightness, value);

  if (is_contrast_control_supported_ &&
      device_->GetControlValue(kControlContrast, &value) == 0)
    update_request(kVendorTagControlContrast, value);

  if (is_pan_control_supported_ &&
      device_->GetControlValue(kControlPan, &value) == 0)
    update_request(kVendorTagControlPan, value);

  if (is_saturation_control_supported_ &&
      device_->GetControlValue(kControlSaturation, &value) == 0)
    update_request(kVendorTagControlSaturation, value);

  if (is_sharpness_control_supported_ &&
      device_->GetControlValue(kControlSharpness, &value) == 0)
    update_request(kVendorTagControlSharpness, value);

  if (is_tilt_control_supported_ &&
      device_->GetControlValue(kControlTilt, &value) == 0)
    update_request(kVendorTagControlTilt, value);

  if (is_zoom_control_supported_ &&
      device_->GetControlValue(kControlZoom, &value) == 0)
    update_request(kVendorTagControlZoom, value);

  if (metadata->exists(ANDROID_CONTROL_AWB_MODE)) {
    update_request(ANDROID_CONTROL_AWB_MODE, ANDROID_CONTROL_AWB_MODE_AUTO);
    if (is_awb_control_supported_ &&
        device_->GetControlValue(kControlAutoWhiteBalance, &value) == 0) {
      if (!value &&  // Not auto white balance.
          device_->GetControlValue(kControlWhiteBalanceTemperature, &value) ==
              0) {
        for (auto& mode_temperature : awb_temperature_) {
          if (value == mode_temperature.second) {
            update_request(ANDROID_CONTROL_AWB_MODE, mode_temperature.first);
            break;
          }
        }
      }
    }
  }

  return 0;
}

bool MetadataHandler::IsValidTemplateType(int template_type) {
  return template_type > 0 && template_type < CAMERA3_TEMPLATE_COUNT;
}

ScopedCameraMetadata MetadataHandler::CreateDefaultRequestSettings(
    int template_type) {
  android::CameraMetadata data(request_template_);

  int ret;
  switch (template_type) {
    case CAMERA3_TEMPLATE_PREVIEW:
      ret = FillDefaultPreviewSettings(&data);
      break;
    case CAMERA3_TEMPLATE_STILL_CAPTURE:
      ret = FillDefaultStillCaptureSettings(&data);
      break;
    case CAMERA3_TEMPLATE_VIDEO_RECORD:
      ret = FillDefaultVideoRecordSettings(&data);
      break;
    case CAMERA3_TEMPLATE_VIDEO_SNAPSHOT:
      ret = FillDefaultVideoSnapshotSettings(&data);
      break;
    case CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG:
      ret = FillDefaultZeroShutterLagSettings(&data);
      break;
    case CAMERA3_TEMPLATE_MANUAL:
      ret = FillDefaultManualSettings(&data);
      break;
    default:
      LOGF(ERROR) << "Invalid template request type: " << template_type;
      return NULL;
  }

  if (ret) {
    return ScopedCameraMetadata();
  }
  return ScopedCameraMetadata(data.release());
}

int MetadataHandler::FillDefaultPreviewSettings(
    android::CameraMetadata* metadata) {
  MetadataUpdater update_request(metadata);

  // android.control
  update_request(ANDROID_CONTROL_CAPTURE_INTENT,
                 ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW);
  update_request(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
                 std::vector<int32_t>{kMinFps, max_supported_fps_});
  update_request(ANDROID_CONTROL_MODE, ANDROID_CONTROL_MODE_AUTO);

  // android.jpeg
  update_request(ANDROID_JPEG_THUMBNAIL_SIZE, std::vector<int32_t>{0, 0});
  return 0;
}

int MetadataHandler::FillDefaultStillCaptureSettings(
    android::CameraMetadata* metadata) {
  MetadataUpdater update_request(metadata);

  // android.colorCorrection
  update_request(ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
                 ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY);

  // android.control
  update_request(ANDROID_CONTROL_CAPTURE_INTENT,
                 ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE);
  update_request(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
                 std::vector<int32_t>{kMinFps, max_supported_fps_});

  update_request(ANDROID_CONTROL_MODE, ANDROID_CONTROL_MODE_AUTO);
  return 0;
}

int MetadataHandler::FillDefaultVideoRecordSettings(
    android::CameraMetadata* metadata) {
  MetadataUpdater update_request(metadata);

  // android.control
  update_request(ANDROID_CONTROL_CAPTURE_INTENT,
                 ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
  if (device_info_.constant_framerate_unsupported) {
    update_request(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
                   std::vector<int32_t>{kMinFps, max_supported_fps_});
  } else {
    update_request(
        ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
        std::vector<int32_t>{max_supported_fps_, max_supported_fps_});
  }

  update_request(ANDROID_CONTROL_MODE, ANDROID_CONTROL_MODE_AUTO);
  return 0;
}

int MetadataHandler::FillDefaultVideoSnapshotSettings(
    android::CameraMetadata* metadata) {
  MetadataUpdater update_request(metadata);

  // android.control
  update_request(ANDROID_CONTROL_CAPTURE_INTENT,
                 ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT);
  if (device_info_.constant_framerate_unsupported) {
    update_request(ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
                   std::vector<int32_t>{kMinFps, max_supported_fps_});
  } else {
    update_request(
        ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
        std::vector<int32_t>{max_supported_fps_, max_supported_fps_});
  }

  update_request(ANDROID_CONTROL_MODE, ANDROID_CONTROL_MODE_AUTO);
  return 0;
}

int MetadataHandler::FillDefaultZeroShutterLagSettings(
    android::CameraMetadata* /*metadata*/) {
  // Do not support ZSL template.
  return -EINVAL;
}

int MetadataHandler::FillDefaultManualSettings(
    android::CameraMetadata* /*metadata*/) {
  // Do not support manual template.
  return -EINVAL;
}

}  // namespace cros
