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

#include <algorithm>
#include <limits>
#include <utility>

#include <base/bind.h>
#include <base/check.h>
#include <base/check_op.h>
#include <base/files/file_util.h>
#include <base/no_destructor.h>
#include <base/strings/string_util.h>
#include <base/threading/thread_task_runner_handle.h>

#include <chromeos-config/libcros_config/cros_config.h>
#include "cros-camera/common.h"
#include "cros-camera/constants.h"
#include "cros-camera/cros_camera_hal.h"
#include "cros-camera/udev_watcher.h"
#include "cros-camera/utils/camera_config.h"
#include "hal/usb/camera_characteristics.h"
#include "hal/usb/common_types.h"
#include "hal/usb/metadata_handler.h"
#include "hal/usb/quirks.h"
#include "hal/usb/stream_format.h"
#include "hal/usb/v4l2_camera_device.h"
#include "hal/usb/vendor_tag.h"

namespace cros {

namespace {

// https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics#SENSOR_INFO_EXPOSURE_TIME_RANGE
constexpr int64_t kMaxMinExposureTime = 100000;  // 100us

bool FillMetadata(const DeviceInfo& device_info,
                  android::CameraMetadata* static_metadata,
                  android::CameraMetadata* request_metadata) {
  if (MetadataHandler::FillDefaultMetadata(static_metadata, request_metadata) !=
      0) {
    return false;
  }

  if (MetadataHandler::FillMetadataFromDeviceInfo(device_info, static_metadata,
                                                  request_metadata) != 0) {
    return false;
  }

  SupportedFormats supported_formats =
      V4L2CameraDevice::GetDeviceSupportedFormats(device_info.device_path);
  SupportedFormats qualified_formats =
      GetQualifiedFormats(supported_formats, device_info.quirks);
  if (MetadataHandler::FillMetadataFromSupportedFormats(
          qualified_formats, device_info, static_metadata, request_metadata) !=
      0) {
    return false;
  }

  if (!device_info.usb_vid.empty()) {
    static_metadata->update(kVendorTagVendorId, device_info.usb_vid);
  }
  if (!device_info.usb_pid.empty()) {
    static_metadata->update(kVendorTagProductId, device_info.usb_pid);
  }
  static_metadata->update(kVendorTagDevicePath, device_info.device_path);
  static_metadata->update(kVendorTagModelName, V4L2CameraDevice::GetModelName(
                                                   device_info.device_path));

  return true;
}

void AdjustMetadataForAE(android::CameraMetadata* data) {
  camera_metadata_entry_t entry =
      data->find(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE);
  if (entry.count == 0) {
    return;
  }

  if (entry.data.i64[0] <= kMaxMinExposureTime)
    return;

  LOGF(INFO) << "Remove AE related metadata";

  if (data->erase(ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE) != 0)
    LOGF(WARNING) << "Fail to delete ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE";

  data->update(ANDROID_CONTROL_AE_AVAILABLE_MODES,
               std::vector<uint8_t>{ANDROID_CONTROL_AE_MODE_ON});

  // Remove ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE in
  // ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS
  entry = data->find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
  if (entry.count != 0) {
    std::vector<int32_t> available_characteristics_keys;
    for (size_t i = 0; i < entry.count; i++) {
      if (entry.data.i32[i] == ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE) {
        continue;
      }
      available_characteristics_keys.push_back(entry.data.i32[i]);
    }
    data->update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
                 available_characteristics_keys);
  }
  // Remove ANDROID_SENSOR_EXPOSURE_TIME in
  // ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS
  entry = data->find(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS);
  if (entry.count != 0) {
    std::vector<int32_t> available_request_keys;
    for (size_t i = 0; i < entry.count; i++) {
      if (entry.data.i32[i] == ANDROID_SENSOR_EXPOSURE_TIME) {
        continue;
      }
      available_request_keys.push_back(entry.data.i32[i]);
    }
    data->update(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
                 available_request_keys);
  }
}

// TODO(mojahsu): Make it work on android side.
void AdjustMetadataForFaceDetection(android::CameraMetadata* data) {
  camera_metadata_entry_t entry =
      data->find(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES);
  // Only support ANDROID_STATISTICS_FACE_DETECT_MODE_OFF or no such metadata.
  if (entry.count <= 1) {
    return;
  }

  LOGF(INFO) << "Remove Face Detection related metadata";

  data->update(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES,
               std::vector<uint8_t>{ANDROID_STATISTICS_FACE_DETECT_MODE_OFF});
  data->update(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, std::vector<int32_t>{0});
}

ScopedCameraMetadata StaticMetadataForAndroid(
    const android::CameraMetadata& static_metadata) {
  android::CameraMetadata data(static_metadata);
  std::vector<int32_t> stream_configurations;

  std::unique_ptr<CameraConfig> camera_config =
      CameraConfig::Create(constants::kCrosCameraConfigPathString);
  int max_width =
      camera_config->GetInteger(constants::kCrosUsbAndroidMaxStreamWidth,
                                std::numeric_limits<int>::max());
  int max_height =
      camera_config->GetInteger(constants::kCrosUsbAndroidMaxStreamHeight,
                                std::numeric_limits<int>::max());
  camera_metadata_entry entry =
      data.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);

