/*
 * Copyright 2020 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 "common/libcamera_connector/camera_client.h"

#include <algorithm>
#include <cmath>
#include <utility>

#include <base/bind.h>
#include <base/check.h>
#include <base/check_op.h>
#include <base/containers/flat_set.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/posix/safe_strerror.h>

#include "common/libcamera_connector/camera_metadata_utils.h"
#include "common/libcamera_connector/supported_formats.h"
#include "common/libcamera_connector/types.h"
#include "cros-camera/camera_service_connector.h"
#include "cros-camera/common.h"
#include "cros-camera/future.h"

namespace {

constexpr int32_t kDefaultFps = 30;

std::string GetCameraName(const cros::mojom::CameraInfoPtr& info) {
  switch (info->facing) {
    case cros::mojom::CameraFacing::CAMERA_FACING_BACK:
      return "Back Camera";
    case cros::mojom::CameraFacing::CAMERA_FACING_FRONT:
      return "Front Camera";
    case cros::mojom::CameraFacing::CAMERA_FACING_EXTERNAL:
      return "External Camera";
    default:
      return "Unknown Camera";
  }
}

int GetCameraFacing(const cros::mojom::CameraInfoPtr& info) {
  switch (info->facing) {
    case cros::mojom::CameraFacing::CAMERA_FACING_BACK:
      return CROS_CAM_FACING_BACK;
    case cros::mojom::CameraFacing::CAMERA_FACING_FRONT:
      return CROS_CAM_FACING_FRONT;
    case cros::mojom::CameraFacing::CAMERA_FACING_EXTERNAL:
      return CROS_CAM_FACING_EXTERNAL;
    default:
      LOGF(ERROR) << "unknown facing " << info->facing;
      return CROS_CAM_FACING_EXTERNAL;
  }
}

base::flat_set<int32_t> GetAvailableFramerates(
    const cros::mojom::CameraMetadataPtr& static_metadata) {
  base::flat_set<int32_t> candidates;
  auto available_fps_ranges = cros::GetMetadataEntryAsSpan<int32_t>(
      static_metadata, cros::mojom::CameraMetadataTag::
                           ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
  if (available_fps_ranges.empty()) {
    // If there is no available target fps ranges listed in metadata, we set a
    // default fps as candidate.
    LOG(WARNING) << "No available fps ranges in metadata. Set default fps as "
                    "candidate.";
    candidates.insert(kDefaultFps);
    return candidates;
  }

  // The available target fps ranges are stored as pairs int32s: (min, max) x n.
  const size_t kRangeMaxOffset = 1;
  const size_t kRangeSize = 2;

  for (size_t i = 0; i < available_fps_ranges.size(); i += kRangeSize) {
    candidates.insert(available_fps_ranges[i + kRangeMaxOffset]);
  }
  return candidates;
}

}  // namespace

namespace cros {

CameraClient::CameraClient()
    : ipc_thread_("CamClientIpc"),
      info_thread_("CamClientInfo"),
      camera_hal_client_(this),
      camera_module_callbacks_(base::Bind(&CameraClient::OnDeviceStatusChange,
                                          base::Unretained(this))),
      cam_info_callback_(nullptr) {}

void CameraClient::Init(RegisterClientCallback register_client_callback,
                        IntOnceCallback init_callback) {
  bool ret = ipc_thread_.StartWithOptions(
      base::Thread::Options(base::MessagePumpType::IO, 0));
  if (!ret) {
    LOGF(ERROR) << "Failed to start IPC thread";
    std::move(init_callback).Run(-ENODEV);
    return;
  }
  if (!info_thread_.Start()) {
    LOGF(ERROR) << "Failed to start camera info callback thread";
    std::move(init_callback).Run(-ENODEV);
    return;
  }
  init_callback_ = std::move(init_callback);
  ipc_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraClient::RegisterClient, base::Unretained(this),
                     std::move(register_client_callback)));
}

int CameraClient::Exit() {
  VLOGF_ENTER();
  int ret = StopCapture(context_.info.camera_id);
  ipc_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraClient::ResetOnIpcThread, base::Unretained(this)));
  ipc_thread_.Stop();
  info_thread_.Stop();
  // The stop might fail due to the camera already being closed. Ignore the
  // failure.
  if (ret == -EIO) {
    LOGF(INFO) << "Camera is already closed";
    ret = 0;
  }
  return ret;
}

int CameraClient::SetCameraInfoCallback(cros_cam_get_cam_info_cb_t callback,
                                        void* context) {
  VLOGF_ENTER();
  base::AutoLock l(camera_info_lock_);

  cam_info_callback_ = callback;
  cam_info_context_ = context;
  SendCameraInfo(camera_id_set_, /*is_removed=*/0);
  return 0;
}

