Flutter Engine
 
Loading...
Searching...
No Matches
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 <sys/system_properties.h>
9#include <cstring>
10#include <optional>
11#include <string>
12#include <vector>
13
14#include "common/settings.h"
16#include "flutter/fml/file.h"
17#include "flutter/fml/logging.h"
30#include "txt/platform.h"
31
32namespace flutter {
33
35
36extern "C" {
37#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
38// Used for debugging dart:* sources.
39extern const uint8_t kPlatformStrongDill[];
40extern const intptr_t kPlatformStrongDillSize;
41#endif
42}
43
44namespace {
45
47
48// Workaround for crashes in Vivante GL driver on Android.
49//
50// See:
51// * https://github.com/flutter/flutter/issues/167850
52// * http://crbug.com/141785
53#ifdef FML_OS_ANDROID
54bool IsVivante() {
55 char product_model[PROP_VALUE_MAX];
56 __system_property_get("ro.hardware.egl", product_model);
57 return strcmp(product_model, "VIVANTE") == 0;
58}
59#else
60bool IsVivante() {
61 return false;
62}
63#endif // FML_OS_ANDROID
64
65} // anonymous namespace
66
67FlutterMain::FlutterMain(const flutter::Settings& settings,
68 flutter::AndroidRenderingAPI android_rendering_api)
69 : settings_(settings), android_rendering_api_(android_rendering_api) {}
70
71FlutterMain::~FlutterMain() = default;
72
73static std::unique_ptr<FlutterMain> g_flutter_main;
74
75FlutterMain& FlutterMain::Get() {
76 FML_CHECK(g_flutter_main) << "ensureInitializationComplete must have already "
77 "been called.";
78 return *g_flutter_main;
79}
80
81const flutter::Settings& FlutterMain::GetSettings() const {
82 return settings_;
83}
84
85flutter::AndroidRenderingAPI FlutterMain::GetAndroidRenderingAPI() {
86 return android_rendering_api_;
87}
88
89void FlutterMain::Init(JNIEnv* env,
90 jclass clazz,
91 jobject context,
92 jobjectArray jargs,
93 jstring kernelPath,
94 jstring appStoragePath,
95 jstring engineCachesPath,
96 jlong initTimeMillis,
97 jint api_level) {
98 std::vector<std::string> args;
99 args.push_back("flutter");
100 for (auto& arg : fml::jni::StringArrayToVector(env, jargs)) {
101 args.push_back(std::move(arg));
102 }
103 auto command_line = fml::CommandLineFromIterators(args.begin(), args.end());
104
105 auto settings = SettingsFromCommandLine(command_line, true);
106
107 // Turn systracing on if ATrace_isEnabled is true and the user did not already
108 // request systracing
109 if (!settings.trace_systrace) {
110 settings.trace_systrace =
112 if (settings.trace_systrace) {
113 __android_log_print(
114 ANDROID_LOG_INFO, "Flutter",
115 "ATrace was enabled at startup. Flutter and Dart "
116 "tracing will be forwarded to systrace and will not show up in "
117 "Dart DevTools.");
118 }
119 }
120 // The API level must be provided from java, as the NDK function
121 // android_get_device_api_level() is only available on API 24 and greater, and
122 // Flutter still supports 21, 22, and 23.
123
124 AndroidRenderingAPI android_rendering_api =
125 SelectedRenderingAPI(settings, api_level);
126
127 settings.warn_on_impeller_opt_out = true;
128#if !SLIMPELLER
129 switch (android_rendering_api) {
130 case AndroidRenderingAPI::kSoftware:
131 case AndroidRenderingAPI::kSkiaOpenGLES:
132 settings.enable_impeller = false;
133 break;
134 case AndroidRenderingAPI::kImpellerOpenGLES:
135 case AndroidRenderingAPI::kImpellerVulkan:
136 case AndroidRenderingAPI::kImpellerAutoselect:
137 settings.enable_impeller = true;
138 break;
139 }
140#endif // !SLIMPELLER
141
142#if FLUTTER_RELEASE
143 // On most platforms the timeline is always disabled in release mode.
144 // On Android, enable it in release mode only when using systrace.
145 settings.enable_timeline_event_handler = settings.trace_systrace;
146#endif // FLUTTER_RELEASE
147
148 // Restore the callback cache.
149 // TODO(chinmaygarde): Route all cache file access through FML and remove this
150 // setter.
152 fml::jni::JavaStringToString(env, appStoragePath));
153
155 fml::jni::JavaStringToString(env, engineCachesPath));
156
158
159 if (!flutter::DartVM::IsRunningPrecompiledCode() && kernelPath) {
160 // Check to see if the appropriate kernel files are present and configure
161 // settings accordingly.
162 auto application_kernel_path =
163 fml::jni::JavaStringToString(env, kernelPath);
164
165 if (fml::IsFile(application_kernel_path)) {
166 settings.application_kernel_asset = application_kernel_path;
167 }
168 }
169
170 settings.task_observer_add = [](intptr_t key, const fml::closure& callback) {
173 callback);
174 return queue_id;
175 };
176
177 settings.task_observer_remove = [](fml::TaskQueueId queue_id, intptr_t key) {
179 key);
180 };
181
182 settings.log_message_callback = [](const std::string& tag,
183 const std::string& message) {
184 __android_log_print(ANDROID_LOG_INFO, tag.c_str(), "%.*s",
185 static_cast<int>(message.size()), message.c_str());
186 };
187
188 settings.enable_platform_isolates = true;
189
190#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
191 // There are no ownership concerns here as all mappings are owned by the
192 // embedder and not the engine.
193 auto make_mapping_callback = [](const uint8_t* mapping, size_t size) {
194 return [mapping, size]() {
195 return std::make_unique<fml::NonOwnedMapping>(mapping, size);
196 };
197 };
198
199 settings.dart_library_sources_kernel =
200 make_mapping_callback(kPlatformStrongDill, kPlatformStrongDillSize);
201#endif // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
202
203 // Not thread safe. Will be removed when FlutterMain is refactored to no
204 // longer be a singleton.
205 g_flutter_main.reset(new FlutterMain(settings, android_rendering_api));
206 g_flutter_main->SetupDartVMServiceUriCallback(env);
207}
208
209void FlutterMain::SetupDartVMServiceUriCallback(JNIEnv* env) {
210 g_flutter_jni_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
211 env, env->FindClass("io/flutter/embedding/engine/FlutterJNI"));
212 if (g_flutter_jni_class->is_null()) {
213 return;
214 }
215 jfieldID uri_field = env->GetStaticFieldID(
216 g_flutter_jni_class->obj(), "vmServiceUri", "Ljava/lang/String;");
217 if (uri_field == nullptr) {
218 return;
219 }
220
221 auto set_uri = [env, uri_field](const std::string& uri) {
224 env->SetStaticObjectField(g_flutter_jni_class->obj(), uri_field,
225 java_uri.obj());
226 };
227
229 fml::RefPtr<fml::TaskRunner> platform_runner =
231
232 vm_service_uri_callback_ = DartServiceIsolate::AddServerStatusCallback(
233 [platform_runner, set_uri](const std::string& uri) {
234 platform_runner->PostTask([uri, set_uri] { set_uri(uri); });
235 });
236}
237
238static void PrefetchDefaultFontManager(JNIEnv* env, jclass jcaller) {
239 // Initialize a singleton owned by Skia.
241}
242
243bool FlutterMain::Register(JNIEnv* env) {
244 static const JNINativeMethod methods[] = {
245 {
246 .name = "nativeInit",
247 .signature = "(Landroid/content/Context;[Ljava/lang/String;Ljava/"
248 "lang/String;Ljava/lang/String;Ljava/lang/String;JI)V",
249 .fnPtr = reinterpret_cast<void*>(&Init),
250 },
251 {
252 .name = "nativePrefetchDefaultFontManager",
253 .signature = "()V",
254 .fnPtr = reinterpret_cast<void*>(&PrefetchDefaultFontManager),
255 },
256 };
257
258 jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
259
260 if (clazz == nullptr) {
261 return false;
262 }
263
264 return env->RegisterNatives(clazz, methods, std::size(methods)) == 0;
265}
266
267// static
268AndroidRenderingAPI FlutterMain::SelectedRenderingAPI(
269 const flutter::Settings& settings,
270 int api_level) {
271#if !SLIMPELLER
272 if (settings.enable_software_rendering) {
273 if (settings.enable_impeller) {
274 FML_CHECK(!settings.enable_impeller)
275 << "Impeller does not support software rendering. Either disable "
276 "software rendering or disable impeller.";
277 }
278 return AndroidRenderingAPI::kSoftware;
279 }
280
281 // Debug/Profile only functionality for testing a specific
282 // backend configuration.
283#ifndef FLUTTER_RELEASE
284 if (settings.requested_rendering_backend == "opengles" &&
285 settings.enable_impeller) {
286 return AndroidRenderingAPI::kImpellerOpenGLES;
287 }
288 if (settings.requested_rendering_backend == "vulkan" &&
289 settings.enable_impeller) {
290 return AndroidRenderingAPI::kImpellerVulkan;
291 }
292#endif
293
294 if (settings.enable_impeller &&
295 api_level >= kMinimumAndroidApiLevelForImpeller && !IsVivante()) {
296 return AndroidRenderingAPI::kImpellerAutoselect;
297 }
298
299 return AndroidRenderingAPI::kSkiaOpenGLES;
300#else
301 return AndroidRenderingAPI::kImpellerAutoselect;
302#endif // !SLIMPELLER
303}
304
305} // 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:176
static void EnsureInitializedForCurrentThread()
fml::RefPtr< fml::TaskRunner > GetTaskRunner() const
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
static TaskQueueId GetCurrentTaskQueueId()
static MessageLoopTaskQueues * GetInstance()
void AddTaskObserver(TaskQueueId queue_id, intptr_t key, const fml::closure &callback)
void RemoveTaskObserver(TaskQueueId queue_id, intptr_t key)
Settings settings_
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_BEGIN_DECLS GBytes * message
FlutterDesktopBinaryReply callback
#define FML_CHECK(condition)
Definition logging.h:104
const intptr_t kPlatformStrongDillSize
FLUTTER_ASSERT_ARC const uint8_t kPlatformStrongDill[]
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all 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
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
constexpr int kMinimumAndroidApiLevelForImpeller
const uint8_t kPlatformStrongDill[]
std::string JavaStringToString(JNIEnv *env, jstring str)
Definition jni_util.cc:70
ScopedJavaLocalRef< jstring > StringToJavaString(JNIEnv *env, const std::string &u8_string)
Definition jni_util.cc:86
void InitializeAndroidCachesPath(std::string caches_path)
bool IsFile(const std::string &path)
std::function< void()> closure
Definition closure.h:14
CommandLine CommandLineFromIterators(InputIterator first, InputIterator last)
const ProcTable & GetProcTable()
Definition proc_table.cc:12
sk_sp< SkFontMgr > GetDefaultFontManager(uint32_t font_initialization_data)
Definition platform.cc:17
bool enable_software_rendering
Definition settings.h:317
std::optional< std::string > requested_rendering_backend
Definition settings.h:248
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