/*
 * 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_adapter/camera_device_adapter.h"

#include <unistd.h>

#include <algorithm>
#include <map>
#include <set>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/logging.h>
#include <base/timer/elapsed_timer.h>
#include <drm_fourcc.h>
#include <libyuv.h>
#include <mojo/public/cpp/system/platform_handle.h>
#include <sync/sync.h>
#include <system/camera_metadata.h>

#include "common/camera_buffer_handle.h"
#include "cros-camera/common.h"
#include "cros-camera/future.h"
#include "cros-camera/ipc_util.h"
#include "hal_adapter/camera3_callback_ops_delegate.h"
#include "hal_adapter/camera3_device_ops_delegate.h"

namespace cros {

constexpr base::TimeDelta kMonitorTimeDelta = base::TimeDelta::FromSeconds(2);

Camera3CaptureRequest::Camera3CaptureRequest(
    const camera3_capture_request_t& req)
    : settings_(android::CameraMetadata(clone_camera_metadata(req.settings))),
      input_buffer_(*req.input_buffer),
      output_stream_buffers_(req.output_buffers,
                             req.output_buffers + req.num_output_buffers) {
  Camera3CaptureRequest::frame_number = req.frame_number;
  Camera3CaptureRequest::settings = settings_.getAndLock();
  Camera3CaptureRequest::input_buffer = &input_buffer_;
  Camera3CaptureRequest::num_output_buffers = req.num_output_buffers;
  Camera3CaptureRequest::output_buffers = output_stream_buffers_.data();
}

CameraMonitor::CameraMonitor(const std::string& name)
    : name_(name), thread_(name + "Monitor"), is_kicked_(false) {}

void CameraMonitor::StartMonitor() {
  thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&CameraMonitor::StartMonitorOnThread,
                                base::Unretained(this)));
}

void CameraMonitor::Kick() {
  base::AutoLock l(lock_);
  is_kicked_ = true;
}

void CameraMonitor::Attach() {
  if (!thread_.Start()) {
    LOGF(ERROR) << "Monitor thread failed to start";
    return;
  }
  auto future = cros::Future<void>::Create(nullptr);
  thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraMonitor::SetTaskRunnerOnThread,
                     base::Unretained(this), cros::GetFutureCallback(future)));
  future->Wait();
}

void CameraMonitor::Detach() {
  thread_.Stop();
  base::OneShotTimer::Stop();
}

void CameraMonitor::SetTaskRunnerOnThread(base::Callback<void()> callback) {
  DCHECK(thread_.task_runner()->BelongsToCurrentThread());
  base::OneShotTimer::SetTaskRunner(thread_.task_runner());
  callback.Run();
}

void CameraMonitor::StartMonitorOnThread() {
  DCHECK(thread_.task_runner()->BelongsToCurrentThread());
  if (base::OneShotTimer::IsRunning()) {
    base::OneShotTimer::Stop();
  }

  base::OneShotTimer::Start(
      FROM_HERE, kMonitorTimeDelta,
      base::Bind(&CameraMonitor::MonitorTimeout, base::Unretained(this)));
  LOG(INFO) << "Start " << name_ << " monitor";
}

void CameraMonitor::MonitorTimeout() {
  DCHECK(thread_.task_runner()->BelongsToCurrentThread());
  base::AutoLock l(lock_);
  if (is_kicked_) {
    base::OneShotTimer::Start(
        FROM_HERE, kMonitorTimeDelta,
        base::Bind(&CameraMonitor::MonitorTimeout, base::Unretained(this)));
  } else {
    LOGF(WARNING) << "No " << name_ << " for more than " << kMonitorTimeDelta;
  }
  is_kicked_ = false;
}

CameraDeviceAdapter::CameraDeviceAdapter(camera3_device_t* camera_device,
                                         const camera_metadata_t* static_info,
                                         base::Callback<void()> close_callback)
    : camera_device_ops_thread_("CameraDeviceOpsThread"),
      camera_callback_ops_thread_("CameraCallbackOpsThread"),
      fence_sync_thread_("FenceSyncThread"),
      reprocess_effect_thread_("ReprocessEffectThread"),
      notify_error_thread_("NotifyErrorThread"),
      close_callback_(close_callback),
      device_closed_(false),
      camera_device_(camera_device),
      static_info_(static_info),
      zsl_helper_(static_info, &frame_number_mapper_),
      camera_metrics_(CameraMetrics::New()),
      capture_request_monitor_("CaptureRequest"),
      capture_result_monitor_("CaptureResult") {
  VLOGF_ENTER() << ":" << camera_device_;
  camera3_callback_ops_t::process_capture_result = ProcessCaptureResult;
  camera3_callback_ops_t::notify = Notify;
}

CameraDeviceAdapter::~CameraDeviceAdapter() {
  VLOGF_ENTER() << ":" << camera_device_;
  camera_device_ops_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&CameraDeviceAdapter::ResetDeviceOpsDelegateOnThread,
                 base::Unretained(this)));
  camera_callback_ops_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&CameraDeviceAdapter::ResetCallbackOpsDelegateOnThread,
                 base::Unretained(this)));
  camera_device_ops_thread_.Stop();
  camera_callback_ops_thread_.Stop();
}

bool CameraDeviceAdapter::Start(
    HasReprocessEffectVendorTagCallback
        has_reprocess_effect_vendor_tag_callback,
    ReprocessEffectCallback reprocess_effect_callback) {
  if (!camera_device_ops_thread_.Start()) {
    LOGF(ERROR) << "Failed to start CameraDeviceOpsThread";
    return false;
  }
  if (!camera_callback_ops_thread_.Start()) {
    LOGF(ERROR) << "Failed to start CameraCallbackOpsThread";
    return false;
  }
  device_ops_delegate_.reset(new Camera3DeviceOpsDelegate(
      this, camera_device_ops_thread_.task_runner()));
  partial_result_count_ = [&]() {
    camera_metadata_ro_entry entry;
    if (find_camera_metadata_ro_entry(
            static_info_, ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &entry) != 0) {
      return 1;
    }
    return entry.data.i32[0];
  }();
  camera_metadata_inspector_ =
      CameraMetadataInspector::Create(partial_result_count_);
  has_reprocess_effect_vendor_tag_callback_ =
      std::move(has_reprocess_effect_vendor_tag_callback);
  reprocess_effect_callback_ = std::move(reprocess_effect_callback);
  return true;
}

void CameraDeviceAdapter::Bind(
    mojom::Camera3DeviceOpsRequest device_ops_request) {
  device_ops_delegate_->Bind(
      device_ops_request.PassMessagePipe(),
      // Close the device when the Mojo channel breaks.
      base::Bind(base::IgnoreResult(&CameraDeviceAdapter::Close),
                 base::Unretained(this)));
}

int32_t CameraDeviceAdapter::Initialize(
    mojom::Camera3CallbackOpsPtr callback_ops) {
  VLOGF_ENTER();
  if (!fence_sync_thread_.Start()) {
    LOGF(ERROR) << "Fence sync thread failed to start";
    return -ENODEV;
  }
  if (!reprocess_effect_thread_.Start()) {
    LOGF(ERROR) << "Reprocessing effect thread failed to start";
    return -ENODEV;
  }
  if (!notify_error_thread_.Start()) {
    LOGF(ERROR) << "Notify error thread failed to start";
    return -ENODEV;
  }
  capture_request_monitor_.Attach();
  capture_result_monitor_.Attach();
  base::AutoLock l(callback_ops_delegate_lock_);
  // Unlike the camera module, only one peer is allowed to access a camera
  // device at any time.
  DCHECK(!callback_ops_delegate_);
  callback_ops_delegate_.reset(new Camera3CallbackOpsDelegate(
      camera_callback_ops_thread_.task_runner()));
  callback_ops_delegate_->Bind(
      callback_ops.PassInterface(),
      base::Bind(&CameraDeviceAdapter::ResetCallbackOpsDelegateOnThread,
                 base::Unretained(this)));
  return camera_device_->ops->initialize(camera_device_, this);
}

int32_t CameraDeviceAdapter::ConfigureStreams(
    mojom::Camera3StreamConfigurationPtr config,
    mojom::Camera3StreamConfigurationPtr* updated_config) {
  VLOGF_ENTER();

  base::ElapsedTimer timer;

  base::AutoLock l(streams_lock_);

  // Free previous allocated buffers before new allocation.
  FreeAllocatedStreamBuffers();

  internal::ScopedStreams new_streams;
  for (const auto& s : config->streams) {
    LOGF(INFO) << "id = " << s->id << ", type = " << s->stream_type
               << ", size = " << s->width << "x" << s->height
               << ", format = " << s->format;
    uint64_t id = s->id;
    std::unique_ptr<camera3_stream_t>& stream = new_streams[id];
    stream.reset(new camera3_stream_t);
    memset(stream.get(), 0, sizeof(*stream.get()));
    stream->stream_type = static_cast<camera3_stream_type_t>(s->stream_type);
    stream->width = s->width;
    stream->height = s->height;
    stream->format = static_cast<int32_t>(s->format);
    stream->usage = s->usage;
    stream->max_buffers = s->max_buffers;
    stream->data_space = static_cast<android_dataspace_t>(s->data_space);
    stream->rotation = static_cast<camera3_stream_rotation_t>(s->rotation);
    stream->crop_rotate_scale_degrees = 0;
    if (s->crop_rotate_scale_info) {
      stream->crop_rotate_scale_degrees =
          static_cast<camera3_stream_rotation_t>(
              s->crop_rotate_scale_info->crop_rotate_scale_degrees);
    }

    // Currently we are not interest in the resolution of input stream and
    // bidirectional stream.
    if (stream->stream_type == CAMERA3_STREAM_OUTPUT) {
      camera_metrics_->SendConfigureStreamResolution(
          stream->width, stream->height, stream->format);
    }
  }
  streams_.swap(new_streams);
  zsl_helper_.SetZslEnabled(zsl_helper_.CanEnableZsl(streams_));

  camera3_stream_configuration_t stream_list;
  stream_list.num_streams = config->streams.size();
  std::vector<camera3_stream_t*> streams(stream_list.num_streams);
  stream_list.streams = streams.data();
  stream_list.operation_mode =
      static_cast<camera3_stream_configuration_mode_t>(config->operation_mode);
  size_t i = 0;
  for (auto it = streams_.begin(); it != streams_.end(); it++) {
    stream_list.streams[i++] = it->second.get();
  }
  if (zsl_helper_.IsZslEnabled()) {
    zsl_helper_.AttachZslStream(&stream_list, &streams);
    zsl_stream_ = streams.back();
  }

  int32_t result =
      camera_device_->ops->configure_streams(camera_device_, &stream_list);
  if (!result) {
    *updated_config = mojom::Camera3StreamConfiguration::New();
    (*updated_config)->operation_mode = config->operation_mode;
    for (const auto& s : streams_) {
      mojom::Camera3StreamPtr ptr = mojom::Camera3Stream::New();
      ptr->id = s.first;
      ptr->format = static_cast<mojom::HalPixelFormat>(s.second->format);
      ptr->width = s.second->width;
      ptr->height = s.second->height;
      ptr->stream_type =
          static_cast<mojom::Camera3StreamType>(s.second->stream_type);
      ptr->data_space = s.second->data_space;
      // HAL should only change usage and max_buffers.
      ptr->usage = s.second->usage;
      ptr->max_buffers = s.second->max_buffers;
      ptr->crop_rotate_scale_info = mojom::CropRotateScaleInfo::New(
          static_cast<mojom::Camera3StreamRotation>(
              s.second->crop_rotate_scale_degrees));
      (*updated_config)->streams.push_back(std::move(ptr));
    }
    capture_request_monitor_.StartMonitor();
    capture_result_monitor_.StartMonitor();
  }

  camera_metrics_->SendConfigureStreamsLatency(timer.Elapsed());

  return result;
}

mojom::CameraMetadataPtr CameraDeviceAdapter::ConstructDefaultRequestSettings(
    mojom::Camera3RequestTemplate type) {
  VLOGF_ENTER();
  const camera_metadata_t* metadata =
      camera_device_->ops->construct_default_request_settings(
          camera_device_, static_cast<int32_t>(type));
  return internal::SerializeCameraMetadata(metadata);
}

int32_t CameraDeviceAdapter::ProcessCaptureRequest(
    mojom::Camera3CaptureRequestPtr request) {
  VLOGF_ENTER();

  // Complete the pending reprocess request first if exists. We need to
  // prioritize reprocess requests because CCA can be waiting for the
  // reprocessed picture before unblocking UI.
  {
    base::AutoLock lock(process_reprocess_request_callback_lock_);
    if (!process_reprocess_request_callback_.is_null())
      std::move(process_reprocess_request_callback_).Run();
  }
  if (!request) {
    return 0;
  }

  camera3_capture_request_t req;
  req.frame_number =
      frame_number_mapper_.GetHalFrameNumber(request->frame_number);

  internal::ScopedCameraMetadata settings =
      internal::DeserializeCameraMetadata(request->settings);

  capture_request_monitor_.Kick();

  // Deserialize input buffer.
  buffer_handle_t input_buffer_handle;
  camera3_stream_buffer_t input_buffer;
  if (!request->input_buffer.is_null()) {
    base::AutoLock streams_lock(streams_lock_);
    base::AutoLock buffer_handles_lock(buffer_handles_lock_);
    if (request->input_buffer->buffer_handle) {
      if (RegisterBufferLocked(
              std::move(request->input_buffer->buffer_handle))) {
        LOGF(ERROR) << "Failed to register input buffer";
        return -EINVAL;
      }
    }
    input_buffer.buffer =
        const_cast<const native_handle_t**>(&input_buffer_handle);
    internal::DeserializeStreamBuffer(request->input_buffer, streams_,
                                      buffer_handles_, &input_buffer);
    req.input_buffer = &input_buffer;
  } else {
    req.input_buffer = nullptr;
  }

  // Deserialize output buffers.
  size_t num_output_buffers = request->output_buffers.size();
  DCHECK_GT(num_output_buffers, 0);

  std::vector<camera3_stream_buffer_t> output_buffers(num_output_buffers);
  std::vector<camera3_stream_buffer_t> still_output_buffers;
  camera3_capture_request_t still_req{.num_output_buffers = 0};
  {
    base::AutoLock streams_lock(streams_lock_);
    base::AutoLock buffer_handles_lock(buffer_handles_lock_);
    for (size_t i = 0; i < num_output_buffers; ++i) {
      mojom::Camera3StreamBufferPtr& out_buf_ptr = request->output_buffers[i];
      if (out_buf_ptr->buffer_handle) {
        if (RegisterBufferLocked(std::move(out_buf_ptr->buffer_handle))) {
          LOGF(ERROR) << "Failed to register output buffer";
          return -EINVAL;
        }
      }
      internal::DeserializeStreamBuffer(out_buf_ptr, streams_, buffer_handles_,
                                        &output_buffers.at(i));
    }
    if (zsl_helper_.IsZslEnabled()) {
      zsl_helper_.ProcessZslCaptureRequest(
          request->frame_number, &req, &output_buffers, &settings, &still_req,
          &still_output_buffers, ZslHelper::SelectionStrategy::CLOSEST_3A);
    }
    req.num_output_buffers = output_buffers.size();
    req.output_buffers =
        const_cast<const camera3_stream_buffer_t*>(output_buffers.data());
  }

  req.settings = settings.get();

  if (camera_metadata_inspector_) {
    camera_metadata_inspector_->InspectRequest(&req);
  }

  // Apply reprocessing effects
  if (req.input_buffer &&
      has_reprocess_effect_vendor_tag_callback_.Run(*req.settings)) {
    VLOGF(1) << "Applying reprocessing effects on input buffer";
    // Run reprocessing effect asynchronously so that it does not block other
    // requests.  It introduces a risk that buffers of the same stream may be
    // returned out of order.  Since CTS would not go this way and GCA would
    // not mix reprocessing effect captures with normal ones, it should be
    // fine.
    auto req_ptr = std::make_unique<Camera3CaptureRequest>(req);
    reprocess_effect_thread_.task_runner()->PostTask(
        FROM_HERE,
        base::Bind(
            &CameraDeviceAdapter::ReprocessEffectsOnReprocessEffectThread,
            base::Unretained(this), base::Passed(&req_ptr)));
    return 0;
  }

  int ret_split;
  bool is_request_split = still_req.num_output_buffers > 0;
  if (is_request_split) {
    // Swap frame numbers to send the split still capture request first.
    // When merging the capture results, the shutter message and result metadata
    // of the second preview capture request will be trimmed, which is safe
    // because we don't reprocess preview frames.
    std::swap(req.frame_number, still_req.frame_number);
    frame_number_mapper_.RegisterCaptureRequest(&still_req, is_request_split,
                                                /*is_request_added=*/false);
    ret_split = camera_device_->ops->process_capture_request(camera_device_,
                                                             &still_req);
    free_camera_metadata(const_cast<camera_metadata_t*>(still_req.settings));
    if (ret_split != 0) {
      LOGF(ERROR) << "Failed to process split still capture request";
      return ret_split;
    }
  }

  frame_number_mapper_.RegisterCaptureRequest(
      &req, is_request_split, /*is_request_added=*/is_request_split);
  int ret = camera_device_->ops->process_capture_request(camera_device_, &req);

  if (is_request_split) {
    // No need to process -ENODEV here since it's not recoverable.
    if (ret == -EINVAL) {
      NotifyAddedFrameError(std::move(still_req),
                            std::move(still_output_buffers));
    }
    // Any errors occurred in the split request are handled separately.
    return 0;
  }
  return ret;
}

