// Copyright 2017 The Chromium 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 "media/capture/video/chromeos/camera_hal_delegate.h"

#include <fcntl.h>
#include <sys/uio.h>

#include <algorithm>
#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/containers/flat_set.h"
#include "base/posix/safe_strerror.h"
#include "base/process/launch.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/system/system_monitor.h"
#include "base/unguessable_token.h"
#include "components/device_event_log/device_event_log.h"
#include "media/capture/video/chromeos/camera_buffer_factory.h"
#include "media/capture/video/chromeos/camera_hal_dispatcher_impl.h"
#include "media/capture/video/chromeos/camera_metadata_utils.h"
#include "media/capture/video/chromeos/video_capture_device_chromeos_delegate.h"
#include "media/capture/video/chromeos/video_capture_device_chromeos_halv3.h"

namespace media {

namespace {

constexpr int32_t kDefaultFps = 30;
constexpr char kVirtualPrefix[] = "VIRTUAL_";

constexpr base::TimeDelta kEventWaitTimeoutSecs = base::Seconds(1);

class LocalCameraClientObserver : public CameraClientObserver {
 public:
  explicit LocalCameraClientObserver(
      scoped_refptr<CameraHalDelegate> camera_hal_delegate,
      cros::mojom::CameraClientType type,
      base::UnguessableToken auth_token)
      : CameraClientObserver(type, std::move(auth_token)),
        camera_hal_delegate_(std::move(camera_hal_delegate)) {}

  void OnChannelCreated(
      mojo::PendingRemote<cros::mojom::CameraModule> camera_module) override {
    camera_hal_delegate_->SetCameraModule(std::move(camera_module));
  }

 private:
  scoped_refptr<CameraHalDelegate> camera_hal_delegate_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(LocalCameraClientObserver);
};

// chromeos::system::StatisticsProvider::IsRunningOnVM() is not available in
// unittest.
bool IsRunningOnVM() {
  static bool is_vm = []() {
    std::string output;
    if (!base::GetAppOutput({"crossystem", "inside_vm"}, &output)) {
      return false;
    }
    return output == "1";
  }();
  return is_vm;
}

bool IsVividLoaded() {
  std::string output;
  if (!base::GetAppOutput({"lsmod"}, &output)) {
    return false;
  }

  std::vector<base::StringPiece> lines = base::SplitStringPieceUsingSubstr(
      output, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);

  return std::any_of(lines.begin(), lines.end(), [](const auto& line) {
    return base::StartsWith(line, "vivid", base::CompareCase::SENSITIVE);
  });
}

void NotifyVideoCaptureDevicesChanged() {
  base::SystemMonitor* monitor = base::SystemMonitor::Get();
  // |monitor| might be nullptr in unittest.
  if (monitor) {
    monitor->ProcessDevicesChanged(
        base::SystemMonitor::DeviceType::DEVTYPE_VIDEO_CAPTURE);
  }
}

base::flat_set<int32_t> GetAvailableFramerates(
    const cros::mojom::CameraInfoPtr& camera_info) {
  base::flat_set<int32_t> candidates;
  auto available_fps_ranges = GetMetadataEntryAsSpan<int32_t>(
      camera_info->static_camera_characteristics,
      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

CameraHalDelegate::CameraHalDelegate(
    scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner)
    : authenticated_(false),
      camera_module_has_been_set_(
          base::WaitableEvent::ResetPolicy::MANUAL,
          base::WaitableEvent::InitialState::NOT_SIGNALED),
      builtin_camera_info_updated_(
          base::WaitableEvent::ResetPolicy::MANUAL,
          base::WaitableEvent::InitialState::NOT_SIGNALED),
      external_camera_info_updated_(
          base::WaitableEvent::ResetPolicy::MANUAL,
          base::WaitableEvent::InitialState::SIGNALED),
      has_camera_connected_(base::WaitableEvent::ResetPolicy::MANUAL,
                            base::WaitableEvent::InitialState::NOT_SIGNALED),
      num_builtin_cameras_(0),
      camera_buffer_factory_(new CameraBufferFactory()),
      ipc_task_runner_(std::move(ipc_task_runner)),
      camera_module_callbacks_(this),
      vendor_tag_ops_delegate_(ipc_task_runner_) {
  DETACH_FROM_SEQUENCE(sequence_checker_);
}

CameraHalDelegate::~CameraHalDelegate() = default;

bool CameraHalDelegate::RegisterCameraClient() {
  auto* dispatcher = CameraHalDispatcherImpl::GetInstance();
  auto type = cros::mojom::CameraClientType::CHROME;
  dispatcher->AddClientObserver(
      std::make_unique<LocalCameraClientObserver>(
          this, type, dispatcher->GetTokenForTrustedClient(type)),
      base::BindOnce(&CameraHalDelegate::OnRegisteredCameraHalClient,
                     base::Unretained(this)));
  camera_hal_client_registered_.Wait();
  return authenticated_;
}

void CameraHalDelegate::OnRegisteredCameraHalClient(int32_t result) {
  if (result != 0) {
    LOG(ERROR) << "Failed to register camera HAL client";
    camera_hal_client_registered_.Signal();
    return;
  }
  CAMERA_LOG(EVENT) << "Registered camera HAL client";
  authenticated_ = true;
  camera_hal_client_registered_.Signal();
}

void CameraHalDelegate::SetCameraModule(
    mojo::PendingRemote<cros::mojom::CameraModule> camera_module) {
  ipc_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&CameraHalDelegate::SetCameraModuleOnIpcThread,
                                this, std::move(camera_module)));
}

void CameraHalDelegate::Reset() {
  ipc_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraHalDelegate::ResetMojoInterfaceOnIpcThread, this));
}

