// Copyright (c) 2012 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 "content/gpu/gpu_child_thread.h"

#include <stddef.h>
#include <utility>

#include "base/allocator/allocator_extension.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/threading/thread_checker.h"
#include "build/build_config.h"
#include "components/viz/common/features.h"
#include "content/child/child_process.h"
#include "content/gpu/gpu_service_factory.h"
#include "content/public/common/connection_filter.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/service_names.mojom.h"
#include "content/public/gpu/content_gpu_client.h"
#include "gpu/command_buffer/common/activity_flags.h"
#include "gpu/ipc/service/gpu_channel_manager.h"
#include "gpu/ipc/service/gpu_init.h"
#include "gpu/ipc/service/gpu_watchdog_thread.h"
#include "ipc/ipc_sync_message_filter.h"
#include "media/gpu/ipc/service/media_gpu_channel_manager.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
#include "third_party/skia/include/core/SkGraphics.h"

#if defined(USE_OZONE)
#include "ui/ozone/public/ozone_platform.h"
#endif

#if defined(OS_ANDROID)
#include "media/base/android/media_drm_bridge_client.h"
#include "media/mojo/clients/mojo_android_overlay.h"
#endif

namespace content {
namespace {

ChildThreadImpl::Options GetOptions() {
  ChildThreadImpl::Options::Builder builder;

#if defined(USE_OZONE)
  IPC::MessageFilter* message_filter =
      ui::OzonePlatform::GetInstance()->GetGpuMessageFilter();
  if (message_filter)
    builder.AddStartupFilter(message_filter);
#endif

  builder.AutoStartServiceManagerConnection(false);
  builder.ConnectToBrowser(true);

  return builder.Build();
}

// This ConnectionFilter queues all incoming bind interface requests until
// Release() is called.
class QueueingConnectionFilter : public ConnectionFilter {
 public:
  QueueingConnectionFilter(
      scoped_refptr<base::SequencedTaskRunner> io_task_runner,
      std::unique_ptr<service_manager::BinderRegistry> registry)
      : io_task_runner_(io_task_runner),
        registry_(std::move(registry)),
        weak_factory_(this) {
    // This will be reattached by any of the IO thread functions on first call.
    io_thread_checker_.DetachFromThread();
  }
  ~QueueingConnectionFilter() override {
    DCHECK(io_thread_checker_.CalledOnValidThread());
  }

  base::OnceClosure GetReleaseCallback() {
    return base::BindOnce(base::IgnoreResult(&base::TaskRunner::PostTask),
                          io_task_runner_, FROM_HERE,
                          base::BindOnce(&QueueingConnectionFilter::Release,
                                         weak_factory_.GetWeakPtr()));
  }

#if defined(USE_OZONE)
  void set_viz_main(viz::VizMainImpl* viz_main) { viz_main_ = viz_main; }
#endif

 private:
  struct PendingRequest {
    std::string interface_name;
    mojo::ScopedMessagePipeHandle interface_pipe;
  };

  bool CanBindInterface(const std::string& interface_name) const {
#if defined(USE_OZONE)
    DCHECK(viz_main_);
    if (viz_main_->CanBindInterface(interface_name))
      return true;
#endif
    return registry_->CanBindInterface(interface_name);
  }

  void BindInterface(const std::string& interface_name,
                     mojo::ScopedMessagePipeHandle interface_pipe) {
    if (registry_->TryBindInterface(interface_name, &interface_pipe))
      return;
#if defined(USE_OZONE)
    DCHECK(viz_main_);
    viz_main_->BindInterface(interface_name, std::move(interface_pipe));
#else
    NOTREACHED();
#endif
  }

  // ConnectionFilter:
  void OnBindInterface(const service_manager::BindSourceInfo& source_info,
                       const std::string& interface_name,
                       mojo::ScopedMessagePipeHandle* interface_pipe,
                       service_manager::Connector* connector) override {
    DCHECK(io_thread_checker_.CalledOnValidThread());

    if (CanBindInterface(interface_name)) {
      if (released_) {
        BindInterface(interface_name, std::move(*interface_pipe));
      } else {
        std::unique_ptr<PendingRequest> request =
            std::make_unique<PendingRequest>();
        request->interface_name = interface_name;
        request->interface_pipe = std::move(*interface_pipe);
        pending_requests_.push_back(std::move(request));
      }
    }
  }

  void Release() {
    DCHECK(io_thread_checker_.CalledOnValidThread());
    released_ = true;
    for (auto& request : pending_requests_) {
      BindInterface(request->interface_name,
                    std::move(request->interface_pipe));
    }
  }

  base::ThreadChecker io_thread_checker_;
  scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
  bool released_ = false;
  std::vector<std::unique_ptr<PendingRequest>> pending_requests_;
  std::unique_ptr<service_manager::BinderRegistry> registry_;

#if defined(USE_OZONE)
  viz::VizMainImpl* viz_main_ = nullptr;
#endif