void CameraDeviceAdapter::Dump(mojo::ScopedHandle fd) {
  VLOGF_ENTER();
  base::ScopedFD dump_fd(mojo::UnwrapPlatformHandle(std::move(fd)).TakeFD());
  camera_device_->ops->dump(camera_device_, dump_fd.get());
}

int32_t CameraDeviceAdapter::Flush() {
  VLOGF_ENTER();
  return camera_device_->ops->flush(camera_device_);
}

static bool IsMatchingFormat(mojom::HalPixelFormat hal_pixel_format,
                             uint32_t drm_format) {
  switch (hal_pixel_format) {
    case mojom::HalPixelFormat::HAL_PIXEL_FORMAT_RGBA_8888:
      return drm_format == DRM_FORMAT_ABGR8888;
    case mojom::HalPixelFormat::HAL_PIXEL_FORMAT_RGBX_8888:
      return drm_format == DRM_FORMAT_XBGR8888;
    case mojom::HalPixelFormat::HAL_PIXEL_FORMAT_BGRA_8888:
      return drm_format == DRM_FORMAT_ARGB8888;
    case mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCrCb_420_SP:
      return drm_format == DRM_FORMAT_NV21;
    case mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_422_I:
      return drm_format == DRM_FORMAT_YUYV;
    case mojom::HalPixelFormat::HAL_PIXEL_FORMAT_BLOB:
      return drm_format == DRM_FORMAT_R8;
    case mojom::HalPixelFormat::HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
      // We can't really check implementation defined formats.
      return true;
    case mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888:
      return (drm_format == DRM_FORMAT_YUV420 ||
              drm_format == DRM_FORMAT_YVU420 ||
              drm_format == DRM_FORMAT_NV21 || drm_format == DRM_FORMAT_NV12);
    case mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YV12:
      return drm_format == DRM_FORMAT_YVU420;
  }
  return false;
}

