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

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

#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/cxx17_backports.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/notreached.h"
#include "base/posix/eintr_wrapper.h"
#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "chromeos/components/sensors/sensor_util.h"
#include "components/device_event_log/device_event_log.h"
#include "media/base/bind_to_current_loop.h"
#include "media/capture/video/chromeos/mojom/camera_common.mojom.h"
#include "media/capture/video/chromeos/mojom/cros_camera_client.mojom.h"
#include "media/capture/video/chromeos/video_capture_features_chromeos.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/platform/named_platform_channel.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/platform/socket_utils_posix.h"
#include "mojo/public/cpp/system/invitation.h"

namespace media {

namespace {

const base::FilePath::CharType kArcCamera3SocketPath[] =
    "/run/camera/camera3.sock";
const char kArcCameraGroup[] = "arc-camera";
const base::FilePath::CharType kForceEnableAePath[] =
    "/run/camera/force_enable_face_ae";
const base::FilePath::CharType kForceDisableAePath[] =
    "/run/camera/force_disable_face_ae";
const base::FilePath::CharType kForceEnableHdrNetPath[] =
    "/run/camera/force_enable_hdrnet";
const base::FilePath::CharType kForceDisableHdrNetPath[] =
    "/run/camera/force_disable_hdrnet";

std::string GenerateRandomToken() {
  char random_bytes[16];
  base::RandBytes(random_bytes, 16);
  return base::HexEncode(random_bytes, 16);
}

// Waits until |raw_socket_fd| is readable.  We signal |raw_cancel_fd| when we
// want to cancel the blocking wait and stop serving connections on
// |raw_socket_fd|.  To notify such a situation, |raw_cancel_fd| is also passed
// to here, and the write side will be closed in such a case.
bool WaitForSocketReadable(int raw_socket_fd, int raw_cancel_fd) {
  struct pollfd fds[2] = {
      {raw_socket_fd, POLLIN, 0},
      {raw_cancel_fd, POLLIN, 0},
  };

  if (HANDLE_EINTR(poll(fds, base::size(fds), -1)) <= 0) {
    PLOG(ERROR) << "poll()";
    return false;
  }

  if (fds[1].revents) {
    VLOG(1) << "Stop() was called";
    return false;
  }

  DCHECK(fds[0].revents);
  return true;
}

bool HasCrosCameraTest() {
  static constexpr char kCrosCameraTestPath[] =
      "/usr/local/bin/cros_camera_test";

  base::FilePath path(kCrosCameraTestPath);
  return base::PathExists(path);
}

class MojoCameraClientObserver : public CameraClientObserver {
 public:
  explicit MojoCameraClientObserver(
      mojo::PendingRemote<cros::mojom::CameraHalClient> client,
      cros::mojom::CameraClientType type,
      base::UnguessableToken auth_token)
      : CameraClientObserver(type, std::move(auth_token)),
        client_(std::move(client)) {}

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

  mojo::Remote<cros::mojom::CameraHalClient>& client() { return client_; }

