1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/gpu/gpu_child_thread.h"
6 
7 #include <stddef.h>
8 #include <utility>
9 
10 #include "base/allocator/allocator_extension.h"
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/command_line.h"
14 #include "base/debug/dump_without_crashing.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/power_monitor/power_monitor.h"
17 #include "base/power_monitor/power_monitor_device_source.h"
18 #include "base/run_loop.h"
19 #include "base/sequenced_task_runner.h"
20 #include "base/threading/thread_checker.h"
21 #include "build/build_config.h"
22 #include "content/child/child_process.h"
23 #include "content/gpu/browser_exposed_gpu_interfaces.h"
24 #include "content/gpu/gpu_service_factory.h"
25 #include "content/public/common/content_client.h"
26 #include "content/public/common/content_switches.h"
27 #include "content/public/common/service_names.mojom.h"
28 #include "content/public/gpu/content_gpu_client.h"
29 #include "gpu/command_buffer/common/activity_flags.h"
30 #include "gpu/ipc/service/gpu_channel_manager.h"
31 #include "gpu/ipc/service/gpu_init.h"
32 #include "gpu/ipc/service/gpu_watchdog_thread.h"
33 #include "ipc/ipc_sync_message_filter.h"
34 #include "media/gpu/ipc/service/media_gpu_channel_manager.h"
35 #include "mojo/public/cpp/bindings/binder_map.h"
36 #include "mojo/public/cpp/bindings/pending_receiver.h"
37 #include "mojo/public/cpp/bindings/pending_remote.h"
38 #include "mojo/public/cpp/bindings/scoped_message_error_crash_key.h"
39 #include "mojo/public/cpp/system/functions.h"
40 #include "services/metrics/public/cpp/mojo_ukm_recorder.h"
41 #include "services/metrics/public/mojom/ukm_interface.mojom.h"
42 #include "services/service_manager/public/cpp/binder_registry.h"
43 #include "services/viz/privileged/mojom/gl/gpu_service.mojom.h"
44 #include "third_party/skia/include/core/SkGraphics.h"
45 
46 #if defined(OS_ANDROID)
47 #include "media/base/android/media_drm_bridge_client.h"
48 #include "media/mojo/clients/mojo_android_overlay.h"
49 #endif
50 
51 namespace content {
52 namespace {
53 
54 // Called when the GPU process receives a bad IPC message.
HandleBadMessage(const std::string & error)55 void HandleBadMessage(const std::string& error) {
56   LOG(ERROR) << "Mojo error in GPU process: " << error;
57   mojo::debug::ScopedMessageErrorCrashKey crash_key_value(error);
58   base::debug::DumpWithoutCrashing();
59 }
60 
GetOptions()61 ChildThreadImpl::Options GetOptions() {
62   ChildThreadImpl::Options::Builder builder;
63 
64   builder.ConnectToBrowser(true);
65   builder.ExposesInterfacesToBrowser();
66 
67   return builder.Build();
68 }
69 
CreateVizMainDependencies()70 viz::VizMainImpl::ExternalDependencies CreateVizMainDependencies() {
71   viz::VizMainImpl::ExternalDependencies deps;
72   if (!base::PowerMonitor::IsInitialized()) {
73     deps.power_monitor_source =
74         std::make_unique<base::PowerMonitorDeviceSource>();
75   }
76   if (GetContentClient()->gpu()) {
77     deps.sync_point_manager = GetContentClient()->gpu()->GetSyncPointManager();
78     deps.shared_image_manager =
79         GetContentClient()->gpu()->GetSharedImageManager();
80     deps.viz_compositor_thread_runner =
81         GetContentClient()->gpu()->GetVizCompositorThreadRunner();
82   }
83   auto* process = ChildProcess::current();
84   deps.shutdown_event = process->GetShutDownEvent();
85   deps.io_thread_task_runner = process->io_task_runner();
86 
87   mojo::PendingRemote<ukm::mojom::UkmRecorderInterface> ukm_recorder;
88   ChildThread::Get()->BindHostReceiver(
89       ukm_recorder.InitWithNewPipeAndPassReceiver());
90   deps.ukm_recorder =
91       std::make_unique<ukm::MojoUkmRecorder>(std::move(ukm_recorder));
92   return deps;
93 }
94 
95 }  // namespace
96 
GpuChildThread(base::RepeatingClosure quit_closure,std::unique_ptr<gpu::GpuInit> gpu_init)97 GpuChildThread::GpuChildThread(base::RepeatingClosure quit_closure,
98                                std::unique_ptr<gpu::GpuInit> gpu_init)
99     : GpuChildThread(std::move(quit_closure),
100                      GetOptions(),
101                      std::move(gpu_init)) {}
102 
GpuChildThread(const InProcessChildThreadParams & params,std::unique_ptr<gpu::GpuInit> gpu_init)103 GpuChildThread::GpuChildThread(const InProcessChildThreadParams& params,
104                                std::unique_ptr<gpu::GpuInit> gpu_init)
105     : GpuChildThread(base::DoNothing(),
106                      ChildThreadImpl::Options::Builder()
107                          .InBrowserProcess(params)
108                          .ConnectToBrowser(true)
109                          .ExposesInterfacesToBrowser()
110                          .Build(),
111                      std::move(gpu_init)) {}
112 
GpuChildThread(base::RepeatingClosure quit_closure,ChildThreadImpl::Options options,std::unique_ptr<gpu::GpuInit> gpu_init)113 GpuChildThread::GpuChildThread(base::RepeatingClosure quit_closure,
114                                ChildThreadImpl::Options options,
115                                std::unique_ptr<gpu::GpuInit> gpu_init)
116     : ChildThreadImpl(MakeQuitSafelyClosure(), std::move(options)),
117       viz_main_(this, CreateVizMainDependencies(), std::move(gpu_init)),
118       quit_closure_(std::move(quit_closure)) {
119   if (in_process_gpu()) {
120     DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
121                switches::kSingleProcess) ||
122            base::CommandLine::ForCurrentProcess()->HasSwitch(
123                switches::kInProcessGPU));
124   }
125 }
126 
127 GpuChildThread::~GpuChildThread() = default;
128 
Init(const base::Time & process_start_time)129 void GpuChildThread::Init(const base::Time& process_start_time) {
130   if (!in_process_gpu())
131     mojo::SetDefaultProcessErrorHandler(base::BindRepeating(&HandleBadMessage));
132 
133   viz_main_.gpu_service()->set_start_time(process_start_time);
134 
135   // When running in in-process mode, this has been set in the browser at
136   // ChromeBrowserMainPartsAndroid::PreMainMessageLoopRun().
137 #if defined(OS_ANDROID)
138   if (!in_process_gpu()) {
139     media::SetMediaDrmBridgeClient(
140         GetContentClient()->GetMediaDrmBridgeClient());
141   }
142 #endif
143 
144   blink::AssociatedInterfaceRegistry* associated_registry =
145       &associated_interfaces_;
146   associated_registry->AddInterface(base::BindRepeating(
147       &GpuChildThread::CreateVizMainService, base::Unretained(this)));
148 
149   memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
150       FROM_HERE, base::BindRepeating(&GpuChildThread::OnMemoryPressure,
151                                      base::Unretained(this)));
152 }
153 
CreateVizMainService(mojo::PendingAssociatedReceiver<viz::mojom::VizMain> pending_receiver)154 void GpuChildThread::CreateVizMainService(
155     mojo::PendingAssociatedReceiver<viz::mojom::VizMain> pending_receiver) {
156   viz_main_.BindAssociated(std::move(pending_receiver));
157 }
158 
in_process_gpu() const159 bool GpuChildThread::in_process_gpu() const {
160   return viz_main_.gpu_service()->gpu_info().in_process_gpu;
161 }
162 
Send(IPC::Message * msg)163 bool GpuChildThread::Send(IPC::Message* msg) {
164   // The GPU process must never send a synchronous IPC message to the browser
165   // process. This could result in deadlock.
166   DCHECK(!msg->is_sync());
167 
168   return ChildThreadImpl::Send(msg);
169 }
170 
OnAssociatedInterfaceRequest(const std::string & name,mojo::ScopedInterfaceEndpointHandle handle)171 void GpuChildThread::OnAssociatedInterfaceRequest(
172     const std::string& name,
173     mojo::ScopedInterfaceEndpointHandle handle) {
174   if (!associated_interfaces_.TryBindInterface(name, &handle))
175     ChildThreadImpl::OnAssociatedInterfaceRequest(name, std::move(handle));
176 }
177 
OnInitializationFailed()178 void GpuChildThread::OnInitializationFailed() {
179   OnChannelError();
180 }
181 
OnGpuServiceConnection(viz::GpuServiceImpl * gpu_service)182 void GpuChildThread::OnGpuServiceConnection(viz::GpuServiceImpl* gpu_service) {
183   media::AndroidOverlayMojoFactoryCB overlay_factory_cb;
184 #if defined(OS_ANDROID)
185   overlay_factory_cb =
186       base::BindRepeating(&GpuChildThread::CreateAndroidOverlay,
187                           base::ThreadTaskRunnerHandle::Get());
188   gpu_service->media_gpu_channel_manager()->SetOverlayFactory(
189       overlay_factory_cb);
190 #endif
191 
192   // Only set once per process instance.
193   service_factory_.reset(new GpuServiceFactory(
194       gpu_service->gpu_preferences(),
195       gpu_service->gpu_channel_manager()->gpu_driver_bug_workarounds(),
196       gpu_service->gpu_feature_info(),
197       gpu_service->media_gpu_channel_manager()->AsWeakPtr(),
198       gpu_service->gpu_memory_buffer_factory(), std::move(overlay_factory_cb)));
199   for (auto& receiver : pending_service_receivers_)
200     BindServiceInterface(std::move(receiver));
201   pending_service_receivers_.clear();
202 
203   if (GetContentClient()->gpu())  // Null in tests.
204     GetContentClient()->gpu()->GpuServiceInitialized();
205 
206   // Start allowing browser-exposed interfaces to be bound.
207   //
208   // NOTE: Do not add new binders within this method. Instead modify
209   // |ExposeGpuInterfacesToBrowser()| in browser_exposed_gpu_interfaces.cc, as
210   // that will ensure security review coverage.
211   mojo::BinderMap binders;
212   content::ExposeGpuInterfacesToBrowser(
213       gpu_service->gpu_preferences(),
214       gpu_service->gpu_channel_manager()->gpu_driver_bug_workarounds(),
215       &binders);
216   ExposeInterfacesToBrowser(std::move(binders));
217 }
218 
PostCompositorThreadCreated(base::SingleThreadTaskRunner * task_runner)219 void GpuChildThread::PostCompositorThreadCreated(
220     base::SingleThreadTaskRunner* task_runner) {
221   auto* gpu_client = GetContentClient()->gpu();
222   if (gpu_client)
223     gpu_client->PostCompositorThreadCreated(task_runner);
224 }
225 
QuitMainMessageLoop()226 void GpuChildThread::QuitMainMessageLoop() {
227   quit_closure_.Run();
228 }
229 
OnMemoryPressure(base::MemoryPressureListener::MemoryPressureLevel level)230 void GpuChildThread::OnMemoryPressure(
231     base::MemoryPressureListener::MemoryPressureLevel level) {
232   if (level != base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL)
233     return;
234 
235   base::allocator::ReleaseFreeMemory();
236   if (viz_main_.discardable_shared_memory_manager())
237     viz_main_.discardable_shared_memory_manager()->ReleaseFreeMemory();
238   SkGraphics::PurgeAllCaches();
239 }
240 
QuitSafelyHelper(scoped_refptr<base::SingleThreadTaskRunner> task_runner)241 void GpuChildThread::QuitSafelyHelper(
242     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
243   // Post a new task (even if we're called on the |task_runner|'s thread) to
244   // ensure that we are post-init.
245   task_runner->PostTask(
246       FROM_HERE, base::BindOnce([]() {
247         ChildThreadImpl* current_child_thread = ChildThreadImpl::current();
248         if (!current_child_thread)
249           return;
250         GpuChildThread* gpu_child_thread =
251             static_cast<GpuChildThread*>(current_child_thread);
252         gpu_child_thread->viz_main_.ExitProcess(
253             viz::ExitCode::RESULT_CODE_NORMAL_EXIT);
254       }));
255 }
256 
257 // Returns a closure which calls into the VizMainImpl to perform shutdown
258 // before quitting the main message loop. Must be called on the main thread.
MakeQuitSafelyClosure()259 base::RepeatingClosure GpuChildThread::MakeQuitSafelyClosure() {
260   return base::BindRepeating(&GpuChildThread::QuitSafelyHelper,
261                              base::ThreadTaskRunnerHandle::Get());
262 }
263 
264 #if defined(OS_ANDROID)
265 // static
CreateAndroidOverlay(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,const base::UnguessableToken & routing_token,media::AndroidOverlayConfig config)266 std::unique_ptr<media::AndroidOverlay> GpuChildThread::CreateAndroidOverlay(
267     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
268     const base::UnguessableToken& routing_token,
269     media::AndroidOverlayConfig config) {
270   mojo::PendingRemote<media::mojom::AndroidOverlayProvider> overlay_provider;
271   if (main_task_runner->RunsTasksInCurrentSequence()) {
272     ChildThread::Get()->BindHostReceiver(
273         overlay_provider.InitWithNewPipeAndPassReceiver());
274   } else {
275     main_task_runner->PostTask(
276         FROM_HERE,
277         base::BindOnce(
278             [](mojo::PendingReceiver<media::mojom::AndroidOverlayProvider>
279                    receiver) {
280               ChildThread::Get()->BindHostReceiver(std::move(receiver));
281             },
282             overlay_provider.InitWithNewPipeAndPassReceiver()));
283   }
284 
285   return std::make_unique<media::MojoAndroidOverlay>(
286       std::move(overlay_provider), std::move(config), routing_token);
287 }
288 #endif
289 
290 }  // namespace content
291