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

#include <algorithm>
#include <iomanip>
#include <string>
#include <tuple>
#include <unordered_map>
#include <utility>

#include <base/bind.h>
#include <base/callback_helpers.h>
#include <base/check.h>
#include <base/check_op.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/notreached.h>
#include <base/stl_util.h>
#include <base/threading/thread_task_runner_handle.h>
#include <camera/camera_metadata.h>
#include <system/camera_metadata_hidden.h>

#include "common/utils/cros_camera_mojo_utils.h"
#include "cros-camera/camera_metrics.h"
#include "cros-camera/common.h"
#include "cros-camera/constants.h"
#include "cros-camera/future.h"
#include "hal_adapter/camera_device_adapter.h"
#include "hal_adapter/camera_module_callbacks_associated_delegate.h"
#include "hal_adapter/camera_module_callbacks_delegate.h"
#include "hal_adapter/camera_module_delegate.h"
#include "hal_adapter/camera_trace_event.h"
#include "hal_adapter/vendor_tag_ops_delegate.h"
#include "hal_adapter/zsl_helper.h"

namespace cros {

namespace {

// A special id used in ResetModuleDelegateOnThread and
// ResetCallbacksDelegateOnThread to specify all the entries present in the
// |module_delegates_| and |callbacks_delegates_| maps.
const uint32_t kIdAll = 0xFFFFFFFF;

}  // namespace

CameraHalAdapter::CameraHalAdapter(
    std::vector<std::pair<camera_module_t*, cros_camera_hal_t*>>
        camera_interfaces,
    CameraMojoChannelManagerToken* token,
    CameraActivityCallback activity_callback)
    : camera_interfaces_(camera_interfaces),
      camera_module_thread_("CameraModuleThread"),
      camera_module_callbacks_thread_("CameraModuleCallbacksThread"),
      module_id_(0),
      callbacks_id_(0),
      vendor_tag_ops_id_(0),
      camera_metrics_(CameraMetrics::New()),
      mojo_manager_token_(token),
      activity_callback_(activity_callback) {
  VLOGF_ENTER();
}

CameraHalAdapter::~CameraHalAdapter() {
  VLOGF_ENTER();
  camera_module_thread_.task_runner()->PostTask(
      FROM_HERE, base::Bind(&CameraHalAdapter::ResetModuleDelegateOnThread,
                            base::Unretained(this), kIdAll));
  camera_module_callbacks_thread_.task_runner()->PostTask(
      FROM_HERE, base::Bind(&CameraHalAdapter::ResetCallbacksDelegateOnThread,
                            base::Unretained(this), kIdAll));
  camera_module_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&CameraHalAdapter::ResetVendorTagOpsDelegateOnThread,
                 base::Unretained(this), kIdAll));
  camera_module_thread_.Stop();
  camera_module_callbacks_thread_.Stop();
  set_camera_metadata_vendor_ops(nullptr);
}

bool CameraHalAdapter::Start() {
  VLOGF_ENTER();
  TRACE_CAMERA_INSTANT();

  if (!camera_module_thread_.Start()) {
    LOGF(ERROR) << "Failed to start CameraModuleThread";
    return false;
  }
  if (!camera_module_callbacks_thread_.Start()) {
    LOGF(ERROR) << "Failed to start CameraCallbacksThread";
    return false;
  }

  auto future = cros::Future<bool>::Create(nullptr);
  camera_module_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&CameraHalAdapter::StartOnThread, base::Unretained(this),
                 cros::GetFutureCallback(future)));
  return future->Get();
}

void CameraHalAdapter::OpenCameraHal(
    mojo::PendingReceiver<mojom::CameraModule> camera_module_receiver,
    mojom::CameraClientType camera_client_type) {
  VLOGF_ENTER();
  TRACE_CAMERA_SCOPED();
  auto module_delegate = std::make_unique<CameraModuleDelegate>(
      this, camera_module_thread_.task_runner(), camera_client_type);
  uint32_t module_id = module_id_++;
  module_delegate->Bind(
      std::move(camera_module_receiver),
      base::Bind(&CameraHalAdapter::ResetModuleDelegateOnThread,
                 base::Unretained(this), module_id));
  base::AutoLock l(module_delegates_lock_);
  module_delegates_[module_id] = std::move(module_delegate);
  VLOGF(1) << "CameraModule " << module_id << " connected";
}