 private:
  mojo::Remote<cros::mojom::CameraHalClient> client_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(MojoCameraClientObserver);
};

}  // namespace

CameraClientObserver::~CameraClientObserver() = default;

bool CameraClientObserver::Authenticate(TokenManager* token_manager) {
  auto authenticated_type =
      token_manager->AuthenticateClient(type_, auth_token_);
  if (!authenticated_type) {
    return false;
  }
  type_ = authenticated_type.value();
  return true;
}

FailedCameraHalServerCallbacks::FailedCameraHalServerCallbacks()
    : callbacks_(this) {}
FailedCameraHalServerCallbacks::~FailedCameraHalServerCallbacks() = default;

mojo::PendingRemote<cros::mojom::CameraHalServerCallbacks>
FailedCameraHalServerCallbacks::GetRemote() {
  return callbacks_.BindNewPipeAndPassRemote();
}

void FailedCameraHalServerCallbacks::CameraDeviceActivityChange(
    int32_t camera_id,
    bool opened,
    cros::mojom::CameraClientType type) {}

void FailedCameraHalServerCallbacks::CameraPrivacySwitchStateChange(
    cros::mojom::CameraPrivacySwitchState state) {}

// static
CameraHalDispatcherImpl* CameraHalDispatcherImpl::GetInstance() {
  return base::Singleton<CameraHalDispatcherImpl>::get();
}

bool CameraHalDispatcherImpl::StartThreads() {
  DCHECK(!proxy_thread_.IsRunning());
  DCHECK(!blocking_io_thread_.IsRunning());

  if (!proxy_thread_.Start()) {
    LOG(ERROR) << "Failed to start proxy thread";
    return false;
  }
  if (!blocking_io_thread_.Start()) {
    LOG(ERROR) << "Failed to start blocking IO thread";
    proxy_thread_.Stop();
    return false;
  }
  proxy_task_runner_ = proxy_thread_.task_runner();
  blocking_io_task_runner_ = blocking_io_thread_.task_runner();
  return true;
}

bool CameraHalDispatcherImpl::Start(
    MojoMjpegDecodeAcceleratorFactoryCB jda_factory,
    MojoJpegEncodeAcceleratorFactoryCB jea_factory) {
  DCHECK(!IsStarted());
  if (!StartThreads()) {
    return false;
  }
  // This event is for adding camera category to categories list.
  TRACE_EVENT0("camera", "CameraHalDispatcherImpl");
  base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);

  {
    base::FilePath enable_file_path(kForceEnableAePath);
    base::FilePath disable_file_path(kForceDisableAePath);
    if (!base::DeleteFile(enable_file_path)) {
      LOG(WARNING) << "Could not delete " << kForceEnableAePath;
    }
    if (!base::DeleteFile(disable_file_path)) {
      LOG(WARNING) << "Could not delete " << kForceDisableAePath;
    }
    const base::CommandLine* command_line =
        base::CommandLine::ForCurrentProcess();
    if (command_line->HasSwitch(media::switches::kForceControlFaceAe)) {
      if (command_line->GetSwitchValueASCII(
              media::switches::kForceControlFaceAe) == "enable") {
        base::File file(enable_file_path, base::File::FLAG_CREATE_ALWAYS);
        file.Close();
      } else {
        base::File file(disable_file_path, base::File::FLAG_CREATE_ALWAYS);
        file.Close();
      }
    }
  }

  {
    base::FilePath enable_file_path(kForceEnableHdrNetPath);
    base::FilePath disable_file_path(kForceDisableHdrNetPath);
    if (!base::DeleteFile(enable_file_path)) {
      LOG(WARNING) << "Could not delete " << kForceEnableHdrNetPath;
    }
    if (!base::DeleteFile(disable_file_path)) {
      LOG(WARNING) << "Could not delete " << kForceDisableHdrNetPath;
    }
    const base::CommandLine* command_line =
        base::CommandLine::ForCurrentProcess();
    if (command_line->HasSwitch(media::switches::kHdrNetOverride)) {
      std::string value =
          command_line->GetSwitchValueASCII(switches::kHdrNetOverride);
      if (value == switches::kHdrNetForceEnabled) {
        base::File file(enable_file_path, base::File::FLAG_CREATE_ALWAYS);
        file.Close();
      } else if (value == switches::kHdrNetForceDisabled) {
        base::File file(disable_file_path, base::File::FLAG_CREATE_ALWAYS);
        file.Close();
      }
    }
  }