  for (size_t i = 0; i < entry.count; i += 4) {
    if (entry.data.i32[i] != HAL_PIXEL_FORMAT_BLOB) {
      if (entry.data.i32[i + 1] > max_width ||
          entry.data.i32[i + 2] > max_height) {
        LOGF(INFO) << "Filter Format: 0x" << std::hex << entry.data.i32[i]
                   << std::dec << "-" << entry.data.i32[i + 1] << "x"
                   << entry.data.i32[i + 2] << " for Android";
        continue;
      }
    }
    stream_configurations.push_back(entry.data.i32[i]);
    stream_configurations.push_back(entry.data.i32[i + 1]);
    stream_configurations.push_back(entry.data.i32[i + 2]);
    stream_configurations.push_back(entry.data.i32[i + 3]);
  }
  data.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
              stream_configurations);

  AdjustMetadataForAE(&data);
  AdjustMetadataForFaceDetection(&data);

  return ScopedCameraMetadata(data.release());
}

ScopedCameraMetadata RequestTemplateForAndroid(
    const camera_metadata_t* static_metadata,
    const android::CameraMetadata& request_template) {
  android::CameraMetadata data(request_template);

  camera_metadata_ro_entry ae_available_modes_entry;
  int ret = find_camera_metadata_ro_entry(static_metadata,
                                          ANDROID_CONTROL_AE_AVAILABLE_MODES,
                                          &ae_available_modes_entry);
  if (ret == 0) {
    // Only support ANDROID_CONTROL_AE_MODE_ON
    if (ae_available_modes_entry.count == 1) {
      camera_metadata_entry entry = data.find(ANDROID_SENSOR_EXPOSURE_TIME);
      if (entry.count == 1 && data.erase(ANDROID_SENSOR_EXPOSURE_TIME) != 0)
        LOGF(WARNING) << "Failed to delete ANDROID_SENSOR_EXPOSURE_TIME";
    }
  }

  return ScopedCameraMetadata(data.release());
}

bool IsVivid(udev_device* dev) {
  const char* product = udev_device_get_property_value(dev, "ID_V4L_PRODUCT");
  return product && strcmp(product, "vivid") == 0;
}