  base::WeakPtrFactory<QueueingConnectionFilter> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(QueueingConnectionFilter);
};

viz::VizMainImpl::ExternalDependencies CreateVizMainDependencies(
    service_manager::Connector* connector) {
  viz::VizMainImpl::ExternalDependencies deps;
  deps.create_display_compositor = features::IsVizDisplayCompositorEnabled();
  if (GetContentClient()->gpu()) {
    deps.sync_point_manager = GetContentClient()->gpu()->GetSyncPointManager();
    deps.shared_image_manager =
        GetContentClient()->gpu()->GetSharedImageManager();
  }
  auto* process = ChildProcess::current();
  deps.shutdown_event = process->GetShutDownEvent();
  deps.io_thread_task_runner = process->io_task_runner();
  deps.connector = connector;
  return deps;
}

}  // namespace

GpuChildThread::GpuChildThread(base::RepeatingClosure quit_closure,
                               std::unique_ptr<gpu::GpuInit> gpu_init,
                               viz::VizMainImpl::LogMessages log_messages)
    : GpuChildThread(std::move(quit_closure),
                     GetOptions(),
                     std::move(gpu_init)) {
  viz_main_.SetLogMessagesForHost(std::move(log_messages));
}

GpuChildThread::GpuChildThread(const InProcessChildThreadParams& params,
                               std::unique_ptr<gpu::GpuInit> gpu_init)
    : GpuChildThread(base::DoNothing(),
                     ChildThreadImpl::Options::Builder()
                         .InBrowserProcess(params)
                         .AutoStartServiceManagerConnection(false)
                         .ConnectToBrowser(true)
                         .Build(),
                     std::move(gpu_init)) {}

GpuChildThread::GpuChildThread(base::RepeatingClosure quit_closure,
                               const ChildThreadImpl::Options& options,
                               std::unique_ptr<gpu::GpuInit> gpu_init)
    : ChildThreadImpl(MakeQuitSafelyClosure(), options),
      viz_main_(this,
                CreateVizMainDependencies(GetConnector()),
                std::move(gpu_init)),
      quit_closure_(std::move(quit_closure)),
      weak_factory_(this) {
  if (in_process_gpu()) {
    DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
               switches::kSingleProcess) ||
           base::CommandLine::ForCurrentProcess()->HasSwitch(
               switches::kInProcessGPU));
  }
}

GpuChildThread::~GpuChildThread() {
}

void GpuChildThread::Init(const base::Time& process_start_time) {
  viz_main_.gpu_service()->set_start_time(process_start_time);

  // When running in in-process mode, this has been set in the browser at
  // ChromeBrowserMainPartsAndroid::PreMainMessageLoopRun().
#if defined(OS_ANDROID)
  if (!in_process_gpu()) {
    media::SetMediaDrmBridgeClient(
        GetContentClient()->GetMediaDrmBridgeClient());
  }
#endif

  blink::AssociatedInterfaceRegistry* associated_registry =
      &associated_interfaces_;
  associated_registry->AddInterface(base::BindRepeating(
      &GpuChildThread::CreateVizMainService, base::Unretained(this)));

  auto registry = std::make_unique<service_manager::BinderRegistry>();
  if (GetContentClient()->gpu())  // nullptr in tests.
    GetContentClient()->gpu()->InitializeRegistry(registry.get());

  std::unique_ptr<QueueingConnectionFilter> filter =
      std::make_unique<QueueingConnectionFilter>(GetIOTaskRunner(),
                                                 std::move(registry));
#if defined(USE_OZONE)
  filter->set_viz_main(&viz_main_);
#endif

  release_pending_requests_closure_ = filter->GetReleaseCallback();

  GetServiceManagerConnection()->AddConnectionFilter(std::move(filter));

  StartServiceManagerConnection();

  memory_pressure_listener_ =
      std::make_unique<base::MemoryPressureListener>(base::BindRepeating(
          &GpuChildThread::OnMemoryPressure, base::Unretained(this)));
}

void GpuChildThread::CreateVizMainService(
    viz::mojom::VizMainAssociatedRequest request) {
  viz_main_.BindAssociated(std::move(request));
}

bool GpuChildThread::in_process_gpu() const {
  return viz_main_.gpu_service()->gpu_info().in_process_gpu;
}

bool GpuChildThread::Send(IPC::Message* msg) {
  // The GPU process must never send a synchronous IPC message to the browser
  // process. This could result in deadlock.
  DCHECK(!msg->is_sync());

  return ChildThreadImpl::Send(msg);
}

void GpuChildThread::RunService(
    const std::string& service_name,
    mojo::PendingReceiver<service_manager::mojom::Service> receiver) {
  if (!service_factory_) {
    pending_service_requests_.emplace_back(service_name, std::move(receiver));
    return;
  }

  DVLOG(1) << "GPU: Handling RunService request for " << service_name;
  service_factory_->RunService(service_name, std::move(receiver));
}