  jda_factory_ = std::move(jda_factory);
  jea_factory_ = std::move(jea_factory);
  base::WaitableEvent started(base::WaitableEvent::ResetPolicy::MANUAL,
                              base::WaitableEvent::InitialState::NOT_SIGNALED);
  // It's important we generate tokens before creating the socket, because once
  // it is available, everyone connecting to socket would start fetching
  // tokens.
  if (!token_manager_.GenerateServerToken()) {
    LOG(ERROR) << "Failed to generate authentication token for server";
    return false;
  }
  if (HasCrosCameraTest() && !token_manager_.GenerateTestClientToken()) {
    LOG(ERROR) << "Failed to generate token for test client";
    return false;
  }
  if (!token_manager_.GenerateServerSensorClientToken()) {
    LOG(ERROR) << "Failed to generate authentication token for server as a "
                  "sensor client";
  }

  blocking_io_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraHalDispatcherImpl::CreateSocket,
                     base::Unretained(this), base::Unretained(&started)));
  started.Wait();
  return IsStarted();
}

void CameraHalDispatcherImpl::AddClientObserver(
    std::unique_ptr<CameraClientObserver> observer,
    base::OnceCallback<void(int32_t)> result_callback) {
  // If |proxy_thread_| fails to start in Start() then CameraHalDelegate will
  // not be created, and this function will not be called.
  DCHECK(proxy_thread_.IsRunning());
  proxy_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraHalDispatcherImpl::AddClientObserverOnProxyThread,
                     base::Unretained(this), std::move(observer),
                     std::move(result_callback)));
}

bool CameraHalDispatcherImpl::IsStarted() {
  return proxy_thread_.IsRunning() && blocking_io_thread_.IsRunning() &&
         proxy_fd_.is_valid();
}

void CameraHalDispatcherImpl::AddActiveClientObserver(
    CameraActiveClientObserver* observer) {
  base::AutoLock lock(opened_camera_id_map_lock_);
  for (auto& opened_camera_id_pair : opened_camera_id_map_) {
    const auto& camera_client_type = opened_camera_id_pair.first;
    const auto& camera_id_set = opened_camera_id_pair.second;
    if (!camera_id_set.empty()) {
      observer->OnActiveClientChange(camera_client_type, /*is_active=*/true);
    }
  }
  active_client_observers_->AddObserver(observer);
}

void CameraHalDispatcherImpl::RemoveActiveClientObserver(
    CameraActiveClientObserver* observer) {
  active_client_observers_->RemoveObserver(observer);
}

cros::mojom::CameraPrivacySwitchState
CameraHalDispatcherImpl::AddCameraPrivacySwitchObserver(
    CameraPrivacySwitchObserver* observer) {
  privacy_switch_observers_->AddObserver(observer);

  base::AutoLock lock(privacy_switch_state_lock_);
  return current_privacy_switch_state_;
}

void CameraHalDispatcherImpl::RemoveCameraPrivacySwitchObserver(
    CameraPrivacySwitchObserver* observer) {
  privacy_switch_observers_->RemoveObserver(observer);
}

void CameraHalDispatcherImpl::RegisterPluginVmToken(
    const base::UnguessableToken& token) {
  token_manager_.RegisterPluginVmToken(token);
}

void CameraHalDispatcherImpl::UnregisterPluginVmToken(
    const base::UnguessableToken& token) {
  token_manager_.UnregisterPluginVmToken(token);
}

CameraHalDispatcherImpl::CameraHalDispatcherImpl()
    : proxy_thread_("CameraProxyThread"),
      blocking_io_thread_("CameraBlockingIOThread"),
      main_task_runner_(base::SequencedTaskRunnerHandle::Get()),
      camera_hal_server_callbacks_(this),
      active_client_observers_(
          new base::ObserverListThreadSafe<CameraActiveClientObserver>()),
      current_privacy_switch_state_(
          cros::mojom::CameraPrivacySwitchState::UNKNOWN),
      privacy_switch_observers_(
          new base::ObserverListThreadSafe<CameraPrivacySwitchObserver>()) {}