const char* GetPreferredPath(udev_device* dev) {
  if (IsVivid(dev)) {
    // Multiple vivid devices may have the same symlink at
    // /dev/v4l/by-path/platform-vivid.0-video-index0, so we use /dev/videoX
    // directly for vivid.
    return udev_device_get_devnode(dev);
  }

  for (udev_list_entry* entry = udev_device_get_devlinks_list_entry(dev);
       entry != nullptr; entry = udev_list_entry_get_next(entry)) {
    const char* name = udev_list_entry_get_name(entry);

    if (!name) {
      LOGF(WARNING) << "udev_list_entry_get_name failed";
      continue;
    }

    // The symlinks in /dev/v4l/by-path/ are generated by
    // 60-persistent-v4l.rules, and supposed to be persistent for built-in
    // cameras so we can safely reuse it across suspend/resume cycles, without
    // updating |path_to_id_| for them.
    // TODO(shik): Fix https://github.com/systemd/systemd/issues/10683 in the
    // upstream udev.
    if (base::StartsWith(name, "/dev/v4l/by-path/",
                         base::CompareCase::SENSITIVE)) {
      return name;
    }
  }

  return udev_device_get_devnode(dev);
}

std::string GetModelId(const DeviceInfo& info) {
  if (info.is_vivid) {
    return "vivid";
  }
  return base::JoinString({info.usb_vid, info.usb_pid}, ":");
}

}  // namespace

CameraHal::CameraHal()
    : task_runner_(nullptr),
      udev_watcher_(std::make_unique<UdevWatcher>(this, "video4linux")),
      cros_device_config_(CrosDeviceConfig::Create()),
      camera_metrics_(CameraMetrics::New()) {
  thread_checker_.DetachFromThread();
}

CameraHal::~CameraHal() {
  udev_watcher_.reset();
}

int CameraHal::GetNumberOfCameras() const {
  return num_builtin_cameras_;
}

CameraHal& CameraHal::GetInstance() {
  static base::NoDestructor<CameraHal> camera_hal;
  return *camera_hal;
}

CameraMojoChannelManagerToken* CameraHal::GetMojoManagerToken() {
  return mojo_manager_token_;
}

int CameraHal::OpenDevice(int id,
                          const hw_module_t* module,
                          hw_device_t** hw_device,
                          ClientType client_type) {
  VLOGFID(1, id);
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!IsValidCameraId(id)) {
    LOGF(ERROR) << "Camera id " << id << " is invalid";
    return -EINVAL;
  }

  if (cameras_.find(id) != cameras_.end()) {
    LOGF(ERROR) << "Camera " << id << " is already opened";
    return -EBUSY;
  }
  if (!cameras_.empty() &&
      (cros_device_config_ != nullptr &&
       (cros_device_config_->GetModelName() == "treeya360" ||
        cros_device_config_->GetModelName() == "nuwani360" ||
        cros_device_config_->GetModelName() == "pompom"))) {
    // It cannot open multiple cameras at the same time due to USB bandwidth
    // limitation (b/147333530, b/171856355).
    // TODO(shik): Use |conflicting_devices| to implement this logic after we
    // hook that in the ARC++ camera HAL shim.
    // TODO(b/163436311): Add a new field in the unibuild schema instead of
    // checking model name here.
    LOGF(WARNING) << "Can't open Camera " << id << " because Camera "
                  << cameras_.begin()->first << " is already opened.";
    return -EUSERS;
  }

  camera_metadata_t* static_metadata;
  camera_metadata_t* request_template;
  if (client_type == ClientType::kAndroid) {
    static_metadata = static_metadata_android_[id].get();
    request_template = request_template_android_[id].get();
  } else {
    static_metadata = static_metadata_[id].get();
    request_template = request_template_[id].get();
  }
  cameras_[id].reset(new CameraClient(id, device_infos_[id], *static_metadata,
                                      *request_template, module, hw_device,
                                      &privacy_switch_monitor_, client_type));
  if (cameras_[id]->OpenDevice()) {
    cameras_.erase(id);
    return -ENODEV;
  }
  if (!task_runner_) {
    task_runner_ = base::ThreadTaskRunnerHandle::Get();
  }
  return 0;
}

bool CameraHal::IsValidCameraId(int id) {
  return device_infos_.find(id) != device_infos_.end();
}