int32_t CameraDeviceAdapter::RegisterBuffer(
    uint64_t buffer_id,
    mojom::Camera3DeviceOps::BufferType type,
    std::vector<mojo::ScopedHandle> fds,
    uint32_t drm_format,
    mojom::HalPixelFormat hal_pixel_format,
    uint32_t width,
    uint32_t height,
    const std::vector<uint32_t>& strides,
    const std::vector<uint32_t>& offsets) {
  base::AutoLock l(buffer_handles_lock_);
  return CameraDeviceAdapter::RegisterBufferLocked(
      buffer_id, type, std::move(fds), drm_format, hal_pixel_format, width,
      height, strides, offsets);
}

int32_t CameraDeviceAdapter::Close() {
  // Close the device.
  VLOGF_ENTER();
  if (device_closed_) {
    return 0;
  }
  reprocess_effect_thread_.Stop();
  notify_error_thread_.Stop();
  int32_t ret = camera_device_->common.close(&camera_device_->common);
  device_closed_ = true;
  DCHECK_EQ(ret, 0);
  fence_sync_thread_.Stop();
  capture_request_monitor_.Detach();
  capture_result_monitor_.Detach();

  FreeAllocatedStreamBuffers();

  close_callback_.Run();
  return ret;
}

int32_t CameraDeviceAdapter::ConfigureStreamsAndGetAllocatedBuffers(
    mojom::Camera3StreamConfigurationPtr config,
    mojom::Camera3StreamConfigurationPtr* updated_config,
    AllocatedBuffers* allocated_buffers) {
  VLOGF_ENTER();
  int32_t result = ConfigureStreams(std::move(config), updated_config);

  // Early return if configure streams failed.
  if (result) {
    return result;
  }

  bool is_success =
      AllocateBuffersForStreams((*updated_config)->streams, allocated_buffers);

  if (!is_success) {
    FreeAllocatedStreamBuffers();
  }

  return result;
}