CameraHalDispatcherImpl::~CameraHalDispatcherImpl() {
  VLOG(1) << "Stopping CameraHalDispatcherImpl...";
  if (proxy_thread_.IsRunning()) {
    proxy_thread_.task_runner()->PostTask(
        FROM_HERE, base::BindOnce(&CameraHalDispatcherImpl::StopOnProxyThread,
                                  base::Unretained(this)));
    proxy_thread_.Stop();
  }
  blocking_io_thread_.Stop();
  CAMERA_LOG(EVENT) << "CameraHalDispatcherImpl stopped";
}

void CameraHalDispatcherImpl::RegisterServer(
    mojo::PendingRemote<cros::mojom::CameraHalServer> camera_hal_server) {
  DCHECK(proxy_task_runner_->BelongsToCurrentThread());
  LOG(ERROR) << "CameraHalDispatcher::RegisterServer is deprecated. "
                "CameraHalServer will not be registered.";
}

void CameraHalDispatcherImpl::RegisterServerWithToken(
    mojo::PendingRemote<cros::mojom::CameraHalServer> camera_hal_server,
    const base::UnguessableToken& token,
    RegisterServerWithTokenCallback callback) {
  DCHECK(proxy_task_runner_->BelongsToCurrentThread());

  if (camera_hal_server_) {
    LOG(ERROR) << "Camera HAL server is already registered";
    std::move(callback).Run(-EALREADY,
                            failed_camera_hal_server_callbacks_.GetRemote());
    return;
  }
  if (!token_manager_.AuthenticateServer(token)) {
    LOG(ERROR) << "Failed to authenticate server";
    std::move(callback).Run(-EPERM,
                            failed_camera_hal_server_callbacks_.GetRemote());
    return;
  }
  camera_hal_server_.Bind(std::move(camera_hal_server));
  camera_hal_server_.set_disconnect_handler(
      base::BindOnce(&CameraHalDispatcherImpl::OnCameraHalServerConnectionError,
                     base::Unretained(this)));
  CAMERA_LOG(EVENT) << "Camera HAL server registered";
  std::move(callback).Run(
      0, camera_hal_server_callbacks_.BindNewPipeAndPassRemote());

  // Set up the Mojo channels for clients which registered before the server
  // registers.
  for (auto& client_observer : client_observers_) {
    EstablishMojoChannel(client_observer.get());
  }
}

void CameraHalDispatcherImpl::RegisterClient(
    mojo::PendingRemote<cros::mojom::CameraHalClient> client) {
  NOTREACHED() << "RegisterClient() is disabled";
}

void CameraHalDispatcherImpl::RegisterClientWithToken(
    mojo::PendingRemote<cros::mojom::CameraHalClient> client,
    cros::mojom::CameraClientType type,
    const base::UnguessableToken& auth_token,
    RegisterClientWithTokenCallback callback) {
  base::UnguessableToken client_auth_token = auth_token;
  // Unretained reference is safe here because CameraHalDispatcherImpl owns
  // |proxy_thread_|.
  proxy_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(
          &CameraHalDispatcherImpl::RegisterClientWithTokenOnProxyThread,
          base::Unretained(this), std::move(client), type,
          std::move(client_auth_token),
          media::BindToCurrentLoop(std::move(callback))));
}

void CameraHalDispatcherImpl::GetMjpegDecodeAccelerator(
    mojo::PendingReceiver<chromeos_camera::mojom::MjpegDecodeAccelerator>
        jda_receiver) {
  jda_factory_.Run(std::move(jda_receiver));
}

void CameraHalDispatcherImpl::GetJpegEncodeAccelerator(
    mojo::PendingReceiver<chromeos_camera::mojom::JpegEncodeAccelerator>
        jea_receiver) {
  jea_factory_.Run(std::move(jea_receiver));
}

