Skip to content

Commit 8c11026

Browse files
author
Jonah Williams
authored
[Android] HC++ external view embedder and JNI plumbing. (#162493)
Part of HC++ work. still not wired up end to end, but only requires a few more swapchain changes and a runtime flag...
1 parent b68321a commit 8c11026

18 files changed

+870
-36
lines changed

engine/src/flutter/ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41611,6 +41611,8 @@ ORIGIN: ../../../flutter/shell/platform/android/context/android_context.cc + ../
4161141611
ORIGIN: ../../../flutter/shell/platform/android/context/android_context.h + ../../../flutter/LICENSE
4161241612
ORIGIN: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder.cc + ../../../flutter/LICENSE
4161341613
ORIGIN: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder.h + ../../../flutter/LICENSE
41614+
ORIGIN: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.cc + ../../../flutter/LICENSE
41615+
ORIGIN: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.h + ../../../flutter/LICENSE
4161441616
ORIGIN: ../../../flutter/shell/platform/android/external_view_embedder/surface_pool.cc + ../../../flutter/LICENSE
4161541617
ORIGIN: ../../../flutter/shell/platform/android/external_view_embedder/surface_pool.h + ../../../flutter/LICENSE
4161641618
ORIGIN: ../../../flutter/shell/platform/android/flutter_main.cc + ../../../flutter/LICENSE
@@ -44563,6 +44565,8 @@ FILE: ../../../flutter/shell/platform/android/context/android_context.cc
4456344565
FILE: ../../../flutter/shell/platform/android/context/android_context.h
4456444566
FILE: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder.cc
4456544567
FILE: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder.h
44568+
FILE: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.cc
44569+
FILE: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.h
4456644570
FILE: ../../../flutter/shell/platform/android/external_view_embedder/surface_pool.cc
4456744571
FILE: ../../../flutter/shell/platform/android/external_view_embedder/surface_pool.h
4456844572
FILE: ../../../flutter/shell/platform/android/flutter_main.cc

engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,12 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceVulkanImpeller::AcquireFrame(
115115
}
116116

117117
SkIRect sk_cull_rect = SkIRect::MakeWH(cull_rect.width, cull_rect.height);
118-
return impeller::RenderToTarget(aiks_context->GetContentContext(), //
119-
render_target, //
120-
display_list, //
121-
sk_cull_rect, //
122-
/*reset_host_buffer=*/true //
118+
return impeller::RenderToTarget(
119+
aiks_context->GetContentContext(), //
120+
render_target, //
121+
display_list, //
122+
sk_cull_rect, //
123+
/*reset_host_buffer=*/surface_frame.submit_info().frame_boundary //
123124
);
124125
};
125126

engine/src/flutter/shell/platform/android/android_shell_holder_unittests.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,25 @@ class MockPlatformViewAndroidJNI : public PlatformViewAndroidJNI {
9191
(),
9292
(override));
9393
MOCK_METHOD(void, FlutterViewDestroyOverlaySurfaces, (), (override));
94+
MOCK_METHOD(ASurfaceTransaction*, createTransaction, (), (override));
95+
MOCK_METHOD(void, swapTransaction, (), (override));
96+
MOCK_METHOD(void, applyTransaction, (), (override));
97+
MOCK_METHOD(void, destroyOverlaySurface2, (), (override));
98+
MOCK_METHOD(std::unique_ptr<PlatformViewAndroidJNI::OverlayMetadata>,
99+
createOverlaySurface2,
100+
(),
101+
(override));
102+
MOCK_METHOD(void,
103+
onDisplayPlatformView2,
104+
(int32_t view_id,
105+
int32_t x,
106+
int32_t y,
107+
int32_t width,
108+
int32_t height,
109+
int32_t viewWidth,
110+
int32_t viewHeight,
111+
MutatorsStack mutators_stack),
112+
(override));
94113
MOCK_METHOD(std::unique_ptr<std::vector<std::string>>,
95114
FlutterViewComputePlatformResolvedLocale,
96115
(std::vector<std::string> supported_locales_data),

engine/src/flutter/shell/platform/android/external_view_embedder/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ source_set("external_view_embedder") {
99
sources = [
1010
"external_view_embedder.cc",
1111
"external_view_embedder.h",
12+
"external_view_embedder_2.cc",
13+
"external_view_embedder_2.h",
1214
"surface_pool.cc",
1315
"surface_pool.h",
1416
]

engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ AndroidExternalViewEmbedder::AndroidExternalViewEmbedder(
1919
android_context_(android_context),
2020
jni_facade_(std::move(jni_facade)),
2121
surface_factory_(std::move(surface_factory)),
22-
surface_pool_(std::make_unique<SurfacePool>()),
22+
surface_pool_(
23+
std::make_unique<SurfacePool>(/*use_new_surface_methods=*/false)),
2324
task_runners_(task_runners) {}
2425

2526
// |ExternalViewEmbedder|

engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,10 @@ class AndroidExternalViewEmbedder final : public ExternalViewEmbedder {
7474
const fml::RefPtr<fml::RasterThreadMerger>&
7575
raster_thread_merger) override;
7676

77+
// |ExternalViewEmbedder|
7778
bool SupportsDynamicThreadMerging() override;
7879

80+
// |ExternalViewEmbedder|
7981
void Teardown() override;
8082

8183
// Gets the rect based on the device pixel ratio of a platform view displayed
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
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+
#include "flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.h"
6+
#include "flow/view_slicer.h"
7+
#include "flutter/common/constants.h"
8+
#include "flutter/fml/synchronization/waitable_event.h"
9+
#include "flutter/fml/trace_event.h"
10+
#include "fml/make_copyable.h"
11+
12+
namespace flutter {
13+
14+
AndroidExternalViewEmbedder2::AndroidExternalViewEmbedder2(
15+
const AndroidContext& android_context,
16+
std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
17+
std::shared_ptr<AndroidSurfaceFactory> surface_factory,
18+
const TaskRunners& task_runners)
19+
: ExternalViewEmbedder(),
20+
android_context_(android_context),
21+
jni_facade_(std::move(jni_facade)),
22+
surface_factory_(std::move(surface_factory)),
23+
surface_pool_(
24+
std::make_unique<SurfacePool>(/*use_new_surface_methods=*/true)),
25+
task_runners_(task_runners) {}
26+
27+
// |ExternalViewEmbedder|
28+
void AndroidExternalViewEmbedder2::PrerollCompositeEmbeddedView(
29+
int64_t view_id,
30+
std::unique_ptr<EmbeddedViewParams> params) {
31+
TRACE_EVENT0("flutter",
32+
"AndroidExternalViewEmbedder2::PrerollCompositeEmbeddedView");
33+
34+
SkRect view_bounds = SkRect::Make(frame_size_);
35+
std::unique_ptr<EmbedderViewSlice> view;
36+
view = std::make_unique<DisplayListEmbedderViewSlice>(view_bounds);
37+
slices_.insert_or_assign(view_id, std::move(view));
38+
39+
composition_order_.push_back(view_id);
40+
// Update params only if they changed.
41+
if (view_params_.count(view_id) == 1 &&
42+
view_params_.at(view_id) == *params.get()) {
43+
return;
44+
}
45+
view_params_.insert_or_assign(view_id, EmbeddedViewParams(*params.get()));
46+
}
47+
48+
// |ExternalViewEmbedder|
49+
DlCanvas* AndroidExternalViewEmbedder2::CompositeEmbeddedView(int64_t view_id) {
50+
if (slices_.count(view_id) == 1) {
51+
return slices_.at(view_id)->canvas();
52+
}
53+
return nullptr;
54+
}
55+
56+
SkRect AndroidExternalViewEmbedder2::GetViewRect(
57+
int64_t view_id,
58+
const std::unordered_map<int64_t, EmbeddedViewParams>& view_params) {
59+
const EmbeddedViewParams& params = view_params.at(view_id);
60+
// https://github.com/flutter/flutter/issues/59821
61+
return SkRect::MakeXYWH(params.finalBoundingRect().x(), //
62+
params.finalBoundingRect().y(), //
63+
params.finalBoundingRect().width(), //
64+
params.finalBoundingRect().height() //
65+
);
66+
}
67+
68+
// |ExternalViewEmbedder|
69+
void AndroidExternalViewEmbedder2::SubmitFlutterView(
70+
int64_t flutter_view_id,
71+
GrDirectContext* context,
72+
const std::shared_ptr<impeller::AiksContext>& aiks_context,
73+
std::unique_ptr<SurfaceFrame> frame) {
74+
TRACE_EVENT0("flutter", "AndroidExternalViewEmbedder2::SubmitFlutterView");
75+
76+
if (!FrameHasPlatformLayers()) {
77+
frame->Submit();
78+
jni_facade_->applyTransaction();
79+
return;
80+
}
81+
82+
std::unordered_map<int64_t, SkRect> view_rects;
83+
for (auto platform_id : composition_order_) {
84+
view_rects[platform_id] = GetViewRect(platform_id, view_params_);
85+
}
86+
87+
std::unordered_map<int64_t, SkRect> overlay_layers =
88+
SliceViews(frame->Canvas(), //
89+
composition_order_, //
90+
slices_, //
91+
view_rects //
92+
);
93+
94+
// Create Overlay frame.
95+
surface_pool_->TrimLayers();
96+
std::unique_ptr<SurfaceFrame> overlay_frame;
97+
if (surface_pool_->HasLayers()) {
98+
for (int64_t view_id : composition_order_) {
99+
std::unordered_map<int64_t, SkRect>::const_iterator overlay =
100+
overlay_layers.find(view_id);
101+
102+
if (overlay == overlay_layers.end()) {
103+
continue;
104+
}
105+
if (overlay_frame == nullptr) {
106+
std::shared_ptr<OverlayLayer> layer = surface_pool_->GetLayer(
107+
context, android_context_, jni_facade_, surface_factory_);
108+
overlay_frame = layer->surface->AcquireFrame(frame_size_);
109+
}
110+
111+
DlCanvas* overlay_canvas = overlay_frame->Canvas();
112+
int restore_count = overlay_canvas->GetSaveCount();
113+
overlay_canvas->Save();
114+
overlay_canvas->ClipRect(overlay->second);
115+
overlay_canvas->Clear(DlColor::kTransparent());
116+
slices_[view_id]->render_into(overlay_canvas);
117+
overlay_canvas->RestoreToCount(restore_count);
118+
}
119+
}
120+
if (overlay_frame != nullptr) {
121+
overlay_frame->set_submit_info({.frame_boundary = false});
122+
overlay_frame->Submit();
123+
}
124+
frame->Submit();
125+
126+
task_runners_.GetPlatformTaskRunner()->PostTask(fml::MakeCopyable(
127+
[&, composition_order = composition_order_, view_params = view_params_,
128+
jni_facade = jni_facade_, device_pixel_ratio = device_pixel_ratio_,
129+
slices = std::move(slices_)]() -> void {
130+
jni_facade->swapTransaction();
131+
for (int64_t view_id : composition_order) {
132+
SkRect view_rect = GetViewRect(view_id, view_params);
133+
const EmbeddedViewParams& params = view_params.at(view_id);
134+
// Display the platform view. If it's already displayed, then it's
135+
// just positioned and sized.
136+
jni_facade->FlutterViewOnDisplayPlatformView(
137+
view_id, //
138+
view_rect.x(), //
139+
view_rect.y(), //
140+
view_rect.width(), //
141+
view_rect.height(), //
142+
params.sizePoints().width() * device_pixel_ratio,
143+
params.sizePoints().height() * device_pixel_ratio,
144+
params.mutatorsStack() //
145+
);
146+
}
147+
if (!surface_pool_->HasLayers()) {
148+
surface_pool_->GetLayer(context, android_context_, jni_facade_,
149+
surface_factory_);
150+
}
151+
jni_facade->FlutterViewEndFrame();
152+
}));
153+
}
154+
155+
// |ExternalViewEmbedder|
156+
std::unique_ptr<SurfaceFrame>
157+
AndroidExternalViewEmbedder2::CreateSurfaceIfNeeded(GrDirectContext* context,
158+
int64_t view_id,
159+
EmbedderViewSlice* slice,
160+
const SkRect& rect) {
161+
std::shared_ptr<OverlayLayer> layer = surface_pool_->GetLayer(
162+
context, android_context_, jni_facade_, surface_factory_);
163+
164+
std::unique_ptr<SurfaceFrame> frame =
165+
layer->surface->AcquireFrame(frame_size_);
166+
167+
DlCanvas* overlay_canvas = frame->Canvas();
168+
overlay_canvas->Clear(DlColor::kTransparent());
169+
// Offset the picture since its absolute position on the scene is determined
170+
// by the position of the overlay view.
171+
slice->render_into(overlay_canvas);
172+
return frame;
173+
}
174+
175+
// |ExternalViewEmbedder|
176+
PostPrerollResult AndroidExternalViewEmbedder2::PostPrerollAction(
177+
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {
178+
return PostPrerollResult::kSuccess;
179+
}
180+
181+
bool AndroidExternalViewEmbedder2::FrameHasPlatformLayers() {
182+
return !composition_order_.empty();
183+
}
184+
185+
// |ExternalViewEmbedder|
186+
DlCanvas* AndroidExternalViewEmbedder2::GetRootCanvas() {
187+
// On Android, the root surface is created from the on-screen render target.
188+
return nullptr;
189+
}
190+
191+
void AndroidExternalViewEmbedder2::Reset() {
192+
previous_frame_view_count_ = composition_order_.size();
193+
194+
composition_order_.clear();
195+
slices_.clear();
196+
}
197+
198+
// |ExternalViewEmbedder|
199+
void AndroidExternalViewEmbedder2::BeginFrame(
200+
GrDirectContext* context,
201+
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {}
202+
203+
// |ExternalViewEmbedder|
204+
void AndroidExternalViewEmbedder2::PrepareFlutterView(
205+
SkISize frame_size,
206+
double device_pixel_ratio) {
207+
Reset();
208+
209+
// The surface size changed. Therefore, destroy existing surfaces as
210+
// the existing surfaces in the pool can't be recycled.
211+
if (frame_size_ != frame_size) {
212+
DestroySurfaces();
213+
}
214+
surface_pool_->SetFrameSize(frame_size);
215+
216+
frame_size_ = frame_size;
217+
device_pixel_ratio_ = device_pixel_ratio;
218+
}
219+
220+
// |ExternalViewEmbedder|
221+
void AndroidExternalViewEmbedder2::CancelFrame() {
222+
Reset();
223+
}
224+
225+
// |ExternalViewEmbedder|
226+
void AndroidExternalViewEmbedder2::EndFrame(
227+
bool should_resubmit_frame,
228+
const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {}
229+
230+
// |ExternalViewEmbedder|
231+
bool AndroidExternalViewEmbedder2::SupportsDynamicThreadMerging() {
232+
return false;
233+
}
234+
235+
// |ExternalViewEmbedder|
236+
void AndroidExternalViewEmbedder2::Teardown() {
237+
DestroySurfaces();
238+
}
239+
240+
// |ExternalViewEmbedder|
241+
void AndroidExternalViewEmbedder2::DestroySurfaces() {
242+
if (!surface_pool_->HasLayers()) {
243+
return;
244+
}
245+
fml::AutoResetWaitableEvent latch;
246+
fml::TaskRunner::RunNowOrPostTask(task_runners_.GetPlatformTaskRunner(),
247+
[&]() {
248+
surface_pool_->DestroyLayers(jni_facade_);
249+
latch.Signal();
250+
});
251+
latch.Wait();
252+
}
253+
254+
} // namespace flutter

0 commit comments

Comments
 (0)