std::unique_ptr<VideoCaptureDevice> CameraHalDelegate::CreateDevice(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer,
    const VideoCaptureDeviceDescriptor& device_descriptor) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  if (!UpdateBuiltInCameraInfo()) {
    return nullptr;
  }
  int camera_id = GetCameraIdFromDeviceId(device_descriptor.device_id);
  if (camera_id == -1) {
    LOG(ERROR) << "Invalid camera device: " << device_descriptor.device_id;
    return nullptr;
  }

  auto* delegate =
      GetVCDDelegate(task_runner_for_screen_observer, device_descriptor);
  return std::make_unique<VideoCaptureDeviceChromeOSHalv3>(delegate,
                                                           device_descriptor);
}

void CameraHalDelegate::GetSupportedFormats(
    const cros::mojom::CameraInfoPtr& camera_info,
    VideoCaptureFormats* supported_formats) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  base::flat_set<int32_t> candidate_fps_set =
      GetAvailableFramerates(camera_info);

  const cros::mojom::CameraMetadataEntryPtr* min_frame_durations =
      GetMetadataEntry(camera_info->static_camera_characteristics,
                       cros::mojom::CameraMetadataTag::
                           ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS);
  if (!min_frame_durations) {
    LOG(ERROR)
        << "Failed to get available min frame durations from camera info";
    return;
  }
  // The min frame durations are stored as tuples of four int64s:
  // (hal_pixel_format, width, height, ns) x n
  const size_t kStreamFormatOffset = 0;
  const size_t kStreamWidthOffset = 1;
  const size_t kStreamHeightOffset = 2;
  const size_t kStreamDurationOffset = 3;
  const size_t kStreamDurationSize = 4;
  int64_t* iter =
      reinterpret_cast<int64_t*>((*min_frame_durations)->data.data());
  for (size_t i = 0; i < (*min_frame_durations)->count;
       i += kStreamDurationSize) {
    auto hal_format =
        static_cast<cros::mojom::HalPixelFormat>(iter[kStreamFormatOffset]);
    int32_t width = base::checked_cast<int32_t>(iter[kStreamWidthOffset]);
    int32_t height = base::checked_cast<int32_t>(iter[kStreamHeightOffset]);
    int64_t duration = iter[kStreamDurationOffset];
    iter += kStreamDurationSize;

    if (hal_format == cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_BLOB) {
      // Skip BLOB formats and use it only for TakePicture() since it's
      // inefficient to stream JPEG frames for CrOS camera HAL.
      continue;
    }

    if (duration <= 0) {
      LOG(ERROR) << "Ignoring invalid frame duration: " << duration;
      continue;
    }
    float max_fps = 1.0 * 1000000000LL / duration;

    // There's no consumer information here to determine the buffer usage, so
    // hard-code the usage that all the clients should be using.
    constexpr gfx::BufferUsage kClientBufferUsage =
        gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE;
    const ChromiumPixelFormat cr_format =
        camera_buffer_factory_->ResolveStreamBufferFormat(hal_format,
                                                          kClientBufferUsage);
    if (cr_format.video_format == PIXEL_FORMAT_UNKNOWN) {
      continue;
    }

    for (auto fps : candidate_fps_set) {
      if (fps > max_fps) {
        continue;
      }

      CAMERA_LOG(DEBUG) << "Supported format: " << width << "x" << height
                        << " fps=" << fps
                        << " format=" << cr_format.video_format;
      supported_formats->emplace_back(gfx::Size(width, height), fps,
                                      cr_format.video_format);
    }
  }
}