int CameraClient::StartCapture(const cros_cam_capture_request_t* request,
                               cros_cam_capture_cb_t callback,
                               void* context) {
  VLOGF_ENTER();

  auto future = cros::Future<int>::Create(nullptr);
  SessionRequest session_request = {
      .type = SessionRequestType::kStart,
      .info = {.camera_id = request->id,
               .format = *request->format,
               .capture_callback = callback,
               .context = context},
      .result_callback = cros::GetFutureCallback(future)};
  PushSessionRequest(std::move(session_request));
  return future->Get();
}

int CameraClient::StopCapture(int id) {
  VLOGF_ENTER();

  auto future = cros::Future<int>::Create(nullptr);
  SessionRequest session_request = {
      .type = SessionRequestType::kStop,
      .info = {.camera_id = id},
      .result_callback = cros::GetFutureCallback(future)};
  PushSessionRequest(std::move(session_request));
  return future->Get();
}

void CameraClient::SetUpChannel(
    mojo::PendingRemote<mojom::CameraModule> camera_module) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  LOGF(INFO) << "Received camera module from camera HAL dispatcher";
  camera_module_.Bind(std::move(camera_module));
  camera_module_.set_disconnect_handler(
      base::Bind(&CameraClient::ResetClientState, base::Unretained(this)));

  GetAllCameraInfo();
}

void CameraClient::RegisterClient(
    RegisterClientCallback register_client_callback) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  std::move(register_client_callback)
      .Run(camera_hal_client_.BindNewPipeAndPassRemote(),
           base::BindOnce(&CameraClient::OnRegisteredClient,
                          base::Unretained(this)));
}

void CameraClient::OnRegisteredClient(int32_t result) {
  if (result != 0) {
    LOGF(ERROR) << "Failed to register client: "
                << base::safe_strerror(-result);
    std::move(init_callback_).Run(result);
  }
  LOGF(INFO) << "Successfully registered client";
}

void CameraClient::ResetOnIpcThread() {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  camera_hal_client_.reset();
}

void CameraClient::ResetClientState() {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());
  base::AutoLock l(camera_info_lock_);

  LOGF(WARNING) << "Mojo connection to HAL server disconnected";
  camera_module_.reset();
  // Notify the user that cameras are down.
  SendCameraInfoAsync(camera_id_set_, /*is_removed=*/1);
  camera_id_set_.clear();
  camera_info_map_.clear();
  pending_camera_id_set_ = {};
  processing_camera_id_set_.clear();
  if (init_callback_) {
    // If mojo disconnects during initialization, we can wait for the mojo
    // connection to come back and re-do the initialization. In addition, We
    // wouldn't have a valid session context here. Hence we don't reset sessions
    // or CameraClientOps.
    return;
  }
  switch (context_.state) {
    case SessionState::kIdle: {
      // No need to do anything.
      break;
    }
    case SessionState::kStarting: {
      std::move(context_.result_callback).Run(-ENODEV);
      break;
    }
    case SessionState::kCapturing: {
      cros_cam_capture_result_t result = {.status = -ENODEV, .frame = nullptr};
      (*context_.info.capture_callback)(context_.info.context, &result);
      break;
    }
    case SessionState::kStopping: {
      std::move(context_.result_callback).Run(-ENODEV);
      break;
    }
  }
  context_.state = SessionState::kIdle;
  FlushInflightSessionRequests(-ENODEV);
  context_.client_ops.Reset();
}

void CameraClient::GetAllCameraInfo() {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  camera_module_->GetNumberOfCameras(
      base::Bind(&CameraClient::OnGotNumberOfCameras, base::Unretained(this)));
}

void CameraClient::OnGotNumberOfCameras(int32_t num_builtin_cameras) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());
  base::AutoLock l(camera_info_lock_);

  LOGF(INFO) << "Number of builtin cameras: " << num_builtin_cameras;

  for (int32_t i = 0; i < num_builtin_cameras; ++i) {
    pending_camera_id_set_.insert(i);
  }
  SetCallbacks();
}

void CameraClient::SetCallbacks() {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  camera_module_->SetCallbacksAssociated(
      camera_module_callbacks_.GetModuleCallbacks(),
      base::Bind(&CameraClient::OnSetCallbacks, base::Unretained(this)));
}

