mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
The engine was using a global to store a timestamp representing the launch of the engine. This timestamp is initialized with a JNI call on Android and during shell setup on other platforms. Later the timestamp is added to a FlutterEngineMainEnter timeline event used to measure engine startup time in benchmarks. This PR removes the global and the JNI call and moves the timestamp into the settings object.
178 lines
5.8 KiB
C++
178 lines
5.8 KiB
C++
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#define FML_USED_ON_EMBEDDER
|
|
|
|
#include "flutter/shell/platform/android/flutter_main.h"
|
|
|
|
#include <vector>
|
|
|
|
#include "flutter/fml/command_line.h"
|
|
#include "flutter/fml/file.h"
|
|
#include "flutter/fml/macros.h"
|
|
#include "flutter/fml/message_loop.h"
|
|
#include "flutter/fml/paths.h"
|
|
#include "flutter/fml/platform/android/jni_util.h"
|
|
#include "flutter/fml/platform/android/paths_android.h"
|
|
#include "flutter/fml/size.h"
|
|
#include "flutter/lib/ui/plugins/callback_cache.h"
|
|
#include "flutter/runtime/dart_vm.h"
|
|
#include "flutter/shell/common/shell.h"
|
|
#include "flutter/shell/common/switches.h"
|
|
#include "third_party/dart/runtime/include/dart_tools_api.h"
|
|
|
|
namespace flutter {
|
|
|
|
extern "C" {
|
|
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
|
|
// Used for debugging dart:* sources.
|
|
extern const uint8_t kPlatformStrongDill[];
|
|
extern const intptr_t kPlatformStrongDillSize;
|
|
#endif
|
|
}
|
|
|
|
namespace {
|
|
|
|
fml::jni::ScopedJavaGlobalRef<jclass>* g_flutter_jni_class = nullptr;
|
|
|
|
} // anonymous namespace
|
|
|
|
FlutterMain::FlutterMain(flutter::Settings settings)
|
|
: settings_(std::move(settings)), observatory_uri_callback_() {}
|
|
|
|
FlutterMain::~FlutterMain() = default;
|
|
|
|
static std::unique_ptr<FlutterMain> g_flutter_main;
|
|
|
|
FlutterMain& FlutterMain::Get() {
|
|
FML_CHECK(g_flutter_main) << "ensureInitializationComplete must have already "
|
|
"been called.";
|
|
return *g_flutter_main;
|
|
}
|
|
|
|
const flutter::Settings& FlutterMain::GetSettings() const {
|
|
return settings_;
|
|
}
|
|
|
|
void FlutterMain::Init(JNIEnv* env,
|
|
jclass clazz,
|
|
jobject context,
|
|
jobjectArray jargs,
|
|
jstring kernelPath,
|
|
jstring appStoragePath,
|
|
jstring engineCachesPath,
|
|
jlong initTimeMillis) {
|
|
std::vector<std::string> args;
|
|
args.push_back("flutter");
|
|
for (auto& arg : fml::jni::StringArrayToVector(env, jargs)) {
|
|
args.push_back(std::move(arg));
|
|
}
|
|
auto command_line = fml::CommandLineFromIterators(args.begin(), args.end());
|
|
|
|
auto settings = SettingsFromCommandLine(command_line);
|
|
|
|
int64_t init_time_micros = initTimeMillis * 1000;
|
|
settings.engine_start_timestamp =
|
|
std::chrono::microseconds(Dart_TimelineGetMicros() - init_time_micros);
|
|
|
|
// Restore the callback cache.
|
|
// TODO(chinmaygarde): Route all cache file access through FML and remove this
|
|
// setter.
|
|
flutter::DartCallbackCache::SetCachePath(
|
|
fml::jni::JavaStringToString(env, appStoragePath));
|
|
|
|
fml::paths::InitializeAndroidCachesPath(
|
|
fml::jni::JavaStringToString(env, engineCachesPath));
|
|
|
|
flutter::DartCallbackCache::LoadCacheFromDisk();
|
|
|
|
if (!flutter::DartVM::IsRunningPrecompiledCode() && kernelPath) {
|
|
// Check to see if the appropriate kernel files are present and configure
|
|
// settings accordingly.
|
|
auto application_kernel_path =
|
|
fml::jni::JavaStringToString(env, kernelPath);
|
|
|
|
if (fml::IsFile(application_kernel_path)) {
|
|
settings.application_kernel_asset = application_kernel_path;
|
|
}
|
|
}
|
|
|
|
settings.task_observer_add = [](intptr_t key, fml::closure callback) {
|
|
fml::MessageLoop::GetCurrent().AddTaskObserver(key, std::move(callback));
|
|
};
|
|
|
|
settings.task_observer_remove = [](intptr_t key) {
|
|
fml::MessageLoop::GetCurrent().RemoveTaskObserver(key);
|
|
};
|
|
|
|
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
|
|
// There are no ownership concerns here as all mappings are owned by the
|
|
// embedder and not the engine.
|
|
auto make_mapping_callback = [](const uint8_t* mapping, size_t size) {
|
|
return [mapping, size]() {
|
|
return std::make_unique<fml::NonOwnedMapping>(mapping, size);
|
|
};
|
|
};
|
|
|
|
settings.dart_library_sources_kernel =
|
|
make_mapping_callback(kPlatformStrongDill, kPlatformStrongDillSize);
|
|
#endif // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
|
|
|
|
// Not thread safe. Will be removed when FlutterMain is refactored to no
|
|
// longer be a singleton.
|
|
g_flutter_main.reset(new FlutterMain(std::move(settings)));
|
|
|
|
g_flutter_main->SetupObservatoryUriCallback(env);
|
|
}
|
|
|
|
void FlutterMain::SetupObservatoryUriCallback(JNIEnv* env) {
|
|
g_flutter_jni_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
|
|
env, env->FindClass("io/flutter/embedding/engine/FlutterJNI"));
|
|
if (g_flutter_jni_class->is_null()) {
|
|
return;
|
|
}
|
|
jfieldID uri_field = env->GetStaticFieldID(
|
|
g_flutter_jni_class->obj(), "observatoryUri", "Ljava/lang/String;");
|
|
if (uri_field == nullptr) {
|
|
return;
|
|
}
|
|
|
|
auto set_uri = [env, uri_field](std::string uri) {
|
|
fml::jni::ScopedJavaLocalRef<jstring> java_uri =
|
|
fml::jni::StringToJavaString(env, uri);
|
|
env->SetStaticObjectField(g_flutter_jni_class->obj(), uri_field,
|
|
java_uri.obj());
|
|
};
|
|
|
|
fml::MessageLoop::EnsureInitializedForCurrentThread();
|
|
fml::RefPtr<fml::TaskRunner> platform_runner =
|
|
fml::MessageLoop::GetCurrent().GetTaskRunner();
|
|
|
|
observatory_uri_callback_ = DartServiceIsolate::AddServerStatusCallback(
|
|
[platform_runner, set_uri](std::string uri) {
|
|
platform_runner->PostTask([uri, set_uri] { set_uri(uri); });
|
|
});
|
|
}
|
|
|
|
bool FlutterMain::Register(JNIEnv* env) {
|
|
static const JNINativeMethod methods[] = {
|
|
{
|
|
.name = "nativeInit",
|
|
.signature = "(Landroid/content/Context;[Ljava/lang/String;Ljava/"
|
|
"lang/String;Ljava/lang/String;Ljava/lang/String;J)V",
|
|
.fnPtr = reinterpret_cast<void*>(&Init),
|
|
},
|
|
};
|
|
|
|
jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
|
|
|
|
if (clazz == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
return env->RegisterNatives(clazz, methods, fml::size(methods)) == 0;
|
|
}
|
|
|
|
} // namespace flutter
|