Flutter Engine
The Flutter Engine
core_implementations.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// This file contains the implementations of any class in the wrapper that
6// - is not fully inline, and
7// - is necessary for all clients of the wrapper (either app or plugin).
8// It exists instead of the usual structure of having some_class_name.cc files
9// so that changes to the set of things that need non-header implementations
10// are not breaking changes for the template.
11//
12// If https://github.com/flutter/flutter/issues/57146 is fixed, this can be
13// removed in favor of the normal structure since templates will no longer
14// manually include files.
15
16#include <cassert>
17#include <iostream>
18#include <variant>
19
25
26namespace flutter {
27
28// ========== binary_messenger_impl.h ==========
29
30namespace {
31
32using FlutterDesktopMessengerScopedLock =
33 std::unique_ptr<FlutterDesktopMessenger,
35
36// Passes |message| to |user_data|, which must be a BinaryMessageHandler, along
37// with a BinaryReply that will send a response on |message|'s response handle.
38//
39// This serves as an adaptor between the function-pointer-based message callback
40// interface provided by the C API and the std::function-based message handler
41// interface of BinaryMessenger.
42void ForwardToHandler(FlutterDesktopMessengerRef messenger,
44 void* user_data) {
45 auto* response_handle = message->response_handle;
46 auto messenger_ptr = std::shared_ptr<FlutterDesktopMessenger>(
49 BinaryReply reply_handler = [messenger_ptr, response_handle](
50 const uint8_t* reply,
51 size_t reply_size) mutable {
52 // Note: This lambda can be called on any thread.
53 auto lock = FlutterDesktopMessengerScopedLock(
54 FlutterDesktopMessengerLock(messenger_ptr.get()),
56 if (!FlutterDesktopMessengerIsAvailable(messenger_ptr.get())) {
57 // Drop reply if it comes in after the engine is destroyed.
58 return;
59 }
60 if (!response_handle) {
61 std::cerr << "Error: Response can be set only once. Ignoring "
62 "duplicate response."
63 << std::endl;
64 return;
65 }
66 FlutterDesktopMessengerSendResponse(messenger_ptr.get(), response_handle,
67 reply, reply_size);
68 // The engine frees the response handle once
69 // FlutterDesktopSendMessageResponse is called.
70 response_handle = nullptr;
71 };
72
73 const BinaryMessageHandler& message_handler =
74 *static_cast<BinaryMessageHandler*>(user_data);
75
76 message_handler(message->message, message->message_size,
77 std::move(reply_handler));
78}
79} // namespace
80
82 FlutterDesktopMessengerRef core_messenger)
83 : messenger_(core_messenger) {}
84
86
87void BinaryMessengerImpl::Send(const std::string& channel,
88 const uint8_t* message,
89 size_t message_size,
90 BinaryReply reply) const {
91 if (reply == nullptr) {
92 FlutterDesktopMessengerSend(messenger_, channel.c_str(), message,
93 message_size);
94 return;
95 }
96 struct Captures {
97 BinaryReply reply;
98 };
99 auto captures = new Captures();
100 captures->reply = reply;
101
102 auto message_reply = [](const uint8_t* data, size_t data_size,
103 void* user_data) {
104 auto captures = reinterpret_cast<Captures*>(user_data);
105 captures->reply(data, data_size);
106 delete captures;
107 };
109 messenger_, channel.c_str(), message, message_size, message_reply,
110 captures);
111 if (!result) {
112 delete captures;
113 }
114}
115
116void BinaryMessengerImpl::SetMessageHandler(const std::string& channel,
117 BinaryMessageHandler handler) {
118 if (!handler) {
119 handlers_.erase(channel);
120 FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(), nullptr,
121 nullptr);
122 return;
123 }
124 // Save the handler, to keep it alive.
125 handlers_[channel] = std::move(handler);
126 BinaryMessageHandler* message_handler = &handlers_[channel];
127 // Set an adaptor callback that will invoke the handler.
128 FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(),
129 ForwardToHandler, message_handler);
130}
131
132// ========== engine_method_result.h ==========
133
134namespace internal {
135
137 : reply_handler_(std::move(reply_handler)) {
138 assert(reply_handler_);
139}
140
142 if (reply_handler_) {
143 // Warn, rather than send a not-implemented response, since the engine may
144 // no longer be valid at this point.
145 std::cerr
146 << "Warning: Failed to respond to a message. This is a memory leak."
147 << std::endl;
148 }
149}
150
151void ReplyManager::SendResponseData(const std::vector<uint8_t>* data) {
152 if (!reply_handler_) {
153 std::cerr
154 << "Error: Only one of Success, Error, or NotImplemented can be "
155 "called,"
156 << " and it can be called exactly once. Ignoring duplicate result."
157 << std::endl;
158 return;
159 }
160
161 const uint8_t* message = data && !data->empty() ? data->data() : nullptr;
162 size_t message_size = data ? data->size() : 0;
163 reply_handler_(message, message_size);
164 reply_handler_ = nullptr;
165}
166
167} // namespace internal
168
169// ========== method_channel.h ==========
170
171namespace {
172
173constexpr char kControlChannelName[] = "dev.flutter/channel-buffers";
174constexpr char kResizeMethod[] = "resize";
175constexpr char kOverflowMethod[] = "overflow";
176
177} // namespace
178
179namespace internal {
180
181void ResizeChannel(BinaryMessenger* messenger, std::string name, int new_size) {
182 auto control_channel = std::make_unique<MethodChannel<EncodableValue>>(
184
185 // The deserialization logic handles only 32 bits values, see
186 // https://github.com/flutter/engine/blob/93e8901490e78c7ba7e319cce4470d9c6478c6dc/lib/ui/channel_buffers.dart#L495.
187 control_channel->InvokeMethod(
188 kResizeMethod, std::make_unique<EncodableValue>(EncodableList{
190 EncodableValue(static_cast<int32_t>(new_size)),
191 }));
192}
193
195 std::string name,
196 bool warns) {
197 auto control_channel = std::make_unique<MethodChannel<EncodableValue>>(
199
200 control_channel->InvokeMethod(kOverflowMethod,
201 std::make_unique<EncodableValue>(EncodableList{
203 EncodableValue(!warns),
204 }));
205}
206
207} // namespace internal
208
209// ========== texture_registrar_impl.h ==========
210
212 FlutterDesktopTextureRegistrarRef texture_registrar_ref)
213 : texture_registrar_ref_(texture_registrar_ref) {}
214
216
219 if (auto pixel_buffer_texture = std::get_if<PixelBufferTexture>(texture)) {
221 info.pixel_buffer_config.user_data = pixel_buffer_texture;
222 info.pixel_buffer_config.callback =
223 [](size_t width, size_t height,
224 void* user_data) -> const FlutterDesktopPixelBuffer* {
225 auto texture = static_cast<PixelBufferTexture*>(user_data);
226 return texture->CopyPixelBuffer(width, height);
227 };
228 } else if (auto gpu_surface_texture =
229 std::get_if<GpuSurfaceTexture>(texture)) {
231 info.gpu_surface_config.struct_size =
233 info.gpu_surface_config.type = gpu_surface_texture->surface_type();
234 info.gpu_surface_config.user_data = gpu_surface_texture;
235 info.gpu_surface_config.callback =
236 [](size_t width, size_t height,
238 auto texture = static_cast<GpuSurfaceTexture*>(user_data);
239 return texture->ObtainDescriptor(width, height);
240 };
241 } else {
242 std::cerr << "Attempting to register unknown texture variant." << std::endl;
243 return -1;
244 }
245
247 texture_registrar_ref_, &info);
248 return texture_id;
249} // namespace flutter
250
253 texture_registrar_ref_, texture_id);
254}
255
257 std::function<void()> callback) {
258 if (callback == nullptr) {
260 texture_registrar_ref_, texture_id, nullptr, nullptr);
261 return;
262 }
263
264 struct Captures {
265 std::function<void()> callback;
266 };
267 auto captures = new Captures();
268 captures->callback = std::move(callback);
270 texture_registrar_ref_, texture_id,
271 [](void* opaque) {
272 auto captures = reinterpret_cast<Captures*>(opaque);
273 captures->callback();
274 delete captures;
275 },
276 captures);
277}
278
281 return true;
282}
283
284} // namespace flutter
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
static NSString *const kOverflowMethod
static NSString *const kResizeMethod
BinaryMessengerImpl(FlutterDesktopMessengerRef core_messenger)
void SetMessageHandler(const std::string &channel, BinaryMessageHandler handler) override
void Send(const std::string &channel, const uint8_t *message, size_t message_size, BinaryReply reply) const override
static const StandardMethodCodec & GetInstance(const StandardCodecSerializer *serializer=nullptr)
int64_t RegisterTexture(TextureVariant *texture) override
bool MarkTextureFrameAvailable(int64_t texture_id) override
TextureRegistrarImpl(FlutterDesktopTextureRegistrarRef texture_registrar_ref)
void UnregisterTexture(int64_t texture_id, std::function< void()> callback) override
ReplyManager(BinaryReply reply_handler_)
void SendResponseData(const std::vector< uint8_t > *data)
static constexpr char kControlChannelName[]
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
GAsyncResult * result
struct FlutterDesktopTextureRegistrar * FlutterDesktopTextureRegistrarRef
@ kFlutterDesktopGpuSurfaceTexture
@ kFlutterDesktopPixelBufferTexture
Dart_NativeFunction function
Definition: fuchsia.cc:51
Win32Message message
FlTexture * texture
void SetChannelWarnsOnOverflow(BinaryMessenger *messenger, std::string name, bool warns)
void ResizeChannel(BinaryMessenger *messenger, std::string name, int new_size)
std::function< void(const uint8_t *message, size_t message_size, BinaryReply reply)> BinaryMessageHandler
std::function< void(const uint8_t *reply, size_t reply_size)> BinaryReply
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition: switches.h:41
std::vector< EncodableValue > EncodableList
std::variant< PixelBufferTexture, GpuSurfaceTexture > TextureVariant
Definition: ref_ptr.h:256
int32_t height
int32_t width
void FlutterDesktopMessengerSetCallback(FlutterDesktopMessengerRef messenger, const char *channel, FlutterDesktopMessageCallback callback, void *user_data)
int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture(FlutterDesktopTextureRegistrarRef texture_registrar, const FlutterDesktopTextureInfo *info)
void FlutterDesktopMessengerSendResponse(FlutterDesktopMessengerRef messenger, const FlutterDesktopMessageResponseHandle *handle, const uint8_t *data, size_t data_length)
bool FlutterDesktopMessengerSendWithReply(FlutterDesktopMessengerRef messenger, const char *channel, const uint8_t *message, const size_t message_size, const FlutterDesktopBinaryReply reply, void *user_data)
bool FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable(FlutterDesktopTextureRegistrarRef texture_registrar, int64_t texture_id)
FlutterDesktopMessengerRef FlutterDesktopMessengerLock(FlutterDesktopMessengerRef messenger)
void FlutterDesktopTextureRegistrarUnregisterExternalTexture(FlutterDesktopTextureRegistrarRef texture_registrar, int64_t texture_id, void(*callback)(void *user_data), void *user_data)
bool FlutterDesktopMessengerIsAvailable(FlutterDesktopMessengerRef messenger)
bool FlutterDesktopMessengerSend(FlutterDesktopMessengerRef messenger, const char *channel, const uint8_t *message, const size_t message_size)
void FlutterDesktopMessengerUnlock(FlutterDesktopMessengerRef messenger)
void FlutterDesktopMessengerRelease(FlutterDesktopMessengerRef messenger)
FlutterDesktopMessengerRef FlutterDesktopMessengerAddRef(FlutterDesktopMessengerRef messenger)
void * user_data
int64_t texture_id