void CameraClient::OnSetCallbacks(int32_t result) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  if (result != 0) {
    LOGF(ERROR) << "Failed to set callbacks" << base::safe_strerror(-result);
    if (init_callback_) {
      std::move(init_callback_).Run(-ENODEV);
    }
    return;
  }
  // After SetCallbacks(), it is guaranteed that all present cameras are probed.
  size_t num_cameras = pending_camera_id_set_.size() +
                       processing_camera_id_set_.size() + camera_id_set_.size();
  if (num_cameras == 0) {
    LOGF(ERROR) << "No built-in or connected cameras found";
    if (init_callback_) {
      std::move(init_callback_).Run(-ENODEV);
    }
    return;
  }
  GetCameraInfo();
}

void CameraClient::GetCameraInfo() {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  for (auto it = pending_camera_id_set_.begin();
       it != pending_camera_id_set_.end();) {
    int32_t camera_id = *it;
    it = pending_camera_id_set_.erase(it);
    processing_camera_id_set_.insert(camera_id);
    camera_module_->GetCameraInfo(
        camera_id, base::Bind(&CameraClient::OnGotCameraInfo,
                              base::Unretained(this), camera_id));
  }
}

void CameraClient::OnGotCameraInfo(int32_t camera_id,
                                   int32_t result,
                                   mojom::CameraInfoPtr info) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());
  base::AutoLock l(camera_info_lock_);

  if (result != 0) {
    LOGF(ERROR) << "Failed to get camera info of " << camera_id << ": "
                << base::safe_strerror(-result);
    processing_camera_id_set_.erase(camera_id);
    if (init_callback_) {
      std::move(init_callback_).Run(-ENODEV);
    }
    return;
  }

  LOGF(INFO) << "Gotten camera info of " << camera_id;

  auto& camera_info = camera_info_map_[camera_id];
  camera_info.facing = GetCameraFacing(info);
  camera_info.name = GetCameraName(info);

  auto& format_info = camera_info_map_[camera_id].format_info;
  auto candidate_fps_set =
      GetAvailableFramerates(info->static_camera_characteristics);
  auto min_frame_durations = GetMetadataEntryAsSpan<int64_t>(
      info->static_camera_characteristics,
      mojom::CameraMetadataTag::ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS);
  for (size_t i = 0; i < min_frame_durations.size(); i += 4) {
    int64_t hal_pixel_format = min_frame_durations[i + 0];
    int64_t width = min_frame_durations[i + 1];
    int64_t height = min_frame_durations[i + 2];
    int64_t duration_ns = min_frame_durations[i + 3];

    uint32_t fourcc = GetV4L2PixelFormat(hal_pixel_format);
    if (fourcc == 0) {
      VLOGF(1) << "Skip unsupported format " << hal_pixel_format;
      continue;
    }

    int max_fps = 1e9 / duration_ns;
    for (auto fps : candidate_fps_set) {
      if (fps > max_fps) {
        continue;
      }
      cros_cam_format_info_t info = {.fourcc = fourcc,
                                     .width = static_cast<int>(width),
                                     .height = static_cast<int>(height),
                                     .fps = fps};

      format_info.push_back(std::move(info));
    }
  }

  camera_info.jpeg_max_size = GetMetadataEntryAsSpan<int32_t>(
      info->static_camera_characteristics,
      mojom::CameraMetadataTag::ANDROID_JPEG_MAX_SIZE)[0];

  camera_id_set_.insert(camera_id);
  processing_camera_id_set_.erase(camera_id);

  if (init_callback_) {
    if (processing_camera_id_set_.empty()) {
      // TODO(lnishan): Initialize all states when multi-device streaming is
      // supported.
      context_.state = SessionState::kIdle;
      std::move(init_callback_).Run(0);
    }
  } else if (cam_info_callback_) {
    SendCameraInfoAsync({camera_id}, /*is_removed=*/0);
  }
}

void CameraClient::SendCameraInfo(const std::set<int32_t>& camera_id_set,
                                  int is_removed) {
  VLOGF_ENTER();
  camera_info_lock_.AssertAcquired();

  for (auto& camera_id : camera_id_set) {
    GenerateAndSendCameraInfo(camera_id, is_removed);
  }
}

void CameraClient::SendCameraInfoAsync(const std::set<int32_t>& camera_id_set,
                                       int is_removed) {
  VLOGF_ENTER();

  info_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraClient::SendCameraInfoAsyncOnInfoThread,
                     base::Unretained(this), camera_id_set, is_removed));
}

void CameraClient::SendCameraInfoAsyncOnInfoThread(
    std::set<int32_t> camera_id_set, int is_removed) {
  VLOGF_ENTER();
  DCHECK(info_thread_.task_runner()->BelongsToCurrentThread());
  base::AutoLock l(camera_info_lock_);

  for (auto& camera_id : camera_id_set) {
    GenerateAndSendCameraInfo(camera_id, is_removed);
  }
}

