Flutter Engine
 
Loading...
Searching...
No Matches
android_shell_holder.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 <pthread.h>
8#include <sys/resource.h>
9#include <sys/time.h>
10#include <memory>
11#include <optional>
12
13#include <string>
14#include <utility>
15
16#include "common/settings.h"
18#include "flutter/fml/logging.h"
30
31namespace flutter {
32
33/// Inheriting ThreadConfigurer and use Android platform thread API to configure
34/// the thread priorities
36 const fml::Thread::ThreadConfig& config) {
37 // set thread name
39 // set thread priority
40 switch (config.priority) {
43 if (::setpriority(PRIO_PROCESS, 0, 10) != 0) {
44 FML_LOG(ERROR) << "Failed to set IO task runner priority";
45 }
46 break;
47 }
50 if (::setpriority(PRIO_PROCESS, 0, -1) != 0) {
51 FML_LOG(ERROR) << "Failed to set UI task runner priority";
52 }
53 break;
54 }
57 // Android describes -8 as "most important display threads, for
58 // compositing the screen and retrieving input events". Conservatively
59 // set the raster thread to slightly lower priority than it.
60 if (::setpriority(PRIO_PROCESS, 0, -5) != 0) {
61 // Defensive fallback. Depending on the OEM, it may not be possible
62 // to set priority to -5.
63 if (::setpriority(PRIO_PROCESS, 0, -2) != 0) {
64 FML_LOG(ERROR) << "Failed to set raster task runner priority";
65 }
66 }
67 break;
68 }
69 default:
71 if (::setpriority(PRIO_PROCESS, 0, 0) != 0) {
72 FML_LOG(ERROR) << "Failed to set priority";
73 }
74 }
75}
77 PlatformData platform_data;
78 platform_data.lifecycle_state = "AppLifecycleState.detached";
79 return platform_data;
80}
81
83 const flutter::Settings& settings,
84 std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
85 AndroidRenderingAPI android_rendering_api)
86 : settings_(settings),
87 jni_facade_(jni_facade),
88 android_rendering_api_(android_rendering_api) {
89 static size_t thread_host_count = 1;
90 auto thread_label = std::to_string(thread_host_count++);
91
93 if (settings.merged_platform_ui_thread !=
96 }
97
99 thread_label, mask, AndroidPlatformThreadConfigSetter);
102 flutter::ThreadHost::Type::kUi, thread_label),
110 flutter::ThreadHost::Type::kIo, thread_label),
112
113 thread_host_ = std::make_shared<ThreadHost>(host_config);
114
115 fml::WeakPtr<PlatformViewAndroid> weak_platform_view;
116 AndroidRenderingAPI rendering_api = android_rendering_api_;
117 Shell::CreateCallback<PlatformView> on_create_platform_view =
118 [&jni_facade, &weak_platform_view, rendering_api](Shell& shell) {
119 std::unique_ptr<PlatformViewAndroid> platform_view_android;
120 platform_view_android = std::make_unique<PlatformViewAndroid>(
121 shell, // delegate
122 shell.GetTaskRunners(), // task runners
123 jni_facade, // JNI interop
124 rendering_api // rendering API
125 );
126 weak_platform_view = platform_view_android->GetWeakPtr();
127 return platform_view_android;
128 };
129
130 Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
131 return std::make_unique<Rasterizer>(shell);
132 };
133
134 // The current thread will be used as the platform thread. Ensure that the
135 // message loop is initialized.
137 fml::RefPtr<fml::TaskRunner> raster_runner;
140 fml::RefPtr<fml::TaskRunner> platform_runner =
142 raster_runner = thread_host_->raster_thread->GetTaskRunner();
143 if (settings.merged_platform_ui_thread ==
145 ui_runner = platform_runner;
146 } else {
147 ui_runner = thread_host_->ui_thread->GetTaskRunner();
148 }
149 io_runner = thread_host_->io_thread->GetTaskRunner();
150
151 flutter::TaskRunners task_runners(thread_label, // label
152 platform_runner, // platform
153 raster_runner, // raster
154 ui_runner, // ui
155 io_runner // io
156 );
157
158 shell_ =
159 Shell::Create(GetDefaultPlatformData(), // window data
160 task_runners, // task runners
161 settings_, // settings
162 on_create_platform_view, // platform view create callback
163 on_create_rasterizer // rasterizer create callback
164 );
165
166 if (shell_) {
167 shell_->GetDartVM()->GetConcurrentMessageLoop()->PostTaskToAllWorkers([]() {
168 if (::setpriority(PRIO_PROCESS, gettid(), 1) != 0) {
169 FML_LOG(ERROR) << "Failed to set Workers task runner priority";
170 }
171 });
172
173 shell_->RegisterImageDecoder(
174 [runner = task_runners.GetIOTaskRunner()](sk_sp<SkData> buffer) {
175 return AndroidImageGenerator::MakeFromData(std::move(buffer), runner);
176 },
177 -1);
178 FML_DLOG(INFO) << "Registered Android SDK image decoder (API level 28+)";
179 }
180
181 platform_view_ = weak_platform_view;
182 FML_DCHECK(platform_view_);
183 is_valid_ = shell_ != nullptr;
184}
185
187 const Settings& settings,
188 const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade,
189 const std::shared_ptr<ThreadHost>& thread_host,
190 std::unique_ptr<Shell> shell,
191 std::unique_ptr<APKAssetProvider> apk_asset_provider,
193 AndroidRenderingAPI rendering_api)
194 : settings_(settings),
195 jni_facade_(jni_facade),
196 platform_view_(platform_view),
197 thread_host_(thread_host),
198 shell_(std::move(shell)),
199 apk_asset_provider_(std::move(apk_asset_provider)),
200 android_rendering_api_(rendering_api) {
201 FML_DCHECK(jni_facade);
202 FML_DCHECK(shell_);
203 FML_DCHECK(shell_->IsSetup());
204 FML_DCHECK(platform_view_);
205 FML_DCHECK(thread_host_);
206 is_valid_ = shell_ != nullptr;
207}
208
210 shell_.reset();
211 thread_host_.reset();
212}
213
215 return is_valid_;
216}
217
219 return settings_;
220}
221
222std::unique_ptr<AndroidShellHolder> AndroidShellHolder::Spawn(
223 std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
224 const std::string& entrypoint,
225 const std::string& libraryUrl,
226 const std::string& initial_route,
227 const std::vector<std::string>& entrypoint_args,
228 int64_t engine_id) const {
229 FML_DCHECK(shell_ && shell_->IsSetup())
230 << "A new Shell can only be spawned "
231 "if the current Shell is properly constructed";
232
233 // Pull out the new PlatformViewAndroid from the new Shell to feed to it to
234 // the new AndroidShellHolder.
235 //
236 // It's a weak pointer because it's owned by the Shell (which we're also)
237 // making below. And the AndroidShellHolder then owns the Shell.
238 fml::WeakPtr<PlatformViewAndroid> weak_platform_view;
239
240 // Take out the old AndroidContext to reuse inside the PlatformViewAndroid
241 // of the new Shell.
242 PlatformViewAndroid* android_platform_view = platform_view_.get();
243 // There's some indirection with platform_view_ being a weak pointer but
244 // we just checked that the shell_ exists above and a valid shell is the
245 // owner of the platform view so this weak pointer always exists.
246 FML_DCHECK(android_platform_view);
247 std::shared_ptr<flutter::AndroidContext> android_context =
248 android_platform_view->GetAndroidContext();
249 FML_DCHECK(android_context);
250
251 // This is a synchronous call, so the captures don't have race checks.
252 Shell::CreateCallback<PlatformView> on_create_platform_view =
253 [&jni_facade, android_context, &weak_platform_view](Shell& shell) {
254 std::unique_ptr<PlatformViewAndroid> platform_view_android;
255 platform_view_android = std::make_unique<PlatformViewAndroid>(
256 shell, // delegate
257 shell.GetTaskRunners(), // task runners
258 jni_facade, // JNI interop
259 android_context // Android context
260 );
261 weak_platform_view = platform_view_android->GetWeakPtr();
262 return platform_view_android;
263 };
264
265 Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
266 return std::make_unique<Rasterizer>(shell);
267 };
268
269 auto config = BuildRunConfiguration(entrypoint, libraryUrl, entrypoint_args);
270 if (!config) {
271 // If the RunConfiguration was null, the kernel blob wasn't readable.
272 // Fail the whole thing.
273 return nullptr;
274 }
275 config->SetEngineId(engine_id);
276
277 std::unique_ptr<flutter::Shell> shell =
278 shell_->Spawn(std::move(config.value()), initial_route,
279 on_create_platform_view, on_create_rasterizer);
280
281 return std::unique_ptr<AndroidShellHolder>(new AndroidShellHolder(
282 GetSettings(), jni_facade, thread_host_, std::move(shell),
283 apk_asset_provider_->Clone(), weak_platform_view,
284 android_context->RenderingApi()));
285}
286
288 std::unique_ptr<APKAssetProvider> apk_asset_provider,
289 const std::string& entrypoint,
290 const std::string& libraryUrl,
291 const std::vector<std::string>& entrypoint_args,
292 int64_t engine_id) {
293 if (!IsValid()) {
294 return;
295 }
296
297 apk_asset_provider_ = std::move(apk_asset_provider);
298 auto config = BuildRunConfiguration(entrypoint, libraryUrl, entrypoint_args);
299 if (!config) {
300 return;
301 }
302 config->SetEngineId(engine_id);
304 shell_->RunEngine(std::move(config.value()));
305}
306
309 bool base64_encode) {
310 if (!IsValid()) {
311 return {nullptr, DlISize(), "", Rasterizer::ScreenshotFormat::kUnknown};
312 }
313 return shell_->Screenshot(type, base64_encode);
314}
315
317 FML_DCHECK(platform_view_);
318 return platform_view_;
319}
320
322 FML_DCHECK(shell_);
323 shell_->NotifyLowMemoryWarning();
324}
325
326std::optional<RunConfiguration> AndroidShellHolder::BuildRunConfiguration(
327 const std::string& entrypoint,
328 const std::string& libraryUrl,
329 const std::vector<std::string>& entrypoint_args) const {
330 std::unique_ptr<IsolateConfiguration> isolate_configuration;
332 isolate_configuration = IsolateConfiguration::CreateForAppSnapshot();
333 } else {
334 std::unique_ptr<fml::Mapping> kernel_blob =
336 GetSettings().application_kernel_asset);
337 if (!kernel_blob) {
338 FML_DLOG(ERROR) << "Unable to load the kernel blob asset.";
339 return std::nullopt;
340 }
341 isolate_configuration =
342 IsolateConfiguration::CreateForKernel(std::move(kernel_blob));
343 }
344
345 RunConfiguration config(std::move(isolate_configuration));
346 config.AddAssetResolver(apk_asset_provider_->Clone());
347
348 {
349 if (!entrypoint.empty() && !libraryUrl.empty()) {
350 config.SetEntrypointAndLibrary(entrypoint, libraryUrl);
351 } else if (!entrypoint.empty()) {
352 config.SetEntrypoint(entrypoint);
353 }
354 if (!entrypoint_args.empty()) {
355 config.SetEntrypointArgs(entrypoint_args);
356 }
357 }
358 return config;
359}
360
362 std::vector<std::unique_ptr<Display>> displays;
363 displays.push_back(std::make_unique<AndroidDisplay>(jni_facade_));
364 shell_->OnDisplayUpdates(std::move(displays));
365}
366
368 return GetPlatformView()->IsSurfaceControlEnabled();
369}
370
371} // namespace flutter
std::unique_ptr< flutter::PlatformViewIOS > platform_view
GLenum type
static std::shared_ptr< ImageGenerator > MakeFromData(sk_sp< SkData > data, const fml::RefPtr< fml::TaskRunner > &task_runner)
This is the Android owner of the core engine Shell.
const flutter::Settings & GetSettings() const
AndroidShellHolder(const flutter::Settings &settings, std::shared_ptr< PlatformViewAndroidJNI > jni_facade, AndroidRenderingAPI android_rendering_api)
std::unique_ptr< AndroidShellHolder > Spawn(std::shared_ptr< PlatformViewAndroidJNI > jni_facade, const std::string &entrypoint, const std::string &libraryUrl, const std::string &initial_route, const std::vector< std::string > &entrypoint_args, int64_t engine_id) const
This is a factory for a derived AndroidShellHolder from an existing AndroidShellHolder.
fml::WeakPtr< PlatformViewAndroid > GetPlatformView()
Rasterizer::Screenshot Screenshot(Rasterizer::ScreenshotType type, bool base64_encode)
void Launch(std::unique_ptr< APKAssetProvider > apk_asset_provider, const std::string &entrypoint, const std::string &libraryUrl, const std::vector< std::string > &entrypoint_args, int64_t engine_id)
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 std::unique_ptr< IsolateConfiguration > CreateForAppSnapshot()
Creates an AOT isolate configuration using snapshot symbols present in the currently loaded process....
static std::unique_ptr< IsolateConfiguration > CreateForKernel(std::unique_ptr< const fml::Mapping > kernel)
Creates a JIT isolate configuration using the specified snapshot. This is a convenience method for th...
const std::shared_ptr< AndroidContext > & GetAndroidContext()
ScreenshotType
The type of the screenshot to obtain of the previously rendered layer tree.
Definition rasterizer.h:348
static std::unique_ptr< Shell > Create(const PlatformData &platform_data, const TaskRunners &task_runners, Settings settings, const CreateCallback< PlatformView > &on_create_platform_view, const CreateCallback< Rasterizer > &on_create_rasterizer, bool is_gpu_disabled=false)
Creates a shell instance using the provided settings. The callbacks to create the various shell subco...
Definition shell.cc:221
std::function< std::unique_ptr< T >(Shell &)> CreateCallback
Definition shell.h:121
fml::RefPtr< fml::TaskRunner > GetIOTaskRunner() const
static std::unique_ptr< FileMapping > CreateReadOnly(const std::string &path)
Definition mapping.cc:20
static void EnsureInitializedForCurrentThread()
fml::RefPtr< fml::TaskRunner > GetTaskRunner() const
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
@ kNormal
Default priority level.
@ kRaster
Suitable for thread which raster data.
@ kBackground
Suitable for threads that shouldn't disrupt high priority work.
@ kDisplay
Suitable for threads which generate data for the display.
static void SetCurrentThreadName(const ThreadConfig &config)
Definition thread.cc:135
Settings settings_
ThreadHost thread_host_
#define FML_DLOG(severity)
Definition logging.h:121
#define FML_LOG(severity)
Definition logging.h:101
#define FML_DCHECK(condition)
Definition logging.h:122
impeller::ISize32 DlISize
static PlatformData GetDefaultPlatformData()
static void AndroidPlatformThreadConfigSetter(const fml::Thread::ThreadConfig &config)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
Definition switch_defs.h:98
@ kNotEfficiency
Request affinity for all non-efficiency cores.
@ kEfficiency
Request CPU affinity for the efficiency cores.
@ kNotPerformance
Request affinity for all non-performance cores.
bool RequestAffinity(CpuAffinity affinity)
Request the given affinity for the current thread.
Definition ref_ptr.h:261
std::vector< FlutterEngineDisplay > * displays
std::string lifecycle_state
A POD type used to return the screenshot data along with the size of the frame.
Definition rasterizer.h:399
MergedPlatformUIThread merged_platform_ui_thread
Definition settings.h:379
std::optional< ThreadConfig > io_config
Definition thread_host.h:78
std::optional< ThreadConfig > ui_config
Definition thread_host.h:76
std::optional< ThreadConfig > raster_config
Definition thread_host.h:77
static std::string MakeThreadName(Type type, const std::string &prefix)
Use the prefix and thread type to generator a thread name.
The ThreadConfig is the thread info include thread name, thread priority.
Definition thread.h:35
ThreadPriority priority
Definition thread.h:45