// static
void CameraDeviceAdapter::ProcessCaptureResult(
    const camera3_callback_ops_t* ops, const camera3_capture_result_t* result) {
  VLOGF_ENTER();
  CameraDeviceAdapter* self = const_cast<CameraDeviceAdapter*>(
      static_cast<const CameraDeviceAdapter*>(ops));

  self->capture_result_monitor_.Kick();

  camera3_capture_result_t res = *result;
  camera3_stream_buffer_t in_buf = {};
  mojom::Camera3CaptureResultPtr result_ptr;
  {
    base::AutoLock reprocess_handles_lock(self->reprocess_handles_lock_);
    if (result->input_buffer && !self->reprocess_handles_.empty() &&
        *result->input_buffer->buffer ==
            *self->reprocess_handles_.front().GetHandle()) {
      in_buf = *result->input_buffer;
      // Restore original input buffer
      base::AutoLock buffer_handles_lock(self->buffer_handles_lock_);
      in_buf.buffer =
          &self->buffer_handles_.at(self->input_buffer_handle_ids_.front())
               ->self;
      self->reprocess_handles_.pop_front();
      self->input_buffer_handle_ids_.pop_front();
      res.input_buffer = &in_buf;
    }
  }
  {
    base::AutoLock reprocess_result_metadata_lock(
        self->reprocess_result_metadata_lock_);
    auto it = self->reprocess_result_metadata_.find(res.frame_number);
    if (it != self->reprocess_result_metadata_.end() && !it->second.isEmpty() &&
        res.result != nullptr) {
      it->second.append(res.result);
      res.result = it->second.getAndLock();
    }
    result_ptr = self->PrepareCaptureResult(&res);
    if (res.result != nullptr) {
      self->reprocess_result_metadata_.erase(res.frame_number);
    }
  }

  if (!result_ptr->result->entries.has_value() &&
      !result_ptr->output_buffers.has_value() &&
      result_ptr->input_buffer.is_null()) {
    // Android camera framework doesn't accept empty capture results. Since ZSL
    // would remove the input buffer, output buffers and metadata it added, it's
    // possible that we end up with an empty capture result.
    return;
  }

  base::AutoLock l(self->callback_ops_delegate_lock_);
  if (self->callback_ops_delegate_) {
    if (self->camera_metadata_inspector_) {
      self->camera_metadata_inspector_->InspectResult(result);
    }
    self->callback_ops_delegate_->ProcessCaptureResult(std::move(result_ptr));
  }
}