int CameraHal::GetCameraInfo(int id,
                             struct camera_info* info,
                             ClientType client_type) {
  VLOGFID(1, id);
  DCHECK(thread_checker_.CalledOnValidThread());
  if (!IsValidCameraId(id)) {
    LOGF(ERROR) << "Camera id " << id << " is invalid";
    return -EINVAL;
  }

  switch (device_infos_[id].lens_facing) {
    case LensFacing::kFront:
      info->facing = CAMERA_FACING_FRONT;
      break;
    case LensFacing::kBack:
      info->facing = CAMERA_FACING_BACK;
      break;
    case LensFacing::kExternal:
      info->facing = CAMERA_FACING_EXTERNAL;
      break;
    default:
      LOGF(ERROR) << "Unknown lens facing: "
                  << static_cast<int>(device_infos_[id].lens_facing);
      return -EINVAL;
  }
  info->orientation = device_infos_[id].sensor_orientation;
  info->device_version = CAMERA_DEVICE_API_VERSION_3_5;
  if (client_type == ClientType::kAndroid) {
    info->static_camera_characteristics = static_metadata_android_[id].get();
  } else {
    info->static_camera_characteristics = static_metadata_[id].get();
  }
  info->resource_cost = 0;
  info->conflicting_devices = nullptr;
  info->conflicting_devices_length = 0;
  return 0;
}

int CameraHal::GetCameraInfo(int id, struct camera_info* info) {
  return GetCameraInfo(id, info, ClientType::kChrome);
}

int CameraHal::SetCallbacks(const camera_module_callbacks_t* callbacks) {
  VLOGF(1) << "New callbacks = " << callbacks;
  DCHECK(thread_checker_.CalledOnValidThread());

  callbacks_ = callbacks;

  // Some external cameras might be detected before SetCallbacks, we should
  // enumerate existing devices again after setting the callbacks.
  if (!udev_watcher_->EnumerateExistingDevices()) {
    LOGF(ERROR) << "Failed to EnumerateExistingDevices()";
  }

  return 0;
}

int CameraHal::Init() {
  DCHECK(thread_checker_.CalledOnValidThread());

  if (cros_device_config_ == nullptr) {
    LOGF(WARNING) << "Failed to initialize CrOS device config, camera HAL may "
                     "function incorrectly";
  }

  if (!udev_watcher_->Start(base::ThreadTaskRunnerHandle::Get())) {
    LOGF(ERROR) << "Failed to Start()";
    return -ENODEV;
  }

  if (!udev_watcher_->EnumerateExistingDevices()) {
    LOGF(ERROR) << "Failed to EnumerateExistingDevices()";
    return -ENODEV;
  }

  // TODO(shik): Some unibuild devices like vayne may have only user-facing
  // camera as "camera1" in |characteristics_|. It's a workaround for them until
  // we revise our config format. (b/111770440)
  if (device_infos_.size() == 1 && device_infos_.cbegin()->first == 1 &&
      num_builtin_cameras_ == 2) {
    LOGF(INFO) << "Renumber camera1 to camera0";

    device_infos_.emplace(0, std::move(device_infos_[1]));
    device_infos_.erase(1);
    device_infos_[0].camera_id = 0;

    DCHECK_EQ(path_to_id_.size(), 1);
    DCHECK_EQ(path_to_id_.begin()->second, 1);
    path_to_id_.begin()->second = 0;

    DCHECK_EQ(static_metadata_.size(), 1);
    DCHECK_EQ(static_metadata_.begin()->first, 1);
    static_metadata_.emplace(0, std::move(static_metadata_[1]));
    static_metadata_.erase(1);

    DCHECK_EQ(static_metadata_android_.size(), 1);
    DCHECK_EQ(static_metadata_android_.begin()->first, 1);
    static_metadata_android_.emplace(0, std::move(static_metadata_android_[1]));
    static_metadata_android_.erase(1);

    DCHECK_EQ(request_template_.size(), 1);
    DCHECK_EQ(request_template_.begin()->first, 1);
    request_template_.emplace(0, std::move(request_template_[1]));
    request_template_.erase(1);

    DCHECK_EQ(request_template_android_.size(), 1);
    DCHECK_EQ(request_template_android_.begin()->first, 1);
    request_template_android_.emplace(0,
                                      std::move(request_template_android_[1]));
    request_template_android_.erase(1);

    num_builtin_cameras_ = 1;
  }

  bool enough_camera_probed = true;
  if (cros_device_config_ != nullptr &&
      cros_device_config_->IsUsbCameraCountAvailable()) {
    if (num_builtin_cameras_ != cros_device_config_->GetUsbCameraCount()) {
      LOGF(ERROR) << "Expected " << cros_device_config_->GetUsbCameraCount()
                  << " cameras from Chrome OS config, found "
                  << num_builtin_cameras_;
      enough_camera_probed = false;
    }
  } else if (CameraCharacteristics::ConfigFileExists() &&
             num_builtin_cameras_ == 0) {
    // TODO(shik): possible race here. We may have 2 built-in cameras but just
    // detect one.
    LOGF(ERROR) << "Expect to find at least one camera if config file exists";
    enough_camera_probed = false;
  }
  if (!enough_camera_probed) {
    if (base::PathExists(
            base::FilePath(constants::kForceStartCrosCameraPath))) {
      LOGF(WARNING) << "Force starting cros-camera: Ignore missing built-in "
                    << "camera error to allow external camera usage";
    } else {
      return -ENODEV;
    }
  }

  for (int i = 0; i < num_builtin_cameras_; i++) {
    if (!IsValidCameraId(i)) {
      LOGF(ERROR)
          << "The camera devices should be numbered 0 through N-1, but id = "
          << i << " is missing";
      return -ENODEV;
    }
  }

  next_external_camera_id_ = num_builtin_cameras_;
  return 0;
}