// Callback interface for camera_module_t APIs.

int32_t CameraHalAdapter::OpenDevice(
    int32_t camera_id,
    mojo::PendingReceiver<mojom::Camera3DeviceOps> device_ops_receiver,
    mojom::CameraClientType camera_client_type) {
  VLOGF_ENTER();
  DCHECK(camera_module_thread_.task_runner()->BelongsToCurrentThread());
  TRACE_CAMERA_SCOPED("camera_id", camera_id);

  session_timer_map_.emplace(std::piecewise_construct,
                             std::forward_as_tuple(camera_id),
                             std::forward_as_tuple());

  camera_module_t* camera_module;
  int internal_camera_id;
  std::tie(camera_module, internal_camera_id) =
      GetInternalModuleAndId(camera_id);

  LOGF(INFO) << camera_client_type << ", camera_id = " << camera_id
             << ", camera_module = " << camera_module->common.name
             << ", internal_camera_id = " << internal_camera_id;

  if (!camera_module) {
    return -EINVAL;
  }

  if (device_adapters_.find(camera_id) != device_adapters_.end()) {
    LOGF(WARNING) << "Multiple calls to OpenDevice on device " << camera_id;
    if (camera_client_type == mojom::CameraClientType::CHROME) {
      LOGF(WARNING) << "Close device to recover from bad state (b/155830039)";
      device_adapters_[camera_id]->Close();
    }
    return -EBUSY;
  }

  int module_id = camera_id_map_[camera_id].first;
  cros_camera_hal_t* cros_camera_hal = camera_interfaces_[module_id].second;
  hw_module_t* common = &camera_module->common;
  camera3_device_t* camera_device;
  int ret;
  if (cros_camera_hal && cros_camera_hal->camera_device_open_ext) {
    ret = cros_camera_hal->camera_device_open_ext(
        common, std::to_string(internal_camera_id).c_str(),
        reinterpret_cast<hw_device_t**>(&camera_device),
        static_cast<ClientType>(camera_client_type));
  } else {
    ret = common->methods->open(
        common, std::to_string(internal_camera_id).c_str(),
        reinterpret_cast<hw_device_t**>(&camera_device));
  }
  if (ret != 0) {
    LOGF(ERROR) << "Failed to open camera device " << camera_id;
    return ret;
  }
  activity_callback_.Run(camera_id, /*opened=*/true, camera_client_type);

  camera_info_t info;
  if (cros_camera_hal && cros_camera_hal->get_camera_info_ext) {
    ret = cros_camera_hal->get_camera_info_ext(
        internal_camera_id, &info, static_cast<ClientType>(camera_client_type));
  } else {
    ret = camera_module->get_camera_info(internal_camera_id, &info);
  }
  if (ret != 0) {
    LOGF(ERROR) << "Failed to get camera info of camera " << camera_id;
    return ret;
  }
  const camera_metadata_t* metadata = GetUpdatedCameraMetadata(
      camera_id, camera_client_type, info.static_camera_characteristics);
  // This method is called by |camera_module_delegate_| on its mojo IPC
  // handler thread.
  // The CameraHalAdapter (and hence |camera_module_delegate_|) must out-live
  // the CameraDeviceAdapters, so it's safe to keep a reference to the task
  // runner of the current thread in the callback functor.
  base::Callback<void()> close_callback = base::Bind(
      &CameraHalAdapter::CloseDeviceCallback, base::Unretained(this),
      base::ThreadTaskRunnerHandle::Get(), camera_id, camera_client_type);
  device_adapters_[camera_id] = std::make_unique<CameraDeviceAdapter>(
      camera_device, metadata, close_callback,
      base::Contains(can_attempt_zsl_camera_ids_, camera_id));

  CameraDeviceAdapter::HasReprocessEffectVendorTagCallback
      has_reprocess_effect_vendor_tag_callback =
          base::Bind(&ReprocessEffectManager::HasReprocessEffectVendorTag,
                     base::Unretained(&reprocess_effect_manager_));
  CameraDeviceAdapter::ReprocessEffectCallback reprocess_effect_callback =
      base::Bind(&ReprocessEffectManager::ReprocessRequest,
                 base::Unretained(&reprocess_effect_manager_));
  if (!device_adapters_[camera_id]->Start(
          std::move(has_reprocess_effect_vendor_tag_callback),
          std::move(reprocess_effect_callback))) {
    device_adapters_.erase(camera_id);
    return -ENODEV;
  }
  device_adapters_.at(camera_id)->Bind(std::move(device_ops_receiver));
  camera_metrics_->SendCameraFacing(info.facing);
  camera_metrics_->SendOpenDeviceClientType(
      static_cast<int>(camera_client_type));
  camera_metrics_->SendOpenDeviceLatency(
      session_timer_map_[camera_id].Elapsed());

  return 0;
}

