• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <vector>
10 
11 #include "flutter/fml/command_line.h"
12 #include "flutter/fml/file.h"
13 #include "flutter/fml/macros.h"
14 #include "flutter/fml/message_loop.h"
15 #include "flutter/fml/paths.h"
16 #include "flutter/fml/platform/android/jni_util.h"
17 #include "flutter/fml/platform/android/paths_android.h"
18 #include "flutter/fml/size.h"
19 #include "flutter/lib/ui/plugins/callback_cache.h"
20 #include "flutter/runtime/dart_vm.h"
21 #include "flutter/runtime/start_up.h"
22 #include "flutter/shell/common/shell.h"
23 #include "flutter/shell/common/switches.h"
24 
25 namespace flutter {
26 
27 extern "C" {
28 #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
29 // Used for debugging dart:* sources.
30 extern const uint8_t kPlatformStrongDill[];
31 extern const intptr_t kPlatformStrongDillSize;
32 #endif
33 }
34 
35 namespace {
36 
37 fml::jni::ScopedJavaGlobalRef<jclass>* g_flutter_jni_class = nullptr;
38 
39 }  // anonymous namespace
40 
FlutterMain(flutter::Settings settings)41 FlutterMain::FlutterMain(flutter::Settings settings)
42     : settings_(std::move(settings)), observatory_uri_callback_() {}
43 
44 FlutterMain::~FlutterMain() = default;
45 
46 static std::unique_ptr<FlutterMain> g_flutter_main;
47 
Get()48 FlutterMain& FlutterMain::Get() {
49   FML_CHECK(g_flutter_main) << "ensureInitializationComplete must have already "
50                                "been called.";
51   return *g_flutter_main;
52 }
53 
GetSettings() const54 const flutter::Settings& FlutterMain::GetSettings() const {
55   return settings_;
56 }
57 
Init(JNIEnv * env,jclass clazz,jobject context,jobjectArray jargs,jstring kernelPath,jstring appStoragePath,jstring engineCachesPath)58 void FlutterMain::Init(JNIEnv* env,
59                        jclass clazz,
60                        jobject context,
61                        jobjectArray jargs,
62                        jstring kernelPath,
63                        jstring appStoragePath,
64                        jstring engineCachesPath) {
65   std::vector<std::string> args;
66   args.push_back("flutter");
67   for (auto& arg : fml::jni::StringArrayToVector(env, jargs)) {
68     args.push_back(std::move(arg));
69   }
70   auto command_line = fml::CommandLineFromIterators(args.begin(), args.end());
71 
72   auto settings = SettingsFromCommandLine(command_line);
73 
74   // Restore the callback cache.
75   // TODO(chinmaygarde): Route all cache file access through FML and remove this
76   // setter.
77   flutter::DartCallbackCache::SetCachePath(
78       fml::jni::JavaStringToString(env, appStoragePath));
79 
80   fml::paths::InitializeAndroidCachesPath(
81       fml::jni::JavaStringToString(env, engineCachesPath));
82 
83   flutter::DartCallbackCache::LoadCacheFromDisk();
84 
85   if (!flutter::DartVM::IsRunningPrecompiledCode() && kernelPath) {
86     // Check to see if the appropriate kernel files are present and configure
87     // settings accordingly.
88     auto application_kernel_path =
89         fml::jni::JavaStringToString(env, kernelPath);
90 
91     if (fml::IsFile(application_kernel_path)) {
92       settings.application_kernel_asset = application_kernel_path;
93     }
94   }
95 
96   settings.task_observer_add = [](intptr_t key, fml::closure callback) {
97     fml::MessageLoop::GetCurrent().AddTaskObserver(key, std::move(callback));
98   };
99 
100   settings.task_observer_remove = [](intptr_t key) {
101     fml::MessageLoop::GetCurrent().RemoveTaskObserver(key);
102   };
103 
104 #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
105   // There are no ownership concerns here as all mappings are owned by the
106   // embedder and not the engine.
107   auto make_mapping_callback = [](const uint8_t* mapping, size_t size) {
108     return [mapping, size]() {
109       return std::make_unique<fml::NonOwnedMapping>(mapping, size);
110     };
111   };
112 
113   settings.dart_library_sources_kernel =
114       make_mapping_callback(kPlatformStrongDill, kPlatformStrongDillSize);
115 #endif  // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
116 
117   // Not thread safe. Will be removed when FlutterMain is refactored to no
118   // longer be a singleton.
119   g_flutter_main.reset(new FlutterMain(std::move(settings)));
120 
121   g_flutter_main->SetupObservatoryUriCallback(env);
122 }
123 
SetupObservatoryUriCallback(JNIEnv * env)124 void FlutterMain::SetupObservatoryUriCallback(JNIEnv* env) {
125   g_flutter_jni_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
126       env, env->FindClass("io/flutter/embedding/engine/FlutterJNI"));
127   if (g_flutter_jni_class->is_null()) {
128     return;
129   }
130   jfieldID uri_field = env->GetStaticFieldID(
131       g_flutter_jni_class->obj(), "observatoryUri", "Ljava/lang/String;");
132   if (uri_field == nullptr) {
133     return;
134   }
135 
136   auto set_uri = [env, uri_field](std::string uri) {
137     fml::jni::ScopedJavaLocalRef<jstring> java_uri =
138         fml::jni::StringToJavaString(env, uri);
139     env->SetStaticObjectField(g_flutter_jni_class->obj(), uri_field,
140                               java_uri.obj());
141   };
142 
143   fml::MessageLoop::EnsureInitializedForCurrentThread();
144   fml::RefPtr<fml::TaskRunner> platform_runner =
145       fml::MessageLoop::GetCurrent().GetTaskRunner();
146 
147   observatory_uri_callback_ = DartServiceIsolate::AddServerStatusCallback(
148       [platform_runner, set_uri](std::string uri) {
149         platform_runner->PostTask([uri, set_uri] { set_uri(uri); });
150       });
151 }
152 
RecordStartTimestamp(JNIEnv * env,jclass jcaller,jlong initTimeMillis)153 static void RecordStartTimestamp(JNIEnv* env,
154                                  jclass jcaller,
155                                  jlong initTimeMillis) {
156   int64_t initTimeMicros =
157       static_cast<int64_t>(initTimeMillis) * static_cast<int64_t>(1000);
158   flutter::engine_main_enter_ts = 0 - initTimeMicros;
159 }
160 
Register(JNIEnv * env)161 bool FlutterMain::Register(JNIEnv* env) {
162   static const JNINativeMethod methods[] = {
163       {
164           .name = "nativeInit",
165           .signature = "(Landroid/content/Context;[Ljava/lang/String;Ljava/"
166                        "lang/String;Ljava/lang/String;Ljava/lang/String;)V",
167           .fnPtr = reinterpret_cast<void*>(&Init),
168       },
169       {
170           .name = "nativeRecordStartTimestamp",
171           .signature = "(J)V",
172           .fnPtr = reinterpret_cast<void*>(&RecordStartTimestamp),
173       },
174   };
175 
176   jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
177 
178   if (clazz == nullptr) {
179     return false;
180   }
181 
182   return env->RegisterNatives(clazz, methods, fml::size(methods)) == 0;
183 }
184 
185 }  // namespace flutter
186