/*
 * Copyright 2017 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_server_impl.h"

#include <dlfcn.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <unistd.h>

#include <deque>
#include <string>
#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/logging.h>
#include <base/posix/safe_strerror.h>
#include <base/threading/thread_task_runner_handle.h>

#include "common/camera_mojo_channel_manager_impl.h"
#include "common/utils/camera_hal_enumerator.h"
#include "cros-camera/camera_mojo_channel_manager.h"
#include "cros-camera/common.h"
#include "cros-camera/future.h"
#include "cros-camera/ipc_util.h"
#include "cros-camera/utils/camera_config.h"
#include "hal_adapter/camera_hal_test_adapter.h"
#include "hal_adapter/camera_trace_event.h"

namespace cros {

CameraHalServerImpl::CameraHalServerImpl()
    : mojo_manager_(CameraMojoChannelManager::FromToken(
          CameraMojoChannelManagerToken::CreateInstance())),
      ipc_bridge_(new IPCBridge(this, mojo_manager_.get())) {
  VLOGF_ENTER();
}

CameraHalServerImpl::~CameraHalServerImpl() {
  VLOGF_ENTER();

  ExitOnMainThread(0);
}

bool CameraHalServerImpl::Start() {
  VLOGF_ENTER();

  LoadCameraHal();

  // We assume that |camera_hal_adapter_| will only be set once. If the
  // assumption changed, we should consider another way to provide
  // CameraHalAdapter.
  mojo_manager_->GetIpcTaskRunner()->PostTask(
      FROM_HERE,
      base::Bind(&CameraHalServerImpl::IPCBridge::Start,
                 ipc_bridge_->GetWeakPtr(), camera_hal_adapter_.get(),
                 base::BindRepeating(
                     [](const std::vector<cros_camera_hal_t*>& hals,
                        PrivacySwitchStateChangeCallback callback) {
                       for (const auto* hal : hals) {
                         if (hal->set_privacy_switch_callback != nullptr) {
                           hal->set_privacy_switch_callback(
                               std::move(callback));
                         }
                       }
                     },
                     cros_camera_hals_)));
  return true;
}

CameraHalServerImpl::IPCBridge::IPCBridge(
    CameraHalServerImpl* camera_hal_server,
    CameraMojoChannelManager* mojo_manager)
    : camera_hal_server_(camera_hal_server),
      mojo_manager_(mojo_manager),
      ipc_task_runner_(mojo_manager_->GetIpcTaskRunner()),
      main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
      binding_(this) {}

CameraHalServerImpl::IPCBridge::~IPCBridge() {
  if (binding_.is_bound()) {
    binding_.Unbind();
  }
  callbacks_.reset();
}

void CameraHalServerImpl::IPCBridge::Start(
    CameraHalAdapter* camera_hal_adapter,
    SetPrivacySwitchCallback set_privacy_switch_callback) {
  VLOGF_ENTER();
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());

  if (binding_.is_bound()) {
    return;
  }

  camera_hal_adapter_ = camera_hal_adapter;

  mojom::CameraHalServerPtr server_ptr;
  binding_.Bind(mojo::MakeRequest(&server_ptr));
  binding_.set_connection_error_handler(
      base::Bind(&CameraHalServerImpl::IPCBridge::OnServiceMojoChannelError,
                 GetWeakPtr()));
  mojo_manager_->RegisterServer(
      std::move(server_ptr),
      base::BindOnce(&CameraHalServerImpl::IPCBridge::OnServerRegistered,
                     GetWeakPtr(), std::move(set_privacy_switch_callback)),
      base::BindOnce(&CameraHalServerImpl::IPCBridge::OnServiceMojoChannelError,
                     GetWeakPtr()));
}

void CameraHalServerImpl::IPCBridge::CreateChannel(
    mojom::CameraModuleRequest camera_module_request,
    mojom::CameraClientType camera_client_type) {
  VLOGF_ENTER();
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());

  camera_hal_adapter_->OpenCameraHal(std::move(camera_module_request),
                                     camera_client_type);
}

void CameraHalServerImpl::IPCBridge::SetTracingEnabled(bool enabled) {
  VLOGF_ENTER();
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());

  TRACE_CAMERA_ENABLE(enabled);
}

void CameraHalServerImpl::IPCBridge::NotifyCameraActivityChange(
    int32_t camera_id, bool opened, mojom::CameraClientType type) {
  VLOGF_ENTER();
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());
  DCHECK(callbacks_.is_bound());

  callbacks_->CameraDeviceActivityChange(camera_id, opened, type);
}

base::WeakPtr<CameraHalServerImpl::IPCBridge>
CameraHalServerImpl::IPCBridge::GetWeakPtr() {
  return weak_ptr_factory_.GetWeakPtr();
}

void CameraHalServerImpl::IPCBridge::OnServerRegistered(
    SetPrivacySwitchCallback set_privacy_switch_callback,
    int32_t result,
    mojom::CameraHalServerCallbacksPtr callbacks) {
  VLOGF_ENTER();
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());

  if (result != 0) {
    LOGF(ERROR) << "Failed to register camera HAL: "
                << base::safe_strerror(-result);
    return;
  }
  callbacks_.Bind(callbacks.PassInterface());

  std::move(set_privacy_switch_callback)
      .Run(base::BindRepeating(
          &CameraHalServerImpl::IPCBridge::OnPrivacySwitchStatusChanged,
          base::Unretained(this)));

  LOGF(INFO) << "Registered camera HAL";
}

void CameraHalServerImpl::IPCBridge::OnServiceMojoChannelError() {
  VLOGF_ENTER();
  DCHECK(ipc_task_runner_->BelongsToCurrentThread());

  // The CameraHalDispatcher Mojo parent is probably dead. We need to restart
  // another process in order to connect to the new Mojo parent.
  LOGF(INFO) << "Mojo connection to CameraHalDispatcher is broken";
  main_task_runner_->PostTask(
      FROM_HERE, base::Bind(&CameraHalServerImpl::ExitOnMainThread,
                            base::Unretained(camera_hal_server_), ECONNRESET));
}

void CameraHalServerImpl::IPCBridge::OnPrivacySwitchStatusChanged(
    PrivacySwitchState state) {
  cros::mojom::CameraPrivacySwitchState state_in_mojo;
  if (state == PrivacySwitchState::kUnknown) {
    state_in_mojo = cros::mojom::CameraPrivacySwitchState::UNKNOWN;
  } else if (state == PrivacySwitchState::kOn) {
    state_in_mojo = cros::mojom::CameraPrivacySwitchState::ON;
  } else {  // state == PrivacySwitchState::kOff
    state_in_mojo = cros::mojom::CameraPrivacySwitchState::OFF;
  }
  callbacks_->CameraPrivacySwitchStateChange(state_in_mojo);
}

void CameraHalServerImpl::LoadCameraHal() {
  VLOGF_ENTER();
  DCHECK(!camera_hal_adapter_);
  DCHECK_EQ(cros_camera_hals_.size(), 0);

  std::vector<camera_module_t*> camera_modules;
  std::unique_ptr<CameraConfig> config =
      CameraConfig::Create(constants::kCrosCameraTestConfigPathString);
  bool enable_front =
           config->GetBoolean(constants::kCrosEnableFrontCameraOption, true),
       enable_back =
           config->GetBoolean(constants::kCrosEnableBackCameraOption, true),
       enable_external =
           config->GetBoolean(constants::kCrosEnableExternalCameraOption, true);

  for (const auto& dll : GetCameraHalPaths()) {
    LOGF(INFO) << "Try to load camera hal " << dll.value();

    void* handle = dlopen(dll.value().c_str(), RTLD_NOW | RTLD_LOCAL);
    if (!handle) {
      LOGF(INFO) << "Failed to dlopen: " << dlerror();
      ExitOnMainThread(ENOENT);
    }

    cros_camera_hal_t* cros_camera_hal = static_cast<cros_camera_hal_t*>(
        dlsym(handle, CROS_CAMERA_HAL_INFO_SYM_AS_STR));
    if (!cros_camera_hal) {
      // TODO(b/151270948): We should report error here once all camera HALs
      // have implemented the interface.
    } else {
      cros_camera_hal->set_up(mojo_manager_.get());
      cros_camera_hals_.push_back(cros_camera_hal);
    }

    auto* module = static_cast<camera_module_t*>(
        dlsym(handle, HAL_MODULE_INFO_SYM_AS_STR));
    if (!module) {
      LOGF(ERROR) << "Failed to get camera_module_t pointer with symbol name "
                  << HAL_MODULE_INFO_SYM_AS_STR << " from " << dll.value();
      ExitOnMainThread(ELIBBAD);
    }

    camera_modules.push_back(module);
  }

  auto active_callback = base::Bind(
      &CameraHalServerImpl::OnCameraActivityChange, base::Unretained(this));
  if (enable_front && enable_back && enable_external) {
    camera_hal_adapter_.reset(new CameraHalAdapter(
        camera_modules, mojo_manager_.get(), active_callback));
  } else {
    camera_hal_adapter_.reset(new CameraHalTestAdapter(
        camera_modules, mojo_manager_.get(), active_callback, enable_front,
        enable_back, enable_external));
  }

  LOGF(INFO) << "Running camera HAL adapter on " << getpid();

  if (!camera_hal_adapter_->Start()) {
    LOGF(ERROR) << "Failed to start camera HAL adapter";
    ExitOnMainThread(ENODEV);
  }
}

void CameraHalServerImpl::ExitOnMainThread(int exit_status) {
  VLOGF_ENTER();
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  for (auto* cros_camera_hal : cros_camera_hals_) {
    cros_camera_hal->tear_down();
  }

  auto future = Future<void>::Create(nullptr);
  auto delete_ipc_bridge = base::BindOnce(
      [](std::unique_ptr<IPCBridge> ipc_bridge,
         base::Callback<void(void)> callback) { std::move(callback).Run(); },
      std::move(ipc_bridge_), cros::GetFutureCallback(future));
  mojo_manager_->GetIpcTaskRunner()->PostTask(FROM_HERE,
                                              std::move(delete_ipc_bridge));
  future->Wait(-1);

  exit(exit_status);
}

void CameraHalServerImpl::OnCameraActivityChange(int32_t camera_id,
                                                 bool opened,
                                                 mojom::CameraClientType type) {
  mojo_manager_->GetIpcTaskRunner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          &CameraHalServerImpl::IPCBridge::NotifyCameraActivityChange,
          ipc_bridge_->GetWeakPtr(), camera_id, opened, type));
}

}  // namespace cros