void CameraHalDelegate::GetDevicesInfo(
    VideoCaptureDeviceFactory::GetDevicesInfoCallback callback) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  if (!UpdateBuiltInCameraInfo()) {
    std::move(callback).Run({});
    return;
  }

  if (!external_camera_info_updated_.TimedWait(kEventWaitTimeoutSecs)) {
    LOG(ERROR) << "Failed to get camera info from all external cameras";
  }

  if (IsRunningOnVM() && IsVividLoaded()) {
    has_camera_connected_.TimedWait(kEventWaitTimeoutSecs);
  }

  std::vector<VideoCaptureDeviceInfo> devices_info;

  {
    base::AutoLock info_lock(camera_info_lock_);
    base::AutoLock id_map_lock(device_id_to_camera_id_lock_);
    base::AutoLock virtual_lock(enable_virtual_device_lock_);
    for (const auto& it : camera_info_) {
      int camera_id = it.first;
      const cros::mojom::CameraInfoPtr& camera_info = it.second;
      if (!camera_info) {
        continue;
      }

      auto get_vendor_string = [&](const std::string& key) -> const char* {
        const VendorTagInfo* info = vendor_tag_ops_delegate_.GetInfoByName(key);
        if (info == nullptr) {
          return nullptr;
        }
        auto val = GetMetadataEntryAsSpan<char>(
            camera_info->static_camera_characteristics, info->tag);
        return val.empty() ? nullptr : val.data();
      };

      VideoCaptureDeviceDescriptor desc;
      desc.capture_api = VideoCaptureApi::ANDROID_API2_LIMITED;
      desc.transport_type = VideoCaptureTransportType::OTHER_TRANSPORT;
      switch (camera_info->facing) {
        case cros::mojom::CameraFacing::CAMERA_FACING_BACK:
          desc.facing = VideoFacingMode::MEDIA_VIDEO_FACING_ENVIRONMENT;
          desc.device_id = base::NumberToString(camera_id);
          desc.set_display_name("Back Camera");
          break;
        case cros::mojom::CameraFacing::CAMERA_FACING_FRONT:
          desc.facing = VideoFacingMode::MEDIA_VIDEO_FACING_USER;
          desc.device_id = base::NumberToString(camera_id);
          desc.set_display_name("Front Camera");
          break;
        case cros::mojom::CameraFacing::CAMERA_FACING_EXTERNAL: {
          desc.facing = VideoFacingMode::MEDIA_VIDEO_FACING_NONE;

          // The webcam_private api expects that |device_id| to be set as the
          // corresponding device path for external cameras used in GVC system.
          auto* path = get_vendor_string("com.google.usb.devicePath");
          desc.device_id =
              path != nullptr ? path : base::NumberToString(camera_id);

          auto* name = get_vendor_string("com.google.usb.modelName");
          desc.set_display_name(name != nullptr ? name : "External Camera");

          break;
          // Mojo validates the input parameters for us so we don't need to
          // worry about malformed values.
        }
        case cros::mojom::CameraFacing::CAMERA_FACING_VIRTUAL_BACK:
        case cros::mojom::CameraFacing::CAMERA_FACING_VIRTUAL_FRONT:
        case cros::mojom::CameraFacing::CAMERA_FACING_VIRTUAL_EXTERNAL:
          // |camera_info_| should not have these facing types.
          LOG(ERROR) << "Invalid facing type: " << camera_info->facing;
          break;
      }
      auto* vid = get_vendor_string("com.google.usb.vendorId");
      auto* pid = get_vendor_string("com.google.usb.productId");
      if (vid != nullptr && pid != nullptr) {
        desc.model_id = base::StrCat({vid, ":", pid});
      }
      desc.set_control_support(GetControlSupport(camera_info));
      device_id_to_camera_id_[desc.device_id] = camera_id;
      devices_info.emplace_back(desc);
      GetSupportedFormats(camera_info_[camera_id],
                          &devices_info.back().supported_formats);

      // Create a virtual device when multiple streams are enabled.
      if (enable_virtual_device_[camera_id]) {
        desc.facing = VideoFacingMode::MEDIA_VIDEO_FACING_NONE;
        desc.device_id =
            std::string(kVirtualPrefix) + base::NumberToString(camera_id);
        desc.set_display_name("Virtual Camera");
        device_id_to_camera_id_[desc.device_id] = camera_id;
        devices_info.emplace_back(desc);
        GetSupportedFormats(camera_info_[camera_id],
                            &devices_info.back().supported_formats);
      }
    }
  }
  // TODO(shik): Report external camera first when lid is closed.
  // TODO(jcliang): Remove this after JS API supports query camera facing
  // (http://crbug.com/543997).
  std::sort(
      devices_info.begin(), devices_info.end(),
      [](const VideoCaptureDeviceInfo& a, const VideoCaptureDeviceInfo& b) {
        return a.descriptor < b.descriptor;
      });
  DVLOG(1) << "Number of devices: " << devices_info.size();

  std::move(callback).Run(std::move(devices_info));
}