int32_t CameraHalAdapter::GetNumberOfCameras() {
  VLOGF_ENTER();
  DCHECK(camera_module_thread_.task_runner()->BelongsToCurrentThread());
  TRACE_CAMERA_SCOPED();
  return num_builtin_cameras_;
}

int32_t CameraHalAdapter::GetCameraInfo(
    int32_t camera_id,
    mojom::CameraInfoPtr* camera_info,
    mojom::CameraClientType camera_client_type) {
  VLOGF_ENTER();
  DCHECK(camera_module_thread_.task_runner()->BelongsToCurrentThread());
  TRACE_CAMERA_SCOPED("camera_id", camera_id);

  camera_module_t* camera_module;
  int internal_camera_id;
  std::tie(camera_module, internal_camera_id) =
      GetInternalModuleAndId(camera_id);

  if (!camera_module) {
    camera_info->reset();
    return -EINVAL;
  }
  int ret;
  int module_id = camera_id_map_[camera_id].first;
  camera_info_t info;
  cros_camera_hal_t* cros_camera_hal = camera_interfaces_[module_id].second;
  if (cros_camera_hal && cros_camera_hal->get_camera_info_ext) {
    ret = cros_camera_hal->get_camera_info_ext(
        internal_camera_id, &info, static_cast<ClientType>(camera_client_type));
  } else {
    ret = camera_module->get_camera_info(internal_camera_id, &info);
  }

  if (ret != 0) {
    LOGF(ERROR) << "Failed to get info of camera " << camera_id;
    camera_info->reset();
    return ret;
  }

  LOGF(INFO) << camera_client_type << " camera_id = " << camera_id
             << ", facing = " << info.facing;

  const camera_metadata_t* metadata = GetUpdatedCameraMetadata(
      camera_id, camera_client_type, info.static_camera_characteristics);

  if (VLOG_IS_ON(2)) {
    dump_camera_metadata(metadata, 2, 3);
  }

  mojom::CameraInfoPtr info_ptr = mojom::CameraInfo::New();
  info_ptr->facing = static_cast<mojom::CameraFacing>(info.facing);
  info_ptr->orientation = info.orientation;
  info_ptr->device_version = info.device_version;
  info_ptr->static_camera_characteristics =
      internal::SerializeCameraMetadata(metadata);
  info_ptr->resource_cost = mojom::CameraResourceCost::New();
  info_ptr->resource_cost->resource_cost = info.resource_cost;

  std::vector<std::string> conflicting_devices;
  for (size_t i = 0; i < info.conflicting_devices_length; i++) {
    int conflicting_id =
        GetExternalId(module_id, atoi(info.conflicting_devices[i]));
    conflicting_devices.push_back(std::to_string(conflicting_id));
  }
  info_ptr->conflicting_devices = std::move(conflicting_devices);

  *camera_info = std::move(info_ptr);
  return 0;
}