void CameraHal::SetUp(CameraMojoChannelManagerToken* token) {
  mojo_manager_token_ = token;
}

void CameraHal::TearDown() {
  mojo_manager_token_ = nullptr;
}

void CameraHal::SetPrivacySwitchCallback(
    PrivacySwitchStateChangeCallback callback) {
  privacy_switch_monitor_.RegisterCallback(std::move(callback));
}

void CameraHal::CloseDeviceOnOpsThread(int id) {
  DCHECK(task_runner_);
  auto future = cros::Future<void>::Create(nullptr);
  task_runner_->PostTask(
      FROM_HERE, base::Bind(&CameraHal::CloseDevice, base::Unretained(this), id,
                            base::RetainedRef(future)));
  future->Wait();
}

void CameraHal::CloseDevice(int id, scoped_refptr<cros::Future<void>> future) {
  VLOGFID(1, id);
  DCHECK(thread_checker_.CalledOnValidThread());

  if (cameras_.find(id) == cameras_.end()) {
    LOGF(ERROR) << "Failed to close camera device " << id
                << ": device is not opened";
    future->Set();
    return;
  }
  cameras_.erase(id);
  future->Set();
}

void CameraHal::OnDeviceAdded(ScopedUdevDevicePtr dev) {
  const char* path = GetPreferredPath(dev.get());
  if (!path) {
    LOGF(ERROR) << "udev_device_get_devnode failed";
    return;
  }

  const char* vid = "";
  const char* pid = "";

  bool is_vivid = IsVivid(dev.get());
  if (!is_vivid) {
    udev_device* parent_dev = udev_device_get_parent_with_subsystem_devtype(
        dev.get(), "usb", "usb_device");
    if (!parent_dev) {
      VLOGF(2) << "Non USB device is ignored";
      return;
    }

    vid = udev_device_get_sysattr_value(parent_dev, "idVendor");
    if (!vid) {
      LOGF(ERROR) << "Failed to get vid";
      return;
    }

    pid = udev_device_get_sysattr_value(parent_dev, "idProduct");
    if (!pid) {
      LOGF(ERROR) << "Failed to get pid";
      return;
    }
  }

  {
    // We have to check this because of:
    //  1. Limitation of libudev
    //  2. Reenumeration after SetCallbacks()
    //  3. Suspend/Resume
    auto it = path_to_id_.find(path);
    if (it != path_to_id_.end()) {
      int id = it->second;
      const DeviceInfo& info = device_infos_[id];
      if (info.usb_vid == vid && info.usb_pid == pid) {
        VLOGF(1) << "Ignore " << path << " since it's already connected";
      } else {
        LOGF(ERROR) << "Device path conflict: " << path;
      }
      return;
    }
  }

  if (!V4L2CameraDevice::IsCameraDevice(path)) {
    VLOGF(1) << path << " is not a camera device";
    return;
  }

  if (is_vivid) {
    LOGF(INFO) << "New vivid camera device at " << path;
  } else {
    LOGF(INFO) << "New usb camera device at " << path << " vid: " << vid
               << " pid: " << pid;
  }

  DeviceInfo info;
  const DeviceInfo* info_ptr = characteristics_.Find(vid, pid);
  if (info_ptr != nullptr) {
    VLOGF(1) << "Found a built-in camera";
    info = *info_ptr;
    num_builtin_cameras_ = std::max(num_builtin_cameras_, info.camera_id + 1);
    if (info.constant_framerate_unsupported) {
      LOGF(WARNING) << "Camera module " << vid << ":" << pid
                    << " does not support constant frame rate";
    }
  } else {
    VLOGF(1) << "Found an external camera";
    if (callbacks_ == nullptr) {
      VLOGF(1) << "No callbacks set, ignore it for now";
      return;
    }
  }

  info.device_path = path;
  info.usb_vid = vid;
  info.usb_pid = pid;
  info.is_vivid = is_vivid;
  info.power_line_frequency = V4L2CameraDevice::GetPowerLineFrequency(path);
  info.constant_framerate_unsupported |=
      !V4L2CameraDevice::IsControlSupported(path, kControlExposureAutoPriority);
  RoiControl roi_control;
  info.region_of_interest_supported =
      V4L2CameraDevice::IsRegionOfInterestSupported(path, &roi_control);

  if (info.region_of_interest_supported) {
    if (!info.enable_face_detection) {
      camera_metrics_->SendFaceAeFunction(FaceAeFunction::kNotEnabled);
    } else if (base::PathExists(
                   base::FilePath(constants::kForceDisableFaceAePath))) {
      camera_metrics_->SendFaceAeFunction(FaceAeFunction::kForceDisabled);
    } else {
      camera_metrics_->SendFaceAeFunction(FaceAeFunction::kEnabled);
    }
  } else {
    camera_metrics_->SendFaceAeFunction(FaceAeFunction::kUnsupported);
  }
  // The force control path is managed by chrome flag, there should be only one
  // file.
  if (base::PathExists(base::FilePath(constants::kForceEnableFaceAePath))) {
    LOGF(INFO) << "force enable face ae";
    info.enable_face_detection = true;
  }
  if (base::PathExists(base::FilePath(constants::kForceDisableFaceAePath))) {
    LOGF(INFO) << "force disable face ae";
    info.enable_face_detection = false;
  }
  if (!is_vivid) {
    info.quirks |= GetQuirks(vid, pid);
  }

  // Mark the camera as v1 if it is a built-in camera and the CrOS device is
  // marked as a v1 device.
  if (info_ptr != nullptr && cros_device_config_ != nullptr &&
      cros_device_config_->IsV1Device()) {
    info.quirks |= kQuirkV1Device;
  }

  if (info_ptr == nullptr) {
    info.lens_facing = LensFacing::kExternal;

    // Try to reuse the same id for the same camera.
    std::string model_id = GetModelId(info);
    std::set<int>& preferred_ids = previous_ids_[model_id];
    if (!preferred_ids.empty()) {
      info.camera_id = *preferred_ids.begin();
      previous_ids_.erase(previous_ids_.begin());
      VLOGF(1) << "Use the previous id " << info.camera_id << " for camera "
               << model_id;
    } else {
      info.camera_id = next_external_camera_id_++;
      VLOGF(1) << "Use a new id " << info.camera_id << " for camera "
               << model_id;
    }

    // Uses software timestamp from userspace for external cameras, because the
    // hardware timestamp is not reliable and sometimes even jump backwards.
    info.quirks |= kQuirkUserSpaceTimestamp;
  }

  android::CameraMetadata static_metadata, request_template;
  if (!FillMetadata(info, &static_metadata, &request_template)) {
    if (info.lens_facing == LensFacing::kExternal) {
      LOGF(ERROR) << "FillMetadata failed, the new external "
                     "camera would be ignored";
      return;
    } else {
      LOGF(FATAL) << "FillMetadata failed for a built-in "
                     "camera, please check your camera config";
    }
  }

  path_to_id_[info.device_path] = info.camera_id;
  device_infos_[info.camera_id] = info;
  static_metadata_android_[info.camera_id] =
      StaticMetadataForAndroid(static_metadata);
  request_template_android_[info.camera_id] = RequestTemplateForAndroid(
      static_metadata_android_[info.camera_id].get(), request_template);
  static_metadata_[info.camera_id] =
      ScopedCameraMetadata(static_metadata.release());
  request_template_[info.camera_id] =
      ScopedCameraMetadata(request_template.release());

  privacy_switch_monitor_.TrySubscribe(info.camera_id, info.device_path);

  if (info.lens_facing == LensFacing::kExternal) {
    callbacks_->camera_device_status_change(callbacks_, info.camera_id,
                                            CAMERA_DEVICE_STATUS_PRESENT);
  }
}

