/*
 * 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/check.h>
#include <base/containers/fixed_flat_set.h>
#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"

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 constexpr auto kInt32EnumTags = base::MakeFixedFlatSet<int>({
        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.contains(tag)) {
      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);
  }

  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_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()) {
    LOGF(ERROR)
        << "Failed to fill metadata since there is no supported formats";
    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::unique_ptr<CameraConfig> camera_config =
      CameraConfig::Create(constants::kCrosCameraConfigPathString);
  int max_width = camera_config->GetInteger(constants::kCrosUsbMaxStreamWidth,
                                            std::numeric_limits<int>::max());
  int max_height = camera_config->GetInteger(constants::kCrosUsbMaxStreamHeight,
                                             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 (format != HAL_PIXEL_FORMAT_BLOB) {
          if (per_format_max_fps < 30) {
            continue;
          }
          if (supported_format.width > max_width ||
              supported_format.height > max_height) {
            LOGF(INFO) << "Filter Format: 0x" << std::hex << format << std::dec
                       << "-" << supported_format.width << "x"
                       << supported_format.height;
            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.width;
    active_array_size[3] = rect.height;
  } 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);

  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});
    update_static(kVendorTagControlBrightnessDefault,
                  std::vector<int32_t>{info.range.default_value});
  }

  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});
    update_static(kVendorTagControlContrastDefault,
                  std::vector<int32_t>{info.range.default_value});
  }

  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});
    update_static(kVendorTagControlPanDefault,
                  std::vector<int32_t>{info.range.default_value});
  }

  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});
    update_static(kVendorTagControlSaturationDefault,
                  std::vector<int32_t>{info.range.default_value});
  }

  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});
    update_static(kVendorTagControlSharpnessDefault,
                  std::vector<int32_t>{info.range.default_value});
  }

  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});
    update_static(kVendorTagControlTiltDefault,
                  std::vector<int32_t>{info.range.default_value});
  }

  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});
    update_static(kVendorTagControlZoomDefault,
                  std::vector<int32_t>{info.range.default_value});
  }

  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 */
                  });
    available_characteristics_keys.push_back(
        ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE);
    // 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_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);

  // Sets face detection.
  if (device_info.enable_face_detection) {
    update_static(
        ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
        std::vector<uint8_t>{ANDROID_STATISTICS_FACE_DETECT_MODE_OFF,
                             ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE});
    // FaceSSD can detect more than 600 faces in one 320x320 image.
    // 100 is enough for our use cases.
    update_static(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, 100);
  } else {
    update_static(
        ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
        std::vector<uint8_t>{ANDROID_STATISTICS_FACE_DETECT_MODE_OFF});
    update_static(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, 0);
  }
  update_request(ANDROID_STATISTICS_FACE_DETECT_MODE,
                 ANDROID_STATISTICS_FACE_DETECT_MODE_OFF);

  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 = 33'300'000;
  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);
    switch (entry.data.u8[0]) {
      case ANDROID_CONTROL_AE_MODE_ON: {
        device_->SetExposureTimeHundredUs(kExposureTimeAuto);
        const int64_t exposure_time = 16'600'000;
        update_request(ANDROID_SENSOR_EXPOSURE_TIME, exposure_time);
        break;
      }

      case ANDROID_CONTROL_AE_MODE_OFF: {
        if (metadata->exists(ANDROID_SENSOR_EXPOSURE_TIME)) {
          int32_t 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,
    const Size& resolution,
    const std::vector<human_sensing::CrosFace>& faces,
    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>{
                                                 0,
                                                 0,
                                                 active_array_size.data.i32[2],
                                                 active_array_size.data.i32[3],
                                             });

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

  // android.statistics
  if (device_info_.enable_face_detection) {
    std::vector<int32_t> face_rectangles;
    std::vector<uint8_t> face_scores;
    Rect<int> roi(0, 0, resolution.width, resolution.height);
    Rect<int> largest_face;
    int largest_size = 0;
    for (auto& face : faces) {
      float x1 = std::max(face.bounding_box.x1, 0.0F);
      float x2 = std::min(face.bounding_box.x2,
                          static_cast<float>(resolution.width - 1));
      float y1 = std::max(face.bounding_box.y1, 0.0F);
      float y2 = std::min(face.bounding_box.y2,
                          static_cast<float>(resolution.height - 1));
      face_rectangles.push_back(x1);
      face_rectangles.push_back(y1);
      face_rectangles.push_back(x2);
      face_rectangles.push_back(y2);
      face_scores.push_back(face.confidence * 100);
      int size = (x2 - x1) * (y2 - y1);
      if (size > largest_size) {
        largest_face = Rect<int>(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
        largest_size = size;
        // Set ROI with largest face to trigger 3A.
        roi = largest_face;
      }
    }
    update_request(ANDROID_STATISTICS_FACE_RECTANGLES, face_rectangles);
    update_request(ANDROID_STATISTICS_FACE_SCORES, face_scores);
    if (device_info_.region_of_interest_supported) {
      device_->SetRegionOfInterest(roi);
    }
  }

  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