void CameraHalDispatcherImpl::RegisterSensorClientWithToken(
    mojo::PendingRemote<chromeos::sensors::mojom::SensorHalClient> client,
    const base::UnguessableToken& auth_token,
    RegisterSensorClientWithTokenCallback callback) {
  DCHECK(proxy_task_runner_->BelongsToCurrentThread());

  main_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(
          &CameraHalDispatcherImpl::RegisterSensorClientWithTokenOnUIThread,
          weak_factory_.GetWeakPtr(), std::move(client), auth_token,
          BindToCurrentLoop(std::move(callback))));
}

void CameraHalDispatcherImpl::CameraDeviceActivityChange(
    int32_t camera_id,
    bool opened,
    cros::mojom::CameraClientType type) {
  VLOG(1) << type << (opened ? " opened " : " closed ") << "camera "
          << camera_id;
  base::AutoLock lock(opened_camera_id_map_lock_);
  auto& camera_id_set = opened_camera_id_map_[type];
  if (opened) {
    auto result = camera_id_set.insert(camera_id);
    if (!result.second) {  // No element inserted.
      LOG(WARNING) << "Received duplicated open notification for camera "
                   << camera_id;
      return;
    }
    if (camera_id_set.size() == 1) {
      VLOG(1) << type << " is active";
      active_client_observers_->Notify(
          FROM_HERE, &CameraActiveClientObserver::OnActiveClientChange, type,
          /*is_active=*/true);
    }
  } else {
    auto it = camera_id_set.find(camera_id);
    if (it == camera_id_set.end()) {
      // This can happen if something happened to the client process and it
      // simultaneous lost connections to both CameraHalDispatcher and
      // CameraHalServer.
      LOG(WARNING) << "Received close notification for camera " << camera_id
                   << " which is not opened";
      return;
    }
    camera_id_set.erase(it);
    if (camera_id_set.empty()) {
      VLOG(1) << type << " is inactive";
      active_client_observers_->Notify(
          FROM_HERE, &CameraActiveClientObserver::OnActiveClientChange, type,
          /*is_active=*/false);
    }
  }
}

void CameraHalDispatcherImpl::CameraPrivacySwitchStateChange(
    cros::mojom::CameraPrivacySwitchState state) {
  DCHECK(proxy_task_runner_->BelongsToCurrentThread());

  base::AutoLock lock(privacy_switch_state_lock_);
  current_privacy_switch_state_ = state;
  privacy_switch_observers_->Notify(
      FROM_HERE,
      &CameraPrivacySwitchObserver::OnCameraPrivacySwitchStatusChanged,
      current_privacy_switch_state_);
  CAMERA_LOG(EVENT) << "Camera privacy switch state changed: "
                    << current_privacy_switch_state_;
}

base::UnguessableToken CameraHalDispatcherImpl::GetTokenForTrustedClient(
    cros::mojom::CameraClientType type) {
  return token_manager_.GetTokenForTrustedClient(type);
}

void CameraHalDispatcherImpl::OnTraceLogEnabled() {
  proxy_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraHalDispatcherImpl::OnTraceLogEnabledOnProxyThread,
                     base::Unretained(this)));
}

void CameraHalDispatcherImpl::OnTraceLogDisabled() {
  proxy_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraHalDispatcherImpl::OnTraceLogDisabledOnProxyThread,
                     base::Unretained(this)));
}