VideoCaptureControlSupport CameraHalDelegate::GetControlSupport(
    const cros::mojom::CameraInfoPtr& camera_info) {
  VideoCaptureControlSupport control_support;

  auto is_vendor_range_valid = [&](const std::string& key) -> bool {
    const VendorTagInfo* info = vendor_tag_ops_delegate_.GetInfoByName(key);
    if (info == nullptr)
      return false;
    auto range = GetMetadataEntryAsSpan<int32_t>(
        camera_info->static_camera_characteristics, info->tag);
    return range.size() == 3 && range[0] < range[1];
  };

  if (is_vendor_range_valid("com.google.control.panRange"))
    control_support.pan = true;

  if (is_vendor_range_valid("com.google.control.tiltRange"))
    control_support.tilt = true;

  if (is_vendor_range_valid("com.google.control.zoomRange"))
    control_support.zoom = true;

  auto max_digital_zoom = GetMetadataEntryAsSpan<float>(
      camera_info->static_camera_characteristics,
      cros::mojom::CameraMetadataTag::
          ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
  if (max_digital_zoom.size() == 1 && max_digital_zoom[0] > 1) {
    control_support.zoom = true;
  }

  return control_support;
}

cros::mojom::CameraInfoPtr CameraHalDelegate::GetCameraInfoFromDeviceId(
    const std::string& device_id) {
  base::AutoLock lock(camera_info_lock_);
  int camera_id = GetCameraIdFromDeviceId(device_id);
  if (camera_id == -1) {
    return {};
  }
  auto it = camera_info_.find(camera_id);
  if (it == camera_info_.end()) {
    return {};
  }
  auto info = it->second.Clone();
  if (base::StartsWith(device_id, std::string(kVirtualPrefix))) {
    switch (it->second->facing) {
      case cros::mojom::CameraFacing::CAMERA_FACING_BACK:
        info->facing = cros::mojom::CameraFacing::CAMERA_FACING_VIRTUAL_BACK;
        break;
      case cros::mojom::CameraFacing::CAMERA_FACING_FRONT:
        info->facing = cros::mojom::CameraFacing::CAMERA_FACING_VIRTUAL_FRONT;
        break;
      case cros::mojom::CameraFacing::CAMERA_FACING_EXTERNAL:
        info->facing =
            cros::mojom::CameraFacing::CAMERA_FACING_VIRTUAL_EXTERNAL;
        break;
      default:
        break;
    }
  }
  return info;
}

void CameraHalDelegate::EnableVirtualDevice(const std::string& device_id,
                                            bool enable) {
  if (base::StartsWith(device_id, std::string(kVirtualPrefix))) {
    return;
  }
  auto camera_id = GetCameraIdFromDeviceId(device_id);
  if (camera_id != -1) {
    base::AutoLock lock(enable_virtual_device_lock_);
    enable_virtual_device_[camera_id] = enable;
  }
}

void CameraHalDelegate::DisableAllVirtualDevices() {
  base::AutoLock lock(enable_virtual_device_lock_);
  for (auto& it : enable_virtual_device_) {
    it.second = false;
  }
}

const VendorTagInfo* CameraHalDelegate::GetVendorTagInfoByName(
    const std::string& full_name) {
  return vendor_tag_ops_delegate_.GetInfoByName(full_name);
}

void CameraHalDelegate::OpenDevice(
    int32_t camera_id,
    mojo::PendingReceiver<cros::mojom::Camera3DeviceOps> device_ops_receiver,
    OpenDeviceCallback callback) {
  DCHECK(!ipc_task_runner_->BelongsToCurrentThread());
  // This method may be called on any thread except |ipc_task_runner_|.
  // Currently this method is used by CameraDeviceDelegate to open a camera
  // device.
  camera_module_has_been_set_.Wait();
  ipc_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraHalDelegate::OpenDeviceOnIpcThread, this, camera_id,
                     std::move(device_ops_receiver), std::move(callback)));
}