void CameraHal::OnDeviceRemoved(ScopedUdevDevicePtr dev) {
  const char* path = GetPreferredPath(dev.get());
  if (!path) {
    LOGF(ERROR) << "udev_device_get_devnode failed";
    return;
  }

  auto it = path_to_id_.find(path);
  if (it == path_to_id_.end()) {
    VLOGF(1) << "Cannot found id for " << path << ", ignore it";
    return;
  }

  int id = it->second;

  if (id < num_builtin_cameras_) {
    VLOGF(1) << "Camera " << id << "is a built-in camera, ignore it";
    return;
  }

  privacy_switch_monitor_.Unsubscribe(id);

  LOGF(INFO) << "Camera " << id << " at " << path << " removed";

  // TODO(shik): Handle this more gracefully, sometimes it even trigger a kernel
  // panic.
  if (cameras_.find(id) != cameras_.end()) {
    LOGF(WARNING)
        << "Unplug an opening camera, exit the camera service to cleanup";
    // Upstart will start the service again.
    _exit(EIO);
  }

  previous_ids_[GetModelId(device_infos_[id])].insert(id);

  path_to_id_.erase(it);
  device_infos_.erase(id);
  static_metadata_.erase(id);
  static_metadata_android_.erase(id);
  request_template_.erase(id);
  request_template_android_.erase(id);

  if (callbacks_) {
    callbacks_->camera_device_status_change(callbacks_, id,
                                            CAMERA_DEVICE_STATUS_NOT_PRESENT);
  }
}