void CameraClient::GenerateAndSendCameraInfo(int32_t camera_id,
                                             int is_removed) {
  VLOGF_ENTER();
  camera_info_lock_.AssertAcquired();

  // Generate camera info
  cros_cam_info_t cam_info;
  if (is_removed) {
    cam_info = {.id = camera_id};
  } else {
    auto it = camera_info_map_.find(camera_id);
    if (it == camera_info_map_.end()) {
      LOGF(ERROR) << "Cannot find the info of camera " << camera_id;
      return;
    }
    auto& camera_info = it->second;
    cam_info = {
        .id = camera_id,
        .facing = camera_info.facing,
        .name = camera_info.name.c_str(),
        .format_count = static_cast<int>(camera_info.format_info.size()),
        .format_info = camera_info.format_info.data()};
  }

  // Send camera info
  if (cam_info_callback_ == nullptr) {
    return;
  }
  int ret = (*cam_info_callback_)(cam_info_context_, &cam_info, is_removed);
  if (ret != 0) {
    // Deregister callback
    cam_info_callback_ = nullptr;
    cam_info_context_ = nullptr;
  }
}

void CameraClient::PushSessionRequest(SessionRequest request) {
  VLOGF_ENTER();

  ipc_thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&CameraClient::PushSessionRequestOnIpcThread,
                                base::Unretained(this), std::move(request)));
}

void CameraClient::PushSessionRequestOnIpcThread(SessionRequest request) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  pending_session_requests_.push(std::move(request));
  TryProcessSessionRequests();
}

void CameraClient::TryProcessSessionRequests() {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  while (!pending_session_requests_.empty() &&
         ProcessSessionRequest(&pending_session_requests_.front()) == 0) {
    pending_session_requests_.pop();
  }
}

int CameraClient::ProcessSessionRequest(SessionRequest* request) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  switch (request->type) {
    case SessionRequestType::kStart:
      return StartCaptureOnIpcThread(request);
    case SessionRequestType::kStop:
      return StopCaptureOnIpcThread(request);
    default:
      LOGF(ERROR) << "Unexpected session request type";
      std::move(request->result_callback).Run(-EINVAL);
      return 0;
  }
}

void CameraClient::FlushInflightSessionRequests(int error) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  while (!pending_session_requests_.empty()) {
    auto request = std::move(pending_session_requests_.front());
    pending_session_requests_.pop();
    std::move(request.result_callback).Run(error);
  }
}

int CameraClient::StartCaptureOnIpcThread(SessionRequest* request) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  if (!IsDeviceActive(request->info.camera_id)) {
    LOGF(ERROR) << "Cannot start capture on an inactive device: "
                << request->info.camera_id;
    std::move(request->result_callback).Run(-ENODEV);
    return 0;
  }

  // TODO(lnishan): Support multi-device streaming by checking against the state
  // of the specified device only.
  switch (context_.state) {
    case SessionState::kIdle:
      // Proceed to start capture.
      break;
    case SessionState::kStarting:
      LOGF(WARNING) << "Capture is already starting";
      std::move(request->result_callback).Run(-EIO);
      return 0;
    case SessionState::kCapturing:
      LOGF(WARNING) << "Capture is already started";
      std::move(request->result_callback).Run(-EIO);
      return 0;
    case SessionState::kStopping:
      // Cannot start capture when the device is still being closed.
      return -EAGAIN;
  }

  LOGF(INFO) << "Starting capture";
  context_.state = SessionState::kStarting;
  context_.info = std::move(request->info);
  context_.result_callback = std::move(request->result_callback);
  auto device_ops_receiver = context_.client_ops.Init(
      base::Bind(&CameraClient::SendCaptureResult, base::Unretained(this)));
  camera_module_->OpenDevice(
      context_.info.camera_id, std::move(device_ops_receiver),
      base::Bind(&CameraClient::OnOpenedDevice, base::Unretained(this)));
  return 0;
}

void CameraClient::OnOpenedDevice(int32_t result) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());
  CHECK_EQ(context_.state, SessionState::kStarting);

  const auto& info = context_.info;
  if (result != 0) {
    LOGF(ERROR) << "Failed to open camera " << info.camera_id << ": "
                << base::safe_strerror(-result);
    context_.state = SessionState::kIdle;
  } else {
    base::AutoLock l(camera_info_lock_);
    LOGF(INFO) << "Camera opened successfully";
    context_.state = SessionState::kCapturing;
    context_.client_ops.StartCapture(
        info.camera_id, &info.format,
        camera_info_map_[info.camera_id].jpeg_max_size);
  }
  std::move(context_.result_callback).Run(result);

  TryProcessSessionRequests();
}