int CameraHalDelegate::GetCameraIdFromDeviceId(const std::string& device_id) {
  base::AutoLock lock(device_id_to_camera_id_lock_);
  auto it = device_id_to_camera_id_.find(device_id);
  if (it == device_id_to_camera_id_.end()) {
    return -1;
  }
  return it->second;
}

VideoCaptureDeviceChromeOSDelegate* CameraHalDelegate::GetVCDDelegate(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_screen_observer,
    const VideoCaptureDeviceDescriptor& device_descriptor) {
  auto camera_id = GetCameraIdFromDeviceId(device_descriptor.device_id);
  auto it = vcd_delegate_map_.find(camera_id);
  if (it == vcd_delegate_map_.end() || it->second->HasDeviceClient() == 0) {
    auto cleanup_callback = base::BindOnce(
        [](int camera_id,
           base::flat_map<int,
                          std::unique_ptr<VideoCaptureDeviceChromeOSDelegate>>*
               vcd_delegate_map) { vcd_delegate_map->erase(camera_id); },
        camera_id, &vcd_delegate_map_);
    auto delegate = std::make_unique<VideoCaptureDeviceChromeOSDelegate>(
        std::move(task_runner_for_screen_observer), device_descriptor, this,
        std::move(cleanup_callback));
    vcd_delegate_map_[camera_id] = std::move(delegate);
    return vcd_delegate_map_[camera_id].get();
  }
  return it->second.get();
}