void GpuChildThread::OnAssociatedInterfaceRequest(
    const std::string& name,
    mojo::ScopedInterfaceEndpointHandle handle) {
  if (!associated_interfaces_.TryBindInterface(name, &handle))
    ChildThreadImpl::OnAssociatedInterfaceRequest(name, std::move(handle));
}

void GpuChildThread::OnInitializationFailed() {
  OnChannelError();
}

void GpuChildThread::OnGpuServiceConnection(viz::GpuServiceImpl* gpu_service) {
  media::AndroidOverlayMojoFactoryCB overlay_factory_cb;
#if defined(OS_ANDROID)
  overlay_factory_cb =
      base::BindRepeating(&GpuChildThread::CreateAndroidOverlay,
                          base::ThreadTaskRunnerHandle::Get());
  gpu_service->media_gpu_channel_manager()->SetOverlayFactory(
      overlay_factory_cb);
#endif

  // Only set once per process instance.
  service_factory_.reset(new GpuServiceFactory(
      gpu_service->gpu_preferences(),
      gpu_service->gpu_channel_manager()->gpu_driver_bug_workarounds(),
      gpu_service->gpu_feature_info(),
      gpu_service->media_gpu_channel_manager()->AsWeakPtr(),
      std::move(overlay_factory_cb)));

  if (GetContentClient()->gpu()) {  // NULL in tests.
    GetContentClient()->gpu()->GpuServiceInitialized(
        gpu_service->gpu_preferences());
  }

  DCHECK(release_pending_requests_closure_);
  std::move(release_pending_requests_closure_).Run();

  for (auto& request : pending_service_requests_)
    RunService(request.service_name, std::move(request.receiver));
  pending_service_requests_.clear();
}

void GpuChildThread::PostCompositorThreadCreated(
    base::SingleThreadTaskRunner* task_runner) {
  auto* gpu_client = GetContentClient()->gpu();
  if (gpu_client)
    gpu_client->PostCompositorThreadCreated(task_runner);
}

void GpuChildThread::QuitMainMessageLoop() {
  quit_closure_.Run();
}

void GpuChildThread::OnMemoryPressure(
    base::MemoryPressureListener::MemoryPressureLevel level) {
  if (level != base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL)
    return;

  base::allocator::ReleaseFreeMemory();
  if (viz_main_.discardable_shared_memory_manager())
    viz_main_.discardable_shared_memory_manager()->ReleaseFreeMemory();
  SkGraphics::PurgeAllCaches();
}

void GpuChildThread::QuitSafelyHelper(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
  // Post a new task (even if we're called on the |task_runner|'s thread) to
  // ensure that we are post-init.
  task_runner->PostTask(
      FROM_HERE, base::BindOnce([]() {
        ChildThreadImpl* current_child_thread = ChildThreadImpl::current();
        if (!current_child_thread)
          return;
        GpuChildThread* gpu_child_thread =
            static_cast<GpuChildThread*>(current_child_thread);
        gpu_child_thread->viz_main_.ExitProcess();
      }));
}

// Returns a closure which calls into the VizMainImpl to perform shutdown
// before quitting the main message loop. Must be called on the main thread.
base::RepeatingClosure GpuChildThread::MakeQuitSafelyClosure() {
  return base::BindRepeating(&GpuChildThread::QuitSafelyHelper,
                             base::ThreadTaskRunnerHandle::Get());
}

#if defined(OS_ANDROID)
// static
std::unique_ptr<media::AndroidOverlay> GpuChildThread::CreateAndroidOverlay(
    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
    const base::UnguessableToken& routing_token,
    media::AndroidOverlayConfig config) {
  media::mojom::AndroidOverlayProviderPtr overlay_provider;
  if (main_task_runner->RunsTasksInCurrentSequence()) {
    ChildThread::Get()->GetConnector()->BindInterface(
        content::mojom::kBrowserServiceName, &overlay_provider);
  } else {
    // Create a connector on this sequence and bind it on the main thread.
    service_manager::mojom::ConnectorRequest request;
    auto connector = service_manager::Connector::Create(&request);
    connector->BindInterface(content::mojom::kBrowserServiceName,
                             &overlay_provider);
    auto bind_connector_request =
        [](service_manager::mojom::ConnectorRequest request) {
          ChildThread::Get()->GetConnector()->BindConnectorRequest(
              std::move(request));
        };
    main_task_runner->PostTask(
        FROM_HERE, base::BindOnce(bind_connector_request, std::move(request)));
  }

  return std::make_unique<media::MojoAndroidOverlay>(
      std::move(overlay_provider), std::move(config), routing_token);
}
#endif

GpuChildThread::PendingServiceRequest::PendingServiceRequest(
    const std::string& service_name,
    mojo::PendingReceiver<service_manager::mojom::Service> receiver)
    : service_name(service_name), receiver(std::move(receiver)) {}

GpuChildThread::PendingServiceRequest::PendingServiceRequest(
    PendingServiceRequest&&) = default;

GpuChildThread::PendingServiceRequest::~PendingServiceRequest() = default;

}  // namespace content