int32_t CameraHalAdapter::SetCallbacks(
    mojo::PendingRemote<mojom::CameraModuleCallbacks> callbacks) {
  VLOGF_ENTER();
  DCHECK(camera_module_thread_.task_runner()->BelongsToCurrentThread());
  TRACE_CAMERA_SCOPED();

  auto callbacks_delegate = std::make_unique<CameraModuleCallbacksDelegate>(
      camera_module_callbacks_thread_.task_runner());
  uint32_t callbacks_id = callbacks_id_++;
  callbacks_delegate->Bind(
      std::move(callbacks),
      base::Bind(&CameraHalAdapter::ResetCallbacksDelegateOnThread,
                 base::Unretained(this), callbacks_id));

  // Send latest status to the new client, so all presented external cameras are
  // available to the client after SetCallbacks() returns.
  for (const auto& it : device_status_map_) {
    int camera_id = it.first;
    camera_device_status_t device_status = it.second;
    if (device_status != default_device_status_map_[camera_id]) {
      NotifyCameraDeviceStatusChange(callbacks_delegate.get(), camera_id,
                                     device_status);
    }
    torch_mode_status_t torch_status = torch_mode_status_map_[camera_id];
    if (torch_status != default_torch_mode_status_map_[camera_id]) {
      NotifyTorchModeStatusChange(callbacks_delegate.get(), camera_id,
                                  torch_status);
    }
  }

  base::AutoLock l(callbacks_delegates_lock_);
  callbacks_delegates_[callbacks_id] = std::move(callbacks_delegate);

  return 0;
}

int32_t CameraHalAdapter::SetTorchMode(int32_t camera_id, bool enabled) {
  VLOGF_ENTER();
  DCHECK(camera_module_thread_.task_runner()->BelongsToCurrentThread());
  TRACE_CAMERA_SCOPED();

  camera_module_t* camera_module;
  int internal_camera_id;
  std::tie(camera_module, internal_camera_id) =
      GetInternalModuleAndId(camera_id);

  if (!camera_module) {
    return -EINVAL;
  }

  if (auto fn = camera_module->set_torch_mode) {
    return fn(std::to_string(internal_camera_id).c_str(), enabled);
  }

  return -ENOSYS;
}

int32_t CameraHalAdapter::Init() {
  VLOGF_ENTER();
  DCHECK(camera_module_thread_.task_runner()->BelongsToCurrentThread());
  TRACE_CAMERA_SCOPED();
  return 0;
}

void CameraHalAdapter::GetVendorTagOps(
    mojo::PendingReceiver<mojom::VendorTagOps> vendor_tag_ops_receiver) {
  VLOGF_ENTER();
  DCHECK(camera_module_thread_.task_runner()->BelongsToCurrentThread());

  auto vendor_tag_ops_delegate = std::make_unique<VendorTagOpsDelegate>(
      camera_module_thread_.task_runner(), &vendor_tag_manager_);
  uint32_t vendor_tag_ops_id = vendor_tag_ops_id_++;
  vendor_tag_ops_delegate->Bind(
      std::move(vendor_tag_ops_receiver),
      base::Bind(&CameraHalAdapter::ResetVendorTagOpsDelegateOnThread,
                 base::Unretained(this), vendor_tag_ops_id));
  vendor_tag_ops_delegates_[vendor_tag_ops_id] =
      std::move(vendor_tag_ops_delegate);
  VLOGF(1) << "VendorTagOps " << vendor_tag_ops_id << " connected";
}

void CameraHalAdapter::CloseDeviceCallback(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
    int32_t camera_id,
    mojom::CameraClientType camera_client_type) {
  task_runner->PostTask(FROM_HERE, base::Bind(&CameraHalAdapter::CloseDevice,
                                              base::Unretained(this), camera_id,
                                              camera_client_type));
}

// static
void CameraHalAdapter::camera_device_status_change(
    const camera_module_callbacks_t* callbacks,
    int internal_camera_id,
    int new_status) {
  VLOGF_ENTER();
  TRACE_CAMERA_SCOPED();

  auto* aux = static_cast<const CameraModuleCallbacksAux*>(callbacks);
  CameraHalAdapter* self = aux->adapter;
  self->camera_module_thread_.task_runner()->PostTask(
      FROM_HERE, base::Bind(&CameraHalAdapter::CameraDeviceStatusChange,
                            base::Unretained(self), aux, internal_camera_id,
                            static_cast<camera_device_status_t>(new_status)));
}

// static
void CameraHalAdapter::torch_mode_status_change(
    const camera_module_callbacks_t* callbacks,
    const char* internal_camera_id,
    int new_status) {
  VLOGF_ENTER();
  TRACE_CAMERA_SCOPED();

  auto* aux = static_cast<const CameraModuleCallbacksAux*>(callbacks);
  CameraHalAdapter* self = aux->adapter;
  self->camera_module_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&CameraHalAdapter::TorchModeStatusChange,
                 base::Unretained(self), aux, atoi(internal_camera_id),
                 static_cast<torch_mode_status_t>(new_status)));
}