void CameraHalDelegate::SetCameraModuleOnIpcThread(
    mojo::PendingRemote<cros::mojom::CameraModule> camera_module) {
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());
  if (camera_module_.is_bound()) {
    LOG(ERROR) << "CameraModule is already bound";
    return;
  }
  if (camera_module.is_valid()) {
    camera_module_.Bind(std::move(camera_module));
    camera_module_.set_disconnect_handler(base::BindOnce(
        &CameraHalDelegate::ResetMojoInterfaceOnIpcThread, this));
  }
  camera_module_has_been_set_.Signal();
}

void CameraHalDelegate::ResetMojoInterfaceOnIpcThread() {
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());
  camera_module_.reset();
  camera_module_callbacks_.reset();
  vendor_tag_ops_delegate_.Reset();
  builtin_camera_info_updated_.Reset();
  camera_module_has_been_set_.Reset();
  has_camera_connected_.Reset();
  external_camera_info_updated_.Signal();

  // Clear all cached camera info, especially external cameras.
  base::AutoLock lock(camera_info_lock_);
  camera_info_.clear();
  pending_external_camera_info_.clear();
}

bool CameraHalDelegate::UpdateBuiltInCameraInfo() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(!ipc_task_runner_->BelongsToCurrentThread());

  camera_module_has_been_set_.Wait();
  if (builtin_camera_info_updated_.IsSignaled()) {
    return true;
  }
  // The built-in camera are static per specification of the Android camera HAL
  // v3 specification.  We only update the built-in camera info once.
  ipc_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraHalDelegate::UpdateBuiltInCameraInfoOnIpcThread,
                     this));
  if (!builtin_camera_info_updated_.TimedWait(kEventWaitTimeoutSecs)) {
    LOG(ERROR) << "Timed out getting camera info";
    return false;
  }
  return true;
}

void CameraHalDelegate::UpdateBuiltInCameraInfoOnIpcThread() {
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());
  camera_module_->GetNumberOfCameras(base::BindOnce(
      &CameraHalDelegate::OnGotNumberOfCamerasOnIpcThread, this));
}

void CameraHalDelegate::OnGotNumberOfCamerasOnIpcThread(int32_t num_cameras) {
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());

  base::AutoLock lock(camera_info_lock_);
  if (num_cameras < 0) {
    builtin_camera_info_updated_.Signal();
    LOG(ERROR) << "Failed to get number of cameras: " << num_cameras;
    return;
  }
  CAMERA_LOG(EVENT) << "Number of built-in cameras: " << num_cameras;
  num_builtin_cameras_ = num_cameras;
  // Per camera HAL v3 specification SetCallbacks() should be called after the
  // first time GetNumberOfCameras() is called, and before other CameraModule
  // functions are called.
  camera_module_->SetCallbacksAssociated(
      camera_module_callbacks_.BindNewEndpointAndPassRemote(),
      base::BindOnce(&CameraHalDelegate::OnSetCallbacksOnIpcThread, this));

  camera_module_->GetVendorTagOps(
      vendor_tag_ops_delegate_.MakeReceiver(),
      base::BindOnce(&CameraHalDelegate::OnGotVendorTagOpsOnIpcThread, this));
}

void CameraHalDelegate::OnSetCallbacksOnIpcThread(int32_t result) {
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());

  base::AutoLock lock(camera_info_lock_);
  if (result) {
    num_builtin_cameras_ = 0;
    builtin_camera_info_updated_.Signal();
    LOG(ERROR) << "Failed to set camera module callbacks: "
               << base::safe_strerror(-result);
    return;
  }

  if (num_builtin_cameras_ == 0) {
    builtin_camera_info_updated_.Signal();
    return;
  }

  for (size_t camera_id = 0; camera_id < num_builtin_cameras_; ++camera_id) {
    GetCameraInfoOnIpcThread(
        camera_id,
        base::BindOnce(&CameraHalDelegate::OnGotCameraInfoOnIpcThread, this,
                       camera_id));
  }
}

void CameraHalDelegate::OnGotVendorTagOpsOnIpcThread() {
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());
  vendor_tag_ops_delegate_.Initialize();
}