void CameraHalDispatcherImpl::CreateSocket(base::WaitableEvent* started) {
  DCHECK(blocking_io_task_runner_->BelongsToCurrentThread());

  base::FilePath socket_path(kArcCamera3SocketPath);
  mojo::NamedPlatformChannel::Options options;
  options.server_name = socket_path.value();
  mojo::NamedPlatformChannel channel(options);
  if (!channel.server_endpoint().is_valid()) {
    LOG(ERROR) << "Failed to create the socket file: " << kArcCamera3SocketPath;
    started->Signal();
    return;
  }

  // TODO(crbug.com/1053569): Remove these lines once the issue is solved.
  base::File::Info info;
  if (!base::GetFileInfo(socket_path, &info)) {
    LOG(WARNING) << "Failed to get the socket info after building Mojo channel";
  } else {
    LOG(WARNING) << "Building Mojo channel. Socket info:"
                 << " creation_time: " << info.creation_time
                 << " last_accessed: " << info.last_accessed
                 << " last_modified: " << info.last_modified;
  }

  // Change permissions on the socket.
  struct group arc_camera_group;
  struct group* result = nullptr;
  char buf[1024];
  if (HANDLE_EINTR(getgrnam_r(kArcCameraGroup, &arc_camera_group, buf,
                              sizeof(buf), &result)) < 0) {
    PLOG(ERROR) << "getgrnam_r()";
    started->Signal();
    return;
  }

  if (!result) {
    LOG(ERROR) << "Group '" << kArcCameraGroup << "' not found";
    started->Signal();
    return;
  }

  if (HANDLE_EINTR(chown(kArcCamera3SocketPath, -1, arc_camera_group.gr_gid)) <
      0) {
    PLOG(ERROR) << "chown()";
    started->Signal();
    return;
  }

  if (!base::SetPosixFilePermissions(socket_path, 0660)) {
    PLOG(ERROR) << "Could not set permissions: " << socket_path.value();
    started->Signal();
    return;
  }

  blocking_io_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&CameraHalDispatcherImpl::StartServiceLoop,
                     base::Unretained(this),
                     channel.TakeServerEndpoint().TakePlatformHandle().TakeFD(),
                     base::Unretained(started)));
}

void CameraHalDispatcherImpl::StartServiceLoop(base::ScopedFD socket_fd,
                                               base::WaitableEvent* started) {
  DCHECK(blocking_io_task_runner_->BelongsToCurrentThread());
  DCHECK(!proxy_fd_.is_valid());
  DCHECK(!cancel_pipe_.is_valid());
  DCHECK(socket_fd.is_valid());

  base::ScopedFD cancel_fd;
  if (!base::CreatePipe(&cancel_fd, &cancel_pipe_, true)) {
    PLOG(ERROR) << "Failed to create cancel pipe";
    started->Signal();
    return;
  }

  proxy_fd_ = std::move(socket_fd);
  started->Signal();
  VLOG(1) << "CameraHalDispatcherImpl started; waiting for incoming connection";

  while (true) {
    if (!WaitForSocketReadable(proxy_fd_.get(), cancel_fd.get())) {
      VLOG(1) << "Quit CameraHalDispatcherImpl IO thread";
      return;
    }

    base::ScopedFD accepted_fd;
    if (mojo::AcceptSocketConnection(proxy_fd_.get(), &accepted_fd, false) &&
        accepted_fd.is_valid()) {
      VLOG(1) << "Accepted a connection";
      // Hardcode pid 0 since it is unused in mojo.
      const base::ProcessHandle kUnusedChildProcessHandle = 0;
      mojo::PlatformChannel channel;
      mojo::OutgoingInvitation invitation;

      // Generate an arbitrary 32-byte string, as we use this length as a
      // protocol version identifier.
      std::string token = GenerateRandomToken();
      mojo::ScopedMessagePipeHandle pipe = invitation.AttachMessagePipe(token);
      mojo::OutgoingInvitation::Send(std::move(invitation),
                                     kUnusedChildProcessHandle,
                                     channel.TakeLocalEndpoint());

      auto remote_endpoint = channel.TakeRemoteEndpoint();
      std::vector<base::ScopedFD> fds;
      fds.emplace_back(remote_endpoint.TakePlatformHandle().TakeFD());

      struct iovec iov = {const_cast<char*>(token.c_str()), token.length()};
      ssize_t result =
          mojo::SendmsgWithHandles(accepted_fd.get(), &iov, 1, fds);
      if (result == -1) {
        PLOG(ERROR) << "sendmsg()";
      } else {
        proxy_task_runner_->PostTask(
            FROM_HERE, base::BindOnce(&CameraHalDispatcherImpl::OnPeerConnected,
                                      base::Unretained(this), std::move(pipe)));
      }
    }
  }
}

