/* 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 <utility>

#include <base/bind.h>
#include <base/strings/string_util.h>
#include <base/threading/thread_task_runner_handle.h>

#include "cros-camera/common.h"
#include "cros-camera/udev_watcher.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 {

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;
}

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()) {
  thread_checker_.DetachFromThread();
}

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

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

CameraHal& CameraHal::GetInstance() {
  static 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) {
  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;
  }
  cameras_[id].reset(new CameraClient(id, device_infos_[id],
                                      *static_metadata_[id].get(),
                                      *request_template_[id].get(), module,
                                      hw_device, &privacy_switch_monitor_));
  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) {
  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_3;
  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::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(request_template_.size(), 1);
    DCHECK_EQ(request_template_.begin()->first, 1);
    request_template_.emplace(0, std::move(request_template_[1]));
    request_template_.erase(1);

    num_builtin_cameras_ = 1;
  }

  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_;
      return -ENODEV;
    }
  } else {
    // TODO(shik): possible race here. We may have 2 built-in cameras but just
    // detect one.
    if (CameraCharacteristics::ConfigFileExists() &&
        num_builtin_cameras_ == 0) {
      LOGF(ERROR) << "Expect to find at least one camera if config file exists";
      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::IsConstantFrameRateSupported(path);
  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_[info.camera_id] =
      ScopedCameraMetadata(static_metadata.release());
  request_template_[info.camera_id] =
      ScopedCameraMetadata(request_template.release());

  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;
  }

  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);
  request_template_.erase(id);

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

static int camera_device_open(const hw_module_t* module,
                              const char* name,
                              hw_device_t** device) {
  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);
}

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));
}

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};
