Flutter Engine
The Flutter Engine
flutter_main.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#define FML_USED_ON_EMBEDDER
6
7#include <android/log.h>
8#include <optional>
9#include <vector>
10
11#include "common/settings.h"
12#include "flutter/fml/command_line.h"
13#include "flutter/fml/file.h"
14#include "flutter/fml/logging.h"
15#include "flutter/fml/macros.h"
16#include "flutter/fml/message_loop.h"
17#include "flutter/fml/native_library.h"
18#include "flutter/fml/paths.h"
19#include "flutter/fml/platform/android/jni_util.h"
20#include "flutter/fml/platform/android/paths_android.h"
21#include "flutter/fml/size.h"
22#include "flutter/lib/ui/plugins/callback_cache.h"
23#include "flutter/runtime/dart_vm.h"
24#include "flutter/shell/common/shell.h"
25#include "flutter/shell/common/switches.h"
26#include "flutter/shell/platform/android/android_context_vulkan_impeller.h"
27#include "flutter/shell/platform/android/flutter_main.h"
30#include "third_party/dart/runtime/include/dart_tools_api.h"
31#include "txt/platform.h"
32
33namespace flutter {
34
36
37extern "C" {
38#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
39// Used for debugging dart:* sources.
40extern const uint8_t kPlatformStrongDill[];
41extern const intptr_t kPlatformStrongDillSize;
42#endif
43}
44
45namespace {
46
48
49} // anonymous namespace
50
51FlutterMain::FlutterMain(const flutter::Settings& settings)
53
54FlutterMain::~FlutterMain() = default;
55
56static std::unique_ptr<FlutterMain> g_flutter_main;
57
59 FML_CHECK(g_flutter_main) << "ensureInitializationComplete must have already "
60 "been called.";
61 return *g_flutter_main;
62}
63
64const flutter::Settings& FlutterMain::GetSettings() const {
65 return settings_;
66}
67
68void FlutterMain::Init(JNIEnv* env,
69 jclass clazz,
70 jobject context,
71 jobjectArray jargs,
72 jstring kernelPath,
73 jstring appStoragePath,
74 jstring engineCachesPath,
75 jlong initTimeMillis) {
76 std::vector<std::string> args;
77 args.push_back("flutter");
78 for (auto& arg : fml::jni::StringArrayToVector(env, jargs)) {
79 args.push_back(std::move(arg));
80 }
81 auto command_line = fml::CommandLineFromIterators(args.begin(), args.end());
82
83 auto settings = SettingsFromCommandLine(command_line);
84
85 // Turn systracing on if ATrace_isEnabled is true and the user did not already
86 // request systracing
87 if (!settings.trace_systrace) {
88 settings.trace_systrace =
90 if (settings.trace_systrace) {
91 __android_log_print(
92 ANDROID_LOG_INFO, "Flutter",
93 "ATrace was enabled at startup. Flutter and Dart "
94 "tracing will be forwarded to systrace and will not show up in "
95 "Dart DevTools.");
96 }
97 }
98
99 settings.android_rendering_api = SelectedRenderingAPI(settings);
100 switch (settings.android_rendering_api) {
102 case AndroidRenderingAPI::kSkiaOpenGLES:
103 settings.enable_impeller = false;
104 break;
105 case AndroidRenderingAPI::kImpellerOpenGLES:
106 case AndroidRenderingAPI::kImpellerVulkan:
107 settings.enable_impeller = true;
108 break;
109 }
110
111#if FLUTTER_RELEASE
112 // On most platforms the timeline is always disabled in release mode.
113 // On Android, enable it in release mode only when using systrace.
114 settings.enable_timeline_event_handler = settings.trace_systrace;
115#endif // FLUTTER_RELEASE
116
117 // Restore the callback cache.
118 // TODO(chinmaygarde): Route all cache file access through FML and remove this
119 // setter.
121 fml::jni::JavaStringToString(env, appStoragePath));
122
124 fml::jni::JavaStringToString(env, engineCachesPath));
125
127
128 if (!flutter::DartVM::IsRunningPrecompiledCode() && kernelPath) {
129 // Check to see if the appropriate kernel files are present and configure
130 // settings accordingly.
131 auto application_kernel_path =
133
134 if (fml::IsFile(application_kernel_path)) {
135 settings.application_kernel_asset = application_kernel_path;
136 }
137 }
138
139 settings.task_observer_add = [](intptr_t key, const fml::closure& callback) {
141 };
142
143 settings.task_observer_remove = [](intptr_t key) {
145 };
146
147 settings.log_message_callback = [](const std::string& tag,
148 const std::string& message) {
149 __android_log_print(ANDROID_LOG_INFO, tag.c_str(), "%.*s",
150 static_cast<int>(message.size()), message.c_str());
151 };
152
153 settings.enable_platform_isolates = true;
154
155#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
156 // There are no ownership concerns here as all mappings are owned by the
157 // embedder and not the engine.
158 auto make_mapping_callback = [](const uint8_t* mapping, size_t size) {
159 return [mapping, size]() {
160 return std::make_unique<fml::NonOwnedMapping>(mapping, size);
161 };
162 };
163
164 settings.dart_library_sources_kernel =
165 make_mapping_callback(kPlatformStrongDill, kPlatformStrongDillSize);
166#endif // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
167
168 // Not thread safe. Will be removed when FlutterMain is refactored to no
169 // longer be a singleton.
170 g_flutter_main.reset(new FlutterMain(settings));
171
172 g_flutter_main->SetupDartVMServiceUriCallback(env);
173}
174
175void FlutterMain::SetupDartVMServiceUriCallback(JNIEnv* env) {
177 env, env->FindClass("io/flutter/embedding/engine/FlutterJNI"));
178 if (g_flutter_jni_class->is_null()) {
179 return;
180 }
181 jfieldID uri_field = env->GetStaticFieldID(
182 g_flutter_jni_class->obj(), "vmServiceUri", "Ljava/lang/String;");
183 if (uri_field == nullptr) {
184 return;
185 }
186
187 auto set_uri = [env, uri_field](const std::string& uri) {
190 env->SetStaticObjectField(g_flutter_jni_class->obj(), uri_field,
191 java_uri.obj());
192 };
193
195 fml::RefPtr<fml::TaskRunner> platform_runner =
197
198 vm_service_uri_callback_ = DartServiceIsolate::AddServerStatusCallback(
199 [platform_runner, set_uri](const std::string& uri) {
200 platform_runner->PostTask([uri, set_uri] { set_uri(uri); });
201 });
202}
203
204static void PrefetchDefaultFontManager(JNIEnv* env, jclass jcaller) {
205 // Initialize a singleton owned by Skia.
207}
208
210 static const JNINativeMethod methods[] = {
211 {
212 .name = "nativeInit",
213 .signature = "(Landroid/content/Context;[Ljava/lang/String;Ljava/"
214 "lang/String;Ljava/lang/String;Ljava/lang/String;J)V",
215 .fnPtr = reinterpret_cast<void*>(&Init),
216 },
217 {
218 .name = "nativePrefetchDefaultFontManager",
219 .signature = "()V",
220 .fnPtr = reinterpret_cast<void*>(&PrefetchDefaultFontManager),
221 },
222 };
223
224 jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
225
226 if (clazz == nullptr) {
227 return false;
228 }
229
230 return env->RegisterNatives(clazz, methods, fml::size(methods)) == 0;
231}
232
233// static
234AndroidRenderingAPI FlutterMain::SelectedRenderingAPI(
236 if (settings.enable_software_rendering) {
237 FML_CHECK(!settings.enable_impeller)
238 << "Impeller does not support software rendering. Either disable "
239 "software rendering or disable impeller.";
241 }
242 constexpr AndroidRenderingAPI kVulkanUnsupportedFallback =
243 AndroidRenderingAPI::kSkiaOpenGLES;
244
245 // Debug/Profile only functionality for testing a specific
246 // backend configuration.
247#ifndef FLUTTER_RELEASE
248 if (settings.requested_rendering_backend == "opengles" &
249 settings.enable_impeller) {
250 return AndroidRenderingAPI::kImpellerOpenGLES;
251 }
252 if (settings.requested_rendering_backend == "vulkan" &&
253 settings.enable_impeller) {
254 return AndroidRenderingAPI::kImpellerVulkan;
255 }
256#endif
257
258 if (settings.enable_impeller) {
259 // Vulkan must only be used on API level 29+, as older API levels do not
260 // have requisite features to support platform views.
261 //
262 // Even if this check returns true, Impeller may determine it cannot use
263 // Vulkan for some other reason, such as a missing required extension or
264 // feature.
265 int api_level = android_get_device_api_level();
266 if (api_level < kMinimumAndroidApiLevelForVulkan) {
267 return kVulkanUnsupportedFallback;
268 }
269 // Determine if Vulkan is supported by creating a Vulkan context and
270 // checking if it is valid.
271 impeller::ScopedValidationDisable disable_validation;
272 auto vulkan_backend = std::make_unique<AndroidContextVulkanImpeller>(
273 /*enable_vulkan_validation=*/false,
274 /*enable_vulkan_gpu_tracing=*/false,
275 /*quiet=*/true);
276 if (!vulkan_backend->IsValid()) {
277 return kVulkanUnsupportedFallback;
278 }
279 return AndroidRenderingAPI::kImpellerVulkan;
280 }
281
282 return AndroidRenderingAPI::kSkiaOpenGLES;
283}
284
285} // namespace flutter
static void SetCachePath(const std::string &path)
static bool IsRunningPrecompiledCode()
Checks if VM instances in the process can run precompiled code. This call can be made at any time and...
Definition: dart_vm.cc:205
void RemoveTaskObserver(intptr_t key)
Definition: message_loop.cc:68
static void EnsureInitializedForCurrentThread()
Definition: message_loop.cc:27
void AddTaskObserver(intptr_t key, const fml::closure &callback)
Definition: message_loop.cc:64
fml::RefPtr< fml::TaskRunner > GetTaskRunner() const
Definition: message_loop.cc:56
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
Definition: message_loop.cc:19
virtual void PostTask(const fml::closure &task) override
Definition: task_runner.cc:24
@ kSoftware
Definition: embedder.h:81
Settings settings_
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
#define FML_CHECK(condition)
Definition: logging.h:85
void Init()
Win32Message message
const GrXPFactory * Get(SkBlendMode mode)
Definition: __init__.py:1
AndroidRenderingAPI
Definition: settings.h:26
constexpr int kMinimumAndroidApiLevelForVulkan
Definition: flutter_main.cc:35
Settings SettingsFromCommandLine(const fml::CommandLine &command_line)
Definition: switches.cc:228
static void PrefetchDefaultFontManager(JNIEnv *env, jclass jcaller)
const intptr_t kPlatformStrongDillSize
static fml::jni::ScopedJavaGlobalRef< jclass > * g_flutter_jni_class
static std::unique_ptr< FlutterMain > g_flutter_main
Definition: flutter_main.cc:56
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
const uint8_t kPlatformStrongDill[]
std::string JavaStringToString(JNIEnv *env, jstring str)
Definition: jni_util.cc:70
std::vector< std::string > StringArrayToVector(JNIEnv *env, jobjectArray array)
Definition: jni_util.cc:96
ScopedJavaLocalRef< jstring > StringToJavaString(JNIEnv *env, const std::string &u8_string)
Definition: jni_util.cc:86
void InitializeAndroidCachesPath(std::string caches_path)
constexpr std::size_t size(T(&array)[N])
Definition: size.h:13
bool IsFile(const std::string &path)
Definition: file_posix.cc:146
std::function< void()> closure
Definition: closure.h:14
CommandLine CommandLineFromIterators(InputIterator first, InputIterator last)
Definition: command_line.h:204
const ProcTable & GetProcTable()
Definition: proc_table.cc:12
sk_sp< SkFontMgr > GetDefaultFontManager(uint32_t font_initialization_data)
Definition: platform.cc:17
bool TraceIsEnabled() const
Check if tracing in enabled in the process. This call can be made at any API level.
Definition: proc_table.cc:69