// 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_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