int CameraClient::StopCaptureOnIpcThread(SessionRequest* request) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  if (!IsDeviceActive(request->info.camera_id)) {
    LOGF(ERROR) << "Cannot stop capture on an inactive device: "
                << request->info.camera_id;
    std::move(request->result_callback).Run(-ENODEV);
    return 0;
  }

  // TODO(lnishan): Support multi-device streaming.
  CHECK_EQ(request->info.camera_id, context_.info.camera_id);

  // TODO(lnishan): Support multi-device streaming by checking against the state
  // of the specified device only.
  switch (context_.state) {
    case SessionState::kIdle:
      LOGF(WARNING) << "Capture is already stopped";
      std::move(request->result_callback).Run(-EIO);
      return 0;
    case SessionState::kStarting:
      return -EAGAIN;
    case SessionState::kCapturing:
      // Proceed to close the camera.
      break;
    case SessionState::kStopping:
      LOGF(WARNING) << "Capture is already stopping";
      std::move(request->result_callback).Run(-EIO);
      return 0;
  }

  LOGF(INFO) << "Stopping capture";
  context_.state = SessionState::kStopping;
  context_.result_callback = std::move(request->result_callback);
  context_.client_ops.StopCapture(
      base::Bind(&CameraClient::OnClosedDevice, base::Unretained(this)));
  return 0;
}

void CameraClient::OnClosedDevice(int32_t result) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());
  CHECK_EQ(context_.state, SessionState::kStopping);

  if (result != 0) {
    LOGF(ERROR) << "Failed to close camera " << context_.info.camera_id << ": "
                << base::safe_strerror(-result);
  } else {
    LOGF(INFO) << "Camera closed successfully";
  }

  // We transition the state to |SessionState::kIdle| here regardless of the
  // result to allow further retries. It's also possible that a device is
  // disconnected while the device is closing, and such an event would be
  // recoverable.
  context_.state = SessionState::kIdle;
  std::move(context_.result_callback).Run(result);

  TryProcessSessionRequests();
}

bool CameraClient::IsDeviceActive(int device) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());
  base::AutoLock l(camera_info_lock_);

  return camera_info_map_.find(device) != camera_info_map_.end();
}

void CameraClient::OnDeviceStatusChange(int32_t camera_id, bool is_present) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  LOGF(INFO) << camera_id << " is " << (is_present ? "present" : "absent");
  if (is_present) {
    pending_camera_id_set_.insert(camera_id);
    GetCameraInfo();
  } else {
    camera_id_set_.erase(camera_id);
    camera_info_map_.erase(camera_id);
    SendCameraInfoAsync({camera_id}, /*is_removed=*/1);
  }
}

void CameraClient::SendCaptureResult(const cros_cam_capture_result_t& result) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  // Only permissible states here are |SessionState::kCapturing| and
  // |SessionState::kStopping|.
  switch (context_.state) {
    case SessionState::kIdle:
      LOGF(ERROR) << "Received a capture result while the device is idle";
      return;
    case SessionState::kStarting:
      LOGF(ERROR) << "Received a capture result while the capture is starting";
      return;
    case SessionState::kCapturing:
      break;
    case SessionState::kStopping:
      // We don't return any capture results if the capture is stopping.
      return;
  }

  int ret = (*context_.info.capture_callback)(context_.info.context, &result);
  // We don't need to do anything if the session is already stopping.
  if (context_.state == SessionState::kStopping) {
    return;
  }
  if (ret != 0 || result.status == -ENODEV) {
    CHECK_EQ(context_.state, SessionState::kCapturing);
    // Flush all inflight session requests to stop the capture immediately.
    FlushInflightSessionRequests(-EIO);
    SessionRequest request = {.type = SessionRequestType::kStop,
                              .info = context_.info,
                              .result_callback = base::BindOnce(
                                  &CameraClient::OnStoppedCaptureFromCallback,
                                  base::Unretained(this))};
    PushSessionRequestOnIpcThread(std::move(request));
    CHECK_EQ(context_.state, SessionState::kStopping);
  }
}

void CameraClient::OnStoppedCaptureFromCallback(int result) {
  VLOGF_ENTER();
  DCHECK(ipc_thread_.task_runner()->BelongsToCurrentThread());

  if (result != 0) {
    LOGF(ERROR) << "Failed to stop capture from capture callback";
  }
}

}  // namespace cros