// static
void CameraDeviceAdapter::Notify(const camera3_callback_ops_t* ops,
                                 const camera3_notify_msg_t* msg) {
  VLOGF_ENTER();
  CameraDeviceAdapter* self = const_cast<CameraDeviceAdapter*>(
      static_cast<const CameraDeviceAdapter*>(ops));
  std::vector<camera3_notify_msg_t> msgs;
  self->PreprocessNotifyMsg(msg, &msgs);
  if (msgs.size() == 0) {
    LOGF(INFO) << "Trimmed a Notify() call";
    return;
  }
  for (auto& msg : msgs) {
    mojom::Camera3NotifyMsgPtr msg_ptr = self->PrepareNotifyMsg(&msg);
    base::AutoLock l(self->callback_ops_delegate_lock_);
    if (msg.type == CAMERA3_MSG_ERROR) {
      self->camera_metrics_->SendError(msg.message.error.error_code);
    }
    if (self->callback_ops_delegate_) {
      self->callback_ops_delegate_->Notify(std::move(msg_ptr));
    }
    if (msg.type == CAMERA3_MSG_ERROR &&
        msg.message.error.error_code == CAMERA3_MSG_ERROR_DEVICE) {
      LOGF(ERROR) << "Fatal device error; aborting the camera service";
      _exit(EIO);
    }
  }
}

bool CameraDeviceAdapter::AllocateBuffersForStreams(
    const std::vector<mojom::Camera3StreamPtr>& streams,
    AllocatedBuffers* allocated_buffers) {
  AllocatedBuffers tmp_allocated_buffers;
  auto* camera_buffer_manager = CameraBufferManager::GetInstance();
  for (const auto& stream : streams) {
    std::vector<mojom::Camera3StreamBufferPtr> new_buffers;
    uint32_t stream_format = static_cast<uint32_t>(stream->format);
    uint64_t stream_id = stream->id;
    DCHECK(stream_format == HAL_PIXEL_FORMAT_BLOB ||
           stream_format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED ||
           stream_format == HAL_PIXEL_FORMAT_YCbCr_420_888);
    uint32_t buffer_width;
    uint32_t buffer_height;
    int status;
    if (stream_format == HAL_PIXEL_FORMAT_BLOB) {
      camera_metadata_ro_entry entry;
      status = find_camera_metadata_ro_entry(static_info_,
                                             ANDROID_JPEG_MAX_SIZE, &entry);
      if (status) {
        LOG(ERROR) << "No Jpeg max size information in metadata.";
        return false;
      }
      buffer_width = entry.data.i32[0];
      buffer_height = 1;
    } else {
      buffer_width = stream->width;
      buffer_height = stream->height;
    }
    for (size_t i = 0; i < stream->max_buffers; i++) {
      mojom::Camera3StreamBufferPtr new_buffer =
          mojom::Camera3StreamBuffer::New();
      new_buffer->stream_id = stream_id;

      mojom::CameraBufferHandlePtr mojo_buffer_handle =
          mojom::CameraBufferHandle::New();

      buffer_handle_t buffer_handle;
      uint32_t buffer_stride;
      status = camera_buffer_manager->Allocate(
          buffer_width, buffer_height, stream_format, stream->usage,
          BufferType::GRALLOC, &buffer_handle, &buffer_stride);
      if (status) {
        LOGF(ERROR) << "Failed to allocate buffer.";
        return false;
      }

      mojo_buffer_handle->width = buffer_width;
      mojo_buffer_handle->height = buffer_height;
      mojo_buffer_handle->drm_format =
          camera_buffer_manager->ResolveDrmFormat(stream_format, stream->usage);
      CHECK_NE(mojo_buffer_handle->drm_format, 0);

      auto num_planes = CameraBufferManager::GetNumPlanes(buffer_handle);
      mojo_buffer_handle->sizes = std::vector<uint32_t>();
      for (size_t plane = 0; plane < num_planes; plane++) {
        mojo_buffer_handle->fds.push_back(
            mojo::WrapPlatformFile(buffer_handle->data[plane]));
        mojo_buffer_handle->strides.push_back(
            CameraBufferManager::GetPlaneStride(buffer_handle, plane));
        mojo_buffer_handle->offsets.push_back(
            CameraBufferManager::GetPlaneOffset(buffer_handle, plane));
        mojo_buffer_handle->sizes->push_back(
            CameraBufferManager::GetPlaneSize(buffer_handle, plane));
      }

      auto* camera_buffer_handle =
          camera_buffer_handle_t::FromBufferHandle(buffer_handle);
      uint64_t buffer_id = camera_buffer_handle->buffer_id;
      mojo_buffer_handle->buffer_id = buffer_id;
      mojo_buffer_handle->hal_pixel_format = stream->format;

      new_buffer->buffer_id = buffer_id;
      new_buffer->buffer_handle = std::move(mojo_buffer_handle);
      new_buffers.push_back(std::move(new_buffer));

      allocated_stream_buffers_[buffer_id] = std::move(buffer_handle);
    }
    tmp_allocated_buffers.insert(
        std::pair<uint64_t, std::vector<mojom::Camera3StreamBufferPtr>>(
            stream_id, std::move(new_buffers)));
  }
  *allocated_buffers = std::move(tmp_allocated_buffers);
  return true;
}

void CameraDeviceAdapter::FreeAllocatedStreamBuffers() {
  auto camera_buffer_manager = CameraBufferManager::GetInstance();
  if (allocated_stream_buffers_.empty()) {
    return;
  }

  for (auto it : allocated_stream_buffers_) {
    camera_buffer_manager->Free(it.second);
  }
  allocated_stream_buffers_.clear();
}