const camera_metadata_t* CameraHalAdapter::GetUpdatedCameraMetadata(
    int camera_id,
    mojom::CameraClientType camera_client_type,
    const camera_metadata_t* static_metadata) {
  auto& metadata_scoped =
      static_metadata_map_[std::make_pair(camera_id, camera_client_type)];
  if (metadata_scoped) {
    return metadata_scoped.get()->getAndLock();
  }

  metadata_scoped = std::make_unique<android::CameraMetadata>();
  auto* metadata = metadata_scoped.get();
  metadata->acquire(clone_camera_metadata(static_metadata));
  reprocess_effect_manager_.UpdateStaticMetadata(metadata);
  if (ZslHelper::TryAddEnableZslKey(metadata)) {
    LOGF(INFO) << "Will attempt to enable ZSL by private reprocessing";
    can_attempt_zsl_camera_ids_.insert(camera_id);
  }
  return metadata->getAndLock();
}

void CameraHalAdapter::CameraDeviceStatusChange(
    const CameraModuleCallbacksAux* aux,
    int internal_camera_id,
    camera_device_status_t new_status) {
  VLOGF_ENTER();
  DCHECK(camera_module_thread_.task_runner()->BelongsToCurrentThread());
  TRACE_CAMERA_SCOPED();

  int external_camera_id = GetExternalId(aux->module_id, internal_camera_id);

  LOGF(INFO) << "module_id = " << aux->module_id
             << ", internal_camera_id = " << internal_camera_id
             << ", new_status = " << new_status;

  switch (new_status) {
    case CAMERA_DEVICE_STATUS_PRESENT:
      if (external_camera_id == -1) {
        external_camera_id = next_external_camera_id_++;
        camera_id_map_[external_camera_id] =
            std::make_pair(aux->module_id, internal_camera_id);
        camera_id_inverse_map_[aux->module_id][internal_camera_id] =
            external_camera_id;
        device_status_map_[external_camera_id] = CAMERA_DEVICE_STATUS_PRESENT;
        default_device_status_map_[external_camera_id] =
            CAMERA_DEVICE_STATUS_NOT_PRESENT;
        torch_mode_status_map_[external_camera_id] =
            TORCH_MODE_STATUS_NOT_AVAILABLE;
        default_torch_mode_status_map_[external_camera_id] =
            TORCH_MODE_STATUS_NOT_AVAILABLE;
      } else {
        device_status_map_[external_camera_id] = CAMERA_DEVICE_STATUS_PRESENT;
      }
      LOGF(INFO) << "External camera plugged, external_camera_id = "
                 << external_camera_id;
      break;
    case CAMERA_DEVICE_STATUS_NOT_PRESENT:
      if (external_camera_id != -1) {
        device_status_map_[external_camera_id] =
            CAMERA_DEVICE_STATUS_NOT_PRESENT;
        torch_mode_status_map_[external_camera_id] =
            default_torch_mode_status_map_[external_camera_id];
        auto it = device_adapters_.find(external_camera_id);
        if (it != device_adapters_.end()) {
          device_adapters_.erase(it);
        }
        LOGF(INFO) << "External camera unplugged"
                   << ", external_camera_id = " << external_camera_id;
      } else {
        LOGF(WARNING) << "Ignore nonexistent camera";
      }
      break;
    default:
      // TODO(shik): What about CAMERA_DEVICE_STATUS_ENUMERATING?
      NOTREACHED() << "Unexpected new status " << new_status;
      break;
  }

  base::AutoLock l(callbacks_delegates_lock_);
  for (auto& it : callbacks_delegates_) {
    NotifyCameraDeviceStatusChange(it.second.get(), external_camera_id,
                                   new_status);
  }
  for (auto& it : callbacks_associated_delegates_) {
    NotifyCameraDeviceStatusChange(it.second.get(), external_camera_id,
                                   new_status);
  }
}

