Flutter Engine
flutter::AndroidShellHolder Class Reference

This is the Android owner of the core engine Shell. More...

#include <android_shell_holder.h>

Public Member Functions

 AndroidShellHolder (flutter::Settings settings, std::shared_ptr< PlatformViewAndroidJNI > jni_facade)
 
 ~AndroidShellHolder ()
 
bool IsValid () const
 
std::unique_ptr< AndroidShellHolderSpawn (std::shared_ptr< PlatformViewAndroidJNI > jni_facade, const std::string &entrypoint, const std::string &libraryUrl, const std::string &initial_route) const
 This is a factory for a derived AndroidShellHolder from an existing AndroidShellHolder. More...
 
void Launch (std::shared_ptr< AssetManager > asset_manager, const std::string &entrypoint, const std::string &libraryUrl)
 
const flutter::SettingsGetSettings () const
 
fml::WeakPtr< PlatformViewAndroidGetPlatformView ()
 
Rasterizer::Screenshot Screenshot (Rasterizer::ScreenshotType type, bool base64_encode)
 
void UpdateAssetManager (fml::RefPtr< flutter::AssetManager > asset_manager)
 
void NotifyLowMemoryWarning ()
 

Detailed Description

This is the Android owner of the core engine Shell.

This is the top orchestrator class on the C++ side for the Android embedding. It corresponds to a FlutterEngine on the Java side. This class is in C++ because the Shell is in C++ and an Android orchestrator needs to exist to compose it with other Android specific C++ components such as the PlatformViewAndroid. This composition of many-to-one C++ components would be difficult to do through JNI whereas a FlutterEngine and AndroidShellHolder has a 1:1 relationship.

Technically, the FlutterJNI class owns this AndroidShellHolder class instance, but the FlutterJNI class is meant to be mostly static and has minimal state to perform the C++ pointer <-> Java class instance translation.

Definition at line 40 of file android_shell_holder.h.

Constructor & Destructor Documentation

◆ AndroidShellHolder()

flutter::AndroidShellHolder::AndroidShellHolder ( flutter::Settings  settings,
std::shared_ptr< PlatformViewAndroidJNI jni_facade 
)

Definition at line 40 of file android_shell_holder.cc.

References buffer, flutter::Shell::Create(), fml::MessageLoop::EnsureInitializedForCurrentThread(), FML_DCHECK, FML_DLOG, FML_LOG, fml::MessageLoop::GetCurrent(), flutter::GetDefaultPlatformData(), flutter::TaskRunners::GetIOTaskRunner(), flutter::TaskRunners::GetRasterTaskRunner(), fml::MessageLoop::GetTaskRunner(), flutter::TaskRunners::GetUITaskRunner(), flutter::kStartup, flutter::AndroidImageGenerator::MakeFromData(), platform_view, and fml::TaskRunner::PostTask().

Referenced by Spawn().