int32_t CameraDeviceAdapter::RegisterBufferLocked(
    uint64_t buffer_id,
    mojom::Camera3DeviceOps::BufferType type,
    std::vector<mojo::ScopedHandle> fds,
    uint32_t drm_format,
    mojom::HalPixelFormat hal_pixel_format,
    uint32_t width,
    uint32_t height,
    const std::vector<uint32_t>& strides,
    const std::vector<uint32_t>& offsets) {
  if (!IsMatchingFormat(hal_pixel_format, drm_format)) {
    LOG(ERROR) << "HAL pixel format " << hal_pixel_format
               << " does not match DRM format " << FormatToString(drm_format);
    return -EINVAL;
  }
  size_t num_planes = fds.size();

  std::unique_ptr<camera_buffer_handle_t> buffer_handle =
      std::make_unique<camera_buffer_handle_t>();
  buffer_handle->base.version = sizeof(buffer_handle->base);
  buffer_handle->base.numFds = kCameraBufferHandleNumFds;
  buffer_handle->base.numInts = kCameraBufferHandleNumInts;

  buffer_handle->magic = kCameraBufferMagic;
  buffer_handle->buffer_id = buffer_id;
  buffer_handle->type = static_cast<int32_t>(type);
  buffer_handle->drm_format = drm_format;
  buffer_handle->hal_pixel_format = static_cast<uint32_t>(hal_pixel_format);
  buffer_handle->width = width;
  buffer_handle->height = height;
  for (size_t i = 0; i < num_planes; ++i) {
    buffer_handle->fds[i] =
        mojo::UnwrapPlatformHandle(std::move(fds[i])).ReleaseFD();
    buffer_handle->strides[i] = strides[i];
    buffer_handle->offsets[i] = offsets[i];
  }
  buffer_handles_[buffer_id] = std::move(buffer_handle);

  VLOGF(1) << std::hex << "Buffer 0x" << buffer_id << " registered: "
           << "format: " << FormatToString(drm_format)
           << " dimension: " << std::dec << width << "x" << height
           << " num_planes: " << num_planes;
  return 0;
}

int32_t CameraDeviceAdapter::RegisterBufferLocked(
    mojom::CameraBufferHandlePtr buffer) {
  return RegisterBufferLocked(
      buffer->buffer_id, mojom::Camera3DeviceOps::BufferType::GRALLOC,
      std::move(buffer->fds), buffer->drm_format, buffer->hal_pixel_format,
      buffer->width, buffer->height, buffer->strides, buffer->offsets);
}

mojom::Camera3CaptureResultPtr CameraDeviceAdapter::PrepareCaptureResult(
    const camera3_capture_result_t* result) {
  mojom::Camera3CaptureResultPtr r = mojom::Camera3CaptureResult::New();

  r->frame_number =
      frame_number_mapper_.GetFrameworkFrameNumber(result->frame_number);

  frame_number_mapper_.RegisterCaptureResult(result, partial_result_count_);

  const camera3_stream_buffer_t* attached_output = nullptr;
  const camera3_stream_buffer_t* transformed_input = nullptr;
  if (zsl_helper_.IsZslEnabled()) {
    base::AutoLock streams_lock(streams_lock_);
    base::AutoLock buffer_handles_lock(buffer_handles_lock_);
    zsl_helper_.ProcessZslCaptureResult(result, &attached_output,
                                        &transformed_input);
  }

  if (frame_number_mapper_.IsAddedFrame(result->frame_number)) {
    // We use the metadata from the sister frame.
    LOGF(INFO) << "Trimming metadata for " << result->frame_number
               << " (framework frame number = " << r->frame_number << ")";
    r->result = cros::mojom::CameraMetadata::New();
    r->partial_result = 0;
  } else {
    r->result = internal::SerializeCameraMetadata(result->result);
    r->partial_result = result->partial_result;
  }

  // Serialize output buffers.  This may be none as num_output_buffers may be 0.
  if (result->output_buffers) {
    base::AutoLock streams_lock(streams_lock_);
    base::AutoLock buffer_handles_lock(buffer_handles_lock_);
    std::vector<mojom::Camera3StreamBufferPtr> output_buffers;
    for (size_t i = 0; i < result->num_output_buffers; i++) {
      if (result->output_buffers + i == attached_output) {
        continue;
      }
      mojom::Camera3StreamBufferPtr out_buf = internal::SerializeStreamBuffer(
          result->output_buffers + i, streams_, buffer_handles_);
      if (out_buf.is_null()) {
        LOGF(ERROR) << "Failed to serialize output stream buffer";
        // TODO(jcliang): Handle error?
      }
      buffer_handles_[out_buf->buffer_id]->state = kReturned;
      RemoveBufferLocked(*(result->output_buffers + i));
      output_buffers.push_back(std::move(out_buf));
    }
    if (output_buffers.size() > 0) {
      r->output_buffers = std::move(output_buffers);
    }
  }

  // Serialize input buffer.
  if (result->input_buffer && result->input_buffer != transformed_input) {
    base::AutoLock streams_lock(streams_lock_);
    base::AutoLock buffer_handles_lock(buffer_handles_lock_);
    mojom::Camera3StreamBufferPtr input_buffer =
        internal::SerializeStreamBuffer(result->input_buffer, streams_,
                                        buffer_handles_);
    if (input_buffer.is_null()) {
      LOGF(ERROR) << "Failed to serialize input stream buffer";
    }
    buffer_handles_[input_buffer->buffer_id]->state = kReturned;
    RemoveBufferLocked(*result->input_buffer);
    r->input_buffer = std::move(input_buffer);
  }

  return r;
}

void CameraDeviceAdapter::PreprocessNotifyMsg(
    const camera3_notify_msg_t* msg, std::vector<camera3_notify_msg_t>* msgs) {
  frame_number_mapper_.PreprocessNotifyMsg(msg, msgs, zsl_stream_);
}

mojom::Camera3NotifyMsgPtr CameraDeviceAdapter::PrepareNotifyMsg(
    const camera3_notify_msg_t* msg) {
  // Fill in the data from msg...
  mojom::Camera3NotifyMsgPtr m = mojom::Camera3NotifyMsg::New();
  m->type = static_cast<mojom::Camera3MsgType>(msg->type);
  m->message = mojom::Camera3NotifyMsgMessage::New();

  if (msg->type == CAMERA3_MSG_ERROR) {
    mojom::Camera3ErrorMsgPtr error = mojom::Camera3ErrorMsg::New();
    error->frame_number = msg->message.error.frame_number;
    uint64_t stream_id = 0;
    {
      base::AutoLock l(streams_lock_);
      for (const auto& s : streams_) {
        if (s.second.get() == msg->message.error.error_stream) {
          stream_id = s.first;
          break;
        }
      }
    }
    error->error_stream_id = stream_id;
    error->error_code =
        static_cast<mojom::Camera3ErrorMsgCode>(msg->message.error.error_code);
    m->message->set_error(std::move(error));
  } else if (msg->type == CAMERA3_MSG_SHUTTER) {
    mojom::Camera3ShutterMsgPtr shutter = mojom::Camera3ShutterMsg::New();
    shutter->frame_number = msg->message.shutter.frame_number;
    shutter->timestamp = msg->message.shutter.timestamp;
    m->message->set_shutter(std::move(shutter));
  } else {
    LOGF(ERROR) << "Invalid notify message type: " << msg->type;
  }

  return m;
}

void CameraDeviceAdapter::RemoveBufferLocked(
    const camera3_stream_buffer_t& buffer) {
  buffer_handles_lock_.AssertAcquired();
  int release_fence = buffer.release_fence;
  base::ScopedFD scoped_release_fence;
  if (release_fence != -1) {
    release_fence = dup(release_fence);
    if (release_fence == -1) {
      PLOGF(ERROR) << "Failed to dup release_fence";
      return;
    }
    scoped_release_fence.reset(release_fence);
  }

  // Remove the allocated camera buffer handle from |buffer_handles_| and
  // pass it to RemoveBufferOnFenceSyncThread. The buffer handle will be
  // freed after the release fence is signalled.
  const camera_buffer_handle_t* handle =
      camera_buffer_handle_t::FromBufferHandle(*(buffer.buffer));
  if (!handle) {
    return;
  }
  // Remove the buffer handle from |buffer_handles_| now to avoid a race
  // condition where the process_capture_request sends down an existing buffer
  // handle which hasn't been removed in RemoveBufferHandleOnFenceSyncThread.
  uint64_t buffer_id = handle->buffer_id;
  if (buffer_handles_[buffer_id]->state == kRegistered) {
    // Framework registered a new buffer with the same |buffer_id| before we
    // remove the old buffer handle from |buffer_handles_|.
    return;
  }
  std::unique_ptr<camera_buffer_handle_t> buffer_handle;
  buffer_handles_[buffer_id].swap(buffer_handle);
  buffer_handles_.erase(buffer_id);

  fence_sync_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&CameraDeviceAdapter::RemoveBufferOnFenceSyncThread,
                 base::Unretained(this), base::Passed(&scoped_release_fence),
                 base::Passed(&buffer_handle)));
}

void CameraDeviceAdapter::RemoveBufferOnFenceSyncThread(
    base::ScopedFD release_fence,
    std::unique_ptr<camera_buffer_handle_t> buffer) {
  // In theory the release fence should be signaled by HAL as soon as possible,
  // and we could just set a large value for the timeout.  The timeout here is
  // set to 3 ms to allow testing multiple fences in round-robin if there are
  // multiple active buffers.
  const int kSyncWaitTimeoutMs = 3;
  const camera_buffer_handle_t* handle = buffer.get();
  DCHECK(handle);

  if (!release_fence.is_valid() ||
      !sync_wait(release_fence.get(), kSyncWaitTimeoutMs)) {
    VLOGF(1) << "Buffer 0x" << std::hex << handle->buffer_id << " removed";
  } else {
    // sync_wait() timeout. Reschedule and try to remove the buffer again.
    VLOGF(2) << "Release fence sync_wait() timeout on buffer 0x" << std::hex
             << handle->buffer_id;
    fence_sync_thread_.task_runner()->PostTask(
        FROM_HERE,
        base::Bind(&CameraDeviceAdapter::RemoveBufferOnFenceSyncThread,
                   base::Unretained(this), base::Passed(&release_fence),
                   base::Passed(&buffer)));
  }
}

void CameraDeviceAdapter::ReprocessEffectsOnReprocessEffectThread(
    std::unique_ptr<Camera3CaptureRequest> req) {
  VLOGF_ENTER();
  camera3_stream_t* input_stream = req->input_buffer->stream;
  camera3_stream_t* output_stream = req->output_buffers[0].stream;
  // Here we assume reprocessing effects can provide only one output of the
  // same size and format as that of input. Invoke HAL reprocessing if more
  // outputs, scaling and/or format conversion are required since ISP
  // may provide hardware acceleration for these operations.
  bool need_hal_reprocessing =
      (req->num_output_buffers != 1) ||
      (input_stream->width != req->output_buffers[0].stream->width) ||
      (input_stream->height != req->output_buffers[0].stream->height) ||
      (input_stream->format != req->output_buffers[0].stream->format);

  struct ReprocessContext {
    ReprocessContext(CameraDeviceAdapter* d,
                     const Camera3CaptureRequest* r,
                     bool n)
        : result(0),
          device_adapter(d),
          capture_request(r),
          need_hal_reprocessing(n) {}

    ~ReprocessContext() {
      if (result != 0) {
        camera3_notify_msg_t msg{
            .type = CAMERA3_MSG_ERROR,
            .message.error.frame_number = capture_request->frame_number,
            .message.error.error_code = CAMERA3_MSG_ERROR_REQUEST};
        device_adapter->Notify(device_adapter, &msg);
      }
      if (result != 0 || !need_hal_reprocessing) {
        camera3_capture_result_t capture_result{
            .frame_number = capture_request->frame_number,
            .result = capture_request->settings,
            .num_output_buffers = capture_request->num_output_buffers,
            .output_buffers = capture_request->output_buffers,
            .input_buffer = capture_request->input_buffer};
        device_adapter->ProcessCaptureResult(device_adapter, &capture_result);
      }
    }

    int32_t result;
    CameraDeviceAdapter* device_adapter;
    const Camera3CaptureRequest* capture_request;
    bool need_hal_reprocessing;
  };
  ReprocessContext reprocess_context(this, req.get(), need_hal_reprocessing);
  ScopedYUVBufferHandle scoped_output_handle =
      need_hal_reprocessing ?
                            // Allocate reprocessing buffer
          ScopedYUVBufferHandle::AllocateScopedYUVHandle(
              input_stream->width, input_stream->height,
              GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)
                            :
                            // Wrap the output buffer
          ScopedYUVBufferHandle::CreateScopedYUVHandle(
              *req->output_buffers[0].buffer, output_stream->width,
              output_stream->height,
              GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
  if (!scoped_output_handle) {
    LOGF(ERROR) << "Failed to create scoped output buffer";
    reprocess_context.result = -EINVAL;
    return;
  }
  ScopedYUVBufferHandle scoped_input_handle =
      ScopedYUVBufferHandle::CreateScopedYUVHandle(
          *req->input_buffer->buffer, input_stream->width, input_stream->height,
          GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
  if (!scoped_input_handle) {
    LOGF(ERROR) << "Failed to create scoped input buffer";
    reprocess_context.result = -EINVAL;
    return;
  }
  android::CameraMetadata reprocess_result_metadata;
  reprocess_context.result = reprocess_effect_callback_.Run(
      *req->settings, &scoped_input_handle, input_stream->width,
      input_stream->height, &reprocess_result_metadata, &scoped_output_handle);
  if (reprocess_context.result != 0) {
    LOGF(ERROR) << "Failed to apply reprocess effect";
    return;
  }
  if (need_hal_reprocessing) {
    // Replace the input buffer with reprocessing output buffer
    {
      base::AutoLock reprocess_handles_lock(reprocess_handles_lock_);
      reprocess_handles_.push_back(std::move(scoped_output_handle));
      input_buffer_handle_ids_.push_back(
          reinterpret_cast<const camera_buffer_handle_t*>(
              *req->input_buffer->buffer)
              ->buffer_id);
      req->input_buffer->buffer = reprocess_handles_.back().GetHandle();
    }
    {
      base::AutoLock reprocess_result_metadata_lock(
          reprocess_result_metadata_lock_);
      reprocess_result_metadata_.emplace(req->frame_number,
                                         reprocess_result_metadata);
    }
    // Store the HAL reprocessing request and wait for CameraDeviceOpsThread to
    // complete it. Also post a null capture request to guarantee it will be
    // called when there's no existing capture requests.
    auto future = cros::Future<int32_t>::Create(nullptr);
    {
      base::AutoLock lock(process_reprocess_request_callback_lock_);
      DCHECK(process_reprocess_request_callback_.is_null());
      process_reprocess_request_callback_ = base::BindOnce(
          &CameraDeviceAdapter::ProcessReprocessRequestOnDeviceOpsThread,
          base::Unretained(this), base::Passed(&req),
          cros::GetFutureCallback(future));
    }
    camera_device_ops_thread_.task_runner()->PostTask(
        FROM_HERE, base::BindOnce(
                       [](CameraDeviceAdapter* adapter) {
                         // Ignore returned value.
                         adapter->ProcessCaptureRequest(nullptr);
                       },
                       base::Unretained(this)));
    reprocess_context.result = future->Get();
    if (reprocess_context.result != 0) {
      LOGF(ERROR) << "Failed to process capture request after reprocessing";
    }
  }
}

void CameraDeviceAdapter::ProcessReprocessRequestOnDeviceOpsThread(
    std::unique_ptr<Camera3CaptureRequest> req,
    base::Callback<void(int32_t)> callback) {
  VLOGF_ENTER();
  frame_number_mapper_.RegisterCaptureRequest(req.get(),
                                              /*is_request_split=*/false,
                                              /*is_request_added=*/false);
  callback.Run(
      camera_device_->ops->process_capture_request(camera_device_, req.get()));
}

void CameraDeviceAdapter::NotifyAddedFrameError(
    camera3_capture_request_t req,
    std::vector<camera3_stream_buffer_t> output_buffers) {
  notify_error_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&CameraDeviceAdapter::NotifyAddedFrameErrorOnNotifyErrorThread,
                 base::Unretained(this), base::Passed(&req),
                 base::Passed(&output_buffers)));
}

void CameraDeviceAdapter::NotifyAddedFrameErrorOnNotifyErrorThread(
    camera3_capture_request_t req,
    std::vector<camera3_stream_buffer_t> output_buffers) {
  uint32_t framework_frame_number =
      frame_number_mapper_.GetFrameworkFrameNumber(req.frame_number);
  if (callback_ops_delegate_) {
    base::AutoLock l(callback_ops_delegate_lock_);
    for (auto& buffer : output_buffers) {
      camera3_notify_msg_t msg{
          .type = CAMERA3_MSG_ERROR,
          .message.error = {.frame_number = framework_frame_number,
                            .error_stream = buffer.stream,
                            .error_code = CAMERA3_MSG_ERROR_BUFFER}};
      mojom::Camera3NotifyMsgPtr msg_ptr = PrepareNotifyMsg(&msg);
      callback_ops_delegate_->Notify(std::move(msg_ptr));
      // Result is not expected from the added frame so need to send
      // CAMERA3_MSG_ERROR_RESULT here.
    }

    // We still need to return the buffer handles back if we use notify() to
    // return  errors.
    camera3_capture_result_t res{
        .frame_number = framework_frame_number,
        .result = nullptr,
        .num_output_buffers = static_cast<uint32_t>(output_buffers.size()),
        .output_buffers = output_buffers.data(),
        .input_buffer = nullptr,  // Added requests don't have input buffer.
        .partial_result = 0};
    mojom::Camera3CaptureResultPtr result_ptr = PrepareCaptureResult(&res);
    callback_ops_delegate_->ProcessCaptureResult(std::move(result_ptr));
  }
}

void CameraDeviceAdapter::ResetDeviceOpsDelegateOnThread() {
  DCHECK(camera_device_ops_thread_.task_runner()->BelongsToCurrentThread());
  device_ops_delegate_.reset();
}

void CameraDeviceAdapter::ResetCallbackOpsDelegateOnThread() {
  DCHECK(camera_callback_ops_thread_.task_runner()->BelongsToCurrentThread());
  base::AutoLock l(callback_ops_delegate_lock_);
  callback_ops_delegate_.reset();
}

}  // namespace cros