void CameraHalAdapter::TorchModeStatusChange(
    const CameraModuleCallbacksAux* aux,
    int internal_camera_id,
    torch_mode_status_t new_status) {
  VLOGF_ENTER();
  DCHECK(camera_module_thread_.task_runner()->BelongsToCurrentThread());
  TRACE_CAMERA_SCOPED();

  int camera_id = GetExternalId(aux->module_id, internal_camera_id);
  if (camera_id == -1) {
    LOGF(WARNING) << "Ignore nonexistent camera"
                  << ", module_id = " << aux->module_id
                  << ", camera_id = " << internal_camera_id;
    return;
  }

  torch_mode_status_map_[camera_id] = new_status;

  base::AutoLock l(callbacks_delegates_lock_);
  for (auto& it : callbacks_delegates_) {
    NotifyTorchModeStatusChange(it.second.get(), camera_id, new_status);
  }
  for (auto& it : callbacks_associated_delegates_) {
    NotifyTorchModeStatusChange(it.second.get(), camera_id, new_status);
  }
}

void CameraHalAdapter::StartOnThread(base::Callback<void(bool)> callback) {
  VLOGF_ENTER();
  DCHECK(camera_module_thread_.task_runner()->BelongsToCurrentThread());

  if (reprocess_effect_manager_.Initialize(mojo_manager_token_) != 0) {
    LOGF(ERROR) << "Failed to initialize reprocess effect manager";
    callback.Run(false);
    return;
  }

  if (!vendor_tag_manager_.Add(&reprocess_effect_manager_)) {
    LOGF(ERROR) << "Failed to add the vendor tags of reprocess effect manager";
    callback.Run(false);
    return;
  }

  // The setup sequence for each camera HAL:
  //   1. get_vendor_tag_ops()
  //   2. init()
  //   3. get_number_of_cameras()
  //   4. set_callbacks()
  //   5. get_camera_info()
  //
  // Normally, init() is the first invoked method in the sequence.  But init()
  // might manipulate vendor tags with libcamera_metadata, which requires
  // set_camera_metadata_vendor_ops() to be invoked already.  To prepare the
  // aggregated |vendor_tag_ops| for set_camera_metadata_vendor_ops(), we need
  // to collect |vendor_tag_ops| from all camera modules by calling
  // get_vendor_tag_ops() first, which should be fine as it just set some
  // function pointers in the struct.
  //
  // Note that camera HALs MAY run callbacks before set_callbacks() returns.

  for (const auto& interface : camera_interfaces_) {
    camera_module_t* m = interface.first;
    if (m->get_vendor_tag_ops) {
      vendor_tag_ops ops = {};
      m->get_vendor_tag_ops(&ops);
      if (ops.get_tag_count == nullptr) {
        continue;
      }
      if (!vendor_tag_manager_.Add(&ops)) {
        LOGF(ERROR) << "Failed to add the vendor tags of camera module "
                    << std::quoted(m->common.name);
        callback.Run(false);
        return;
      }
    }
  }

  if (set_camera_metadata_vendor_ops(&vendor_tag_manager_) != 0) {
    LOGF(ERROR) << "Failed to set vendor ops to camera metadata";
  }

  const bool force_start =
      base::PathExists(base::FilePath(constants::kForceStartCrosCameraPath));
  for (auto iter = camera_interfaces_.begin();
       iter != camera_interfaces_.end();) {
    camera_module_t* m = iter->first;
    if (m->init) {
      int ret = m->init();
      if (ret != 0) {
        if (force_start) {
          LOGF(WARNING) << "Disabled camera module "
                        << std::quoted(m->common.name)
                        << " to force start cros-camera";
          iter = camera_interfaces_.erase(iter);
          continue;
        }
        LOGF(ERROR) << "Failed to init camera module "
                    << std::quoted(m->common.name);
        callback.Run(false);
        return;
      }
    }
    iter++;
  }
  CHECK_GT(camera_interfaces_.size(), 0);

  std::vector<std::tuple<int, int, int>> cameras;
  std::vector<std::vector<bool>> has_flash_unit(camera_interfaces_.size());

  camera_id_inverse_map_.resize(camera_interfaces_.size());
  for (size_t module_id = 0; module_id < camera_interfaces_.size();
       module_id++) {
    camera_module_t* m = camera_interfaces_[module_id].first;

    int n = m->get_number_of_cameras();
    LOGF(INFO) << "Camera module " << std::quoted(m->common.name) << " has "
               << n << " built-in camera(s)";

    auto aux = std::make_unique<CameraModuleCallbacksAux>();
    aux->camera_device_status_change = camera_device_status_change;
    aux->torch_mode_status_change = torch_mode_status_change;
    aux->module_id = module_id;
    aux->adapter = this;
    if (m->set_callbacks(aux.get()) != 0) {
      LOGF(ERROR) << "Failed to set_callbacks on camera module " << module_id;
      callback.Run(false);
      return;
    }
    callbacks_auxs_.push_back(std::move(aux));

    for (int camera_id = 0; camera_id < n; camera_id++) {
      camera_info_t info;
      if (m->get_camera_info(camera_id, &info) != 0) {
        LOGF(ERROR) << "Failed to get info of camera " << camera_id
                    << " from module " << module_id;
        callback.Run(false);
        return;
      }

      camera_metadata_ro_entry_t entry;
      if (find_camera_metadata_ro_entry(info.static_camera_characteristics,
                                        ANDROID_FLASH_INFO_AVAILABLE,
                                        &entry) != 0) {
        LOGF(ERROR) << "Failed to get flash info in metadata of camera "
                    << camera_id << " from module " << module_id;
        callback.Run(false);
        return;
      }

      cameras.emplace_back(info.facing, static_cast<int>(module_id), camera_id);
      has_flash_unit[module_id].push_back(entry.data.u8[0] ==
                                          ANDROID_FLASH_INFO_AVAILABLE_TRUE);
    }
  }

  sort(cameras.begin(), cameras.end());
  for (size_t i = 0; i < cameras.size(); i++) {
    int module_id = std::get<1>(cameras[i]);
    int camera_id = std::get<2>(cameras[i]);
    camera_id_map_[i] = std::make_pair(module_id, camera_id);
    camera_id_inverse_map_[module_id][camera_id] = i;
    device_status_map_[i] = CAMERA_DEVICE_STATUS_PRESENT;
    default_device_status_map_[i] = device_status_map_[i];
    torch_mode_status_map_[i] = has_flash_unit[module_id][camera_id]
                                    ? TORCH_MODE_STATUS_AVAILABLE_OFF
                                    : TORCH_MODE_STATUS_NOT_AVAILABLE;
    default_torch_mode_status_map_[i] = torch_mode_status_map_[i];
  }

  num_builtin_cameras_ = cameras.size();
  next_external_camera_id_ = num_builtin_cameras_;

  LOGF(INFO) << "SuperHAL started with " << camera_interfaces_.size()
             << " modules and " << num_builtin_cameras_ << " built-in cameras";

  callback.Run(true);
}