void CameraHalDelegate::GetCameraInfoOnIpcThread(
    int32_t camera_id,
    GetCameraInfoCallback callback) {
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());
  camera_module_->GetCameraInfo(camera_id, std::move(callback));
}

void CameraHalDelegate::OnGotCameraInfoOnIpcThread(
    int32_t camera_id,
    int32_t result,
    cros::mojom::CameraInfoPtr camera_info) {
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());
  DVLOG(1) << "Got camera info of camera " << camera_id;
  if (result) {
    LOG(ERROR) << "Failed to get camera info. Camera id: " << camera_id;
    return;
  }
  SortCameraMetadata(&camera_info->static_camera_characteristics);

  base::AutoLock lock(camera_info_lock_);
  camera_info_[camera_id] = std::move(camera_info);

  if (camera_id < base::checked_cast<int32_t>(num_builtin_cameras_)) {
    // |camera_info_| might contain some entries for external cameras as well,
    // we should check all built-in cameras explicitly.
    bool all_updated = [&]() {
      camera_info_lock_.AssertAcquired();
      for (size_t i = 0; i < num_builtin_cameras_; i++) {
        if (camera_info_.find(i) == camera_info_.end()) {
          return false;
        }
      }
      return true;
    }();

    if (all_updated) {
      builtin_camera_info_updated_.Signal();
    }
  } else {
    // It's an external camera.
    pending_external_camera_info_.erase(camera_id);
    if (pending_external_camera_info_.empty()) {
      external_camera_info_updated_.Signal();
    }
    NotifyVideoCaptureDevicesChanged();
  }

  if (camera_info_.size() == 1) {
    has_camera_connected_.Signal();
  }
}

void CameraHalDelegate::OpenDeviceOnIpcThread(
    int32_t camera_id,
    mojo::PendingReceiver<cros::mojom::Camera3DeviceOps> device_ops_receiver,
    OpenDeviceCallback callback) {
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());
  camera_module_->OpenDevice(camera_id, std::move(device_ops_receiver),
                             std::move(callback));
}

// CameraModuleCallbacks implementations.
void CameraHalDelegate::CameraDeviceStatusChange(
    int32_t camera_id,
    cros::mojom::CameraDeviceStatus new_status) {
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());
  CAMERA_LOG(EVENT) << "camera_id = " << camera_id
                    << ", new_status = " << new_status;
  base::AutoLock lock(camera_info_lock_);
  auto it = camera_info_.find(camera_id);
  switch (new_status) {
    case cros::mojom::CameraDeviceStatus::CAMERA_DEVICE_STATUS_PRESENT:
      if (it == camera_info_.end()) {
        // Get info for the newly connected external camera.
        // |has_camera_connected_| might be signaled in
        // OnGotCameraInfoOnIpcThread().
        pending_external_camera_info_.insert(camera_id);
        if (pending_external_camera_info_.size() == 1) {
          external_camera_info_updated_.Reset();
        }
        GetCameraInfoOnIpcThread(
            camera_id,
            base::BindOnce(&CameraHalDelegate::OnGotCameraInfoOnIpcThread, this,
                           camera_id));
      } else {
        LOG(WARNING) << "Ignore duplicated camera_id = " << camera_id;
      }
      break;
    case cros::mojom::CameraDeviceStatus::CAMERA_DEVICE_STATUS_NOT_PRESENT:
      if (it != camera_info_.end()) {
        camera_info_.erase(it);
        if (camera_info_.empty()) {
          has_camera_connected_.Reset();
        }
        NotifyVideoCaptureDevicesChanged();
      } else {
        LOG(WARNING) << "Ignore nonexistent camera_id = " << camera_id;
      }
      break;
    default:
      NOTREACHED() << "Unexpected new status " << new_status;
  }
}

void CameraHalDelegate::TorchModeStatusChange(
    int32_t camera_id,
    cros::mojom::TorchModeStatus new_status) {
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());
  // Do nothing here as we don't care about torch mode status.
}

}  // namespace media