static int camera_device_open_ext(const hw_module_t* module,
                                  const char* name,
                                  hw_device_t** device,
                                  ClientType client_type) {
  VLOGF_ENTER();
  // Make sure hal adapter loads the correct symbol.
  if (module != &HAL_MODULE_INFO_SYM.common) {
    LOGF(ERROR) << std::hex << "Invalid module 0x" << module << " expected 0x"
                << &HAL_MODULE_INFO_SYM.common << std::dec;
    return -EINVAL;
  }

  char* nameEnd;
  int id = strtol(name, &nameEnd, 10);
  if (*nameEnd != '\0') {
    LOGF(ERROR) << "Invalid camera name " << name;
    return -EINVAL;
  }

  return CameraHal::GetInstance().OpenDevice(id, module, device, client_type);
}

static int camera_device_open(const hw_module_t* module,
                              const char* name,
                              hw_device_t** device) {
  return camera_device_open_ext(module, name, device, ClientType::kChrome);
}

static int get_number_of_cameras() {
  return CameraHal::GetInstance().GetNumberOfCameras();
}

static int get_camera_info(int id, struct camera_info* info) {
  return CameraHal::GetInstance().GetCameraInfo(id, info);
}

static int set_callbacks(const camera_module_callbacks_t* callbacks) {
  return CameraHal::GetInstance().SetCallbacks(callbacks);
}