void CameraHalAdapter::NotifyCameraDeviceStatusChange(
    CameraModuleCallbacksDelegate* delegate,
    int camera_id,
    camera_device_status_t status) {
  delegate->CameraDeviceStatusChange(camera_id, status);
}

void CameraHalAdapter::NotifyCameraDeviceStatusChange(
    CameraModuleCallbacksAssociatedDelegate* delegate,
    int camera_id,
    camera_device_status_t status) {
  delegate->CameraDeviceStatusChange(camera_id, status);
}

void CameraHalAdapter::NotifyTorchModeStatusChange(
    CameraModuleCallbacksDelegate* delegate,
    int camera_id,
    torch_mode_status_t status) {
  delegate->TorchModeStatusChange(camera_id, status);
}

void CameraHalAdapter::NotifyTorchModeStatusChange(
    CameraModuleCallbacksAssociatedDelegate* delegate,
    int camera_id,
    torch_mode_status_t status) {
  delegate->TorchModeStatusChange(camera_id, status);
}

std::pair<camera_module_t*, int> CameraHalAdapter::GetInternalModuleAndId(
    int camera_id) {
  if (camera_id_map_.find(camera_id) == camera_id_map_.end()) {
    LOGF(ERROR) << "Invalid camera id: " << camera_id;
    return {};
  }
  std::pair<int, int> idx = camera_id_map_[camera_id];
  return {camera_interfaces_[idx.first].first, idx.second};
}