43  : settings_(std::move(settings)), jni_facade_(jni_facade) {
44  static size_t thread_host_count = 1;
45  auto thread_label = std::to_string(thread_host_count++);
46 
47  thread_host_ = std::make_shared<ThreadHost>();
48  *thread_host_ = {thread_label, ThreadHost::Type::UI |
49  ThreadHost::Type::RASTER |
50  ThreadHost::Type::IO};
51 
52  fml::WeakPtr<PlatformViewAndroid> weak_platform_view;
53  Shell::CreateCallback<PlatformView> on_create_platform_view =
54  [&jni_facade, &weak_platform_view](Shell& shell) {
55  std::unique_ptr<PlatformViewAndroid> platform_view_android;
56  platform_view_android = std::make_unique<PlatformViewAndroid>(
57  shell, // delegate
58  shell.GetTaskRunners(), // task runners
59  jni_facade, // JNI interop
60  shell.GetSettings()
61  .enable_software_rendering // use software rendering
62  );
63  weak_platform_view = platform_view_android->GetWeakPtr();
64  auto display = Display(jni_facade->GetDisplayRefreshRate());
65  shell.OnDisplayUpdates(DisplayUpdateType::kStartup, {display});
66  return platform_view_android;
67  };
68 
69  Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
70  return std::make_unique<Rasterizer>(shell);
71  };
72 
73  // The current thread will be used as the platform thread. Ensure that the
74  // message loop is initialized.
76  fml::RefPtr<fml::TaskRunner> raster_runner;
79  fml::RefPtr<fml::TaskRunner> platform_runner =
81  raster_runner = thread_host_->raster_thread->GetTaskRunner();
82  ui_runner = thread_host_->ui_thread->GetTaskRunner();
83  io_runner = thread_host_->io_thread->GetTaskRunner();
84 
85  flutter::TaskRunners task_runners(thread_label, // label
86  platform_runner, // platform
87  raster_runner, // raster
88  ui_runner, // ui
89  io_runner // io
90  );
91  task_runners.GetRasterTaskRunner()->PostTask([]() {
92  // Android describes -8 as "most important display threads, for
93  // compositing the screen and retrieving input events". Conservatively
94  // set the raster thread to slightly lower priority than it.
95  if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
96  // Defensive fallback. Depending on the OEM, it may not be possible
97  // to set priority to -5.
98  if (::setpriority(PRIO_PROCESS, gettid(), -2) != 0) {
99  FML_LOG(ERROR) << "Failed to set raster task runner priority";
100  }
101  }
102  });
103  task_runners.GetUITaskRunner()->PostTask([]() {
104  if (::setpriority(PRIO_PROCESS, gettid(), -1) != 0) {
105  FML_LOG(ERROR) << "Failed to set UI task runner priority";
106  }
107  });
108  task_runners.GetIOTaskRunner()->PostTask([]() {
109  if (::setpriority(PRIO_PROCESS, gettid(), 1) != 0) {
110  FML_LOG(ERROR) << "Failed to set IO task runner priority";
111  }
112  });
113 
114  shell_ =
115  Shell::Create(GetDefaultPlatformData(), // window data
116  task_runners, // task runners
117  settings_, // settings
118  on_create_platform_view, // platform view create callback
119  on_create_rasterizer // rasterizer create callback
120  );
121 
122  if (shell_) {
123  shell_->GetDartVM()->GetConcurrentMessageLoop()->PostTaskToAllWorkers([]() {
124  if (::setpriority(PRIO_PROCESS, gettid(), 1) != 0) {
125  FML_LOG(ERROR) << "Failed to set Workers task runner priority";
126  }
127  });
128 
129  shell_->RegisterImageDecoder(
130  [runner = task_runners.GetIOTaskRunner()](sk_sp<SkData> buffer) {
132  },
133  -1);
134  FML_DLOG(INFO) << "Registered Android SDK image decoder (API level 28+)";
135  }
136 
137  platform_view_ = weak_platform_view;
138  FML_DCHECK(platform_view_);
139  is_valid_ = shell_ != nullptr;
140 }
#define FML_DCHECK(condition)
Definition: logging.h:86
static std::shared_ptr< ImageGenerator > MakeFromData(sk_sp< SkData > data, fml::RefPtr< fml::TaskRunner > task_runner)
static FML_EMBEDDER_ONLY MessageLoop & GetCurrent()
Definition: message_loop.cc:19
static void EnsureInitializedForCurrentThread()
Definition: message_loop.cc:27
#define FML_LOG(severity)
Definition: logging.h:65
fml::RefPtr< fml::TaskRunner > GetTaskRunner() const
Definition: message_loop.cc:56
static std::unique_ptr< Shell > Create(const PlatformData &platform_data, 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:126
static PlatformData GetDefaultPlatformData()
static const uint8_t buffer[]
#define FML_DLOG(severity)
Definition: logging.h:85

◆ ~AndroidShellHolder()

flutter::AndroidShellHolder::~AndroidShellHolder ( )

Definition at line 161 of file android_shell_holder.cc.

161  {
162  shell_.reset();
163  thread_host_.reset();
164 }

Member Function Documentation

◆ GetPlatformView()

fml::WeakPtr< PlatformViewAndroid > flutter::AndroidShellHolder::GetPlatformView ( )

Definition at line 263 of file android_shell_holder.cc.

References FML_DCHECK.

263  {
264  FML_DCHECK(platform_view_);
265  return platform_view_;
266 }
#define FML_DCHECK(condition)
Definition: logging.h:86

◆ GetSettings()

const flutter::Settings & flutter::AndroidShellHolder::GetSettings ( ) const

Definition at line 170 of file android_shell_holder.cc.

Referenced by NotifyLowMemoryWarning(), and Spawn().

170  {
171  return settings_;
172 }

◆ IsValid()

bool flutter::AndroidShellHolder::IsValid ( ) const

Definition at line 166 of file android_shell_holder.cc.

Referenced by Launch(), and Screenshot().

166  {
167  return is_valid_;
168 }

◆ Launch()

void flutter::AndroidShellHolder::Launch ( std::shared_ptr< AssetManager asset_manager,
const std::string &  entrypoint,
const std::string &  libraryUrl 
)

Definition at line 239 of file android_shell_holder.cc.

References IsValid().

241  {
242  if (!IsValid()) {
243  return;
244  }
245 
246  asset_manager_ = asset_manager;
247  auto config = BuildRunConfiguration(asset_manager, entrypoint, libraryUrl);
248  if (!config) {
249  return;
250  }
251  shell_->RunEngine(std::move(config.value()));
252 }

◆ NotifyLowMemoryWarning()

◆ Screenshot()

Rasterizer::Screenshot flutter::AndroidShellHolder::Screenshot ( Rasterizer::ScreenshotType  type,
bool  base64_encode 
)

Definition at line 254 of file android_shell_holder.cc.

References IsValid().

256  {
257  if (!IsValid()) {
258  return {nullptr, SkISize::MakeEmpty()};
259  }
260  return shell_->Screenshot(type, base64_encode);
261 }
KeyCallType type

◆ Spawn()

std::unique_ptr< AndroidShellHolder > flutter::AndroidShellHolder::Spawn ( std::shared_ptr< PlatformViewAndroidJNI jni_facade,
const std::string &  entrypoint,
const std::string &  libraryUrl,
const std::string &  initial_route 
) const

This is a factory for a derived AndroidShellHolder from an existing AndroidShellHolder.

Creates one Shell from another Shell where the created Shell takes the opportunity to share any internal components it can. This results is a Shell that has a smaller startup time cost and a smaller memory footprint than an Shell created with a Create function.

The new Shell is returned in a new AndroidShellHolder instance.

The new Shell's flutter::Settings cannot be changed from that of the initial Shell. The RunConfiguration subcomponent can be changed however in the spawned Shell to run a different entrypoint than the existing shell.

Since the AndroidShellHolder both binds downwards to a Shell and also upwards to JNI callbacks that the PlatformViewAndroid makes, the JNI instance holding this AndroidShellHolder should be created first to supply the jni_facade callback.

Parameters
[in]jni_facadethis argument should be the JNI callback facade of a new JNI instance meant to hold this AndroidShellHolder.
Returns
A new AndroidShellHolder containing a new Shell. Returns nullptr when a new Shell can't be created.

Definition at line 174 of file android_shell_holder.cc.

References AndroidShellHolder(), FML_DCHECK, flutter::PlatformViewAndroid::GetAndroidContext(), GetSettings(), and flutter::kStartup.

178  {
179  FML_DCHECK(shell_ && shell_->IsSetup())
180  << "A new Shell can only be spawned "
181  "if the current Shell is properly constructed";
182 
183  // Pull out the new PlatformViewAndroid from the new Shell to feed to it to
184  // the new AndroidShellHolder.
185  //
186  // It's a weak pointer because it's owned by the Shell (which we're also)
187  // making below. And the AndroidShellHolder then owns the Shell.
188  fml::WeakPtr<PlatformViewAndroid> weak_platform_view;
189 
190  // Take out the old AndroidContext to reuse inside the PlatformViewAndroid
191  // of the new Shell.
192  PlatformViewAndroid* android_platform_view = platform_view_.get();
193  // There's some indirection with platform_view_ being a weak pointer but
194  // we just checked that the shell_ exists above and a valid shell is the
195  // owner of the platform view so this weak pointer always exists.
196  FML_DCHECK(android_platform_view);
197  std::shared_ptr<flutter::AndroidContext> android_context =
198  android_platform_view->GetAndroidContext();
199  FML_DCHECK(android_context);
200 
201  // This is a synchronous call, so the captures don't have race checks.
202  Shell::CreateCallback<PlatformView> on_create_platform_view =
203  [&jni_facade, android_context, &weak_platform_view](Shell& shell) {
204  std::unique_ptr<PlatformViewAndroid> platform_view_android;
205  platform_view_android = std::make_unique<PlatformViewAndroid>(
206  shell, // delegate
207  shell.GetTaskRunners(), // task runners
208  jni_facade, // JNI interop
209  android_context // Android context
210  );
211  weak_platform_view = platform_view_android->GetWeakPtr();
212  auto display = Display(jni_facade->GetDisplayRefreshRate());
213  shell.OnDisplayUpdates(DisplayUpdateType::kStartup, {display});
214  return platform_view_android;
215  };
216 
217  Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
218  return std::make_unique<Rasterizer>(shell);
219  };
220 
221  // TODO(xster): could be worth tracing this to investigate whether
222  // the IsolateConfiguration could be cached somewhere.
223  auto config = BuildRunConfiguration(asset_manager_, entrypoint, libraryUrl);
224  if (!config) {
225  // If the RunConfiguration was null, the kernel blob wasn't readable.
226  // Fail the whole thing.
227  return nullptr;
228  }
229 
230  std::unique_ptr<flutter::Shell> shell =
231  shell_->Spawn(std::move(config.value()), initial_route,
232  on_create_platform_view, on_create_rasterizer);
233 
234  return std::unique_ptr<AndroidShellHolder>(
235  new AndroidShellHolder(GetSettings(), jni_facade, thread_host_,
236  std::move(shell), weak_platform_view));
237 }
#define FML_DCHECK(condition)
Definition: logging.h:86
AndroidShellHolder(flutter::Settings settings, std::shared_ptr< PlatformViewAndroidJNI > jni_facade)
const flutter::Settings & GetSettings() const

◆ UpdateAssetManager()

void flutter::AndroidShellHolder::UpdateAssetManager ( fml::RefPtr< flutter::AssetManager asset_manager)

The documentation for this class was generated from the following files: