Flutter Engine
The Flutter Engine
platform_view_android.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter 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 "flutter/shell/platform/android/platform_view_android.h"
6
7#include <android/api-level.h>
8#include <memory>
9#include <utility>
10
11#include "flutter/common/graphics/texture.h"
12#include "flutter/fml/synchronization/waitable_event.h"
13#include "flutter/shell/common/shell_io_manager.h"
14#include "flutter/shell/gpu/gpu_surface_gl_delegate.h"
15#include "flutter/shell/platform/android/android_context_gl_impeller.h"
16#include "flutter/shell/platform/android/android_context_gl_skia.h"
17#include "flutter/shell/platform/android/android_context_vulkan_impeller.h"
18#include "flutter/shell/platform/android/android_surface_gl_impeller.h"
19#include "flutter/shell/platform/android/android_surface_gl_skia.h"
20#include "flutter/shell/platform/android/android_surface_software.h"
21#include "flutter/shell/platform/android/image_external_texture_gl.h"
22#include "flutter/shell/platform/android/surface_texture_external_texture_gl.h"
23#include "fml/logging.h"
24#if IMPELLER_ENABLE_VULKAN // b/258506856 for why this is behind an if
25#include "flutter/shell/platform/android/android_surface_vulkan_impeller.h"
26#include "flutter/shell/platform/android/image_external_texture_vk.h"
27#endif
28#include "flutter/shell/platform/android/context/android_context.h"
29#include "flutter/shell/platform/android/external_view_embedder/external_view_embedder.h"
30#include "flutter/shell/platform/android/jni/platform_view_android_jni.h"
31#include "flutter/shell/platform/android/platform_message_response_android.h"
32#include "flutter/shell/platform/android/surface/android_surface.h"
33#include "flutter/shell/platform/android/surface/snapshot_surface_producer.h"
34#include "flutter/shell/platform/android/vsync_waiter_android.h"
35
36namespace flutter {
37
39 const std::shared_ptr<AndroidContext>& context,
40 bool enable_impeller)
41 : android_context_(context), enable_impeller_(enable_impeller) {}
42
44
45std::unique_ptr<AndroidSurface> AndroidSurfaceFactoryImpl::CreateSurface() {
46 switch (android_context_->RenderingApi()) {
48 return std::make_unique<AndroidSurfaceSoftware>();
50 return std::make_unique<AndroidSurfaceGLImpeller>(
51 std::static_pointer_cast<AndroidContextGLImpeller>(android_context_));
53 return std::make_unique<AndroidSurfaceGLSkia>(
54 std::static_pointer_cast<AndroidContextGLSkia>(android_context_));
56 return std::make_unique<AndroidSurfaceVulkanImpeller>(
57 std::static_pointer_cast<AndroidContextVulkanImpeller>(
58 android_context_));
59 }
61}
62
63static std::shared_ptr<flutter::AndroidContext> CreateAndroidContext(
64 bool use_software_rendering,
65 const flutter::TaskRunners& task_runners,
66 AndroidRenderingAPI android_rendering_api,
67 bool enable_vulkan_validation,
68 bool enable_opengl_gpu_tracing,
69 bool enable_vulkan_gpu_tracing) {
70 switch (android_rendering_api) {
72 return std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
74 return std::make_unique<AndroidContextGLImpeller>(
75 std::make_unique<impeller::egl::Display>(),
76 enable_opengl_gpu_tracing);
78 return std::make_unique<AndroidContextVulkanImpeller>(
79 enable_vulkan_validation, enable_vulkan_gpu_tracing);
81 return std::make_unique<AndroidContextGLSkia>(
82 fml::MakeRefCounted<AndroidEnvironmentGL>(), //
83 task_runners //
84 );
85 }
87}
88
90 PlatformView::Delegate& delegate,
91 const flutter::TaskRunners& task_runners,
92 const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
93 bool use_software_rendering)
95 delegate,
96 task_runners,
97 jni_facade,
99 use_software_rendering,
100 task_runners,
101 delegate.OnPlatformViewGetSettings().android_rendering_api,
102 delegate.OnPlatformViewGetSettings().enable_vulkan_validation,
103 delegate.OnPlatformViewGetSettings().enable_opengl_gpu_tracing,
104 delegate.OnPlatformViewGetSettings().enable_vulkan_gpu_tracing)) {
105}
106
108 PlatformView::Delegate& delegate,
109 const flutter::TaskRunners& task_runners,
110 const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
111 const std::shared_ptr<flutter::AndroidContext>& android_context)
112 : PlatformView(delegate, task_runners),
113 jni_facade_(jni_facade),
114 android_context_(android_context),
115 platform_view_android_delegate_(jni_facade),
116 platform_message_handler_(new PlatformMessageHandlerAndroid(jni_facade)) {
117 if (android_context_) {
118 FML_CHECK(android_context_->IsValid())
119 << "Could not create surface from invalid Android context.";
120 surface_factory_ = std::make_shared<AndroidSurfaceFactoryImpl>(
121 android_context_, //
123 );
124 android_surface_ = surface_factory_->CreateSurface();
125 FML_CHECK(android_surface_ && android_surface_->IsValid())
126 << "Could not create an OpenGL, Vulkan or Software surface to set up "
127 "rendering.";
128 }
129}
130
132
134 fml::RefPtr<AndroidNativeWindow> native_window) {
135 if (android_surface_) {
136 InstallFirstFrameCallback();
137
141 [&latch, surface = android_surface_.get(),
142 native_window = std::move(native_window)]() {
143 surface->SetNativeWindow(native_window);
144 latch.Signal();
145 });
146 latch.Wait();
147 }
148
150}
151
153 fml::RefPtr<AndroidNativeWindow> native_window) {
154 if (android_surface_) {
158 [&latch, surface = android_surface_.get(),
159 native_window = std::move(native_window)]() {
160 surface->TeardownOnScreenContext();
161 surface->SetNativeWindow(native_window);
162 latch.Signal();
163 });
164 latch.Wait();
165 }
166
168}
169
172
173 if (android_surface_) {
177 [&latch, surface = android_surface_.get()]() {
178 surface->TeardownOnScreenContext();
179 latch.Signal();
180 });
181 latch.Wait();
182 }
183}
184
186 if (!android_surface_) {
187 return;
188 }
192 [&latch, surface = android_surface_.get(), size]() {
193 surface->OnScreenSurfaceResize(size);
194 latch.Signal();
195 });
196 latch.Wait();
197}
198
200 std::string name,
201 jobject java_message_data,
202 jint java_message_position,
203 jint response_id) {
204 uint8_t* message_data =
205 static_cast<uint8_t*>(env->GetDirectBufferAddress(java_message_data));
207 fml::MallocMapping::Copy(message_data, java_message_position);
208
210 if (response_id) {
211 response = fml::MakeRefCounted<PlatformMessageResponseAndroid>(
212 response_id, jni_facade_, task_runners_.GetPlatformTaskRunner());
213 }
214
216 std::make_unique<flutter::PlatformMessage>(
217 std::move(name), std::move(message), std::move(response)));
218}
219
221 std::string name,
222 jint response_id) {
224 if (response_id) {
225 response = fml::MakeRefCounted<PlatformMessageResponseAndroid>(
226 response_id, jni_facade_, task_runners_.GetPlatformTaskRunner());
227 }
228
230 std::make_unique<flutter::PlatformMessage>(std::move(name),
231 std::move(response)));
232}
233
234// |PlatformView|
235void PlatformViewAndroid::HandlePlatformMessage(
236 std::unique_ptr<flutter::PlatformMessage> message) {
237 // Called from the ui thread.
238 platform_message_handler_->HandlePlatformMessage(std::move(message));
239}
240
241// |PlatformView|
242void PlatformViewAndroid::OnPreEngineRestart() const {
243 jni_facade_->FlutterViewOnPreEngineRestart();
244}
245
247 jint id,
248 jint action,
249 jobject args,
250 jint args_position) {
251 if (env->IsSameObject(args, NULL)) {
253 id, static_cast<flutter::SemanticsAction>(action),
255 return;
256 }
257
258 uint8_t* args_data = static_cast<uint8_t*>(env->GetDirectBufferAddress(args));
259 auto args_vector = fml::MallocMapping::Copy(args_data, args_position);
260
262 id, static_cast<flutter::SemanticsAction>(action),
263 std::move(args_vector));
264}
265
266// |PlatformView|
267void PlatformViewAndroid::UpdateSemantics(
270 platform_view_android_delegate_.UpdateSemantics(update, actions);
271}
272
274 int64_t texture_id,
275 const fml::jni::ScopedJavaGlobalRef<jobject>& surface_texture) {
276 switch (android_context_->RenderingApi()) {
278 // Impeller GLES.
279 RegisterTexture(std::make_shared<SurfaceTextureExternalTextureImpellerGL>(
280 std::static_pointer_cast<impeller::ContextGLES>(
281 android_context_->GetImpellerContext()),
282 texture_id, surface_texture, jni_facade_));
283 break;
285 // Legacy GL.
286 RegisterTexture(std::make_shared<SurfaceTextureExternalTextureGL>(
287 texture_id, surface_texture, jni_facade_));
288 break;
290 FML_LOG(INFO) << "Software rendering does not support external textures.";
291 break;
293 FML_LOG(ERROR) << "Impeller requires migrating plugins that create and "
294 "register surface textures to the new surface producer "
295 "API. See "
296 "https://docs.flutter.dev/release/breaking-changes/"
297 "android-surface-plugins";
298 }
299}
300
302 int64_t texture_id,
303 const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry) {
304 switch (android_context_->RenderingApi()) {
306 // Impeller GLES.
307 RegisterTexture(std::make_shared<ImageExternalTextureGLImpeller>(
308 std::static_pointer_cast<impeller::ContextGLES>(
309 android_context_->GetImpellerContext()),
310 texture_id, image_texture_entry, jni_facade_));
311 break;
313 // Legacy GL.
314 RegisterTexture(std::make_shared<ImageExternalTextureGLSkia>(
315 std::static_pointer_cast<AndroidContextGLSkia>(android_context_),
316 texture_id, image_texture_entry, jni_facade_));
317 break;
319 RegisterTexture(std::make_shared<ImageExternalTextureVK>(
320 std::static_pointer_cast<impeller::ContextVK>(
321 android_context_->GetImpellerContext()),
322 texture_id, image_texture_entry, jni_facade_));
323 break;
325 FML_LOG(INFO) << "Software rendering does not support external textures.";
326 break;
327 }
328}
329
330// |PlatformView|
331std::unique_ptr<VsyncWaiter> PlatformViewAndroid::CreateVSyncWaiter() {
332 return std::make_unique<VsyncWaiterAndroid>(task_runners_);
333}
334
335// |PlatformView|
336std::unique_ptr<Surface> PlatformViewAndroid::CreateRenderingSurface() {
337 if (!android_surface_) {
338 return nullptr;
339 }
340 return android_surface_->CreateGPUSurface(
341 android_context_->GetMainSkiaContext().get());
342}
343
344// |PlatformView|
345std::shared_ptr<ExternalViewEmbedder>
346PlatformViewAndroid::CreateExternalViewEmbedder() {
347 return std::make_shared<AndroidExternalViewEmbedder>(
348 *android_context_, jni_facade_, surface_factory_, task_runners_);
349}
350
351// |PlatformView|
352std::unique_ptr<SnapshotSurfaceProducer>
353PlatformViewAndroid::CreateSnapshotSurfaceProducer() {
354 if (!android_surface_) {
355 return nullptr;
356 }
357 return std::make_unique<AndroidSnapshotSurfaceProducer>(*android_surface_);
358}
359
360// |PlatformView|
361sk_sp<GrDirectContext> PlatformViewAndroid::CreateResourceContext() const {
362 if (!android_surface_) {
363 return nullptr;
364 }
365 sk_sp<GrDirectContext> resource_context;
366 if (android_surface_->ResourceContextMakeCurrent()) {
367 // TODO(chinmaygarde): Currently, this code depends on the fact that only
368 // the OpenGL surface will be able to make a resource context current. If
369 // this changes, this assumption breaks. Handle the same.
373 } else {
374 FML_DLOG(ERROR) << "Could not make the resource context current.";
375 }
376
377 return resource_context;
378}
379
380// |PlatformView|
381void PlatformViewAndroid::ReleaseResourceContext() const {
382 if (android_surface_) {
383 android_surface_->ResourceContextClearCurrent();
384 }
385}
386
387// |PlatformView|
388std::shared_ptr<impeller::Context> PlatformViewAndroid::GetImpellerContext()
389 const {
390 if (android_surface_) {
391 return android_surface_->GetImpellerContext();
392 }
393 return nullptr;
394}
395
396// |PlatformView|
397std::unique_ptr<std::vector<std::string>>
398PlatformViewAndroid::ComputePlatformResolvedLocales(
399 const std::vector<std::string>& supported_locale_data) {
400 return jni_facade_->FlutterViewComputePlatformResolvedLocale(
401 supported_locale_data);
402}
403
404// |PlatformView|
405void PlatformViewAndroid::RequestDartDeferredLibrary(intptr_t loading_unit_id) {
406 if (jni_facade_->RequestDartDeferredLibrary(loading_unit_id)) {
407 return;
408 }
409 return; // TODO(garyq): Call LoadDartDeferredLibraryFailure()
410}
411
412// |PlatformView|
414 intptr_t loading_unit_id,
415 std::unique_ptr<const fml::Mapping> snapshot_data,
416 std::unique_ptr<const fml::Mapping> snapshot_instructions) {
417 delegate_.LoadDartDeferredLibrary(loading_unit_id, std::move(snapshot_data),
418 std::move(snapshot_instructions));
419}
420
421// |PlatformView|
423 intptr_t loading_unit_id,
424 const std::string error_message,
425 bool transient) {
426 delegate_.LoadDartDeferredLibraryError(loading_unit_id, error_message,
427 transient);
428}
429
430// |PlatformView|
432 std::unique_ptr<AssetResolver> updated_asset_resolver,
434 delegate_.UpdateAssetResolverByType(std::move(updated_asset_resolver), type);
435}
436
437void PlatformViewAndroid::InstallFirstFrameCallback() {
438 // On Platform Task Runner.
441 platform_task_runner = task_runners_.GetPlatformTaskRunner()]() {
442 // On GPU Task Runner.
443 platform_task_runner->PostTask([platform_view]() {
444 // Back on Platform Task Runner.
445 if (platform_view) {
446 reinterpret_cast<PlatformViewAndroid*>(platform_view.get())
447 ->FireFirstFrameCallback();
448 }
449 });
450 });
451}
452
453void PlatformViewAndroid::FireFirstFrameCallback() {
454 jni_facade_->FlutterViewOnFirstFrame();
455}
456
457double PlatformViewAndroid::GetScaledFontSize(double unscaled_font_size,
458 int configuration_id) const {
459 return jni_facade_->FlutterViewGetScaledFontSize(unscaled_font_size,
460 configuration_id);
461}
462} // namespace flutter
std::unique_ptr< flutter::PlatformViewIOS > platform_view
GLenum type
std::unique_ptr< AndroidSurface > CreateSurface() override
AndroidSurfaceFactoryImpl(const std::shared_ptr< AndroidContext > &context, bool enable_impeller)
AssetResolverType
Identifies the type of AssetResolver an instance is.
static sk_sp< const GrGLInterface > GetDefaultPlatformGLInterface()
void UpdateSemantics(const flutter::SemanticsNodeUpdates &update, const flutter::CustomAccessibilityActionUpdates &actions)
void DispatchPlatformMessage(JNIEnv *env, std::string name, jobject message_data, jint message_position, jint response_id)
void NotifyChanged(const SkISize &size)
void RegisterExternalTexture(int64_t texture_id, const fml::jni::ScopedJavaGlobalRef< jobject > &surface_texture)
void NotifySurfaceWindowChanged(fml::RefPtr< AndroidNativeWindow > native_window)
void RegisterImageTexture(int64_t texture_id, const fml::jni::ScopedJavaGlobalRef< jobject > &image_texture_entry)
void DispatchEmptyPlatformMessage(JNIEnv *env, std::string name, jint response_id)
void NotifyDestroyed() override
Used by embedders to notify the shell that the platform view has been destroyed. This notification us...
PlatformViewAndroid(PlatformView::Delegate &delegate, const flutter::TaskRunners &task_runners, const std::shared_ptr< PlatformViewAndroidJNI > &jni_facade, bool use_software_rendering)
void UpdateAssetResolverByType(std::unique_ptr< AssetResolver > updated_asset_resolver, AssetResolver::AssetResolverType type) override
Replaces the asset resolver handled by the engine's AssetManager of the specified type with updated_a...
void DispatchSemanticsAction(JNIEnv *env, jint id, jint action, jobject args, jint args_position)
void LoadDartDeferredLibraryError(intptr_t loading_unit_id, const std::string error_message, bool transient) override
Indicates to the dart VM that the request to load a deferred library with the specified loading unit ...
void LoadDartDeferredLibrary(intptr_t loading_unit_id, std::unique_ptr< const fml::Mapping > snapshot_data, std::unique_ptr< const fml::Mapping > snapshot_instructions) override
Loads the Dart shared library into the Dart VM. When the Dart library is loaded successfully,...
Used to forward events from the platform view to interested subsystems. This forwarding is done by th...
Definition: platform_view.h:60
virtual void UpdateAssetResolverByType(std::unique_ptr< AssetResolver > updated_asset_resolver, AssetResolver::AssetResolverType type)=0
Replaces the asset resolver handled by the engine's AssetManager of the specified type with updated_a...
virtual const Settings & OnPlatformViewGetSettings() const =0
Called by the platform view on the platform thread to get the settings object associated with the pla...
virtual void LoadDartDeferredLibrary(intptr_t loading_unit_id, std::unique_ptr< const fml::Mapping > snapshot_data, std::unique_ptr< const fml::Mapping > snapshot_instructions)=0
Loads the dart shared library into the dart VM. When the dart library is loaded successfully,...
virtual void LoadDartDeferredLibraryError(intptr_t loading_unit_id, const std::string error_message, bool transient)=0
Indicates to the dart VM that the request to load a deferred library with the specified loading unit ...
Platform views are created by the shell on the platform task runner. Unless explicitly specified,...
Definition: platform_view.h:51
virtual void NotifyDestroyed()
Used by embedders to notify the shell that the platform view has been destroyed. This notification us...
void SetNextFrameCallback(const fml::closure &closure)
Sets a callback that gets executed when the rasterizer renders the next frame. Due to the asynchronou...
void RegisterTexture(std::shared_ptr< flutter::Texture > texture)
Used by the embedder to specify a texture that it wants the rasterizer to composite within the Flutte...
void DispatchPlatformMessage(std::unique_ptr< PlatformMessage > message)
Used by embedders to dispatch a platform message to a running root isolate hosted by the engine....
PlatformView::Delegate & delegate_
void NotifyCreated()
Used by embedders to notify the shell that a platform view has been created. This notification is use...
fml::WeakPtr< PlatformView > GetWeakPtr() const
Returns a weak pointer to the platform view. Since the platform view may only be created,...
void DispatchSemanticsAction(int32_t node_id, SemanticsAction action, fml::MallocMapping args)
Used by embedders to dispatch an accessibility action to a running isolate hosted by the engine.
void ScheduleFrame()
Used by embedders to schedule a frame. In response to this call, the framework may need to start gene...
const TaskRunners task_runners_
static sk_sp< GrDirectContext > CreateCompatibleResourceLoadingContext(GrBackendApi backend, const sk_sp< const GrGLInterface > &gl_interface)
fml::RefPtr< fml::TaskRunner > GetRasterTaskRunner() const
Definition: task_runners.cc:42
fml::RefPtr< fml::TaskRunner > GetPlatformTaskRunner() const
Definition: task_runners.cc:30
A Mapping like NonOwnedMapping, but uses Free as its release proc.
Definition: mapping.h:144
static MallocMapping Copy(const T *begin, const T *end)
Definition: mapping.h:162
static void RunNowOrPostTask(const fml::RefPtr< fml::TaskRunner > &runner, const fml::closure &task)
Definition: task_runner.cc:55
VkSurfaceKHR surface
Definition: main.cc:49
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
#define FML_DLOG(severity)
Definition: logging.h:102
#define FML_LOG(severity)
Definition: logging.h:82
#define FML_CHECK(condition)
Definition: logging.h:85
#define FML_UNREACHABLE()
Definition: logging.h:109
Win32Message message
Definition: __init__.py:1
static std::shared_ptr< flutter::AndroidContext > CreateAndroidContext(bool use_software_rendering, const flutter::TaskRunners &task_runners, AndroidRenderingAPI android_rendering_api, bool enable_vulkan_validation, bool enable_opengl_gpu_tracing, bool enable_vulkan_gpu_tracing)
AndroidRenderingAPI
Definition: settings.h:26
std::unordered_map< int32_t, SemanticsNode > SemanticsNodeUpdates
std::unordered_map< int32_t, CustomAccessibilityAction > CustomAccessibilityActionUpdates
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
Definition: update.py:1
Definition: SkSize.h:16
bool enable_impeller
Definition: settings.h:229
int64_t texture_id
#define ERROR(message)
Definition: elf_loader.cc:260