void CameraHalDispatcherImpl::RegisterClientWithTokenOnProxyThread(
    mojo::PendingRemote<cros::mojom::CameraHalClient> client,
    cros::mojom::CameraClientType type,
    base::UnguessableToken auth_token,
    RegisterClientWithTokenCallback callback) {
  DCHECK(proxy_task_runner_->BelongsToCurrentThread());
  auto client_observer = std::make_unique<MojoCameraClientObserver>(
      std::move(client), type, std::move(auth_token));
  client_observer->client().set_disconnect_handler(base::BindOnce(
      &CameraHalDispatcherImpl::OnCameraHalClientConnectionError,
      base::Unretained(this), base::Unretained(client_observer.get())));
  AddClientObserverOnProxyThread(std::move(client_observer),
                                 std::move(callback));
}

void CameraHalDispatcherImpl::AddClientObserverOnProxyThread(
    std::unique_ptr<CameraClientObserver> observer,
    base::OnceCallback<void(int32_t)> result_callback) {
  DCHECK(proxy_task_runner_->BelongsToCurrentThread());
  if (!observer->Authenticate(&token_manager_)) {
    LOG(ERROR) << "Failed to authenticate camera client observer";
    std::move(result_callback).Run(-EPERM);
    return;
  }
  if (camera_hal_server_) {
    EstablishMojoChannel(observer.get());
  }
  client_observers_.insert(std::move(observer));
  std::move(result_callback).Run(0);
  CAMERA_LOG(EVENT) << "Camera HAL client registered";
}

void CameraHalDispatcherImpl::EstablishMojoChannel(
    CameraClientObserver* client_observer) {
  DCHECK(proxy_task_runner_->BelongsToCurrentThread());
  mojo::PendingRemote<cros::mojom::CameraModule> camera_module;
  const auto& type = client_observer->GetType();
  CAMERA_LOG(EVENT) << "Establishing server channel for " << type;
  camera_hal_server_->CreateChannel(
      camera_module.InitWithNewPipeAndPassReceiver(), type);
  client_observer->OnChannelCreated(std::move(camera_module));
}

void CameraHalDispatcherImpl::OnPeerConnected(
    mojo::ScopedMessagePipeHandle message_pipe) {
  DCHECK(proxy_task_runner_->BelongsToCurrentThread());
  receiver_set_.Add(this,
                    mojo::PendingReceiver<cros::mojom::CameraHalDispatcher>(
                        std::move(message_pipe)));
  VLOG(1) << "New CameraHalDispatcher binding added";
}

void CameraHalDispatcherImpl::OnCameraHalServerConnectionError() {
  DCHECK(proxy_task_runner_->BelongsToCurrentThread());
  base::AutoLock lock(opened_camera_id_map_lock_);
  CAMERA_LOG(EVENT) << "Camera HAL server connection lost";
  camera_hal_server_.reset();
  camera_hal_server_callbacks_.reset();
  for (auto& opened_camera_id_pair : opened_camera_id_map_) {
    auto camera_client_type = opened_camera_id_pair.first;
    const auto& camera_id_set = opened_camera_id_pair.second;
    if (!camera_id_set.empty()) {
      active_client_observers_->Notify(
          FROM_HERE, &CameraActiveClientObserver::OnActiveClientChange,
          camera_client_type, /*is_active=*/false);
    }
  }
  opened_camera_id_map_.clear();

  base::AutoLock privacy_lock(privacy_switch_state_lock_);
  current_privacy_switch_state_ =
      cros::mojom::CameraPrivacySwitchState::UNKNOWN;
  privacy_switch_observers_->Notify(
      FROM_HERE,
      &CameraPrivacySwitchObserver::OnCameraPrivacySwitchStatusChanged,
      current_privacy_switch_state_);
}

