• 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/android_shell_holder.h"
8 
9 #include <pthread.h>
10 #include <sys/resource.h>
11 #include <sys/time.h>
12 
13 #include <sstream>
14 #include <string>
15 #include <utility>
16 
17 #include "flutter/fml/make_copyable.h"
18 #include "flutter/fml/message_loop.h"
19 #include "flutter/shell/common/rasterizer.h"
20 #include "flutter/shell/platform/android/platform_view_android.h"
21 
22 namespace flutter {
23 
AndroidShellHolder(flutter::Settings settings,fml::jni::JavaObjectWeakGlobalRef java_object,bool is_background_view)24 AndroidShellHolder::AndroidShellHolder(
25     flutter::Settings settings,
26     fml::jni::JavaObjectWeakGlobalRef java_object,
27     bool is_background_view)
28     : settings_(std::move(settings)), java_object_(java_object) {
29   static size_t shell_count = 1;
30   auto thread_label = std::to_string(shell_count++);
31 
32   FML_CHECK(pthread_key_create(&thread_destruct_key_, ThreadDestructCallback) ==
33             0);
34 
35   if (is_background_view) {
36     thread_host_ = {thread_label, ThreadHost::Type::UI};
37   } else {
38     thread_host_ = {thread_label, ThreadHost::Type::UI | ThreadHost::Type::GPU |
39                                       ThreadHost::Type::IO};
40   }
41 
42   // Detach from JNI when the UI and GPU threads exit.
43   auto jni_exit_task([key = thread_destruct_key_]() {
44     FML_CHECK(pthread_setspecific(key, reinterpret_cast<void*>(1)) == 0);
45   });
46   thread_host_.ui_thread->GetTaskRunner()->PostTask(jni_exit_task);
47   if (!is_background_view) {
48     thread_host_.gpu_thread->GetTaskRunner()->PostTask(jni_exit_task);
49   }
50 
51   fml::WeakPtr<PlatformViewAndroid> weak_platform_view;
52   Shell::CreateCallback<PlatformView> on_create_platform_view =
53       [is_background_view, java_object, &weak_platform_view](Shell& shell) {
54         std::unique_ptr<PlatformViewAndroid> platform_view_android;
55         if (is_background_view) {
56           platform_view_android = std::make_unique<PlatformViewAndroid>(
57               shell,                   // delegate
58               shell.GetTaskRunners(),  // task runners
59               java_object              // java object handle for JNI interop
60           );
61 
62         } else {
63           platform_view_android = std::make_unique<PlatformViewAndroid>(
64               shell,                   // delegate
65               shell.GetTaskRunners(),  // task runners
66               java_object,             // java object handle for JNI interop
67               shell.GetSettings()
68                   .enable_software_rendering  // use software rendering
69           );
70         }
71         weak_platform_view = platform_view_android->GetWeakPtr();
72         return platform_view_android;
73       };
74 
75   Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {
76     return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
77   };
78 
79   // The current thread will be used as the platform thread. Ensure that the
80   // message loop is initialized.
81   fml::MessageLoop::EnsureInitializedForCurrentThread();
82   fml::RefPtr<fml::TaskRunner> gpu_runner;
83   fml::RefPtr<fml::TaskRunner> ui_runner;
84   fml::RefPtr<fml::TaskRunner> io_runner;
85   fml::RefPtr<fml::TaskRunner> platform_runner =
86       fml::MessageLoop::GetCurrent().GetTaskRunner();
87   if (is_background_view) {
88     auto single_task_runner = thread_host_.ui_thread->GetTaskRunner();
89     gpu_runner = single_task_runner;
90     ui_runner = single_task_runner;
91     io_runner = single_task_runner;
92   } else {
93     gpu_runner = thread_host_.gpu_thread->GetTaskRunner();
94     ui_runner = thread_host_.ui_thread->GetTaskRunner();
95     io_runner = thread_host_.io_thread->GetTaskRunner();
96   }
97   flutter::TaskRunners task_runners(thread_label,     // label
98                                     platform_runner,  // platform
99                                     gpu_runner,       // gpu
100                                     ui_runner,        // ui
101                                     io_runner         // io
102   );
103 
104   shell_ =
105       Shell::Create(task_runners,             // task runners
106                     settings_,                // settings
107                     on_create_platform_view,  // platform view create callback
108                     on_create_rasterizer      // rasterizer create callback
109       );
110 
111   platform_view_ = weak_platform_view;
112   FML_DCHECK(platform_view_);
113 
114   is_valid_ = shell_ != nullptr;
115 
116   if (is_valid_) {
117     task_runners.GetGPUTaskRunner()->PostTask([]() {
118       // Android describes -8 as "most important display threads, for
119       // compositing the screen and retrieving input events". Conservatively
120       // set the GPU thread to slightly lower priority than it.
121       if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
122         // Defensive fallback. Depending on the OEM, it may not be possible
123         // to set priority to -5.
124         if (::setpriority(PRIO_PROCESS, gettid(), -2) != 0) {
125           FML_LOG(ERROR) << "Failed to set GPU task runner priority";
126         }
127       }
128     });
129     task_runners.GetUITaskRunner()->PostTask([]() {
130       if (::setpriority(PRIO_PROCESS, gettid(), -1) != 0) {
131         FML_LOG(ERROR) << "Failed to set UI task runner priority";
132       }
133     });
134   }
135 }
136 
~AndroidShellHolder()137 AndroidShellHolder::~AndroidShellHolder() {
138   shell_.reset();
139   thread_host_.Reset();
140   FML_CHECK(pthread_key_delete(thread_destruct_key_) == 0);
141 }
142 
ThreadDestructCallback(void * value)143 void AndroidShellHolder::ThreadDestructCallback(void* value) {
144   fml::jni::DetachFromVM();
145 }
146 
IsValid() const147 bool AndroidShellHolder::IsValid() const {
148   return is_valid_;
149 }
150 
GetSettings() const151 const flutter::Settings& AndroidShellHolder::GetSettings() const {
152   return settings_;
153 }
154 
Launch(RunConfiguration config)155 void AndroidShellHolder::Launch(RunConfiguration config) {
156   if (!IsValid()) {
157     return;
158   }
159 
160   shell_->RunEngine(std::move(config));
161 }
162 
Screenshot(Rasterizer::ScreenshotType type,bool base64_encode)163 Rasterizer::Screenshot AndroidShellHolder::Screenshot(
164     Rasterizer::ScreenshotType type,
165     bool base64_encode) {
166   if (!IsValid()) {
167     return {nullptr, SkISize::MakeEmpty()};
168   }
169   return shell_->Screenshot(type, base64_encode);
170 }
171 
GetPlatformView()172 fml::WeakPtr<PlatformViewAndroid> AndroidShellHolder::GetPlatformView() {
173   FML_DCHECK(platform_view_);
174   return platform_view_;
175 }
176 
177 }  // namespace flutter
178