static void get_vendor_tag_ops(vendor_tag_ops_t* ops) {
  ops->get_all_tags = VendorTagOps::GetAllTags;
  ops->get_tag_count = VendorTagOps::GetTagCount;
  ops->get_section_name = VendorTagOps::GetSectionName;
  ops->get_tag_name = VendorTagOps::GetTagName;
  ops->get_tag_type = VendorTagOps::GetTagType;
}

static int open_legacy(const struct hw_module_t* /*module*/,
                       const char* /*id*/,
                       uint32_t /*halVersion*/,
                       struct hw_device_t** /*device*/) {
  return -ENOSYS;
}

static int set_torch_mode(const char* /*camera_id*/, bool /*enabled*/) {
  return -ENOSYS;
}

static int init() {
  return CameraHal::GetInstance().Init();
}

static void set_up(CameraMojoChannelManagerToken* token) {
  CameraHal::GetInstance().SetUp(token);
}

static void tear_down() {
  CameraHal::GetInstance().TearDown();
}

static void set_privacy_switch_callback(
    PrivacySwitchStateChangeCallback callback) {
  CameraHal::GetInstance().SetPrivacySwitchCallback(std::move(callback));
}

static int get_camera_info_ext(int id,
                               struct camera_info* info,
                               ClientType client_type) {
  return CameraHal::GetInstance().GetCameraInfo(id, info, client_type);
}

int camera_device_close(struct hw_device_t* hw_device) {
  camera3_device_t* cam_dev = reinterpret_cast<camera3_device_t*>(hw_device);
  CameraClient* cam = static_cast<CameraClient*>(cam_dev->priv);
  if (!cam) {
    LOGF(ERROR) << "Camera device is NULL";
    return -EIO;
  }
  cam_dev->priv = NULL;
  int ret = cam->CloseDevice();
  CameraHal::GetInstance().CloseDeviceOnOpsThread(cam->GetId());
  return ret;
}

}  // namespace cros

static hw_module_methods_t gCameraModuleMethods = {
    .open = cros::camera_device_open};

camera_module_t HAL_MODULE_INFO_SYM CROS_CAMERA_EXPORT = {
    .common = {.tag = HARDWARE_MODULE_TAG,
               .module_api_version = CAMERA_MODULE_API_VERSION_2_4,
               .hal_api_version = HARDWARE_HAL_API_VERSION,
               .id = CAMERA_HARDWARE_MODULE_ID,
               .name = "V4L2 UVC Camera HAL v3",
               .author = "The Chromium OS Authors",
               .methods = &gCameraModuleMethods,
               .dso = NULL,
               .reserved = {0}},
    .get_number_of_cameras = cros::get_number_of_cameras,
    .get_camera_info = cros::get_camera_info,
    .set_callbacks = cros::set_callbacks,
    .get_vendor_tag_ops = cros::get_vendor_tag_ops,
    .open_legacy = cros::open_legacy,
    .set_torch_mode = cros::set_torch_mode,
    .init = cros::init,
    .reserved = {0}};

cros::cros_camera_hal_t CROS_CAMERA_HAL_INFO_SYM CROS_CAMERA_EXPORT = {
    .set_up = cros::set_up,
    .tear_down = cros::tear_down,
    .set_privacy_switch_callback = cros::set_privacy_switch_callback,
    .camera_device_open_ext = cros::camera_device_open_ext,
    .get_camera_info_ext = cros::get_camera_info_ext};