void CameraHalDispatcherImpl::OnCameraHalClientConnectionError(
    CameraClientObserver* client_observer) {
  DCHECK(proxy_task_runner_->BelongsToCurrentThread());
  base::AutoLock lock(opened_camera_id_map_lock_);
  auto camera_client_type = client_observer->GetType();
  auto opened_it = opened_camera_id_map_.find(camera_client_type);
  if (opened_it == opened_camera_id_map_.end()) {
    // This can happen if this camera client never opened a camera.
    return;
  }
  const auto& camera_id_set = opened_it->second;
  if (!camera_id_set.empty()) {
    active_client_observers_->Notify(
        FROM_HERE, &CameraActiveClientObserver::OnActiveClientChange,
        camera_client_type, /*is_active=*/false);
  }
  opened_camera_id_map_.erase(opened_it);

  auto it = client_observers_.find(client_observer);
  if (it != client_observers_.end()) {
    client_observers_.erase(it);
    CAMERA_LOG(EVENT) << "Camera HAL client connection lost";
  }
}

void CameraHalDispatcherImpl::RegisterSensorClientWithTokenOnUIThread(
    mojo::PendingRemote<chromeos::sensors::mojom::SensorHalClient> client,
    const base::UnguessableToken& auth_token,
    RegisterSensorClientWithTokenCallback callback) {
  DCHECK(main_task_runner_->RunsTasksInCurrentSequence());

  if (!token_manager_.AuthenticateServerSensorClient(auth_token)) {
    std::move(callback).Run(-EPERM);
    return;
  }

  if (!chromeos::sensors::BindSensorHalClient(std::move(client))) {
    LOG(ERROR) << "Failed to bind SensorHalClient to SensorHalDispatcher";
    std::move(callback).Run(-ENOSYS);
    return;
  }

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

void CameraHalDispatcherImpl::StopOnProxyThread() {
  DCHECK(proxy_task_runner_->BelongsToCurrentThread());
  base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);

  // TODO(crbug.com/1053569): Remove these lines once the issue is solved.
  base::File::Info info;
  if (!base::GetFileInfo(base::FilePath(kArcCamera3SocketPath), &info)) {
    LOG(WARNING) << "Failed to get socket info before deleting";
  } else {
    LOG(WARNING) << "Delete socket. Socket info:"
                 << " creation_time: " << info.creation_time
                 << " last_accessed: " << info.last_accessed
                 << " last_modified: " << info.last_modified;
  }

  if (!base::DeleteFile(base::FilePath(kArcCamera3SocketPath))) {
    LOG(ERROR) << "Failed to delete " << kArcCamera3SocketPath;
  }
  // Close |cancel_pipe_| to quit the loop in WaitForIncomingConnection.
  cancel_pipe_.reset();
  client_observers_.clear();
  camera_hal_server_callbacks_.reset();
  camera_hal_server_.reset();
  receiver_set_.Clear();
}

void CameraHalDispatcherImpl::OnTraceLogEnabledOnProxyThread() {
  DCHECK(proxy_task_runner_->BelongsToCurrentThread());
  if (!camera_hal_server_) {
    return;
  }
  bool camera_event_enabled = false;
  TRACE_EVENT_CATEGORY_GROUP_ENABLED("camera", &camera_event_enabled);
  if (camera_event_enabled) {
    camera_hal_server_->SetTracingEnabled(true);
  }
}

void CameraHalDispatcherImpl::OnTraceLogDisabledOnProxyThread() {
  DCHECK(proxy_task_runner_->BelongsToCurrentThread());
  if (!camera_hal_server_) {
    return;
  }
  camera_hal_server_->SetTracingEnabled(false);
}

TokenManager* CameraHalDispatcherImpl::GetTokenManagerForTesting() {
  return &token_manager_;
}

}  // namespace media
