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

#include "camera3_test/camera3_service.h"

#include <unistd.h>

#include <algorithm>
#include <string>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/command_line.h>
#include <base/strings/string_number_conversions.h>

#include "camera3_test/camera3_perf_log.h"

namespace camera3_test {

namespace {

constexpr int kWaitForStopPreviewTimeoutMs = 3000;
constexpr int kWaitForStopRecordingTimeoutMs = 3000;

double Get3ATimeoutMultiplier() {
  static double multiplier = [] {
    constexpr char kSwitch[] = "3a_timeout_multiplier";
    const auto* cl = base::CommandLine::ForCurrentProcess();
    std::string val = cl->GetSwitchValueASCII(kSwitch);
    double out;
    if (val.empty() || !base::StringToDouble(val, &out)) {
      return 1.0;
    }
    return out;
  }();
  return multiplier;
}

int GetWaitForFocusDoneTimeoutMs() {
  return static_cast<int>(6000 * Get3ATimeoutMultiplier());
}

int GetWaitForAWBConvergedTimeoutMs() {
  return static_cast<int>(3000 * Get3ATimeoutMultiplier());
}

}  // namespace

Camera3Service::~Camera3Service() {}

int Camera3Service::Initialize(
    ProcessStillCaptureResultCallback still_capture_cb,
    ProcessRecordingResultCallback recording_cb) {
  base::AutoLock l(lock_);
  if (initialized_) {
    LOG(ERROR) << "Camera service is already initialized";
    return -EINVAL;
  }
  for (const auto& it : cam_ids_) {
    cam_dev_service_map_[it].reset(new Camera3Service::Camera3DeviceService(
        it, still_capture_cb, recording_cb));
    int result = cam_dev_service_map_[it]->Initialize();
    if (result != 0) {
      LOG(ERROR) << "Camera device " << it << " service initialization fails";
      cam_dev_service_map_.clear();
      return result;
    }
  }
  initialized_ = true;
  return 0;
}

void Camera3Service::Destroy() {
  base::AutoLock l(lock_);
  if (!initialized_) {
    return;
  }
  for (auto& it : cam_dev_service_map_) {
    it.second->Destroy();
  }
  cam_dev_service_map_.clear();
  initialized_ = false;
}

int Camera3Service::StartPreview(int cam_id,
                                 const ResolutionInfo& preview_resolution,
                                 const ResolutionInfo& still_capture_resolution,
                                 const ResolutionInfo& recording_resolution) {
  base::AutoLock l(lock_);
  if (!initialized_ ||
      cam_dev_service_map_.find(cam_id) == cam_dev_service_map_.end()) {
    return -ENODEV;
  }
  return cam_dev_service_map_[cam_id]->StartPreview(
      preview_resolution, still_capture_resolution, recording_resolution);
}

void Camera3Service::StopPreview(int cam_id) {
  base::AutoLock l(lock_);
  if (initialized_ &&
      cam_dev_service_map_.find(cam_id) != cam_dev_service_map_.end()) {
    cam_dev_service_map_[cam_id]->StopPreview();
  }
}

void Camera3Service::StartAutoFocus(int cam_id) {
  base::AutoLock l(lock_);
  if (initialized_ &&
      cam_dev_service_map_.find(cam_id) != cam_dev_service_map_.end()) {
    cam_dev_service_map_[cam_id]->StartAutoFocus();
  }
}

int Camera3Service::WaitForAutoFocusDone(int cam_id) {
  base::AutoLock l(lock_);
  if (!initialized_ ||
      cam_dev_service_map_.find(cam_id) == cam_dev_service_map_.end()) {
    return -ENODEV;
  }
  return cam_dev_service_map_[cam_id]->WaitForAutoFocusDone();
}

int Camera3Service::WaitForAWBConvergedAndLock(int cam_id) {
  base::AutoLock l(lock_);
  if (!initialized_ ||
      cam_dev_service_map_.find(cam_id) == cam_dev_service_map_.end()) {
    return -ENODEV;
  }
  return cam_dev_service_map_[cam_id]->WaitForAWBConvergedAndLock();
}

void Camera3Service::StartAEPrecapture(int cam_id) {
  base::AutoLock l(lock_);
  if (initialized_ &&
      cam_dev_service_map_.find(cam_id) != cam_dev_service_map_.end()) {
    cam_dev_service_map_[cam_id]->StartAEPrecapture();
  }
}

int Camera3Service::WaitForAEStable(int cam_id) {
  base::AutoLock l(lock_);
  if (!initialized_ ||
      cam_dev_service_map_.find(cam_id) == cam_dev_service_map_.end()) {
    return -ENODEV;
  }
  return cam_dev_service_map_[cam_id]->WaitForAEStable();
}

void Camera3Service::TakeStillCapture(int cam_id,
                                      const camera_metadata_t* metadata) {
  base::AutoLock l(lock_);
  if (initialized_ &&
      cam_dev_service_map_.find(cam_id) != cam_dev_service_map_.end()) {
    cam_dev_service_map_[cam_id]->TakeStillCapture(metadata);
  }
}

int Camera3Service::StartRecording(int cam_id,
                                   const camera_metadata_t* metadata) {
  base::AutoLock l(lock_);
  if (!initialized_ ||
      cam_dev_service_map_.find(cam_id) == cam_dev_service_map_.end()) {
    return -ENODEV;
  }
  return cam_dev_service_map_[cam_id]->StartRecording(metadata);
}

void Camera3Service::StopRecording(int cam_id) {
  base::AutoLock l(lock_);
  if (initialized_ &&
      cam_dev_service_map_.find(cam_id) != cam_dev_service_map_.end()) {
    cam_dev_service_map_[cam_id]->StopRecording();
  }
}

int Camera3Service::WaitForPreviewFrames(int cam_id,
                                         uint32_t num_frames,
                                         uint32_t timeout_ms) {
  base::AutoLock l(lock_);
  if (!initialized_ ||
      cam_dev_service_map_.find(cam_id) == cam_dev_service_map_.end()) {
    return -ENODEV;
  }
  return cam_dev_service_map_[cam_id]->WaitForPreviewFrames(num_frames,
                                                            timeout_ms);
}

const Camera3Device::StaticInfo* Camera3Service::GetStaticInfo(int cam_id) {
  base::AutoLock l(lock_);
  if (initialized_ &&
      cam_dev_service_map_.find(cam_id) != cam_dev_service_map_.end()) {
    return cam_dev_service_map_[cam_id]->GetStaticInfo();
  }
  return nullptr;
}

const camera_metadata_t* Camera3Service::ConstructDefaultRequestSettings(
    int cam_id, int type) {
  base::AutoLock l(lock_);
  if (initialized_ &&
      cam_dev_service_map_.find(cam_id) != cam_dev_service_map_.end()) {
    return cam_dev_service_map_[cam_id]->ConstructDefaultRequestSettings(type);
  }
  return nullptr;
}

int Camera3Service::Camera3DeviceService::Initialize() {
  Camera3Module cam_module;
  if (cam_module.Initialize() != 0) {
    LOG(ERROR) << "Camera module initialization fails";
    return -ENODEV;
  }
  if (cam_device_.Initialize(&cam_module) != 0) {
    LOG(ERROR) << "Camera device initialization fails";
    return -ENODEV;
  }
  if (!service_thread_.Start()) {
    LOG(ERROR) << "Failed to start thread";
    return -EINVAL;
  }
  cam_device_.RegisterResultMetadataOutputBufferCallback(base::Bind(
      &Camera3Service::Camera3DeviceService::ProcessResultMetadataOutputBuffers,
      base::Unretained(this)));
  repeating_preview_metadata_.reset(clone_camera_metadata(
      cam_device_.ConstructDefaultRequestSettings(CAMERA3_TEMPLATE_PREVIEW)));
  if (!repeating_preview_metadata_) {
    LOG(ERROR) << "Failed to create preview metadata";
    return -ENOMEM;
  }
  sem_init(&preview_frame_sem_, 0, 0);
  return 0;
}

void Camera3Service::Camera3DeviceService::Destroy() {
  service_thread_.Stop();
  sem_destroy(&preview_frame_sem_);
  cam_device_.Destroy();
}

int Camera3Service::Camera3DeviceService::StartPreview(
    const ResolutionInfo& preview_resolution,
    const ResolutionInfo& still_capture_resolution,
    const ResolutionInfo& recording_resolution) {
  VLOGF_ENTER();
  int result = -EIO;
  service_thread_.PostTaskSync(
      FROM_HERE,
      base::Bind(
          &Camera3Service::Camera3DeviceService::StartPreviewOnServiceThread,
          base::Unretained(this), preview_resolution, still_capture_resolution,
          recording_resolution, &result));
  return result;
}

void Camera3Service::Camera3DeviceService::StopPreview() {
  VLOGF_ENTER();
  auto future = cros::Future<void>::Create(nullptr);
  service_thread_.PostTaskAsync(
      FROM_HERE,
      base::Bind(
          &Camera3Service::Camera3DeviceService::StopPreviewOnServiceThread,
          base::Unretained(this), cros::GetFutureCallback(future)));
  if (!future->Wait(kWaitForStopPreviewTimeoutMs)) {
    LOG(ERROR) << "Timeout stopping preview";
  }
}

void Camera3Service::Camera3DeviceService::StartAutoFocus() {
  service_thread_.PostTaskAsync(
      FROM_HERE,
      base::Bind(
          &Camera3Service::Camera3DeviceService::StartAutoFocusOnServiceThread,
          base::Unretained(this)));
}

int Camera3Service::Camera3DeviceService::WaitForAutoFocusDone() {
  VLOGF_ENTER();
  auto future = cros::Future<void>::Create(nullptr);
  int32_t result;
  service_thread_.PostTaskAsync(
      FROM_HERE, base::Bind(&Camera3Service::Camera3DeviceService::
                                AddMetadataListenerOnServiceThread,
                            base::Unretained(this), ANDROID_CONTROL_AF_STATE,
                            std::unordered_set<int32_t>(
                                {ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED,
                                 ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED}),
                            cros::GetFutureCallback(future), &result));
  if (!future->Wait(GetWaitForFocusDoneTimeoutMs())) {
    service_thread_.PostTaskSync(
        FROM_HERE,
        base::Bind(&Camera3Service::Camera3DeviceService::
                       DeleteMetadataListenerOnServiceThread,
                   base::Unretained(this), ANDROID_CONTROL_AF_STATE,
                   std::unordered_set<int32_t>(
                       {ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED,
                        ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED})));
    return -ETIMEDOUT;
  }
  if (result == ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) {
    VLOGF(1) << "Auto-focus did not lock";
  }
  return 0;
}

int Camera3Service::Camera3DeviceService::WaitForAWBConvergedAndLock() {
  VLOGF_ENTER();
  auto future = cros::Future<void>::Create(nullptr);
  service_thread_.PostTaskAsync(
      FROM_HERE, base::Bind(&Camera3Service::Camera3DeviceService::
                                AddMetadataListenerOnServiceThread,
                            base::Unretained(this), ANDROID_CONTROL_AWB_STATE,
                            std::unordered_set<int32_t>(
                                {ANDROID_CONTROL_AWB_STATE_CONVERGED}),
                            cros::GetFutureCallback(future), nullptr));
  if (!future->Wait(GetWaitForAWBConvergedTimeoutMs())) {
    service_thread_.PostTaskSync(
        FROM_HERE, base::Bind(&Camera3Service::Camera3DeviceService::
                                  DeleteMetadataListenerOnServiceThread,
                              base::Unretained(this), ANDROID_CONTROL_AWB_STATE,
                              std::unordered_set<int32_t>(
                                  {ANDROID_CONTROL_AWB_STATE_CONVERGED})));
    return -ETIMEDOUT;
  }

  if (cam_device_.GetStaticInfo()->IsAWBLockSupported()) {
    service_thread_.PostTaskAsync(
        FROM_HERE,
        base::Bind(
            &Camera3Service::Camera3DeviceService::LockAWBOnServiceThread,
            base::Unretained(this)));
  }
  return 0;
}

void Camera3Service::Camera3DeviceService::StartAEPrecapture() {
  VLOGF_ENTER();
  service_thread_.PostTaskAsync(
      FROM_HERE, base::Bind(&Camera3Service::Camera3DeviceService::
                                StartAEPrecaptureOnServiceThread,
                            base::Unretained(this)));
}

int Camera3Service::Camera3DeviceService::WaitForAEStable() {
  VLOGF_ENTER();
  auto future = cros::Future<void>::Create(nullptr);
  int32_t result;
  service_thread_.PostTaskAsync(
      FROM_HERE, base::Bind(&Camera3Service::Camera3DeviceService::
                                AddMetadataListenerOnServiceThread,
                            base::Unretained(this), ANDROID_CONTROL_AE_STATE,
                            std::unordered_set<int32_t>(
                                {ANDROID_CONTROL_AE_STATE_CONVERGED,
                                 ANDROID_CONTROL_AE_STATE_FLASH_REQUIRED}),
                            cros::GetFutureCallback(future), &result));
  if (!future->Wait(GetWaitForFocusDoneTimeoutMs())) {
    service_thread_.PostTaskSync(
        FROM_HERE, base::Bind(&Camera3Service::Camera3DeviceService::
                                  DeleteMetadataListenerOnServiceThread,
                              base::Unretained(this), ANDROID_CONTROL_AE_STATE,
                              std::unordered_set<int32_t>(
                                  {ANDROID_CONTROL_AE_STATE_CONVERGED,
                                   ANDROID_CONTROL_AE_STATE_FLASH_REQUIRED})));
    return -ETIMEDOUT;
  }
  if (result == ANDROID_CONTROL_AE_STATE_FLASH_REQUIRED) {
    VLOGF(1) << "Flash needs to be fired for good quality still capture";
  }
  return 0;
}

void Camera3Service::Camera3DeviceService::TakeStillCapture(
    const camera_metadata_t* metadata) {
  VLOGF_ENTER();
  auto future = cros::Future<void>::Create(nullptr);
  service_thread_.PostTaskAsync(
      FROM_HERE, base::Bind(&Camera3Service::Camera3DeviceService::
                                TakeStillCaptureOnServiceThread,
                            base::Unretained(this), metadata,
                            cros::GetFutureCallback(future)));
  // Wait for ProcessPreviewRequestOnServiceThread() to finish processing
  // |metadata|
  future->Wait();
}

int Camera3Service::Camera3DeviceService::StartRecording(
    const camera_metadata_t* metadata) {
  VLOGF_ENTER();
  auto future = cros::Future<int>::Create(nullptr);
  service_thread_.PostTaskSync(
      FROM_HERE,
      base::Bind(
          &Camera3Service::Camera3DeviceService::StartRecordingOnServiceThread,
          base::Unretained(this), metadata, cros::GetFutureCallback(future)));
  return future->Wait();
}

void Camera3Service::Camera3DeviceService::StopRecording() {
  VLOGF_ENTER();
  auto future = cros::Future<void>::Create(nullptr);
  service_thread_.PostTaskAsync(
      FROM_HERE,
      base::Bind(
          &Camera3Service::Camera3DeviceService::StopRecordingOnServiceThread,
          base::Unretained(this), cros::GetFutureCallback(future)));
  if (!future->Wait(kWaitForStopRecordingTimeoutMs)) {
    LOG(ERROR) << "Timeout stopping preview";
  }
}

int Camera3Service::Camera3DeviceService::WaitForPreviewFrames(
    uint32_t num_frames, uint32_t timeout_ms) {
  VLOGF_ENTER();
  while (sem_trywait(&preview_frame_sem_) == 0) {
  }
  for (uint32_t i = 0; i < num_frames; ++i) {
    struct timespec timeout = {};
    if (clock_gettime(CLOCK_REALTIME, &timeout)) {
      LOGF(ERROR) << "Failed to get clock time";
      return -errno;
    }
    timeout.tv_sec += timeout_ms / 1000;
    timeout.tv_nsec += (timeout_ms % 1000) * 1000;
    if (sem_timedwait(&preview_frame_sem_, &timeout) != 0) {
      return -errno;
    }
  }
  return 0;
}

const Camera3Device::StaticInfo*
Camera3Service::Camera3DeviceService::GetStaticInfo() const {
  return cam_device_.GetStaticInfo();
}

const camera_metadata_t*
Camera3Service::Camera3DeviceService::ConstructDefaultRequestSettings(
    int type) {
  return cam_device_.ConstructDefaultRequestSettings(type);
}

void Camera3Service::Camera3DeviceService::ProcessResultMetadataOutputBuffers(
    uint32_t frame_number,
    ScopedCameraMetadata metadata,
    std::vector<ScopedBufferHandle> buffers) {
  VLOGF_ENTER();
  service_thread_.PostTaskAsync(
      FROM_HERE,
      base::Bind(&Camera3Service::Camera3DeviceService::
                     ProcessResultMetadataOutputBuffersOnServiceThread,
                 base::Unretained(this), frame_number, base::Passed(&metadata),
                 base::Passed(&buffers)));
}

void Camera3Service::Camera3DeviceService::StartPreviewOnServiceThread(
    const ResolutionInfo preview_resolution,
    const ResolutionInfo still_capture_resolution,
    const ResolutionInfo recording_resolution,
    int* result) {
  DCHECK(service_thread_.IsCurrentThread());
  VLOGF_ENTER();
  if (preview_state_ != PREVIEW_STOPPED) {
    LOG(ERROR) << "Failed to start preview because it is not stopped";
    *result = -EAGAIN;
    return;
  }

  if (still_capture_resolution.Area()) {
    cam_device_.AddOutputStream(
        HAL_PIXEL_FORMAT_BLOB, still_capture_resolution.Width(),
        still_capture_resolution.Height(), CAMERA3_STREAM_ROTATION_0);
  }
  if (recording_resolution.Area()) {
    cam_device_.AddOutputStream(
        HAL_PIXEL_FORMAT_YCbCr_420_888, recording_resolution.Width(),
        recording_resolution.Height(), CAMERA3_STREAM_ROTATION_0);
  }
  cam_device_.AddOutputStream(
      HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, preview_resolution.Width(),
      preview_resolution.Height(), CAMERA3_STREAM_ROTATION_0);
  if (cam_device_.ConfigureStreams(&streams_) != 0) {
    ADD_FAILURE() << "Configuring stream fails";
    *result = -EINVAL;
    return;
  }
  auto GetStream = [this](int format) {
    auto it = std::find_if(streams_.begin(), streams_.end(),
                           [&](const camera3_stream_t* stream) {
                             return (stream->format == format);
                           });
    return (it == streams_.end()) ? nullptr : *it;
  };
  const camera3_stream_t* preview_stream =
      GetStream(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
  const camera3_stream_t* record_stream =
      GetStream(HAL_PIXEL_FORMAT_YCbCr_420_888);
  if (!preview_stream || (recording_resolution.Area() && !record_stream)) {
    ADD_FAILURE() << "Failed to find configured stream";
    *result = -EINVAL;
    return;
  }

  number_of_capture_requests_ = preview_stream->max_buffers;
  if (recording_resolution.Area()) {
    number_of_capture_requests_ =
        std::min(number_of_capture_requests_, record_stream->max_buffers);
  }
  capture_requests_.resize(number_of_capture_requests_);
  output_stream_buffers_ = std::vector<std::vector<camera3_stream_buffer_t>>(
      number_of_capture_requests_,
      std::vector<camera3_stream_buffer_t>(kNumberOfOutputStreamBuffers));
  // Submit initial preview capture requests to fill the HAL pipeline first.
  // Then when a result callback is processed, the corresponding capture
  // request (and output buffer) is recycled and submitted again.
  for (uint32_t i = 0; i < number_of_capture_requests_; i++) {
    std::vector<const camera3_stream_t*> streams(1, preview_stream);
    std::vector<camera3_stream_buffer_t> output_buffers;
    if (cam_device_.AllocateOutputBuffersByStreams(streams, &output_buffers) !=
        0) {
      ADD_FAILURE() << "Failed to allocate output buffer";
      *result = -EINVAL;
      return;
    }
    output_stream_buffers_[i][kPreviewOutputStreamIdx] = output_buffers.front();
    capture_requests_[i] = std::make_pair(
        camera3_capture_request_t{
            .frame_number =
                UINT32_MAX,  // Will be overwritten with correct value
            .settings = repeating_preview_metadata_.get(),
            .input_buffer = NULL,
            .num_output_buffers = 1,
            .output_buffers = output_stream_buffers_[i].data()},
        false);
    ProcessPreviewRequestOnServiceThread();
  }
  preview_state_ = PREVIEW_STARTING;
  *result = 0;
}

void Camera3Service::Camera3DeviceService::StopPreviewOnServiceThread(
    base::Callback<void()> cb) {
  DCHECK(service_thread_.IsCurrentThread());
  VLOGF_ENTER();
  if (preview_state_ != PREVIEW_STARTED && preview_state_ != PREVIEW_STARTING) {
    return;
  }
  preview_state_ = PREVIEW_STOPPING;
  stop_preview_cb_ = cb;
}

void Camera3Service::Camera3DeviceService::StartAutoFocusOnServiceThread() {
  DCHECK(service_thread_.IsCurrentThread());
  uint8_t af_mode = ANDROID_CONTROL_AF_MODE_AUTO;
  EXPECT_EQ(0, UpdateMetadata(ANDROID_CONTROL_AF_MODE, &af_mode, 1,
                              &repeating_preview_metadata_));
  if (!oneshot_preview_metadata_.get()) {
    oneshot_preview_metadata_.reset(
        clone_camera_metadata(repeating_preview_metadata_.get()));
  }
  uint8_t af_trigger = ANDROID_CONTROL_AF_TRIGGER_START;
  EXPECT_EQ(0, UpdateMetadata(ANDROID_CONTROL_AF_TRIGGER, &af_trigger, 1,
                              &oneshot_preview_metadata_));
}

void Camera3Service::Camera3DeviceService::AddMetadataListenerOnServiceThread(
    int32_t key,
    std::unordered_set<int32_t> values,
    base::Callback<void()> cb,
    int32_t* result) {
  DCHECK(service_thread_.IsCurrentThread());
  metadata_listener_list_.emplace_back(key, values, cb, result);
}

void Camera3Service::Camera3DeviceService::
    DeleteMetadataListenerOnServiceThread(int32_t key,
                                          std::unordered_set<int32_t> values) {
  DCHECK(service_thread_.IsCurrentThread());
  for (auto it = metadata_listener_list_.begin();
       it != metadata_listener_list_.end(); it++) {
    if (it->key == key && it->values == values) {
      it = metadata_listener_list_.erase(it);
      break;
    }
  }
}

void Camera3Service::Camera3DeviceService::LockAWBOnServiceThread() {
  DCHECK(service_thread_.IsCurrentThread());
  uint8_t awb_lock = ANDROID_CONTROL_AWB_LOCK_ON;
  EXPECT_EQ(0, UpdateMetadata(ANDROID_CONTROL_AWB_LOCK, &awb_lock, 1,
                              &repeating_preview_metadata_));
}

void Camera3Service::Camera3DeviceService::StartAEPrecaptureOnServiceThread() {
  DCHECK(service_thread_.IsCurrentThread());
  if (!oneshot_preview_metadata_.get()) {
    oneshot_preview_metadata_.reset(
        clone_camera_metadata(repeating_preview_metadata_.get()));
  }
  uint8_t ae_trigger = ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START;
  EXPECT_EQ(0, UpdateMetadata(ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
                              &ae_trigger, 1, &oneshot_preview_metadata_));
}

void Camera3Service::Camera3DeviceService::TakeStillCaptureOnServiceThread(
    const camera_metadata_t* metadata, base::Callback<void()> cb) {
  DCHECK(service_thread_.IsCurrentThread());
  still_capture_metadata_ = metadata;
  still_capture_cb_ = cb;
}

void Camera3Service::Camera3DeviceService::StartRecordingOnServiceThread(
    const camera_metadata_t* metadata, base::Callback<void(int)> cb) {
  DCHECK(service_thread_.IsCurrentThread());
  VLOGF_ENTER();
  if (!metadata) {
    LOG(ERROR) << "Invalid metadata settings";
    cb.Run(-EINVAL);
    return;
  }
  if (preview_state_ != PREVIEW_STARTED) {
    VLOGF(2) << "Preview is not started yet. Retrying...";
    usleep(500);
    service_thread_.PostTaskAsync(
        FROM_HERE, base::Bind(&Camera3Service::Camera3DeviceService::
                                  StartRecordingOnServiceThread,
                              base::Unretained(this), metadata, cb));
    return;
  }
  auto it = std::find_if(
      streams_.begin(), streams_.end(), [](const camera3_stream_t* stream) {
        return (stream->format == HAL_PIXEL_FORMAT_YCbCr_420_888);
      });
  if (it == streams_.end()) {
    ADD_FAILURE() << "Failed to find configured recording stream";
    cb.Run(-EINVAL);
    return;
  }
  const camera3_stream_t* record_stream = *it;

  for (uint32_t i = 0; i < number_of_capture_requests_; i++) {
    std::vector<const camera3_stream_t*> streams(1, record_stream);
    std::vector<camera3_stream_buffer_t> output_buffers;
    if (cam_device_.AllocateOutputBuffersByStreams(streams, &output_buffers) !=
        0) {
      ADD_FAILURE() << "Failed to allocate output buffer";
      cb.Run(-EINVAL);
      return;
    }
    output_stream_buffers_[i][kRecordingOutputStreamIdx] =
        output_buffers.front();
  }
  recording_metadata_ = metadata;
  cb.Run(0);
}

void Camera3Service::Camera3DeviceService::StopRecordingOnServiceThread(
    base::Callback<void()> cb) {
  VLOGF_ENTER();
  recording_metadata_ = nullptr;
  stop_recording_cb_ = cb;
}

void Camera3Service::Camera3DeviceService::
    ProcessPreviewRequestOnServiceThread() {
  DCHECK(service_thread_.IsCurrentThread());
  size_t capture_request_idx = 0;
  for (; capture_request_idx < capture_requests_.size();
       capture_request_idx++) {
    if (!capture_requests_[capture_request_idx].second) {
      break;
    }
  }
  ASSERT_NE(capture_request_idx, capture_requests_.size())
      << "Out of captures requests";
  capture_requests_[capture_request_idx].second = true;
  camera3_capture_request_t* request =
      &capture_requests_[capture_request_idx].first;
  // Initially there is preview stream only
  request->num_output_buffers = 1;
  if (recording_metadata_) {
    request->settings = recording_metadata_;
    ++request->num_output_buffers;
  }
  if (still_capture_metadata_) {
    auto it = std::find_if(streams_.begin(), streams_.end(),
                           [](const camera3_stream_t* stream) {
                             return (stream->format == HAL_PIXEL_FORMAT_BLOB);
                           });
    ASSERT_NE(streams_.end(), it)
        << "Failed to find configured still capture stream";
    const camera3_stream_t* still_capture_stream = *it;
    std::vector<const camera3_stream_t*> streams(1, still_capture_stream);
    std::vector<camera3_stream_buffer_t> output_buffers;
    ASSERT_EQ(
        0, cam_device_.AllocateOutputBuffersByStreams(streams, &output_buffers))
        << "Failed to allocate output buffer";
    request->settings = still_capture_metadata_;
    output_stream_buffers_[capture_request_idx][request->num_output_buffers] =
        output_buffers.front();
    ++request->num_output_buffers;
  }
  if (!recording_metadata_ && !still_capture_metadata_) {
    // Request with one-shot metadata if there is one
    request->settings = oneshot_preview_metadata_.get()
                            ? oneshot_preview_metadata_.get()
                            : repeating_preview_metadata_.get();
  }
  ASSERT_EQ(0, cam_device_.ProcessCaptureRequest(request))
      << "Failed to process capture request";
  ++number_of_in_flight_requests_;
  VLOGF(1) << "Capture request";
  VLOGF(1) << "  Frame " << request->frame_number;
  VLOGF(1) << "  Index " << capture_request_idx;
  for (size_t i = 0; i < request->num_output_buffers; i++) {
    VLOGF(1) << "  Buffer " << *request->output_buffers[i].buffer
             << " (format:" << request->output_buffers[i].stream->format << ","
             << request->output_buffers[i].stream->width << "x"
             << request->output_buffers[i].stream->height << ")";
  }
  VLOGF(1) << "  Settings " << request->settings;
  if (still_capture_metadata_) {
    still_capture_metadata_ = nullptr;
    still_capture_cb_.Run();
  } else if (!recording_metadata_ && !still_capture_metadata_ &&
             oneshot_preview_metadata_.get()) {
    oneshot_preview_metadata_.reset(nullptr);
  }
}

void Camera3Service::Camera3DeviceService::
    ProcessResultMetadataOutputBuffersOnServiceThread(
        uint32_t frame_number,
        ScopedCameraMetadata metadata,
        std::vector<ScopedBufferHandle> buffers) {
  DCHECK(service_thread_.IsCurrentThread());
  --number_of_in_flight_requests_;
  size_t capture_request_idx = 0;
  for (; capture_request_idx < capture_requests_.size();
       capture_request_idx++) {
    if (capture_requests_[capture_request_idx].first.frame_number ==
        frame_number) {
      break;
    }
  }
  ASSERT_NE(capture_request_idx, capture_requests_.size())
      << "Failed to find frame " << frame_number << " in the requests";
  VLOGF(1) << "Capture result";
  VLOGF(1) << "  Frame " << frame_number;
  VLOGF(1) << "  Index " << capture_request_idx;
  // Process result metadata according to listeners
  for (auto it = metadata_listener_list_.begin();
       it != metadata_listener_list_.end();) {
    camera_metadata_ro_entry_t entry;
    if (find_camera_metadata_ro_entry(metadata.get(), it->key, &entry) == 0 &&
        it->values.find(entry.data.i32[0]) != it->values.end()) {
      VLOGF(1) << "Metadata listener gets tag "
               << get_camera_metadata_tag_name(it->key) << " value "
               << entry.data.i32[0];
      if (it->result) {
        *it->result = entry.data.i32[0];
      }
      it->cb.Run();
      it = metadata_listener_list_.erase(it);
    } else {
      it++;
    }
  }
  // Process output buffers and record perf logs. We record preview and video
  // perf logs only if there's no still capture in this result since it is
  // expected to take longer time.
  const bool has_still_capture = std::any_of(
      buffers.begin(), buffers.end(), [](const ScopedBufferHandle& buffer) {
        return Camera3TestGralloc::GetFormat(*buffer) == HAL_PIXEL_FORMAT_BLOB;
      });
  const bool stopping_preview =
      (preview_state_ == PREVIEW_STOPPING) && !still_capture_metadata_;
  bool have_yuv_buffer = false;
  for (auto& it : buffers) {
    VLOGF(1) << "  Buffer " << *it
             << " (format:" << Camera3TestGralloc::GetFormat(*it) << ")";
    switch (Camera3TestGralloc::GetFormat(*it)) {
      case HAL_PIXEL_FORMAT_BLOB:
        Camera3PerfLog::GetInstance()->UpdateFrameEvent(
            cam_id_, frame_number, FrameEvent::STILL_CAPTURE_RESULT,
            base::TimeTicks::Now());
        if (!process_still_capture_result_cb_.is_null()) {
          process_still_capture_result_cb_.Run(
              cam_id_, frame_number, std::move(metadata), std::move(it));
        }
        break;
      case HAL_PIXEL_FORMAT_YCbCr_420_888:
        have_yuv_buffer = true;
        if (!has_still_capture) {
          Camera3PerfLog::GetInstance()->UpdateFrameEvent(
              cam_id_, frame_number, FrameEvent::VIDEO_RECORD_RESULT,
              base::TimeTicks::Now());
        }
        if (!process_recording_result_cb_.is_null()) {
          process_recording_result_cb_.Run(cam_id_, frame_number,
                                           std::move(metadata));
        }
        if (recording_metadata_ && !stopping_preview) {
          // Register buffer back to be used by future requests
          cam_device_.RegisterOutputBuffer(
              *output_stream_buffers_[capture_request_idx]
                                     [kRecordingOutputStreamIdx]
                                         .stream,
              std::move(it));
        }
        break;
      default:
        if (!has_still_capture) {
          Camera3PerfLog::GetInstance()->UpdateFrameEvent(
              cam_id_, frame_number, FrameEvent::PREVIEW_RESULT,
              base::TimeTicks::Now());
        }
        if (!stopping_preview) {
          // Register buffer back to be used by future requests
          cam_device_.RegisterOutputBuffer(
              *output_stream_buffers_[capture_request_idx]
                                     [kPreviewOutputStreamIdx]
                                         .stream,
              std::move(it));
        }
    }
  }
  if (preview_state_ == PREVIEW_STARTING) {
    preview_state_ = PREVIEW_STARTED;
    Camera3PerfLog::GetInstance()->UpdateDeviceEvent(
        cam_id_, DeviceEvent::PREVIEW_STARTED, base::TimeTicks::Now());
  }
  sem_post(&preview_frame_sem_);

  if (!stop_recording_cb_.is_null() && !have_yuv_buffer) {
    stop_recording_cb_.Run();
    stop_recording_cb_.Reset();
  }
  if (stopping_preview) {
    VLOGF(1) << "Stopping preview ... (" << number_of_in_flight_requests_
             << " requests in flight";
    if (number_of_in_flight_requests_ == 0) {
      preview_state_ = PREVIEW_STOPPED;
      stop_preview_cb_.Run();
      stop_preview_cb_.Reset();
    }
    return;
  }
  capture_requests_[capture_request_idx].second = false;
  ProcessPreviewRequestOnServiceThread();
}

}  // namespace camera3_test