int CameraHalAdapter::GetExternalId(int module_id, int camera_id) {
  if (module_id < 0 ||
      static_cast<size_t>(module_id) >= camera_id_inverse_map_.size()) {
    return -1;
  }

  std::map<int, int>& id_map = camera_id_inverse_map_[module_id];
  auto it = id_map.find(camera_id);
  return it != id_map.end() ? it->second : -1;
}

void CameraHalAdapter::CloseDevice(int32_t camera_id,
                                   mojom::CameraClientType camera_client_type) {
  VLOGF_ENTER();
  DCHECK(camera_module_thread_.task_runner()->BelongsToCurrentThread());
  TRACE_CAMERA_SCOPED("camera_id", camera_id);
  LOGF(INFO) << camera_client_type << ", camera_id = " << camera_id;
  if (device_adapters_.find(camera_id) == device_adapters_.end()) {
    LOGF(ERROR) << "Failed to close camera device " << camera_id
                << ": device is not opened";
    return;
  }
  device_adapters_.erase(camera_id);

  activity_callback_.Run(camera_id, /*opened=*/false, camera_client_type);

  camera_metrics_->SendSessionDuration(session_timer_map_[camera_id].Elapsed());
  session_timer_map_.erase(camera_id);
}

void CameraHalAdapter::ResetModuleDelegateOnThread(uint32_t module_id) {
  VLOGF_ENTER();
  DCHECK(camera_module_thread_.task_runner()->BelongsToCurrentThread());
  base::AutoLock l(module_delegates_lock_);
  if (module_id == kIdAll) {
    module_delegates_.clear();
  } else {
    module_delegates_.erase(module_id);
  }
}

void CameraHalAdapter::ResetCallbacksDelegateOnThread(uint32_t callbacks_id) {
  VLOGF_ENTER();
  DCHECK(
      camera_module_callbacks_thread_.task_runner()->BelongsToCurrentThread());
  base::AutoLock l(callbacks_delegates_lock_);
  if (callbacks_id == kIdAll) {
    callbacks_delegates_.clear();
    callbacks_associated_delegates_.clear();
  } else {
    callbacks_delegates_.erase(callbacks_id);
    callbacks_associated_delegates_.erase(callbacks_id);
  }
}

void CameraHalAdapter::ResetVendorTagOpsDelegateOnThread(
    uint32_t vendor_tag_ops_id) {
  VLOGF_ENTER();
  DCHECK(camera_module_thread_.task_runner()->BelongsToCurrentThread());
  base::AutoLock l(module_delegates_lock_);
  if (vendor_tag_ops_id == kIdAll) {
    vendor_tag_ops_delegates_.clear();
  } else {
    vendor_tag_ops_delegates_.erase(vendor_tag_ops_id);
  }
}

int32_t CameraHalAdapter::SetCallbacksAssociated(
    mojo::PendingAssociatedRemote<mojom::CameraModuleCallbacks> callbacks) {
  VLOGF_ENTER();
  DCHECK(camera_module_thread_.task_runner()->BelongsToCurrentThread());
  TRACE_CAMERA_SCOPED();

  auto callbacks_delegate =
      std::make_unique<CameraModuleCallbacksAssociatedDelegate>(
          camera_module_callbacks_thread_.task_runner());
  uint32_t callbacks_id = callbacks_id_++;
  callbacks_delegate->Bind(
      std::move(callbacks),
      base::Bind(&CameraHalAdapter::ResetCallbacksDelegateOnThread,
                 base::Unretained(this), callbacks_id));

  // Send latest status to the new client, so all presented external cameras are
  // available to the client after SetCallbacks() returns.
  for (const auto& it : device_status_map_) {
    int camera_id = it.first;
    camera_device_status_t device_status = it.second;
    if (device_status != default_device_status_map_[camera_id]) {
      NotifyCameraDeviceStatusChange(callbacks_delegate.get(), camera_id,
                                     device_status);
    }
    torch_mode_status_t torch_status = torch_mode_status_map_[camera_id];
    if (torch_status != default_torch_mode_status_map_[camera_id]) {
      NotifyTorchModeStatusChange(callbacks_delegate.get(), camera_id,
                                  torch_status);
    }
  }

  base::AutoLock l(callbacks_delegates_lock_);
  callbacks_associated_delegates_[callbacks_id] = std::move(callbacks_delegate);

  return 0;
}
}  // namespace cros
