mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Some components in the Flutter engine were derived from the forked blink codebase. While the forked components have either been removed or rewritten, the use of the blink namespace has mostly (and inconsistently) remained. This renames the blink namesapce to flutter for consistency. There are no functional changes in this patch.
224 lines
7.4 KiB
C++
224 lines
7.4 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/android_shell_holder.h"
|
|
|
|
#include <pthread.h>
|
|
#include <sys/resource.h>
|
|
#include <sys/time.h>
|
|
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
#include "flutter/fml/make_copyable.h"
|
|
#include "flutter/fml/message_loop.h"
|
|
#include "flutter/shell/common/rasterizer.h"
|
|
#include "flutter/shell/platform/android/platform_view_android.h"
|
|
|
|
namespace shell {
|
|
|
|
AndroidShellHolder::AndroidShellHolder(
|
|
flutter::Settings settings,
|
|
fml::jni::JavaObjectWeakGlobalRef java_object,
|
|
bool is_background_view)
|
|
: settings_(std::move(settings)), java_object_(java_object) {
|
|
static size_t shell_count = 1;
|
|
auto thread_label = std::to_string(shell_count++);
|
|
|
|
FML_CHECK(pthread_key_create(&thread_destruct_key_, ThreadDestructCallback) ==
|
|
0);
|
|
|
|
if (is_background_view) {
|
|
thread_host_ = {thread_label, ThreadHost::Type::UI};
|
|
} else {
|
|
thread_host_ = {thread_label, ThreadHost::Type::UI | ThreadHost::Type::GPU |
|
|
ThreadHost::Type::IO};
|
|
}
|
|
|
|
// Detach from JNI when the UI and GPU threads exit.
|
|
auto jni_exit_task([key = thread_destruct_key_]() {
|
|
FML_CHECK(pthread_setspecific(key, reinterpret_cast<void*>(1)) == 0);
|
|
});
|
|
thread_host_.ui_thread->GetTaskRunner()->PostTask(jni_exit_task);
|
|
if (!is_background_view) {
|
|
thread_host_.gpu_thread->GetTaskRunner()->PostTask(jni_exit_task);
|
|
}
|
|
|
|
fml::WeakPtr<PlatformViewAndroid> weak_platform_view;
|
|
Shell::CreateCallback<PlatformView> on_create_platform_view =
|
|
[is_background_view, java_object, &weak_platform_view](Shell& shell) {
|
|
std::unique_ptr<PlatformViewAndroid> platform_view_android;
|
|
if (is_background_view) {
|
|
platform_view_android = std::make_unique<PlatformViewAndroid>(
|
|
shell, // delegate
|
|
shell.GetTaskRunners(), // task runners
|
|
java_object // java object handle for JNI interop
|
|
);
|
|
|
|
} else {
|
|
platform_view_android = std::make_unique<PlatformViewAndroid>(
|
|
shell, // delegate
|
|
shell.GetTaskRunners(), // task runners
|
|
java_object, // java object handle for JNI interop
|
|
shell.GetSettings()
|
|
.enable_software_rendering // use software rendering
|
|
);
|
|
}
|
|
weak_platform_view = platform_view_android->GetWeakPtr();
|
|
return platform_view_android;
|
|
};
|
|
|
|
Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
|
|
return std::make_unique<Rasterizer>(shell.GetTaskRunners());
|
|
};
|
|
|
|
// The current thread will be used as the platform thread. Ensure that the
|
|
// message loop is initialized.
|
|
fml::MessageLoop::EnsureInitializedForCurrentThread();
|
|
fml::RefPtr<fml::TaskRunner> gpu_runner;
|
|
fml::RefPtr<fml::TaskRunner> ui_runner;
|
|
fml::RefPtr<fml::TaskRunner> io_runner;
|
|
fml::RefPtr<fml::TaskRunner> platform_runner =
|
|
fml::MessageLoop::GetCurrent().GetTaskRunner();
|
|
if (is_background_view) {
|
|
auto single_task_runner = thread_host_.ui_thread->GetTaskRunner();
|
|
gpu_runner = single_task_runner;
|
|
ui_runner = single_task_runner;
|
|
io_runner = single_task_runner;
|
|
} else {
|
|
gpu_runner = thread_host_.gpu_thread->GetTaskRunner();
|
|
ui_runner = thread_host_.ui_thread->GetTaskRunner();
|
|
io_runner = thread_host_.io_thread->GetTaskRunner();
|
|
}
|
|
flutter::TaskRunners task_runners(thread_label, // label
|
|
platform_runner, // platform
|
|
gpu_runner, // gpu
|
|
ui_runner, // ui
|
|
io_runner // io
|
|
);
|
|
|
|
shell_ =
|
|
Shell::Create(task_runners, // task runners
|
|
settings_, // settings
|
|
on_create_platform_view, // platform view create callback
|
|
on_create_rasterizer // rasterizer create callback
|
|
);
|
|
|
|
platform_view_ = weak_platform_view;
|
|
FML_DCHECK(platform_view_);
|
|
|
|
is_valid_ = shell_ != nullptr;
|
|
|
|
if (is_valid_) {
|
|
task_runners.GetGPUTaskRunner()->PostTask([]() {
|
|
// Android describes -8 as "most important display threads, for
|
|
// compositing the screen and retrieving input events". Conservatively
|
|
// set the GPU thread to slightly lower priority than it.
|
|
if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
|
|
// Defensive fallback. Depending on the OEM, it may not be possible
|
|
// to set priority to -5.
|
|
if (::setpriority(PRIO_PROCESS, gettid(), -2) != 0) {
|
|
FML_LOG(ERROR) << "Failed to set GPU task runner priority";
|
|
}
|
|
}
|
|
});
|
|
task_runners.GetUITaskRunner()->PostTask([]() {
|
|
if (::setpriority(PRIO_PROCESS, gettid(), -1) != 0) {
|
|
FML_LOG(ERROR) << "Failed to set UI task runner priority";
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
AndroidShellHolder::~AndroidShellHolder() {
|
|
shell_.reset();
|
|
thread_host_.Reset();
|
|
FML_CHECK(pthread_key_delete(thread_destruct_key_) == 0);
|
|
}
|
|
|
|
void AndroidShellHolder::ThreadDestructCallback(void* value) {
|
|
fml::jni::DetachFromVM();
|
|
}
|
|
|
|
bool AndroidShellHolder::IsValid() const {
|
|
return is_valid_;
|
|
}
|
|
|
|
const flutter::Settings& AndroidShellHolder::GetSettings() const {
|
|
return settings_;
|
|
}
|
|
|
|
void AndroidShellHolder::Launch(RunConfiguration config) {
|
|
if (!IsValid()) {
|
|
return;
|
|
}
|
|
|
|
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(
|
|
fml::MakeCopyable([engine = shell_->GetEngine(), //
|
|
config = std::move(config) //
|
|
]() mutable {
|
|
FML_LOG(INFO) << "Attempting to launch engine configuration...";
|
|
if (!engine || engine->Run(std::move(config)) ==
|
|
shell::Engine::RunStatus::Failure) {
|
|
FML_LOG(ERROR) << "Could not launch engine in configuration.";
|
|
} else {
|
|
FML_LOG(INFO) << "Isolate for engine configuration successfully "
|
|
"started and run.";
|
|
}
|
|
}));
|
|
}
|
|
|
|
void AndroidShellHolder::SetViewportMetrics(
|
|
const flutter::ViewportMetrics& metrics) {
|
|
if (!IsValid()) {
|
|
return;
|
|
}
|
|
|
|
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(
|
|
[engine = shell_->GetEngine(), metrics]() {
|
|
if (engine) {
|
|
engine->SetViewportMetrics(metrics);
|
|
}
|
|
});
|
|
}
|
|
|
|
void AndroidShellHolder::DispatchPointerDataPacket(
|
|
std::unique_ptr<flutter::PointerDataPacket> packet) {
|
|
if (!IsValid()) {
|
|
return;
|
|
}
|
|
|
|
TRACE_EVENT0("flutter", "AndroidShellHolder::DispatchPointerDataPacket");
|
|
TRACE_FLOW_BEGIN("flutter", "PointerEvent", next_pointer_flow_id_);
|
|
|
|
shell_->GetTaskRunners().GetUITaskRunner()->PostTask(fml::MakeCopyable(
|
|
[engine = shell_->GetEngine(), packet = std::move(packet),
|
|
flow_id = next_pointer_flow_id_] {
|
|
if (engine) {
|
|
engine->DispatchPointerDataPacket(*packet, flow_id);
|
|
}
|
|
}));
|
|
|
|
next_pointer_flow_id_++;
|
|
}
|
|
|
|
Rasterizer::Screenshot AndroidShellHolder::Screenshot(
|
|
Rasterizer::ScreenshotType type,
|
|
bool base64_encode) {
|
|
if (!IsValid()) {
|
|
return {nullptr, SkISize::MakeEmpty()};
|
|
}
|
|
return shell_->Screenshot(type, base64_encode);
|
|
}
|
|
|
|
fml::WeakPtr<PlatformViewAndroid> AndroidShellHolder::GetPlatformView() {
|
|
FML_DCHECK(platform_view_);
|
|
return platform_view_;
|
|
}
|
|
|
|
} // namespace shell
|