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 "flutter/shell/platform/android/flutter_main.h"
8 
9 #include <android/log.h>
10 
11 #include <optional>
12 #include <vector>
13 
14 #include "flutter/fml/command_line.h"
15 #include "flutter/fml/file.h"
16 #include "flutter/fml/macros.h"
17 #include "flutter/fml/message_loop.h"
18 #include "flutter/fml/native_library.h"
19 #include "flutter/fml/paths.h"
20 #include "flutter/fml/platform/android/jni_util.h"
21 #include "flutter/fml/platform/android/paths_android.h"
22 #include "flutter/fml/size.h"
23 #include "flutter/lib/ui/plugins/callback_cache.h"
24 #include "flutter/runtime/dart_vm.h"
25 #include "flutter/shell/common/shell.h"
26 #include "flutter/shell/common/switches.h"
27 #include "third_party/dart/runtime/include/dart_tools_api.h"
28 #include "third_party/skia/include/core/SkFontMgr.h"
29 
30 namespace flutter {
31 
32 extern "C" {
33 #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
34 // Used for debugging dart:* sources.
35 extern const uint8_t kPlatformStrongDill[];
36 extern const intptr_t kPlatformStrongDillSize;
37 #endif
38 }
39 
40 namespace {
41 
42 // This is only available on API 23+, so dynamically look it up.
43 // This method is only called once at shell creation.
44 // Do this in C++ because the API is available at level 23 here, but only 29+ in
45 // Java.
46 bool IsATraceEnabled() {
47  auto libandroid = fml::NativeLibrary::Create("libandroid.so");
48  FML_CHECK(libandroid);
49  auto atrace_fn =
50  libandroid->ResolveFunction<bool (*)(void)>("ATrace_isEnabled");
51  if (atrace_fn) {
52  return atrace_fn.value()();
53  }
54  return false;
55 }
56 
58 
59 } // anonymous namespace
60 
61 FlutterMain::FlutterMain(flutter::Settings settings)
62  : settings_(std::move(settings)), observatory_uri_callback_() {}
63 
64 FlutterMain::~FlutterMain() = default;
65 
66 static std::unique_ptr<FlutterMain> g_flutter_main;
67 
69  FML_CHECK(g_flutter_main) << "ensureInitializationComplete must have already "
70  "been called.";
71  return *g_flutter_main;
72 }
73 
75  return settings_;
76 }
77 
78 void FlutterMain::Init(JNIEnv* env,
79  jclass clazz,
80  jobject context,
81  jobjectArray jargs,
82  jstring kernelPath,
83  jstring appStoragePath,
84  jstring engineCachesPath,
85  jlong initTimeMillis) {
86  std::vector<std::string> args;
87  args.push_back("flutter");
88  for (auto& arg : fml::jni::StringArrayToVector(env, jargs)) {
89  args.push_back(std::move(arg));
90  }
91  auto command_line = fml::CommandLineFromIterators(args.begin(), args.end());
92 
93  auto settings = SettingsFromCommandLine(command_line);
94 
95  // Turn systracing on if ATrace_isEnabled is true and the user did not already
96  // request systracing
97  if (!settings.trace_systrace) {
98  settings.trace_systrace = IsATraceEnabled();
99  if (settings.trace_systrace) {
100  __android_log_print(
101  ANDROID_LOG_INFO, "Flutter",
102  "ATrace was enabled at startup. Flutter and Dart "
103  "tracing will be forwarded to systrace and will not show up in the "
104  "Observatory timeline or Dart DevTools.");
105  }
106  }
107 
108  int64_t init_time_micros = initTimeMillis * 1000;
109  settings.engine_start_timestamp =
110  std::chrono::microseconds(Dart_TimelineGetMicros() - init_time_micros);
111 
112  // Restore the callback cache.
113  // TODO(chinmaygarde): Route all cache file access through FML and remove this
114  // setter.
116  fml::jni::JavaStringToString(env, appStoragePath));
117 
119  fml::jni::JavaStringToString(env, engineCachesPath));
120 
122 
123  if (!flutter::DartVM::IsRunningPrecompiledCode() && kernelPath) {
124  // Check to see if the appropriate kernel files are present and configure
125  // settings accordingly.
126  auto application_kernel_path =
127  fml::jni::JavaStringToString(env, kernelPath);
128 
129  if (fml::IsFile(application_kernel_path)) {
130  settings.application_kernel_asset = application_kernel_path;
131  }
132  }
133 
134  settings.task_observer_add = [](intptr_t key, fml::closure callback) {
136  };
137 
138  settings.task_observer_remove = [](intptr_t key) {
140  };
141 
142  settings.log_message_callback = [](const std::string& tag,
143  const std::string& message) {
144  __android_log_print(ANDROID_LOG_INFO, tag.c_str(), "%.*s",
145  (int)message.size(), message.c_str());
146  };
147 
148 #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
149  // There are no ownership concerns here as all mappings are owned by the
150  // embedder and not the engine.
151  auto make_mapping_callback = [](const uint8_t* mapping, size_t size) {
152  return [mapping, size]() {
153  return std::make_unique<fml::NonOwnedMapping>(mapping, size);
154  };
155  };
156 
157  settings.dart_library_sources_kernel =
158  make_mapping_callback(kPlatformStrongDill, kPlatformStrongDillSize);
159 #endif // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
160 
161  // Not thread safe. Will be removed when FlutterMain is refactored to no
162  // longer be a singleton.
163  g_flutter_main.reset(new FlutterMain(std::move(settings)));
164 
165  g_flutter_main->SetupObservatoryUriCallback(env);
166 }
167 
168 void FlutterMain::SetupObservatoryUriCallback(JNIEnv* env) {
170  env, env->FindClass("io/flutter/embedding/engine/FlutterJNI"));
171  if (g_flutter_jni_class->is_null()) {
172  return;
173  }
174  jfieldID uri_field = env->GetStaticFieldID(
175  g_flutter_jni_class->obj(), "observatoryUri", "Ljava/lang/String;");
176  if (uri_field == nullptr) {
177  return;
178  }
179 
180  auto set_uri = [env, uri_field](std::string uri) {
183  env->SetStaticObjectField(g_flutter_jni_class->obj(), uri_field,
184  java_uri.obj());
185  };
186 
188  fml::RefPtr<fml::TaskRunner> platform_runner =
190 
191  observatory_uri_callback_ = DartServiceIsolate::AddServerStatusCallback(
192  [platform_runner, set_uri](std::string uri) {
193  platform_runner->PostTask([uri, set_uri] { set_uri(uri); });
194  });
195 }
196 
197 static void PrefetchDefaultFontManager(JNIEnv* env, jclass jcaller) {
198  // Initialize a singleton owned by Skia.
199  SkFontMgr::RefDefault();
200 }
201 
202 bool FlutterMain::Register(JNIEnv* env) {
203  static const JNINativeMethod methods[] = {
204  {
205  .name = "nativeInit",
206  .signature = "(Landroid/content/Context;[Ljava/lang/String;Ljava/"
207  "lang/String;Ljava/lang/String;Ljava/lang/String;J)V",
208  .fnPtr = reinterpret_cast<void*>(&Init),
209  },
210  {
211  .name = "nativePrefetchDefaultFontManager",
212  .signature = "()V",
213  .fnPtr = reinterpret_cast<void*>(&PrefetchDefaultFontManager),
214  },
215  };
216 
217  jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
218 
219  if (clazz == nullptr) {
220  return false;
221  }
222 
223  return env->RegisterNatives(clazz, methods, fml::size(methods)) == 0;
224 }
225 
226 } // namespace flutter
G_BEGIN_DECLS FlValue * args
static std::unique_ptr< FlutterMain > g_flutter_main
Definition: flutter_main.cc:66
void AddTaskObserver(intptr_t key, const fml::closure &callback)
Definition: message_loop.cc:64
const intptr_t kPlatformStrongDillSize
static void PrefetchDefaultFontManager(JNIEnv *env, jclass jcaller)
ScopedJavaLocalRef< jstring > StringToJavaString(JNIEnv *env, const std::string &u8_string)
Definition: jni_util.cc:96
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
Definition: message_loop.cc:19
static void EnsureInitializedForCurrentThread()
Definition: message_loop.cc:27
constexpr std::size_t size(T(&array)[N])
Definition: size.h:13
static void SetCachePath(const std::string &path)
Settings SettingsFromCommandLine(const fml::CommandLine &command_line)
Definition: switches.cc:228
const flutter::Settings & GetSettings() const
Definition: flutter_main.cc:74
static CallbackHandle AddServerStatusCallback(const ObservatoryServerStateCallback &callback)
Add a callback that will get invoked when the observatory starts up. If the observatory has already s...
static fml::jni::ScopedJavaGlobalRef< jclass > * g_flutter_jni_class
FlKeyEvent FlKeyResponderAsyncCallback callback
fml::RefPtr< fml::TaskRunner > GetTaskRunner() const
Definition: message_loop.cc:56
const uint8_t kPlatformStrongDill[]
std::function< void()> closure
Definition: closure.h:14
static fml::RefPtr< NativeLibrary > Create(const char *path)
static FlutterMain & Get()
Definition: flutter_main.cc:68
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:202
static bool Register(JNIEnv *env)
void InitializeAndroidCachesPath(std::string caches_path)
#define FML_CHECK(condition)
Definition: logging.h:68
bool IsFile(const std::string &path)
Definition: file_posix.cc:145
void RemoveTaskObserver(intptr_t key)
Definition: message_loop.cc:68
std::string JavaStringToString(JNIEnv *env, jstring str)
Definition: jni_util.cc:76
Settings settings_
std::vector< std::string > StringArrayToVector(JNIEnv *env, jobjectArray array)
Definition: jni_util.cc:106
virtual void PostTask(const fml::closure &task) override
Definition: task_runner.cc:24
CommandLine CommandLineFromIterators(InputIterator first, InputIterator last)
Definition: command_line.h:201