Flutter Engine
 
Loading...
Searching...
No Matches
platform_view_android_jni_impl.cc File Reference

Go to the source code of this file.

Namespaces

namespace  flutter
 

Macros

#define ANDROID_SHELL_HOLDER    (reinterpret_cast<AndroidShellHolder*>(shell_holder))
 
#define FLUTTER_FOR_EACH_JNI_METHOD(V)
 
#define FLUTTER_DECLARE_JNI(global_field, jni_name, jni_arg)    static jmethodID global_field = nullptr;
 
#define FLUTTER_BIND_JNI(global_field, jni_name, jni_arg)
 

Functions

static jlong flutter::AttachJNI (JNIEnv *env, jclass clazz, jobject flutterJNI)
 
static void flutter::DestroyJNI (JNIEnv *env, jobject jcaller, jlong shell_holder)
 
static jobject flutter::SpawnJNI (JNIEnv *env, jobject jcaller, jlong shell_holder, jstring jEntrypoint, jstring jLibraryUrl, jstring jInitialRoute, jobject jEntrypointArgs, jlong engineId)
 
static void flutter::SurfaceCreated (JNIEnv *env, jobject jcaller, jlong shell_holder, jobject jsurface)
 
static void flutter::SurfaceWindowChanged (JNIEnv *env, jobject jcaller, jlong shell_holder, jobject jsurface)
 
static void flutter::SurfaceChanged (JNIEnv *env, jobject jcaller, jlong shell_holder, jint width, jint height)
 
static void flutter::SurfaceDestroyed (JNIEnv *env, jobject jcaller, jlong shell_holder)
 
static void flutter::RunBundleAndSnapshotFromLibrary (JNIEnv *env, jobject jcaller, jlong shell_holder, jstring jBundlePath, jstring jEntrypoint, jstring jLibraryUrl, jobject jAssetManager, jobject jEntrypointArgs, jlong engineId)
 
static jobject flutter::LookupCallbackInformation (JNIEnv *env, jobject, jlong handle)
 
static void flutter::SetViewportMetrics (JNIEnv *env, jobject jcaller, jlong shell_holder, jfloat devicePixelRatio, jint physicalWidth, jint physicalHeight, jint physicalPaddingTop, jint physicalPaddingRight, jint physicalPaddingBottom, jint physicalPaddingLeft, jint physicalViewInsetTop, jint physicalViewInsetRight, jint physicalViewInsetBottom, jint physicalViewInsetLeft, jint systemGestureInsetTop, jint systemGestureInsetRight, jint systemGestureInsetBottom, jint systemGestureInsetLeft, jint physicalTouchSlop, jintArray javaDisplayFeaturesBounds, jintArray javaDisplayFeaturesType, jintArray javaDisplayFeaturesState)
 
static void flutter::UpdateDisplayMetrics (JNIEnv *env, jobject jcaller, jlong shell_holder)
 
static bool flutter::IsSurfaceControlEnabled (JNIEnv *env, jobject jcaller, jlong shell_holder)
 
static jobject flutter::GetBitmap (JNIEnv *env, jobject jcaller, jlong shell_holder)
 
static void flutter::DispatchPlatformMessage (JNIEnv *env, jobject jcaller, jlong shell_holder, jstring channel, jobject message, jint position, jint responseId)
 
static void flutter::DispatchEmptyPlatformMessage (JNIEnv *env, jobject jcaller, jlong shell_holder, jstring channel, jint responseId)
 
static void flutter::CleanupMessageData (JNIEnv *env, jobject jcaller, jlong message_data)
 
static void flutter::DispatchPointerDataPacket (JNIEnv *env, jobject jcaller, jlong shell_holder, jobject buffer, jint position)
 
static void flutter::DispatchSemanticsAction (JNIEnv *env, jobject jcaller, jlong shell_holder, jint id, jint action, jobject args, jint args_position)
 
static void flutter::SetSemanticsEnabled (JNIEnv *env, jobject jcaller, jlong shell_holder, jboolean enabled)
 
static void flutter::SetAccessibilityFeatures (JNIEnv *env, jobject jcaller, jlong shell_holder, jint flags)
 
static jboolean flutter::GetIsSoftwareRendering (JNIEnv *env, jobject jcaller)
 
static void flutter::RegisterTexture (JNIEnv *env, jobject jcaller, jlong shell_holder, jlong texture_id, jobject surface_texture)
 
static void flutter::RegisterImageTexture (JNIEnv *env, jobject jcaller, jlong shell_holder, jlong texture_id, jobject image_texture_entry, jboolean reset_on_background)
 
static void flutter::UnregisterTexture (JNIEnv *env, jobject jcaller, jlong shell_holder, jlong texture_id)
 
static void flutter::MarkTextureFrameAvailable (JNIEnv *env, jobject jcaller, jlong shell_holder, jlong texture_id)
 
static void flutter::ScheduleFrame (JNIEnv *env, jobject jcaller, jlong shell_holder)
 
static void flutter::InvokePlatformMessageResponseCallback (JNIEnv *env, jobject jcaller, jlong shell_holder, jint responseId, jobject message, jint position)
 
static void flutter::InvokePlatformMessageEmptyResponseCallback (JNIEnv *env, jobject jcaller, jlong shell_holder, jint responseId)
 
static void flutter::NotifyLowMemoryWarning (JNIEnv *env, jobject obj, jlong shell_holder)
 
static jboolean flutter::FlutterTextUtilsIsEmoji (JNIEnv *env, jobject obj, jint codePoint)
 
static jboolean flutter::FlutterTextUtilsIsEmojiModifier (JNIEnv *env, jobject obj, jint codePoint)
 
static jboolean flutter::FlutterTextUtilsIsEmojiModifierBase (JNIEnv *env, jobject obj, jint codePoint)
 
static jboolean flutter::FlutterTextUtilsIsVariationSelector (JNIEnv *env, jobject obj, jint codePoint)
 
static jboolean flutter::FlutterTextUtilsIsRegionalIndicator (JNIEnv *env, jobject obj, jint codePoint)
 
static void flutter::LoadLoadingUnitFailure (intptr_t loading_unit_id, const std::string &message, bool transient)
 
static void flutter::DeferredComponentInstallFailure (JNIEnv *env, jobject obj, jint jLoadingUnitId, jstring jError, jboolean jTransient)
 
static void flutter::LoadDartDeferredLibrary (JNIEnv *env, jobject obj, jlong shell_holder, jint jLoadingUnitId, jobjectArray jSearchPaths)
 
static void flutter::UpdateJavaAssetManager (JNIEnv *env, jobject obj, jlong shell_holder, jobject jAssetManager, jstring jAssetBundlePath)
 
bool flutter::RegisterApi (JNIEnv *env)
 

Variables

static fml::jni::ScopedJavaGlobalRef< jclass > * flutter::g_flutter_callback_info_class
 
static fml::jni::ScopedJavaGlobalRef< jclass > * flutter::g_flutter_jni_class = nullptr
 
static fml::jni::ScopedJavaGlobalRef< jclass > * flutter::g_java_weak_reference_class
 
static fml::jni::ScopedJavaGlobalRef< jclass > * flutter::g_texture_wrapper_class = nullptr
 
static fml::jni::ScopedJavaGlobalRef< jclass > * flutter::g_image_consumer_texture_registry_interface = nullptr
 
static fml::jni::ScopedJavaGlobalRef< jclass > * flutter::g_image_class = nullptr
 
static fml::jni::ScopedJavaGlobalRef< jclass > * flutter::g_hardware_buffer_class = nullptr
 
static fml::jni::ScopedJavaGlobalRef< jclass > * flutter::g_java_long_class = nullptr
 
static fml::jni::ScopedJavaGlobalRef< jclass > * flutter::g_bitmap_class = nullptr
 
static fml::jni::ScopedJavaGlobalRef< jclass > * flutter::g_bitmap_config_class = nullptr
 
static jmethodID flutter::g_flutter_callback_info_constructor = nullptr
 
static jfieldID flutter::g_jni_shell_holder_field = nullptr
 
static jmethodID flutter::g_jni_constructor = nullptr
 
static jmethodID flutter::g_long_constructor = nullptr
 
static jmethodID flutter::g_java_weak_reference_get_method = nullptr
 
static jmethodID flutter::g_attach_to_gl_context_method = nullptr
 
static jmethodID flutter::g_surface_texture_wrapper_should_update = nullptr
 
static jmethodID flutter::g_update_tex_image_method = nullptr
 
static jmethodID flutter::g_get_transform_matrix_method = nullptr
 
static jmethodID flutter::g_detach_from_gl_context_method = nullptr
 
static jmethodID flutter::g_acquire_latest_image_method = nullptr
 
static jmethodID flutter::g_image_get_hardware_buffer_method = nullptr
 
static jmethodID flutter::g_image_close_method = nullptr
 
static jmethodID flutter::g_hardware_buffer_close_method = nullptr
 
static jmethodID flutter::g_compute_platform_resolved_locale_method = nullptr
 
static jmethodID flutter::g_request_dart_deferred_library_method = nullptr
 
static jmethodID flutter::g_overlay_surface_id_method = nullptr
 
static jmethodID flutter::g_overlay_surface_surface_method = nullptr
 
static jmethodID flutter::g_bitmap_create_bitmap_method = nullptr
 
static jmethodID flutter::g_bitmap_copy_pixels_from_buffer_method = nullptr
 
static jmethodID flutter::g_bitmap_config_value_of = nullptr
 
static fml::jni::ScopedJavaGlobalRef< jclass > * flutter::g_mutators_stack_class = nullptr
 
static jmethodID flutter::g_mutators_stack_init_method = nullptr
 
static jmethodID flutter::g_mutators_stack_push_transform_method = nullptr
 
static jmethodID flutter::g_mutators_stack_push_cliprect_method = nullptr
 
static jmethodID flutter::g_mutators_stack_push_cliprrect_method = nullptr
 
static jmethodID flutter::g_mutators_stack_push_opacity_method = nullptr
 
static jmethodID flutter::g_mutators_stack_push_clippath_method = nullptr
 
static fml::jni::ScopedJavaGlobalRef< jclass > * flutter::path_class = nullptr
 
static jmethodID flutter::path_constructor = nullptr
 
static jmethodID flutter::path_move_to_method = nullptr
 
static jmethodID flutter::path_line_to_method = nullptr
 
static jmethodID flutter::path_quad_to_method = nullptr
 
static jmethodID flutter::path_cubic_to_method = nullptr
 
static jmethodID flutter::path_conic_to_method = nullptr
 
static jmethodID flutter::path_close_method = nullptr
 
static jmethodID flutter::path_set_fill_type_method = nullptr
 
static fml::jni::ScopedJavaGlobalRef< jclass > * flutter::g_path_fill_type_class = nullptr
 
static jfieldID flutter::g_path_fill_type_winding_field = nullptr
 
static jfieldID flutter::g_path_fill_type_even_odd_field = nullptr
 

Macro Definition Documentation

◆ ANDROID_SHELL_HOLDER

#define ANDROID_SHELL_HOLDER    (reinterpret_cast<AndroidShellHolder*>(shell_holder))

Definition at line 31 of file platform_view_android_jni_impl.cc.

33 {
34
36 nullptr;
37
39
41 nullptr;
42
44
47
49
51
53
55
57
58// Called By Native
59
60static jmethodID g_flutter_callback_info_constructor = nullptr;
61
62static jfieldID g_jni_shell_holder_field = nullptr;
63
64#define FLUTTER_FOR_EACH_JNI_METHOD(V) \
65 V(g_handle_platform_message_method, handlePlatformMessage, \
66 "(Ljava/lang/String;Ljava/nio/ByteBuffer;IJ)V") \
67 V(g_handle_platform_message_response_method, handlePlatformMessageResponse, \
68 "(ILjava/nio/ByteBuffer;)V") \
69 V(g_update_semantics_method, updateSemantics, \
70 "(Ljava/nio/ByteBuffer;[Ljava/lang/String;[Ljava/nio/ByteBuffer;)V") \
71 V(g_set_application_locale_method, setApplicationLocale, \
72 "(Ljava/lang/String;)V") \
73 V(g_on_display_platform_view_method, onDisplayPlatformView, \
74 "(IIIIIIILio/flutter/embedding/engine/mutatorsstack/" \
75 "FlutterMutatorsStack;)V") \
76 V(g_on_begin_frame_method, onBeginFrame, "()V") \
77 V(g_on_end_frame_method, onEndFrame, "()V") \
78 V(g_on_display_overlay_surface_method, onDisplayOverlaySurface, "(IIIII)V") \
79 V(g_create_transaction_method, createTransaction, \
80 "()Landroid/view/SurfaceControl$Transaction;") \
81 V(g_swap_transaction_method, swapTransactions, "()V") \
82 V(g_apply_transaction_method, applyTransactions, "()V") \
83 V(g_create_overlay_surface2_method, createOverlaySurface2, \
84 "()Lio/flutter/embedding/engine/FlutterOverlaySurface;") \
85 V(g_destroy_overlay_surface2_method, destroyOverlaySurface2, "()V") \
86 V(g_on_display_platform_view2_method, onDisplayPlatformView2, \
87 "(IIIIIIILio/flutter/embedding/engine/mutatorsstack/" \
88 "FlutterMutatorsStack;)V") \
89 V(g_hide_platform_view2_method, hidePlatformView2, "(I)V") \
90 V(g_on_end_frame2_method, endFrame2, "()V") \
91 V(g_show_overlay_surface2_method, showOverlaySurface2, "()V") \
92 V(g_hide_overlay_surface2_method, hideOverlaySurface2, "()V") \
93 V(g_get_scaled_font_size_method, getScaledFontSize, "(FI)F") \
94 V(g_update_custom_accessibility_actions_method, \
95 updateCustomAccessibilityActions, \
96 "(Ljava/nio/ByteBuffer;[Ljava/lang/String;)V") \
97 V(g_on_first_frame_method, onFirstFrame, "()V") \
98 V(g_on_engine_restart_method, onPreEngineRestart, "()V") \
99 V(g_create_overlay_surface_method, createOverlaySurface, \
100 "()Lio/flutter/embedding/engine/FlutterOverlaySurface;") \
101 V(g_destroy_overlay_surfaces_method, destroyOverlaySurfaces, "()V")
102
103//
104
105#define FLUTTER_DECLARE_JNI(global_field, jni_name, jni_arg) \
106 static jmethodID global_field = nullptr;
107
108#define FLUTTER_BIND_JNI(global_field, jni_name, jni_arg) \
109 global_field = \
110 env->GetMethodID(g_flutter_jni_class->obj(), #jni_name, jni_arg); \
111 if (global_field == nullptr) { \
112 FML_LOG(ERROR) << "Could not locate " << #jni_name << " method."; \
113 return false; \
114 }
115
116static jmethodID g_jni_constructor = nullptr;
117
118static jmethodID g_long_constructor = nullptr;
119
121
122static jmethodID g_java_weak_reference_get_method = nullptr;
123
124static jmethodID g_attach_to_gl_context_method = nullptr;
125
126static jmethodID g_surface_texture_wrapper_should_update = nullptr;
127
128static jmethodID g_update_tex_image_method = nullptr;
129
130static jmethodID g_get_transform_matrix_method = nullptr;
131
132static jmethodID g_detach_from_gl_context_method = nullptr;
133
134static jmethodID g_acquire_latest_image_method = nullptr;
135
136static jmethodID g_image_get_hardware_buffer_method = nullptr;
137
138static jmethodID g_image_close_method = nullptr;
139
140static jmethodID g_hardware_buffer_close_method = nullptr;
141
142static jmethodID g_compute_platform_resolved_locale_method = nullptr;
143
144static jmethodID g_request_dart_deferred_library_method = nullptr;
145
146// Called By Java
147
148static jmethodID g_overlay_surface_id_method = nullptr;
149
150static jmethodID g_overlay_surface_surface_method = nullptr;
151
152static jmethodID g_bitmap_create_bitmap_method = nullptr;
153
154static jmethodID g_bitmap_copy_pixels_from_buffer_method = nullptr;
155
156static jmethodID g_bitmap_config_value_of = nullptr;
157
158// Mutators
160static jmethodID g_mutators_stack_init_method = nullptr;
161static jmethodID g_mutators_stack_push_transform_method = nullptr;
162static jmethodID g_mutators_stack_push_cliprect_method = nullptr;
163static jmethodID g_mutators_stack_push_cliprrect_method = nullptr;
164static jmethodID g_mutators_stack_push_opacity_method = nullptr;
165static jmethodID g_mutators_stack_push_clippath_method = nullptr;
166
167// android.graphics.Path class, methods, and nested classes.
169static jmethodID path_constructor = nullptr;
170static jmethodID path_move_to_method = nullptr;
171static jmethodID path_line_to_method = nullptr;
172static jmethodID path_quad_to_method = nullptr;
173static jmethodID path_cubic_to_method = nullptr;
174static jmethodID path_conic_to_method = nullptr;
175static jmethodID path_close_method = nullptr;
176static jmethodID path_set_fill_type_method = nullptr;
177
179static jfieldID g_path_fill_type_winding_field = nullptr;
180static jfieldID g_path_fill_type_even_odd_field = nullptr;
181
182// Called By Java
183static jlong AttachJNI(JNIEnv* env, jclass clazz, jobject flutterJNI) {
184 fml::jni::JavaObjectWeakGlobalRef java_object(env, flutterJNI);
185 std::shared_ptr<PlatformViewAndroidJNI> jni_facade =
186 std::make_shared<PlatformViewAndroidJNIImpl>(java_object);
187 auto shell_holder = std::make_unique<AndroidShellHolder>(
188 FlutterMain::Get().GetSettings(), jni_facade,
189 FlutterMain::Get().GetAndroidRenderingAPI());
190 if (shell_holder->IsValid()) {
191 return reinterpret_cast<jlong>(shell_holder.release());
192 } else {
193 return 0;
194 }
195}
196
197static void DestroyJNI(JNIEnv* env, jobject jcaller, jlong shell_holder) {
199}
200
201// Signature is similar to RunBundleAndSnapshotFromLibrary but it can't change
202// the bundle path or asset manager since we can only spawn with the same
203// AOT.
204//
205// The shell_holder instance must be a pointer address to the current
206// AndroidShellHolder whose Shell will be used to spawn a new Shell.
207//
208// This creates a Java Long that points to the newly created
209// AndroidShellHolder's raw pointer, connects that Long to a newly created
210// FlutterJNI instance, then returns the FlutterJNI instance.
211static jobject SpawnJNI(JNIEnv* env,
212 jobject jcaller,
213 jlong shell_holder,
214 jstring jEntrypoint,
215 jstring jLibraryUrl,
216 jstring jInitialRoute,
217 jobject jEntrypointArgs,
218 jlong engineId) {
219 jobject jni = env->NewObject(g_flutter_jni_class->obj(), g_jni_constructor);
220 if (jni == nullptr) {
221 FML_LOG(ERROR) << "Could not create a FlutterJNI instance";
222 return nullptr;
223 }
224
225 fml::jni::JavaObjectWeakGlobalRef java_jni(env, jni);
226 std::shared_ptr<PlatformViewAndroidJNI> jni_facade =
227 std::make_shared<PlatformViewAndroidJNIImpl>(java_jni);
228
229 auto entrypoint = fml::jni::JavaStringToString(env, jEntrypoint);
230 auto libraryUrl = fml::jni::JavaStringToString(env, jLibraryUrl);
231 auto initial_route = fml::jni::JavaStringToString(env, jInitialRoute);
232 auto entrypoint_args = fml::jni::StringListToVector(env, jEntrypointArgs);
233
234 auto spawned_shell_holder =
235 ANDROID_SHELL_HOLDER->Spawn(jni_facade, entrypoint, libraryUrl,
236 initial_route, entrypoint_args, engineId);
237
238 if (spawned_shell_holder == nullptr || !spawned_shell_holder->IsValid()) {
239 FML_LOG(ERROR) << "Could not spawn Shell";
240 return nullptr;
241 }
242
243 jobject javaLong = env->CallStaticObjectMethod(
244 g_java_long_class->obj(), g_long_constructor,
245 reinterpret_cast<jlong>(spawned_shell_holder.release()));
246 if (javaLong == nullptr) {
247 FML_LOG(ERROR) << "Could not create a Long instance";
248 return nullptr;
249 }
250
251 env->SetObjectField(jni, g_jni_shell_holder_field, javaLong);
252
253 return jni;
254}
255
256static void SurfaceCreated(JNIEnv* env,
257 jobject jcaller,
258 jlong shell_holder,
259 jobject jsurface) {
260 // Note: This frame ensures that any local references used by
261 // ANativeWindow_fromSurface are released immediately. This is needed as a
262 // workaround for https://code.google.com/p/android/issues/detail?id=68174
263 fml::jni::ScopedJavaLocalFrame scoped_local_reference_frame(env);
264 auto window = fml::MakeRefCounted<AndroidNativeWindow>(
265 ANativeWindow_fromSurface(env, jsurface));
266 ANDROID_SHELL_HOLDER->GetPlatformView()->NotifyCreated(std::move(window));
267}
268
269static void SurfaceWindowChanged(JNIEnv* env,
270 jobject jcaller,
271 jlong shell_holder,
272 jobject jsurface) {
273 // Note: This frame ensures that any local references used by
274 // ANativeWindow_fromSurface are released immediately. This is needed as a
275 // workaround for https://code.google.com/p/android/issues/detail?id=68174
276 fml::jni::ScopedJavaLocalFrame scoped_local_reference_frame(env);
277 auto window = fml::MakeRefCounted<AndroidNativeWindow>(
278 ANativeWindow_fromSurface(env, jsurface));
279 ANDROID_SHELL_HOLDER->GetPlatformView()->NotifySurfaceWindowChanged(
280 std::move(window));
281}
282
283static void SurfaceChanged(JNIEnv* env,
284 jobject jcaller,
285 jlong shell_holder,
286 jint width,
287 jint height) {
288 ANDROID_SHELL_HOLDER->GetPlatformView()->NotifyChanged(
290}
291
292static void SurfaceDestroyed(JNIEnv* env, jobject jcaller, jlong shell_holder) {
293 ANDROID_SHELL_HOLDER->GetPlatformView()->NotifyDestroyed();
294}
295
296static void RunBundleAndSnapshotFromLibrary(JNIEnv* env,
297 jobject jcaller,
298 jlong shell_holder,
299 jstring jBundlePath,
300 jstring jEntrypoint,
301 jstring jLibraryUrl,
302 jobject jAssetManager,
303 jobject jEntrypointArgs,
304 jlong engineId) {
305 auto apk_asset_provider = std::make_unique<flutter::APKAssetProvider>(
306 env, // jni environment
307 jAssetManager, // asset manager
308 fml::jni::JavaStringToString(env, jBundlePath) // apk asset dir
309 );
310 auto entrypoint = fml::jni::JavaStringToString(env, jEntrypoint);
311 auto libraryUrl = fml::jni::JavaStringToString(env, jLibraryUrl);
312 auto entrypoint_args = fml::jni::StringListToVector(env, jEntrypointArgs);
313
314 ANDROID_SHELL_HOLDER->Launch(std::move(apk_asset_provider), entrypoint,
315 libraryUrl, entrypoint_args, engineId);
316}
317
318static jobject LookupCallbackInformation(JNIEnv* env,
319 /* unused */ jobject,
320 jlong handle) {
322 if (cbInfo == nullptr) {
323 return nullptr;
324 }
325 return env->NewObject(g_flutter_callback_info_class->obj(),
326 g_flutter_callback_info_constructor,
327 env->NewStringUTF(cbInfo->name.c_str()),
328 env->NewStringUTF(cbInfo->class_name.c_str()),
329 env->NewStringUTF(cbInfo->library_path.c_str()));
330}
331
332static void SetViewportMetrics(JNIEnv* env,
333 jobject jcaller,
334 jlong shell_holder,
335 jfloat devicePixelRatio,
336 jint physicalWidth,
337 jint physicalHeight,
338 jint physicalPaddingTop,
339 jint physicalPaddingRight,
340 jint physicalPaddingBottom,
341 jint physicalPaddingLeft,
342 jint physicalViewInsetTop,
343 jint physicalViewInsetRight,
344 jint physicalViewInsetBottom,
345 jint physicalViewInsetLeft,
346 jint systemGestureInsetTop,
347 jint systemGestureInsetRight,
348 jint systemGestureInsetBottom,
349 jint systemGestureInsetLeft,
350 jint physicalTouchSlop,
351 jintArray javaDisplayFeaturesBounds,
352 jintArray javaDisplayFeaturesType,
353 jintArray javaDisplayFeaturesState) {
354 // Convert java->c++. javaDisplayFeaturesBounds, javaDisplayFeaturesType and
355 // javaDisplayFeaturesState cannot be null
356 jsize rectSize = env->GetArrayLength(javaDisplayFeaturesBounds);
357 std::vector<int> boundsIntVector(rectSize);
358 env->GetIntArrayRegion(javaDisplayFeaturesBounds, 0, rectSize,
359 &boundsIntVector[0]);
360 std::vector<double> displayFeaturesBounds(boundsIntVector.begin(),
361 boundsIntVector.end());
362 jsize typeSize = env->GetArrayLength(javaDisplayFeaturesType);
363 std::vector<int> displayFeaturesType(typeSize);
364 env->GetIntArrayRegion(javaDisplayFeaturesType, 0, typeSize,
365 &displayFeaturesType[0]);
366
367 jsize stateSize = env->GetArrayLength(javaDisplayFeaturesState);
368 std::vector<int> displayFeaturesState(stateSize);
369 env->GetIntArrayRegion(javaDisplayFeaturesState, 0, stateSize,
370 &displayFeaturesState[0]);
371
372 // TODO(boetger): update for https://github.com/flutter/flutter/issues/149033
373 const flutter::ViewportMetrics metrics{
374 static_cast<double>(devicePixelRatio), // p_device_pixel_ratio
375 static_cast<double>(physicalWidth), // p_physical_width
376 static_cast<double>(physicalHeight), // p_physical_height
377 static_cast<double>(physicalWidth), // p_physical_min_width_constraint
378 static_cast<double>(physicalWidth), // p_physical_max_width_constraint
379 static_cast<double>(physicalHeight), // p_physical_min_height_constraint
380 static_cast<double>(physicalHeight), // p_physical_max_height_constraint
381 static_cast<double>(physicalPaddingTop), // p_physical_padding_top
382 static_cast<double>(physicalPaddingRight), // p_physical_padding_right
383 static_cast<double>(physicalPaddingBottom), // p_physical_padding_bottom
384 static_cast<double>(physicalPaddingLeft), // p_physical_padding_left
385 static_cast<double>(physicalViewInsetTop), // p_physical_view_inset_top
386 static_cast<double>(
387 physicalViewInsetRight), // p_physical_view_inset_right
388 static_cast<double>(
389 physicalViewInsetBottom), // p_physical_view_inset_bottom
390 static_cast<double>(physicalViewInsetLeft), // p_physical_view_inset_left
391 static_cast<double>(
392 systemGestureInsetTop), // p_physical_system_gesture_inset_top
393 static_cast<double>(
394 systemGestureInsetRight), // p_physical_system_gesture_inset_right
395 static_cast<double>(
396 systemGestureInsetBottom), // p_physical_system_gesture_inset_bottom
397 static_cast<double>(
398 systemGestureInsetLeft), // p_physical_system_gesture_inset_left
399 static_cast<double>(physicalTouchSlop), // p_physical_touch_slop
400 displayFeaturesBounds, // p_physical_display_features_bounds
401 displayFeaturesType, // p_physical_display_features_type
402 displayFeaturesState, // p_physical_display_features_state
403 0, // p_display_id
404 };
405
406 ANDROID_SHELL_HOLDER->GetPlatformView()->SetViewportMetrics(
407 kFlutterImplicitViewId, metrics);
408}
409
410static void UpdateDisplayMetrics(JNIEnv* env,
411 jobject jcaller,
412 jlong shell_holder) {
413 ANDROID_SHELL_HOLDER->UpdateDisplayMetrics();
414}
415
416static bool IsSurfaceControlEnabled(JNIEnv* env,
417 jobject jcaller,
418 jlong shell_holder) {
419 return ANDROID_SHELL_HOLDER->IsSurfaceControlEnabled();
420}
421
422static jobject GetBitmap(JNIEnv* env, jobject jcaller, jlong shell_holder) {
423 auto screenshot = ANDROID_SHELL_HOLDER->Screenshot(
424 Rasterizer::ScreenshotType::UncompressedImage, false);
425 if (screenshot.data == nullptr) {
426 return nullptr;
427 }
428
429 jstring argb = env->NewStringUTF("ARGB_8888");
430 if (argb == nullptr) {
431 return nullptr;
432 }
433
434 jobject bitmap_config = env->CallStaticObjectMethod(
435 g_bitmap_config_class->obj(), g_bitmap_config_value_of, argb);
436 if (bitmap_config == nullptr) {
437 return nullptr;
438 }
439
440 auto bitmap = env->CallStaticObjectMethod(
441 g_bitmap_class->obj(), g_bitmap_create_bitmap_method,
442 screenshot.frame_size.width, screenshot.frame_size.height, bitmap_config);
443
445 env,
446 env->NewDirectByteBuffer(const_cast<uint8_t*>(screenshot.data->bytes()),
447 screenshot.data->size()));
448
449 env->CallVoidMethod(bitmap, g_bitmap_copy_pixels_from_buffer_method,
450 buffer.obj());
451
452 return bitmap;
453}
454
455static void DispatchPlatformMessage(JNIEnv* env,
456 jobject jcaller,
457 jlong shell_holder,
458 jstring channel,
459 jobject message,
460 jint position,
461 jint responseId) {
462 ANDROID_SHELL_HOLDER->GetPlatformView()->DispatchPlatformMessage(
463 env, //
465 message, //
466 position, //
467 responseId //
468 );
469}
470
471static void DispatchEmptyPlatformMessage(JNIEnv* env,
472 jobject jcaller,
473 jlong shell_holder,
474 jstring channel,
475 jint responseId) {
476 ANDROID_SHELL_HOLDER->GetPlatformView()->DispatchEmptyPlatformMessage(
477 env, //
479 responseId //
480 );
481}
482
483static void CleanupMessageData(JNIEnv* env,
484 jobject jcaller,
485 jlong message_data) {
486 // Called from any thread.
487 free(reinterpret_cast<void*>(message_data));
488}
489
490static void DispatchPointerDataPacket(JNIEnv* env,
491 jobject jcaller,
492 jlong shell_holder,
493 jobject buffer,
494 jint position) {
495 uint8_t* data = static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer));
496 auto packet = std::make_unique<flutter::PointerDataPacket>(data, position);
497 ANDROID_SHELL_HOLDER->GetPlatformView()->DispatchPointerDataPacket(
498 std::move(packet));
499}
500
501static void DispatchSemanticsAction(JNIEnv* env,
502 jobject jcaller,
503 jlong shell_holder,
504 jint id,
505 jint action,
506 jobject args,
507 jint args_position) {
508 ANDROID_SHELL_HOLDER->GetPlatformView()->DispatchSemanticsAction(
509 env, //
510 id, //
511 action, //
512 args, //
513 args_position //
514 );
515}
516
517static void SetSemanticsEnabled(JNIEnv* env,
518 jobject jcaller,
519 jlong shell_holder,
520 jboolean enabled) {
521 ANDROID_SHELL_HOLDER->GetPlatformView()->SetSemanticsEnabled(enabled);
522}
523
524static void SetAccessibilityFeatures(JNIEnv* env,
525 jobject jcaller,
526 jlong shell_holder,
527 jint flags) {
528 ANDROID_SHELL_HOLDER->GetPlatformView()->SetAccessibilityFeatures(flags);
529}
530
531static jboolean GetIsSoftwareRendering(JNIEnv* env, jobject jcaller) {
532 return FlutterMain::Get().GetSettings().enable_software_rendering;
533}
534
535static void RegisterTexture(JNIEnv* env,
536 jobject jcaller,
537 jlong shell_holder,
538 jlong texture_id,
539 jobject surface_texture) {
540 ANDROID_SHELL_HOLDER->GetPlatformView()->RegisterExternalTexture(
541 static_cast<int64_t>(texture_id), //
542 fml::jni::ScopedJavaGlobalRef<jobject>(env, surface_texture) //
543 );
544}
545
546static void RegisterImageTexture(JNIEnv* env,
547 jobject jcaller,
548 jlong shell_holder,
549 jlong texture_id,
550 jobject image_texture_entry,
551 jboolean reset_on_background) {
552 ImageExternalTexture::ImageLifecycle lifecycle =
553 reset_on_background ? ImageExternalTexture::ImageLifecycle::kReset
554 : ImageExternalTexture::ImageLifecycle::kKeepAlive;
555
556 ANDROID_SHELL_HOLDER->GetPlatformView()->RegisterImageTexture(
557 static_cast<int64_t>(texture_id), //
558 fml::jni::ScopedJavaGlobalRef<jobject>(env, image_texture_entry), //
559 lifecycle //
560 );
561}
562
563static void UnregisterTexture(JNIEnv* env,
564 jobject jcaller,
565 jlong shell_holder,
566 jlong texture_id) {
567 ANDROID_SHELL_HOLDER->GetPlatformView()->UnregisterTexture(
568 static_cast<int64_t>(texture_id));
569}
570
571static void MarkTextureFrameAvailable(JNIEnv* env,
572 jobject jcaller,
573 jlong shell_holder,
574 jlong texture_id) {
575 ANDROID_SHELL_HOLDER->GetPlatformView()->MarkTextureFrameAvailable(
576 static_cast<int64_t>(texture_id));
577}
578
579static void ScheduleFrame(JNIEnv* env, jobject jcaller, jlong shell_holder) {
580 ANDROID_SHELL_HOLDER->GetPlatformView()->ScheduleFrame();
581}
582
583static void InvokePlatformMessageResponseCallback(JNIEnv* env,
584 jobject jcaller,
585 jlong shell_holder,
586 jint responseId,
587 jobject message,
588 jint position) {
589 uint8_t* response_data =
590 static_cast<uint8_t*>(env->GetDirectBufferAddress(message));
591 FML_DCHECK(response_data != nullptr);
592 auto mapping = std::make_unique<fml::MallocMapping>(
593 fml::MallocMapping::Copy(response_data, response_data + position));
594 ANDROID_SHELL_HOLDER->GetPlatformMessageHandler()
595 ->InvokePlatformMessageResponseCallback(responseId, std::move(mapping));
596}
597
598static void InvokePlatformMessageEmptyResponseCallback(JNIEnv* env,
599 jobject jcaller,
600 jlong shell_holder,
601 jint responseId) {
602 ANDROID_SHELL_HOLDER->GetPlatformMessageHandler()
603 ->InvokePlatformMessageEmptyResponseCallback(responseId);
604}
605
606static void NotifyLowMemoryWarning(JNIEnv* env,
607 jobject obj,
608 jlong shell_holder) {
609 ANDROID_SHELL_HOLDER->NotifyLowMemoryWarning();
610}
611
612static jboolean FlutterTextUtilsIsEmoji(JNIEnv* env,
613 jobject obj,
614 jint codePoint) {
615 return u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI);
616}
617
618static jboolean FlutterTextUtilsIsEmojiModifier(JNIEnv* env,
619 jobject obj,
620 jint codePoint) {
621 return u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI_MODIFIER);
622}
623
624static jboolean FlutterTextUtilsIsEmojiModifierBase(JNIEnv* env,
625 jobject obj,
626 jint codePoint) {
627 return u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI_MODIFIER_BASE);
628}
629
630static jboolean FlutterTextUtilsIsVariationSelector(JNIEnv* env,
631 jobject obj,
632 jint codePoint) {
633 return u_hasBinaryProperty(codePoint, UProperty::UCHAR_VARIATION_SELECTOR);
634}
635
636static jboolean FlutterTextUtilsIsRegionalIndicator(JNIEnv* env,
637 jobject obj,
638 jint codePoint) {
639 return u_hasBinaryProperty(codePoint, UProperty::UCHAR_REGIONAL_INDICATOR);
640}
641
642static void LoadLoadingUnitFailure(intptr_t loading_unit_id,
643 const std::string& message,
644 bool transient) {
645 // TODO(garyq): Implement
646}
647
648static void DeferredComponentInstallFailure(JNIEnv* env,
649 jobject obj,
650 jint jLoadingUnitId,
651 jstring jError,
652 jboolean jTransient) {
653 LoadLoadingUnitFailure(static_cast<intptr_t>(jLoadingUnitId),
654 fml::jni::JavaStringToString(env, jError),
655 static_cast<bool>(jTransient));
656}
657
658static void LoadDartDeferredLibrary(JNIEnv* env,
659 jobject obj,
660 jlong shell_holder,
661 jint jLoadingUnitId,
662 jobjectArray jSearchPaths) {
663 // Convert java->c++
664 intptr_t loading_unit_id = static_cast<intptr_t>(jLoadingUnitId);
665 std::vector<std::string> search_paths =
666 fml::jni::StringArrayToVector(env, jSearchPaths);
667
668 // Use dlopen here to directly check if handle is nullptr before creating a
669 // NativeLibrary.
670 void* handle = nullptr;
671 while (handle == nullptr && !search_paths.empty()) {
672 std::string path = search_paths.back();
673 handle = ::dlopen(path.c_str(), RTLD_NOW);
674 search_paths.pop_back();
675 }
676 if (handle == nullptr) {
677 LoadLoadingUnitFailure(loading_unit_id,
678 "No lib .so found for provided search paths.", true);
679 return;
680 }
683
684 // Resolve symbols.
685 std::unique_ptr<const fml::SymbolMapping> data_mapping =
686 std::make_unique<const fml::SymbolMapping>(
687 native_lib, DartSnapshot::kIsolateDataSymbol);
688 std::unique_ptr<const fml::SymbolMapping> instructions_mapping =
689 std::make_unique<const fml::SymbolMapping>(
690 native_lib, DartSnapshot::kIsolateInstructionsSymbol);
691
692 ANDROID_SHELL_HOLDER->GetPlatformView()->LoadDartDeferredLibrary(
693 loading_unit_id, std::move(data_mapping),
694 std::move(instructions_mapping));
695}
696
697static void UpdateJavaAssetManager(JNIEnv* env,
698 jobject obj,
699 jlong shell_holder,
700 jobject jAssetManager,
701 jstring jAssetBundlePath) {
702 auto asset_resolver = std::make_unique<flutter::APKAssetProvider>(
703 env, // jni environment
704 jAssetManager, // asset manager
705 fml::jni::JavaStringToString(env, jAssetBundlePath)); // apk asset dir
706
707 ANDROID_SHELL_HOLDER->GetPlatformView()->UpdateAssetResolverByType(
708 std::move(asset_resolver),
709 AssetResolver::AssetResolverType::kApkAssetProvider);
710}
711
712bool RegisterApi(JNIEnv* env) {
713 static const JNINativeMethod flutter_jni_methods[] = {
714 // Start of methods from FlutterJNI
715 {
716 .name = "nativeAttach",
717 .signature = "(Lio/flutter/embedding/engine/FlutterJNI;)J",
718 .fnPtr = reinterpret_cast<void*>(&AttachJNI),
719 },
720 {
721 .name = "nativeDestroy",
722 .signature = "(J)V",
723 .fnPtr = reinterpret_cast<void*>(&DestroyJNI),
724 },
725 {
726 .name = "nativeSpawn",
727 .signature = "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/"
728 "String;Ljava/util/List;J)Lio/flutter/"
729 "embedding/engine/FlutterJNI;",
730 .fnPtr = reinterpret_cast<void*>(&SpawnJNI),
731 },
732 {
733 .name = "nativeRunBundleAndSnapshotFromLibrary",
734 .signature = "(JLjava/lang/String;Ljava/lang/String;"
735 "Ljava/lang/String;Landroid/content/res/"
736 "AssetManager;Ljava/util/List;J)V",
737 .fnPtr = reinterpret_cast<void*>(&RunBundleAndSnapshotFromLibrary),
738 },
739 {
740 .name = "nativeDispatchEmptyPlatformMessage",
741 .signature = "(JLjava/lang/String;I)V",
742 .fnPtr = reinterpret_cast<void*>(&DispatchEmptyPlatformMessage),
743 },
744 {
745 .name = "nativeCleanupMessageData",
746 .signature = "(J)V",
747 .fnPtr = reinterpret_cast<void*>(&CleanupMessageData),
748 },
749 {
750 .name = "nativeDispatchPlatformMessage",
751 .signature = "(JLjava/lang/String;Ljava/nio/ByteBuffer;II)V",
752 .fnPtr = reinterpret_cast<void*>(&DispatchPlatformMessage),
753 },
754 {
755 .name = "nativeInvokePlatformMessageResponseCallback",
756 .signature = "(JILjava/nio/ByteBuffer;I)V",
757 .fnPtr =
758 reinterpret_cast<void*>(&InvokePlatformMessageResponseCallback),
759 },
760 {
761 .name = "nativeInvokePlatformMessageEmptyResponseCallback",
762 .signature = "(JI)V",
763 .fnPtr = reinterpret_cast<void*>(
765 },
766 {
767 .name = "nativeNotifyLowMemoryWarning",
768 .signature = "(J)V",
769 .fnPtr = reinterpret_cast<void*>(&NotifyLowMemoryWarning),
770 },
771
772 // Start of methods from FlutterView
773 {
774 .name = "nativeGetBitmap",
775 .signature = "(J)Landroid/graphics/Bitmap;",
776 .fnPtr = reinterpret_cast<void*>(&GetBitmap),
777 },
778 {
779 .name = "nativeSurfaceCreated",
780 .signature = "(JLandroid/view/Surface;)V",
781 .fnPtr = reinterpret_cast<void*>(&SurfaceCreated),
782 },
783 {
784 .name = "nativeSurfaceWindowChanged",
785 .signature = "(JLandroid/view/Surface;)V",
786 .fnPtr = reinterpret_cast<void*>(&SurfaceWindowChanged),
787 },
788 {
789 .name = "nativeSurfaceChanged",
790 .signature = "(JII)V",
791 .fnPtr = reinterpret_cast<void*>(&SurfaceChanged),
792 },
793 {
794 .name = "nativeSurfaceDestroyed",
795 .signature = "(J)V",
796 .fnPtr = reinterpret_cast<void*>(&SurfaceDestroyed),
797 },
798 {
799 .name = "nativeSetViewportMetrics",
800 .signature = "(JFIIIIIIIIIIIIIII[I[I[I)V",
801 .fnPtr = reinterpret_cast<void*>(&SetViewportMetrics),
802 },
803 {
804 .name = "nativeDispatchPointerDataPacket",
805 .signature = "(JLjava/nio/ByteBuffer;I)V",
806 .fnPtr = reinterpret_cast<void*>(&DispatchPointerDataPacket),
807 },
808 {
809 .name = "nativeDispatchSemanticsAction",
810 .signature = "(JIILjava/nio/ByteBuffer;I)V",
811 .fnPtr = reinterpret_cast<void*>(&DispatchSemanticsAction),
812 },
813 {
814 .name = "nativeSetSemanticsEnabled",
815 .signature = "(JZ)V",
816 .fnPtr = reinterpret_cast<void*>(&SetSemanticsEnabled),
817 },
818 {
819 .name = "nativeSetAccessibilityFeatures",
820 .signature = "(JI)V",
821 .fnPtr = reinterpret_cast<void*>(&SetAccessibilityFeatures),
822 },
823 {
824 .name = "nativeGetIsSoftwareRenderingEnabled",
825 .signature = "()Z",
826 .fnPtr = reinterpret_cast<void*>(&GetIsSoftwareRendering),
827 },
828 {
829 .name = "nativeRegisterTexture",
830 .signature = "(JJLjava/lang/ref/"
831 "WeakReference;)V",
832 .fnPtr = reinterpret_cast<void*>(&RegisterTexture),
833 },
834 {
835 .name = "nativeRegisterImageTexture",
836 .signature = "(JJLjava/lang/ref/"
837 "WeakReference;Z)V",
838 .fnPtr = reinterpret_cast<void*>(&RegisterImageTexture),
839 },
840 {
841 .name = "nativeMarkTextureFrameAvailable",
842 .signature = "(JJ)V",
843 .fnPtr = reinterpret_cast<void*>(&MarkTextureFrameAvailable),
844 },
845 {
846 .name = "nativeScheduleFrame",
847 .signature = "(J)V",
848 .fnPtr = reinterpret_cast<void*>(&ScheduleFrame),
849 },
850 {
851 .name = "nativeUnregisterTexture",
852 .signature = "(JJ)V",
853 .fnPtr = reinterpret_cast<void*>(&UnregisterTexture),
854 },
855 // Methods for Dart callback functionality.
856 {
857 .name = "nativeLookupCallbackInformation",
858 .signature = "(J)Lio/flutter/view/FlutterCallbackInformation;",
859 .fnPtr = reinterpret_cast<void*>(&LookupCallbackInformation),
860 },
861
862 // Start of methods for FlutterTextUtils
863 {
864 .name = "nativeFlutterTextUtilsIsEmoji",
865 .signature = "(I)Z",
866 .fnPtr = reinterpret_cast<void*>(&FlutterTextUtilsIsEmoji),
867 },
868 {
869 .name = "nativeFlutterTextUtilsIsEmojiModifier",
870 .signature = "(I)Z",
871 .fnPtr = reinterpret_cast<void*>(&FlutterTextUtilsIsEmojiModifier),
872 },
873 {
874 .name = "nativeFlutterTextUtilsIsEmojiModifierBase",
875 .signature = "(I)Z",
876 .fnPtr =
877 reinterpret_cast<void*>(&FlutterTextUtilsIsEmojiModifierBase),
878 },
879 {
880 .name = "nativeFlutterTextUtilsIsVariationSelector",
881 .signature = "(I)Z",
882 .fnPtr =
883 reinterpret_cast<void*>(&FlutterTextUtilsIsVariationSelector),
884 },
885 {
886 .name = "nativeFlutterTextUtilsIsRegionalIndicator",
887 .signature = "(I)Z",
888 .fnPtr =
889 reinterpret_cast<void*>(&FlutterTextUtilsIsRegionalIndicator),
890 },
891 {
892 .name = "nativeLoadDartDeferredLibrary",
893 .signature = "(JI[Ljava/lang/String;)V",
894 .fnPtr = reinterpret_cast<void*>(&LoadDartDeferredLibrary),
895 },
896 {
897 .name = "nativeUpdateJavaAssetManager",
898 .signature =
899 "(JLandroid/content/res/AssetManager;Ljava/lang/String;)V",
900 .fnPtr = reinterpret_cast<void*>(&UpdateJavaAssetManager),
901 },
902 {
903 .name = "nativeDeferredComponentInstallFailure",
904 .signature = "(ILjava/lang/String;Z)V",
905 .fnPtr = reinterpret_cast<void*>(&DeferredComponentInstallFailure),
906 },
907 {
908 .name = "nativeUpdateDisplayMetrics",
909 .signature = "(J)V",
910 .fnPtr = reinterpret_cast<void*>(&UpdateDisplayMetrics),
911 },
912 {
913 .name = "nativeIsSurfaceControlEnabled",
914 .signature = "(J)Z",
915 .fnPtr = reinterpret_cast<void*>(&IsSurfaceControlEnabled),
916 }};
917
918 if (env->RegisterNatives(g_flutter_jni_class->obj(), flutter_jni_methods,
919 std::size(flutter_jni_methods)) != 0) {
920 FML_LOG(ERROR) << "Failed to RegisterNatives with FlutterJNI";
921 return false;
922 }
923
924 g_jni_shell_holder_field = env->GetFieldID(
925 g_flutter_jni_class->obj(), "nativeShellHolderId", "Ljava/lang/Long;");
926
927 if (g_jni_shell_holder_field == nullptr) {
928 FML_LOG(ERROR) << "Could not locate FlutterJNI's nativeShellHolderId field";
929 return false;
930 }
931
933 env->GetMethodID(g_flutter_jni_class->obj(), "<init>", "()V");
934
935 if (g_jni_constructor == nullptr) {
936 FML_LOG(ERROR) << "Could not locate FlutterJNI's constructor";
937 return false;
938 }
939
940 g_long_constructor = env->GetStaticMethodID(g_java_long_class->obj(),
941 "valueOf", "(J)Ljava/lang/Long;");
942 if (g_long_constructor == nullptr) {
943 FML_LOG(ERROR) << "Could not locate Long's constructor";
944 return false;
945 }
946
948
949 fml::jni::ScopedJavaLocalRef<jclass> overlay_surface_class(
950 env, env->FindClass("io/flutter/embedding/engine/FlutterOverlaySurface"));
951 if (overlay_surface_class.is_null()) {
952 FML_LOG(ERROR) << "Could not locate FlutterOverlaySurface class";
953 return false;
954 }
956 env->GetMethodID(overlay_surface_class.obj(), "getId", "()I");
957 if (g_overlay_surface_id_method == nullptr) {
958 FML_LOG(ERROR) << "Could not locate FlutterOverlaySurface#getId() method";
959 return false;
960 }
961 g_overlay_surface_surface_method = env->GetMethodID(
962 overlay_surface_class.obj(), "getSurface", "()Landroid/view/Surface;");
963 if (g_overlay_surface_surface_method == nullptr) {
964 FML_LOG(ERROR)
965 << "Could not locate FlutterOverlaySurface#getSurface() method";
966 return false;
967 }
968
970 env, env->FindClass("android/graphics/Bitmap"));
971 if (g_bitmap_class->is_null()) {
972 FML_LOG(ERROR) << "Could not locate Bitmap Class";
973 return false;
974 }
975
976 g_bitmap_create_bitmap_method = env->GetStaticMethodID(
977 g_bitmap_class->obj(), "createBitmap",
978 "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
979 if (g_bitmap_create_bitmap_method == nullptr) {
980 FML_LOG(ERROR) << "Could not locate Bitmap.createBitmap method";
981 return false;
982 }
983
985 g_bitmap_class->obj(), "copyPixelsFromBuffer", "(Ljava/nio/Buffer;)V");
986 if (g_bitmap_copy_pixels_from_buffer_method == nullptr) {
987 FML_LOG(ERROR) << "Could not locate Bitmap.copyPixelsFromBuffer method";
988 return false;
989 }
990
992 env, env->FindClass("android/graphics/Bitmap$Config"));
993 if (g_bitmap_config_class->is_null()) {
994 FML_LOG(ERROR) << "Could not locate Bitmap.Config Class";
995 return false;
996 }
997
998 g_bitmap_config_value_of = env->GetStaticMethodID(
999 g_bitmap_config_class->obj(), "valueOf",
1000 "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");
1001 if (g_bitmap_config_value_of == nullptr) {
1002 FML_LOG(ERROR) << "Could not locate Bitmap.Config.valueOf method";
1003 return false;
1004 }
1005
1006 return true;
1007}
1008
1009bool PlatformViewAndroid::Register(JNIEnv* env) {
1010 if (env == nullptr) {
1011 FML_LOG(ERROR) << "No JNIEnv provided";
1012 return false;
1013 }
1014
1016 env, env->FindClass("io/flutter/view/FlutterCallbackInformation"));
1017 if (g_flutter_callback_info_class->is_null()) {
1018 FML_LOG(ERROR) << "Could not locate FlutterCallbackInformation class";
1019 return false;
1020 }
1021
1022 g_flutter_callback_info_constructor = env->GetMethodID(
1023 g_flutter_callback_info_class->obj(), "<init>",
1024 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
1025 if (g_flutter_callback_info_constructor == nullptr) {
1026 FML_LOG(ERROR) << "Could not locate FlutterCallbackInformation constructor";
1027 return false;
1028 }
1029
1031 env, env->FindClass("io/flutter/embedding/engine/FlutterJNI"));
1032 if (g_flutter_jni_class->is_null()) {
1033 FML_LOG(ERROR) << "Failed to find FlutterJNI Class.";
1034 return false;
1035 }
1036
1038 env,
1039 env->FindClass(
1040 "io/flutter/embedding/engine/mutatorsstack/FlutterMutatorsStack"));
1041 if (g_mutators_stack_class == nullptr) {
1042 FML_LOG(ERROR) << "Could not locate FlutterMutatorsStack";
1043 return false;
1044 }
1045
1047 env->GetMethodID(g_mutators_stack_class->obj(), "<init>", "()V");
1048 if (g_mutators_stack_init_method == nullptr) {
1049 FML_LOG(ERROR) << "Could not locate FlutterMutatorsStack.init method";
1050 return false;
1051 }
1052
1054 env->GetMethodID(g_mutators_stack_class->obj(), "pushTransform", "([F)V");
1055 if (g_mutators_stack_push_transform_method == nullptr) {
1056 FML_LOG(ERROR)
1057 << "Could not locate FlutterMutatorsStack.pushTransform method";
1058 return false;
1059 }
1060
1061 g_mutators_stack_push_cliprect_method = env->GetMethodID(
1062 g_mutators_stack_class->obj(), "pushClipRect", "(IIII)V");
1063 if (g_mutators_stack_push_cliprect_method == nullptr) {
1064 FML_LOG(ERROR)
1065 << "Could not locate FlutterMutatorsStack.pushClipRect method";
1066 return false;
1067 }
1068
1069 g_mutators_stack_push_cliprrect_method = env->GetMethodID(
1070 g_mutators_stack_class->obj(), "pushClipRRect", "(IIII[F)V");
1071 if (g_mutators_stack_push_cliprrect_method == nullptr) {
1072 FML_LOG(ERROR)
1073 << "Could not locate FlutterMutatorsStack.pushClipRRect method";
1074 return false;
1075 }
1076
1078 env->GetMethodID(g_mutators_stack_class->obj(), "pushOpacity", "(F)V");
1079 if (g_mutators_stack_push_opacity_method == nullptr) {
1080 FML_LOG(ERROR)
1081 << "Could not locate FlutterMutatorsStack.pushOpacity method";
1082 return false;
1083 }
1084
1086 env->GetMethodID(g_mutators_stack_class->obj(), "pushClipPath",
1087 "(Landroid/graphics/Path;)V");
1088 if (g_mutators_stack_push_clippath_method == nullptr) {
1089 FML_LOG(ERROR)
1090 << "Could not locate FlutterMutatorsStack.pushClipPath method";
1091 return false;
1092 }
1093
1095 env, env->FindClass("java/lang/ref/WeakReference"));
1096 if (g_java_weak_reference_class->is_null()) {
1097 FML_LOG(ERROR) << "Could not locate WeakReference class";
1098 return false;
1099 }
1100
1101 g_java_weak_reference_get_method = env->GetMethodID(
1102 g_java_weak_reference_class->obj(), "get", "()Ljava/lang/Object;");
1103 if (g_java_weak_reference_get_method == nullptr) {
1104 FML_LOG(ERROR) << "Could not locate WeakReference.get method";
1105 return false;
1106 }
1107
1109 env, env->FindClass(
1110 "io/flutter/embedding/engine/renderer/SurfaceTextureWrapper"));
1111 if (g_texture_wrapper_class->is_null()) {
1112 FML_LOG(ERROR) << "Could not locate SurfaceTextureWrapper class";
1113 return false;
1114 }
1115
1116 g_attach_to_gl_context_method = env->GetMethodID(
1117 g_texture_wrapper_class->obj(), "attachToGLContext", "(I)V");
1118
1119 if (g_attach_to_gl_context_method == nullptr) {
1120 FML_LOG(ERROR) << "Could not locate attachToGlContext method";
1121 return false;
1122 }
1123
1125 env->GetMethodID(g_texture_wrapper_class->obj(), "shouldUpdate", "()Z");
1126
1127 if (g_surface_texture_wrapper_should_update == nullptr) {
1128 FML_LOG(ERROR)
1129 << "Could not locate SurfaceTextureWrapper.shouldUpdate method";
1130 return false;
1131 }
1132
1134 env->GetMethodID(g_texture_wrapper_class->obj(), "updateTexImage", "()V");
1135
1136 if (g_update_tex_image_method == nullptr) {
1137 FML_LOG(ERROR) << "Could not locate updateTexImage method";
1138 return false;
1139 }
1140
1141 g_get_transform_matrix_method = env->GetMethodID(
1142 g_texture_wrapper_class->obj(), "getTransformMatrix", "([F)V");
1143
1144 if (g_get_transform_matrix_method == nullptr) {
1145 FML_LOG(ERROR) << "Could not locate getTransformMatrix method";
1146 return false;
1147 }
1148
1149 g_detach_from_gl_context_method = env->GetMethodID(
1150 g_texture_wrapper_class->obj(), "detachFromGLContext", "()V");
1151
1152 if (g_detach_from_gl_context_method == nullptr) {
1153 FML_LOG(ERROR) << "Could not locate detachFromGlContext method";
1154 return false;
1155 }
1158 env, env->FindClass("io/flutter/view/TextureRegistry$ImageConsumer"));
1160 FML_LOG(ERROR) << "Could not locate TextureRegistry.ImageConsumer class";
1161 return false;
1162 }
1163
1165 env->GetMethodID(g_image_consumer_texture_registry_interface->obj(),
1166 "acquireLatestImage", "()Landroid/media/Image;");
1167 if (g_acquire_latest_image_method == nullptr) {
1168 FML_LOG(ERROR) << "Could not locate acquireLatestImage on "
1169 "TextureRegistry.ImageConsumer class";
1170 return false;
1171 }
1172
1174 env, env->FindClass("android/media/Image"));
1175 if (g_image_class->is_null()) {
1176 FML_LOG(ERROR) << "Could not locate Image class";
1177 return false;
1178 }
1179
1180 // Ensure we don't have any pending exceptions.
1182
1184 env->GetMethodID(g_image_class->obj(), "getHardwareBuffer",
1185 "()Landroid/hardware/HardwareBuffer;");
1186
1187 if (g_image_get_hardware_buffer_method == nullptr) {
1188 // Continue on as this method may not exist at API <= 29.
1189 fml::jni::ClearException(env, true);
1190 }
1191
1192 g_image_close_method = env->GetMethodID(g_image_class->obj(), "close", "()V");
1193
1194 if (g_image_close_method == nullptr) {
1195 FML_LOG(ERROR) << "Could not locate close on Image class";
1196 return false;
1197 }
1198
1199 // Ensure we don't have any pending exceptions.
1202 env, env->FindClass("android/hardware/HardwareBuffer"));
1203
1204 if (!g_hardware_buffer_class->is_null()) {
1206 env->GetMethodID(g_hardware_buffer_class->obj(), "close", "()V");
1207 if (g_hardware_buffer_close_method == nullptr) {
1208 // Continue on as this class may not exist at API <= 26.
1209 fml::jni::ClearException(env, true);
1210 }
1211 } else {
1212 // Continue on as this class may not exist at API <= 26.
1213 fml::jni::ClearException(env, true);
1214 }
1215
1217 g_flutter_jni_class->obj(), "computePlatformResolvedLocale",
1218 "([Ljava/lang/String;)[Ljava/lang/String;");
1219
1220 if (g_compute_platform_resolved_locale_method == nullptr) {
1221 FML_LOG(ERROR) << "Could not locate computePlatformResolvedLocale method";
1222 return false;
1223 }
1224
1225 g_request_dart_deferred_library_method = env->GetMethodID(
1226 g_flutter_jni_class->obj(), "requestDartDeferredLibrary", "(I)V");
1227
1228 if (g_request_dart_deferred_library_method == nullptr) {
1229 FML_LOG(ERROR) << "Could not locate requestDartDeferredLibrary method";
1230 return false;
1231 }
1232
1234 env, env->FindClass("java/lang/Long"));
1235 if (g_java_long_class->is_null()) {
1236 FML_LOG(ERROR) << "Could not locate java.lang.Long class";
1237 return false;
1238 }
1239
1240 // Android path class and methods.
1242 env, env->FindClass("android/graphics/Path"));
1243 if (path_class->is_null()) {
1244 FML_LOG(ERROR) << "Could not locate android.graphics.Path class";
1245 return false;
1246 }
1247
1248 path_constructor = env->GetMethodID(path_class->obj(), "<init>", "()V");
1249 if (path_constructor == nullptr) {
1250 FML_LOG(ERROR) << "Could not locate android.graphics.Path constructor";
1251 return false;
1252 }
1253
1254 path_set_fill_type_method = env->GetMethodID(
1255 path_class->obj(), "setFillType", "(Landroid/graphics/Path$FillType;)V");
1256 if (path_set_fill_type_method == nullptr) {
1257 FML_LOG(ERROR)
1258 << "Could not locate android.graphics.Path.setFillType method";
1259 return false;
1260 }
1261
1262 path_move_to_method = env->GetMethodID(path_class->obj(), "moveTo", "(FF)V");
1263 if (path_move_to_method == nullptr) {
1264 FML_LOG(ERROR) << "Could not locate android.graphics.Path.moveTo method";
1265 return false;
1266 }
1267 path_line_to_method = env->GetMethodID(path_class->obj(), "lineTo", "(FF)V");
1268 if (path_line_to_method == nullptr) {
1269 FML_LOG(ERROR) << "Could not locate android.graphics.Path.lineTo method";
1270 return false;
1271 }
1273 env->GetMethodID(path_class->obj(), "quadTo", "(FFFF)V");
1274 if (path_quad_to_method == nullptr) {
1275 FML_LOG(ERROR) << "Could not locate android.graphics.Path.quadTo method";
1276 return false;
1277 }
1279 env->GetMethodID(path_class->obj(), "cubicTo", "(FFFFFF)V");
1280 if (path_cubic_to_method == nullptr) {
1281 FML_LOG(ERROR) << "Could not locate android.graphics.Path.cubicTo method";
1282 return false;
1283 }
1284 // Ensure we don't have any pending exceptions.
1286
1288 env->GetMethodID(path_class->obj(), "conicTo", "(FFFFF)V");
1289 if (path_conic_to_method == nullptr) {
1290 // Continue on as this method may not exist at API <= 34.
1291 fml::jni::ClearException(env, true);
1292 }
1293 path_close_method = env->GetMethodID(path_class->obj(), "close", "()V");
1294 if (path_close_method == nullptr) {
1295 FML_LOG(ERROR) << "Could not locate android.graphics.Path.close method";
1296 return false;
1297 }
1298
1300 env, env->FindClass("android/graphics/Path$FillType"));
1301 if (g_path_fill_type_class->is_null()) {
1302 FML_LOG(ERROR) << "Could not locate android.graphics.Path$FillType class";
1303 return false;
1304 }
1305
1307 env->GetStaticFieldID(g_path_fill_type_class->obj(), "WINDING",
1308 "Landroid/graphics/Path$FillType;");
1309 if (g_path_fill_type_winding_field == nullptr) {
1310 FML_LOG(ERROR) << "Could not locate Path.FillType.WINDING field";
1311 return false;
1312 }
1313
1315 env->GetStaticFieldID(g_path_fill_type_class->obj(), "EVEN_ODD",
1316 "Landroid/graphics/Path$FillType;");
1317 if (g_path_fill_type_even_odd_field == nullptr) {
1318 FML_LOG(ERROR) << "Could not locate Path.FillType.EVEN_ODD field";
1319 return false;
1320 }
1321
1322 return RegisterApi(env);
1323}
1324
1325PlatformViewAndroidJNIImpl::PlatformViewAndroidJNIImpl(
1326 const fml::jni::JavaObjectWeakGlobalRef& java_object)
1327 : java_object_(java_object) {}
1328
1329PlatformViewAndroidJNIImpl::~PlatformViewAndroidJNIImpl() = default;
1330
1331void PlatformViewAndroidJNIImpl::FlutterViewHandlePlatformMessage(
1332 std::unique_ptr<flutter::PlatformMessage> message,
1333 int responseId) {
1334 // Called from any thread.
1335 JNIEnv* env = fml::jni::AttachCurrentThread();
1336
1337 auto java_object = java_object_.get(env);
1338 if (java_object.is_null()) {
1339 return;
1340 }
1341
1343 fml::jni::StringToJavaString(env, message->channel());
1344
1345 if (message->hasData()) {
1347 env, env->NewDirectByteBuffer(
1348 const_cast<uint8_t*>(message->data().GetMapping()),
1349 message->data().GetSize()));
1350 // Message data is deleted in CleanupMessageData.
1351 fml::MallocMapping mapping = message->releaseData();
1352 env->CallVoidMethod(java_object.obj(), g_handle_platform_message_method,
1353 java_channel.obj(), message_array.obj(), responseId,
1354 reinterpret_cast<jlong>(mapping.Release()));
1355 } else {
1356 env->CallVoidMethod(java_object.obj(), g_handle_platform_message_method,
1357 java_channel.obj(), nullptr, responseId, nullptr);
1358 }
1359
1361}
1362
1363void PlatformViewAndroidJNIImpl::FlutterViewSetApplicationLocale(
1364 std::string locale) {
1365 JNIEnv* env = fml::jni::AttachCurrentThread();
1366
1367 auto java_object = java_object_.get(env);
1368 if (java_object.is_null()) {
1369 return;
1370 }
1371
1373 fml::jni::StringToJavaString(env, locale);
1374
1375 env->CallVoidMethod(java_object.obj(), g_set_application_locale_method,
1376 jlocale.obj());
1377
1379}
1380
1381void PlatformViewAndroidJNIImpl::FlutterViewHandlePlatformMessageResponse(
1382 int responseId,
1383 std::unique_ptr<fml::Mapping> data) {
1384 // We are on the platform thread. Attempt to get the strong reference to
1385 // the Java object.
1386 JNIEnv* env = fml::jni::AttachCurrentThread();
1387
1388 auto java_object = java_object_.get(env);
1389 if (java_object.is_null()) {
1390 // The Java object was collected before this message response got to
1391 // it. Drop the response on the floor.
1392 return;
1393 }
1394 if (data == nullptr) { // Empty response.
1395 env->CallVoidMethod(java_object.obj(),
1396 g_handle_platform_message_response_method, responseId,
1397 nullptr);
1398 } else {
1399 // Convert the vector to a Java byte array.
1401 env, env->NewDirectByteBuffer(const_cast<uint8_t*>(data->GetMapping()),
1402 data->GetSize()));
1403
1404 env->CallVoidMethod(java_object.obj(),
1405 g_handle_platform_message_response_method, responseId,
1406 data_array.obj());
1407 }
1408
1410}
1411
1412double PlatformViewAndroidJNIImpl::FlutterViewGetScaledFontSize(
1413 double font_size,
1414 int configuration_id) const {
1415 JNIEnv* env = fml::jni::AttachCurrentThread();
1416
1417 auto java_object = java_object_.get(env);
1418 if (java_object.is_null()) {
1419 return -3;
1420 }
1421
1422 const jfloat scaledSize = env->CallFloatMethod(
1423 java_object.obj(), g_get_scaled_font_size_method,
1424 static_cast<jfloat>(font_size), static_cast<jint>(configuration_id));
1426 return static_cast<double>(scaledSize);
1427}
1428
1429void PlatformViewAndroidJNIImpl::FlutterViewUpdateSemantics(
1430 std::vector<uint8_t> buffer,
1431 std::vector<std::string> strings,
1432 std::vector<std::vector<uint8_t>> string_attribute_args) {
1433 JNIEnv* env = fml::jni::AttachCurrentThread();
1434
1435 auto java_object = java_object_.get(env);
1436 if (java_object.is_null()) {
1437 return;
1438 }
1439
1441 env, env->NewDirectByteBuffer(buffer.data(), buffer.size()));
1443 fml::jni::VectorToStringArray(env, strings);
1444 fml::jni::ScopedJavaLocalRef<jobjectArray> jstring_attribute_args =
1445 fml::jni::VectorToBufferArray(env, string_attribute_args);
1446
1447 env->CallVoidMethod(java_object.obj(), g_update_semantics_method,
1448 direct_buffer.obj(), jstrings.obj(),
1449 jstring_attribute_args.obj());
1450
1452}
1453
1454void PlatformViewAndroidJNIImpl::FlutterViewUpdateCustomAccessibilityActions(
1455 std::vector<uint8_t> actions_buffer,
1456 std::vector<std::string> strings) {
1457 JNIEnv* env = fml::jni::AttachCurrentThread();
1458
1459 auto java_object = java_object_.get(env);
1460 if (java_object.is_null()) {
1461 return;
1462 }
1463
1464 fml::jni::ScopedJavaLocalRef<jobject> direct_actions_buffer(
1465 env,
1466 env->NewDirectByteBuffer(actions_buffer.data(), actions_buffer.size()));
1467
1469 fml::jni::VectorToStringArray(env, strings);
1470
1471 env->CallVoidMethod(java_object.obj(),
1472 g_update_custom_accessibility_actions_method,
1473 direct_actions_buffer.obj(), jstrings.obj());
1474
1476}
1477
1478void PlatformViewAndroidJNIImpl::FlutterViewOnFirstFrame() {
1479 JNIEnv* env = fml::jni::AttachCurrentThread();
1480
1481 auto java_object = java_object_.get(env);
1482 if (java_object.is_null()) {
1483 return;
1484 }
1485
1486 env->CallVoidMethod(java_object.obj(), g_on_first_frame_method);
1487
1489}
1490
1491void PlatformViewAndroidJNIImpl::FlutterViewOnPreEngineRestart() {
1492 JNIEnv* env = fml::jni::AttachCurrentThread();
1493
1494 auto java_object = java_object_.get(env);
1495 if (java_object.is_null()) {
1496 return;
1497 }
1498
1499 env->CallVoidMethod(java_object.obj(), g_on_engine_restart_method);
1500
1502}
1503
1504void PlatformViewAndroidJNIImpl::SurfaceTextureAttachToGLContext(
1505 JavaLocalRef surface_texture,
1506 int textureId) {
1507 JNIEnv* env = fml::jni::AttachCurrentThread();
1508
1509 if (surface_texture.is_null()) {
1510 return;
1511 }
1512
1513 fml::jni::ScopedJavaLocalRef<jobject> surface_texture_local_ref(
1514 env, env->CallObjectMethod(surface_texture.obj(),
1515 g_java_weak_reference_get_method));
1516
1517 if (surface_texture_local_ref.is_null()) {
1518 return;
1519 }
1520
1521 env->CallVoidMethod(surface_texture_local_ref.obj(),
1522 g_attach_to_gl_context_method, textureId);
1523
1525}
1526
1527bool PlatformViewAndroidJNIImpl::SurfaceTextureShouldUpdate(
1528 JavaLocalRef surface_texture) {
1529 JNIEnv* env = fml::jni::AttachCurrentThread();
1530
1531 if (surface_texture.is_null()) {
1532 return false;
1533 }
1534
1535 fml::jni::ScopedJavaLocalRef<jobject> surface_texture_local_ref(
1536 env, env->CallObjectMethod(surface_texture.obj(),
1537 g_java_weak_reference_get_method));
1538 if (surface_texture_local_ref.is_null()) {
1539 return false;
1540 }
1541
1542 jboolean shouldUpdate = env->CallBooleanMethod(
1543 surface_texture_local_ref.obj(), g_surface_texture_wrapper_should_update);
1544
1546
1547 return shouldUpdate;
1548}
1549
1550void PlatformViewAndroidJNIImpl::SurfaceTextureUpdateTexImage(
1551 JavaLocalRef surface_texture) {
1552 JNIEnv* env = fml::jni::AttachCurrentThread();
1553
1554 if (surface_texture.is_null()) {
1555 return;
1556 }
1557
1558 fml::jni::ScopedJavaLocalRef<jobject> surface_texture_local_ref(
1559 env, env->CallObjectMethod(surface_texture.obj(),
1560 g_java_weak_reference_get_method));
1561 if (surface_texture_local_ref.is_null()) {
1562 return;
1563 }
1564
1565 env->CallVoidMethod(surface_texture_local_ref.obj(),
1566 g_update_tex_image_method);
1567
1569}
1570
1571SkM44 PlatformViewAndroidJNIImpl::SurfaceTextureGetTransformMatrix(
1572 JavaLocalRef surface_texture) {
1573 JNIEnv* env = fml::jni::AttachCurrentThread();
1574
1575 if (surface_texture.is_null()) {
1576 return {};
1577 }
1578
1579 fml::jni::ScopedJavaLocalRef<jobject> surface_texture_local_ref(
1580 env, env->CallObjectMethod(surface_texture.obj(),
1581 g_java_weak_reference_get_method));
1582 if (surface_texture_local_ref.is_null()) {
1583 return {};
1584 }
1585
1587 env, env->NewFloatArray(16));
1588
1589 env->CallVoidMethod(surface_texture_local_ref.obj(),
1590 g_get_transform_matrix_method, transformMatrix.obj());
1592
1593 float* m = env->GetFloatArrayElements(transformMatrix.obj(), nullptr);
1594
1595 static_assert(sizeof(SkScalar) == sizeof(float));
1596 const auto transform = SkM44::ColMajor(m);
1597
1598 env->ReleaseFloatArrayElements(transformMatrix.obj(), m, JNI_ABORT);
1599
1600 return transform;
1601}
1602
1603void PlatformViewAndroidJNIImpl::SurfaceTextureDetachFromGLContext(
1604 JavaLocalRef surface_texture) {
1605 JNIEnv* env = fml::jni::AttachCurrentThread();
1606
1607 if (surface_texture.is_null()) {
1608 return;
1609 }
1610
1611 fml::jni::ScopedJavaLocalRef<jobject> surface_texture_local_ref(
1612 env, env->CallObjectMethod(surface_texture.obj(),
1613 g_java_weak_reference_get_method));
1614 if (surface_texture_local_ref.is_null()) {
1615 return;
1616 }
1617
1618 env->CallVoidMethod(surface_texture_local_ref.obj(),
1619 g_detach_from_gl_context_method);
1620
1622}
1623
1625PlatformViewAndroidJNIImpl::ImageProducerTextureEntryAcquireLatestImage(
1626 JavaLocalRef image_producer_texture_entry) {
1627 JNIEnv* env = fml::jni::AttachCurrentThread();
1628
1629 if (image_producer_texture_entry.is_null()) {
1630 // Return null.
1631 return JavaLocalRef();
1632 }
1633
1634 // Convert the weak reference to ImageTextureEntry into a strong local
1635 // reference.
1636 fml::jni::ScopedJavaLocalRef<jobject> image_producer_texture_entry_local_ref(
1637 env, env->CallObjectMethod(image_producer_texture_entry.obj(),
1638 g_java_weak_reference_get_method));
1639
1640 if (image_producer_texture_entry_local_ref.is_null()) {
1641 // Return null.
1642 return JavaLocalRef();
1643 }
1644
1646 env, env->CallObjectMethod(image_producer_texture_entry_local_ref.obj(),
1647 g_acquire_latest_image_method));
1648 if (fml::jni::CheckException(env)) {
1649 return r;
1650 }
1651 // Return null.
1652 return JavaLocalRef();
1653}
1654
1655JavaLocalRef PlatformViewAndroidJNIImpl::ImageGetHardwareBuffer(
1656 JavaLocalRef image) {
1657 FML_CHECK(g_image_get_hardware_buffer_method != nullptr);
1658 JNIEnv* env = fml::jni::AttachCurrentThread();
1659 if (image.is_null()) {
1660 // Return null.
1661 return JavaLocalRef();
1662 }
1664 env,
1665 env->CallObjectMethod(image.obj(), g_image_get_hardware_buffer_method));
1667 return r;
1668}
1669
1670void PlatformViewAndroidJNIImpl::ImageClose(JavaLocalRef image) {
1671 JNIEnv* env = fml::jni::AttachCurrentThread();
1672 if (image.is_null()) {
1673 return;
1674 }
1675 env->CallVoidMethod(image.obj(), g_image_close_method);
1677}
1678
1679void PlatformViewAndroidJNIImpl::HardwareBufferClose(
1680 JavaLocalRef hardware_buffer) {
1681 FML_CHECK(g_hardware_buffer_close_method != nullptr);
1682 JNIEnv* env = fml::jni::AttachCurrentThread();
1683 if (hardware_buffer.is_null()) {
1684 return;
1685 }
1686 env->CallVoidMethod(hardware_buffer.obj(), g_hardware_buffer_close_method);
1688}
1689
1690void PlatformViewAndroidJNIImpl::FlutterViewOnDisplayPlatformView(
1691 int view_id,
1692 int x,
1693 int y,
1694 int width,
1695 int height,
1696 int viewWidth,
1697 int viewHeight,
1698 MutatorsStack mutators_stack) {
1699 JNIEnv* env = fml::jni::AttachCurrentThread();
1700 auto java_object = java_object_.get(env);
1701 if (java_object.is_null()) {
1702 return;
1703 }
1704
1705 jobject mutatorsStack = env->NewObject(g_mutators_stack_class->obj(),
1706 g_mutators_stack_init_method);
1707
1708 std::vector<std::shared_ptr<Mutator>>::const_iterator iter =
1709 mutators_stack.Begin();
1710 while (iter != mutators_stack.End()) {
1711 switch ((*iter)->GetType()) {
1712 case MutatorType::kTransform: {
1713 const DlMatrix& matrix = (*iter)->GetMatrix();
1714 DlScalar matrix_array[9]{
1715 matrix.m[0], matrix.m[4], matrix.m[12], //
1716 matrix.m[1], matrix.m[5], matrix.m[13], //
1717 matrix.m[3], matrix.m[7], matrix.m[15],
1718 };
1720 env, env->NewFloatArray(9));
1721
1722 env->SetFloatArrayRegion(transformMatrix.obj(), 0, 9, matrix_array);
1723 env->CallVoidMethod(mutatorsStack,
1724 g_mutators_stack_push_transform_method,
1725 transformMatrix.obj());
1726 break;
1727 }
1728 case MutatorType::kClipRect: {
1729 const DlRect& rect = (*iter)->GetRect();
1730 env->CallVoidMethod(mutatorsStack,
1731 g_mutators_stack_push_cliprect_method,
1732 static_cast<int>(rect.GetLeft()), //
1733 static_cast<int>(rect.GetTop()), //
1734 static_cast<int>(rect.GetRight()), //
1735 static_cast<int>(rect.GetBottom()));
1736 break;
1737 }
1738 case MutatorType::kClipRRect: {
1739 const DlRoundRect& rrect = (*iter)->GetRRect();
1740 const DlRect& rect = rrect.GetBounds();
1741 const DlRoundingRadii radii = rrect.GetRadii();
1742 SkScalar radiis[8] = {
1743 radii.top_left.width, radii.top_left.height,
1744 radii.top_right.width, radii.top_right.height,
1745 radii.bottom_right.width, radii.bottom_right.height,
1746 radii.bottom_left.width, radii.bottom_left.height,
1747 };
1749 env, env->NewFloatArray(8));
1750 env->SetFloatArrayRegion(radiisArray.obj(), 0, 8, radiis);
1751 env->CallVoidMethod(mutatorsStack,
1752 g_mutators_stack_push_cliprrect_method,
1753 static_cast<int>(rect.GetLeft()), //
1754 static_cast<int>(rect.GetTop()), //
1755 static_cast<int>(rect.GetRight()), //
1756 static_cast<int>(rect.GetBottom()), //
1757 radiisArray.obj());
1758 break;
1759 }
1760 case MutatorType::kClipRSE: {
1761 const DlRoundRect& rrect = (*iter)->GetRSEApproximation();
1762 const DlRect& rect = rrect.GetBounds();
1763 const DlRoundingRadii radii = rrect.GetRadii();
1764 SkScalar radiis[8] = {
1765 radii.top_left.width, radii.top_left.height,
1766 radii.top_right.width, radii.top_right.height,
1767 radii.bottom_right.width, radii.bottom_right.height,
1768 radii.bottom_left.width, radii.bottom_left.height,
1769 };
1771 env, env->NewFloatArray(8));
1772 env->SetFloatArrayRegion(radiisArray.obj(), 0, 8, radiis);
1773 env->CallVoidMethod(mutatorsStack,
1774 g_mutators_stack_push_cliprrect_method,
1775 static_cast<int>(rect.GetLeft()), //
1776 static_cast<int>(rect.GetTop()), //
1777 static_cast<int>(rect.GetRight()), //
1778 static_cast<int>(rect.GetBottom()), //
1779 radiisArray.obj());
1780 break;
1781 }
1782 // TODO(cyanglaz): Implement other mutators.
1783 // https://github.com/flutter/flutter/issues/58426
1784 case MutatorType::kClipPath:
1785 case MutatorType::kOpacity:
1786 case MutatorType::kBackdropFilter:
1787 break;
1788 }
1789 ++iter;
1790 }
1791
1792 env->CallVoidMethod(java_object.obj(), g_on_display_platform_view_method,
1793 view_id, x, y, width, height, viewWidth, viewHeight,
1794 mutatorsStack);
1795
1797}
1798
1799void PlatformViewAndroidJNIImpl::FlutterViewDisplayOverlaySurface(
1800 int surface_id,
1801 int x,
1802 int y,
1803 int width,
1804 int height) {
1805 JNIEnv* env = fml::jni::AttachCurrentThread();
1806
1807 auto java_object = java_object_.get(env);
1808 if (java_object.is_null()) {
1809 return;
1810 }
1811
1812 env->CallVoidMethod(java_object.obj(), g_on_display_overlay_surface_method,
1813 surface_id, x, y, width, height);
1814
1816}
1817
1818void PlatformViewAndroidJNIImpl::FlutterViewBeginFrame() {
1819 JNIEnv* env = fml::jni::AttachCurrentThread();
1820
1821 auto java_object = java_object_.get(env);
1822 if (java_object.is_null()) {
1823 return;
1824 }
1825
1826 env->CallVoidMethod(java_object.obj(), g_on_begin_frame_method);
1827
1829}
1830
1831void PlatformViewAndroidJNIImpl::FlutterViewEndFrame() {
1832 JNIEnv* env = fml::jni::AttachCurrentThread();
1833
1834 auto java_object = java_object_.get(env);
1835 if (java_object.is_null()) {
1836 return;
1837 }
1838
1839 env->CallVoidMethod(java_object.obj(), g_on_end_frame_method);
1840
1842}
1843
1844std::unique_ptr<PlatformViewAndroidJNI::OverlayMetadata>
1845PlatformViewAndroidJNIImpl::FlutterViewCreateOverlaySurface() {
1846 JNIEnv* env = fml::jni::AttachCurrentThread();
1847
1848 auto java_object = java_object_.get(env);
1849 if (java_object.is_null()) {
1850 return nullptr;
1851 }
1852
1854 env, env->CallObjectMethod(java_object.obj(),
1855 g_create_overlay_surface_method));
1857
1858 if (overlay.is_null()) {
1859 return std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(0,
1860 nullptr);
1861 }
1862
1863 jint overlay_id =
1864 env->CallIntMethod(overlay.obj(), g_overlay_surface_id_method);
1865
1866 jobject overlay_surface =
1867 env->CallObjectMethod(overlay.obj(), g_overlay_surface_surface_method);
1868
1869 auto overlay_window = fml::MakeRefCounted<AndroidNativeWindow>(
1870 ANativeWindow_fromSurface(env, overlay_surface));
1871
1872 return std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
1873 overlay_id, std::move(overlay_window));
1874}
1875
1876void PlatformViewAndroidJNIImpl::FlutterViewDestroyOverlaySurfaces() {
1877 JNIEnv* env = fml::jni::AttachCurrentThread();
1878
1879 auto java_object = java_object_.get(env);
1880 if (java_object.is_null()) {
1881 return;
1882 }
1883
1884 env->CallVoidMethod(java_object.obj(), g_destroy_overlay_surfaces_method);
1885
1887}
1888
1889std::unique_ptr<std::vector<std::string>>
1890PlatformViewAndroidJNIImpl::FlutterViewComputePlatformResolvedLocale(
1891 std::vector<std::string> supported_locales_data) {
1892 JNIEnv* env = fml::jni::AttachCurrentThread();
1893
1894 std::unique_ptr<std::vector<std::string>> out =
1895 std::make_unique<std::vector<std::string>>();
1896
1897 auto java_object = java_object_.get(env);
1898 if (java_object.is_null()) {
1899 return out;
1900 }
1902 fml::jni::VectorToStringArray(env, supported_locales_data);
1903 jobjectArray result = static_cast<jobjectArray>(env->CallObjectMethod(
1904 java_object.obj(), g_compute_platform_resolved_locale_method,
1905 j_locales_data.obj()));
1906
1908
1909 int length = env->GetArrayLength(result);
1910 for (int i = 0; i < length; i++) {
1911 out->emplace_back(fml::jni::JavaStringToString(
1912 env, static_cast<jstring>(env->GetObjectArrayElement(result, i))));
1913 }
1914 return out;
1915}
1916
1917double PlatformViewAndroidJNIImpl::GetDisplayRefreshRate() {
1918 JNIEnv* env = fml::jni::AttachCurrentThread();
1919
1920 auto java_object = java_object_.get(env);
1921 if (java_object.is_null()) {
1922 return kUnknownDisplayRefreshRate;
1923 }
1924
1926 env, env->GetObjectClass(java_object.obj()));
1927 if (clazz.is_null()) {
1928 return kUnknownDisplayRefreshRate;
1929 }
1930
1931 jfieldID fid = env->GetStaticFieldID(clazz.obj(), "refreshRateFPS", "F");
1932 return static_cast<double>(env->GetStaticFloatField(clazz.obj(), fid));
1933}
1934
1935double PlatformViewAndroidJNIImpl::GetDisplayWidth() {
1936 JNIEnv* env = fml::jni::AttachCurrentThread();
1937
1938 auto java_object = java_object_.get(env);
1939 if (java_object.is_null()) {
1940 return -1;
1941 }
1942
1944 env, env->GetObjectClass(java_object.obj()));
1945 if (clazz.is_null()) {
1946 return -1;
1947 }
1948
1949 jfieldID fid = env->GetStaticFieldID(clazz.obj(), "displayWidth", "F");
1950 return static_cast<double>(env->GetStaticFloatField(clazz.obj(), fid));
1951}
1952
1953double PlatformViewAndroidJNIImpl::GetDisplayHeight() {
1954 JNIEnv* env = fml::jni::AttachCurrentThread();
1955
1956 auto java_object = java_object_.get(env);
1957 if (java_object.is_null()) {
1958 return -1;
1959 }
1960
1962 env, env->GetObjectClass(java_object.obj()));
1963 if (clazz.is_null()) {
1964 return -1;
1965 }
1966
1967 jfieldID fid = env->GetStaticFieldID(clazz.obj(), "displayHeight", "F");
1968 return static_cast<double>(env->GetStaticFloatField(clazz.obj(), fid));
1969}
1970
1971double PlatformViewAndroidJNIImpl::GetDisplayDensity() {
1972 JNIEnv* env = fml::jni::AttachCurrentThread();
1973
1974 auto java_object = java_object_.get(env);
1975 if (java_object.is_null()) {
1976 return -1;
1977 }
1978
1980 env, env->GetObjectClass(java_object.obj()));
1981 if (clazz.is_null()) {
1982 return -1;
1983 }
1984
1985 jfieldID fid = env->GetStaticFieldID(clazz.obj(), "displayDensity", "F");
1986 return static_cast<double>(env->GetStaticFloatField(clazz.obj(), fid));
1987}
1988
1989bool PlatformViewAndroidJNIImpl::RequestDartDeferredLibrary(
1990 int loading_unit_id) {
1991 JNIEnv* env = fml::jni::AttachCurrentThread();
1992
1993 auto java_object = java_object_.get(env);
1994 if (java_object.is_null()) {
1995 return true;
1996 }
1997
1998 env->CallVoidMethod(java_object.obj(), g_request_dart_deferred_library_method,
1999 loading_unit_id);
2000
2002 return true;
2003}
2004
2005// New Platform View Support.
2006
2007ASurfaceTransaction* PlatformViewAndroidJNIImpl::createTransaction() {
2008 JNIEnv* env = fml::jni::AttachCurrentThread();
2009
2010 auto java_object = java_object_.get(env);
2011 if (java_object.is_null()) {
2012 return nullptr;
2013 }
2014
2016 env,
2017 env->CallObjectMethod(java_object.obj(), g_create_transaction_method));
2018 if (transaction.is_null()) {
2019 return nullptr;
2020 }
2022
2023 return impeller::android::GetProcTable().ASurfaceTransaction_fromJava(
2024 env, transaction.obj());
2025}
2026
2027void PlatformViewAndroidJNIImpl::swapTransaction() {
2028 JNIEnv* env = fml::jni::AttachCurrentThread();
2029
2030 auto java_object = java_object_.get(env);
2031 if (java_object.is_null()) {
2032 return;
2033 }
2034
2035 env->CallVoidMethod(java_object.obj(), g_swap_transaction_method);
2036
2038}
2039
2040void PlatformViewAndroidJNIImpl::applyTransaction() {
2041 JNIEnv* env = fml::jni::AttachCurrentThread();
2042
2043 auto java_object = java_object_.get(env);
2044 if (java_object.is_null()) {
2045 return;
2046 }
2047
2048 env->CallVoidMethod(java_object.obj(), g_apply_transaction_method);
2049
2051}
2052
2053std::unique_ptr<PlatformViewAndroidJNI::OverlayMetadata>
2054PlatformViewAndroidJNIImpl::createOverlaySurface2() {
2055 JNIEnv* env = fml::jni::AttachCurrentThread();
2056
2057 auto java_object = java_object_.get(env);
2058 if (java_object.is_null()) {
2059 return nullptr;
2060 }
2061
2063 env, env->CallObjectMethod(java_object.obj(),
2064 g_create_overlay_surface2_method));
2066
2067 if (overlay.is_null()) {
2068 return std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(0,
2069 nullptr);
2070 }
2071
2072 jint overlay_id =
2073 env->CallIntMethod(overlay.obj(), g_overlay_surface_id_method);
2074
2075 jobject overlay_surface =
2076 env->CallObjectMethod(overlay.obj(), g_overlay_surface_surface_method);
2077
2078 auto overlay_window = fml::MakeRefCounted<AndroidNativeWindow>(
2079 ANativeWindow_fromSurface(env, overlay_surface));
2080
2081 return std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
2082 overlay_id, std::move(overlay_window));
2083}
2084
2085void PlatformViewAndroidJNIImpl::destroyOverlaySurface2() {
2086 JNIEnv* env = fml::jni::AttachCurrentThread();
2087
2088 auto java_object = java_object_.get(env);
2089 if (java_object.is_null()) {
2090 return;
2091 }
2092
2093 env->CallVoidMethod(java_object.obj(), g_destroy_overlay_surface2_method);
2094
2096}
2097
2098namespace {
2099class AndroidPathReceiver final : public DlPathReceiver {
2100 public:
2101 explicit AndroidPathReceiver(JNIEnv* env)
2102 : env_(env),
2103 android_path_(env->NewObject(path_class->obj(), path_constructor)) {}
2104
2105 void SetFillType(DlPathFillType type) {
2106 jfieldID fill_type_field_id;
2107 switch (type) {
2108 case DlPathFillType::kOdd:
2109 fill_type_field_id = g_path_fill_type_even_odd_field;
2110 break;
2111 case DlPathFillType::kNonZero:
2112 fill_type_field_id = g_path_fill_type_winding_field;
2113 break;
2114 default:
2115 // DlPathFillType does not have corresponding kInverseEvenOdd or
2116 // kInverseWinding fill types.
2117 return;
2118 }
2119
2120 // Get the static enum field value (Path.FillType.WINDING or
2121 // Path.FillType.EVEN_ODD)
2124 env_, env_->GetStaticObjectField(g_path_fill_type_class->obj(),
2125 fill_type_field_id));
2127 FML_CHECK(!fill_type_enum.is_null());
2128
2129 // Call Path.setFillType(Path.FillType)
2130 env_->CallVoidMethod(android_path_, path_set_fill_type_method,
2131 fill_type_enum.obj());
2133 }
2134
2135 void MoveTo(const DlPoint& p2, bool will_be_closed) override {
2136 env_->CallVoidMethod(android_path_, path_move_to_method, p2.x, p2.y);
2137 }
2138 void LineTo(const DlPoint& p2) override {
2139 env_->CallVoidMethod(android_path_, path_line_to_method, p2.x, p2.y);
2140 }
2141 void QuadTo(const DlPoint& cp, const DlPoint& p2) override {
2142 env_->CallVoidMethod(android_path_, path_quad_to_method, //
2143 cp.x, cp.y, p2.x, p2.y);
2144 }
2145 bool ConicTo(const DlPoint& cp, const DlPoint& p2, DlScalar weight) override {
2146 if (!path_conic_to_method) {
2147 return false;
2148 }
2149 env_->CallVoidMethod(android_path_, path_conic_to_method, //
2150 cp.x, cp.y, p2.x, p2.y, weight);
2151 return true;
2152 };
2153 void CubicTo(const DlPoint& cp1,
2154 const DlPoint& cp2,
2155 const DlPoint& p2) override {
2156 env_->CallVoidMethod(android_path_, path_cubic_to_method, //
2157 cp1.x, cp1.y, cp2.x, cp2.y, p2.x, p2.y);
2158 }
2159 void Close() override {
2160 env_->CallVoidMethod(android_path_, path_close_method);
2161 }
2162
2163 jobject TakePath() const { return android_path_; }
2164
2165 private:
2166 JNIEnv* env_;
2167 jobject android_path_;
2168};
2169} // namespace
2170
2171void PlatformViewAndroidJNIImpl::onDisplayPlatformView2(
2172 int32_t view_id,
2173 int32_t x,
2174 int32_t y,
2175 int32_t width,
2176 int32_t height,
2177 int32_t viewWidth,
2178 int32_t viewHeight,
2179 MutatorsStack mutators_stack) {
2180 JNIEnv* env = fml::jni::AttachCurrentThread();
2181 auto java_object = java_object_.get(env);
2182 if (java_object.is_null()) {
2183 return;
2184 }
2185
2186 jobject mutatorsStack = env->NewObject(g_mutators_stack_class->obj(),
2187 g_mutators_stack_init_method);
2188
2189 std::vector<std::shared_ptr<Mutator>>::const_iterator iter =
2190 mutators_stack.Begin();
2191 while (iter != mutators_stack.End()) {
2192 switch ((*iter)->GetType()) {
2193 case MutatorType::kTransform: {
2194 const DlMatrix& matrix = (*iter)->GetMatrix();
2195 DlScalar matrix_array[9]{
2196 matrix.m[0], matrix.m[4], matrix.m[12], //
2197 matrix.m[1], matrix.m[5], matrix.m[13], //
2198 matrix.m[3], matrix.m[7], matrix.m[15],
2199 };
2201 env, env->NewFloatArray(9));
2202
2203 env->SetFloatArrayRegion(transformMatrix.obj(), 0, 9, matrix_array);
2204 env->CallVoidMethod(mutatorsStack,
2205 g_mutators_stack_push_transform_method,
2206 transformMatrix.obj());
2207 break;
2208 }
2209 case MutatorType::kClipRect: {
2210 const DlRect& rect = (*iter)->GetRect();
2211 env->CallVoidMethod(mutatorsStack,
2212 g_mutators_stack_push_cliprect_method,
2213 static_cast<int>(rect.GetLeft()), //
2214 static_cast<int>(rect.GetTop()), //
2215 static_cast<int>(rect.GetRight()), //
2216 static_cast<int>(rect.GetBottom()));
2217 break;
2218 }
2219 case MutatorType::kClipRRect: {
2220 const DlRoundRect& rrect = (*iter)->GetRRect();
2221 const DlRect& rect = rrect.GetBounds();
2222 const DlRoundingRadii& radii = rrect.GetRadii();
2223 SkScalar radiis[8] = {
2224 radii.top_left.width, radii.top_left.height,
2225 radii.top_right.width, radii.top_right.height,
2226 radii.bottom_right.width, radii.bottom_right.height,
2227 radii.bottom_left.width, radii.bottom_left.height,
2228 };
2230 env, env->NewFloatArray(8));
2231 env->SetFloatArrayRegion(radiisArray.obj(), 0, 8, radiis);
2232 env->CallVoidMethod(mutatorsStack,
2233 g_mutators_stack_push_cliprrect_method,
2234 static_cast<int>(rect.GetLeft()), //
2235 static_cast<int>(rect.GetTop()), //
2236 static_cast<int>(rect.GetRight()), //
2237 static_cast<int>(rect.GetBottom()), //
2238 radiisArray.obj());
2239 break;
2240 }
2241 case MutatorType::kClipRSE: {
2242 const DlRoundRect& rrect = (*iter)->GetRSEApproximation();
2243 const DlRect& rect = rrect.GetBounds();
2244 const DlRoundingRadii& radii = rrect.GetRadii();
2245 SkScalar radiis[8] = {
2246 radii.top_left.width, radii.top_left.height,
2247 radii.top_right.width, radii.top_right.height,
2248 radii.bottom_right.width, radii.bottom_right.height,
2249 radii.bottom_left.width, radii.bottom_left.height,
2250 };
2252 env, env->NewFloatArray(8));
2253 env->SetFloatArrayRegion(radiisArray.obj(), 0, 8, radiis);
2254 env->CallVoidMethod(mutatorsStack,
2255 g_mutators_stack_push_cliprrect_method,
2256 static_cast<int>(rect.GetLeft()), //
2257 static_cast<int>(rect.GetTop()), //
2258 static_cast<int>(rect.GetRight()), //
2259 static_cast<int>(rect.GetBottom()), //
2260 radiisArray.obj());
2261 break;
2262 }
2263 case MutatorType::kOpacity: {
2264 float opacity = (*iter)->GetAlphaFloat();
2265 env->CallVoidMethod(mutatorsStack, g_mutators_stack_push_opacity_method,
2266 opacity);
2267 break;
2268 }
2269 case MutatorType::kClipPath: {
2270 auto& dlPath = (*iter)->GetPath();
2271 // The layer mutator mechanism should have already caught and
2272 // redirected these simplified path cases, which is important because
2273 // the conics they generate (in the case of oval and rrect) will
2274 // not match the results of an impeller path conversion very closely.
2275 FML_DCHECK(!dlPath.IsRect());
2276 FML_DCHECK(!dlPath.IsOval());
2277 FML_DCHECK(!dlPath.IsRoundRect());
2278
2279 // Define and populate an Android Path with data from the DlPath
2280 AndroidPathReceiver receiver(env);
2281 receiver.SetFillType(dlPath.GetFillType());
2282
2283 // TODO(flar): https://github.com/flutter/flutter/issues/164808
2284 // Need to convert the fill type to the Android enum and
2285 // call setFillType on the path...
2286 dlPath.Dispatch(receiver);
2287
2288 env->CallVoidMethod(mutatorsStack,
2289 g_mutators_stack_push_clippath_method,
2290 receiver.TakePath());
2291 break;
2292 }
2293 // TODO(cyanglaz): Implement other mutators.
2294 // https://github.com/flutter/flutter/issues/58426
2295 case MutatorType::kBackdropFilter:
2296 break;
2297 }
2298 ++iter;
2299 }
2300
2301 env->CallVoidMethod(java_object.obj(), g_on_display_platform_view2_method,
2302 view_id, x, y, width, height, viewWidth, viewHeight,
2303 mutatorsStack);
2304
2306}
2307
2308void PlatformViewAndroidJNIImpl::hidePlatformView2(int32_t view_id) {
2309 JNIEnv* env = fml::jni::AttachCurrentThread();
2310 auto java_object = java_object_.get(env);
2311 if (java_object.is_null()) {
2312 return;
2313 }
2314
2315 env->CallVoidMethod(java_object.obj(), g_hide_platform_view2_method, view_id);
2316}
2317
2318void PlatformViewAndroidJNIImpl::onEndFrame2() {
2319 JNIEnv* env = fml::jni::AttachCurrentThread();
2320
2321 auto java_object = java_object_.get(env);
2322 if (java_object.is_null()) {
2323 return;
2324 }
2325
2326 env->CallVoidMethod(java_object.obj(), g_on_end_frame2_method);
2327
2329}
2330
2331void PlatformViewAndroidJNIImpl::showOverlaySurface2() {
2332 JNIEnv* env = fml::jni::AttachCurrentThread();
2333
2334 auto java_object = java_object_.get(env);
2335 if (java_object.is_null()) {
2336 return;
2337 }
2338
2339 env->CallVoidMethod(java_object.obj(), g_show_overlay_surface2_method);
2341}
2342
2343void PlatformViewAndroidJNIImpl::hideOverlaySurface2() {
2344 JNIEnv* env = fml::jni::AttachCurrentThread();
2345
2346 auto java_object = java_object_.get(env);
2347 if (java_object.is_null()) {
2348 return;
2349 }
2350
2351 env->CallVoidMethod(java_object.obj(), g_hide_overlay_surface2_method);
2353}
2354
2355} // namespace flutter
GLenum type
static std::unique_ptr< DartCallbackRepresentation > GetCallbackInformation(int64_t handle)
A Mapping like NonOwnedMapping, but uses Free as its release proc.
Definition mapping.h:144
static MallocMapping Copy(const T *begin, const T *end)
Definition mapping.h:162
uint8_t * Release()
Definition mapping.cc:155
static fml::RefPtr< NativeLibrary > CreateWithHandle(Handle handle, bool close_handle_when_done)
int32_t x
FlutterVulkanImage * image
GLFWwindow * window
Definition main.cc:60
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const gchar * channel
G_BEGIN_DECLS GBytes * message
G_BEGIN_DECLS FlutterViewId view_id
#define FML_LOG(severity)
Definition logging.h:101
#define FML_CHECK(condition)
Definition logging.h:104
#define FML_DCHECK(condition)
Definition logging.h:122
size_t length
double y
static jmethodID g_hardware_buffer_close_method
impeller::Scalar DlScalar
static void RunBundleAndSnapshotFromLibrary(JNIEnv *env, jobject jcaller, jlong shell_holder, jstring jBundlePath, jstring jEntrypoint, jstring jLibraryUrl, jobject jAssetManager, jobject jEntrypointArgs, jlong engineId)
impeller::PathReceiver DlPathReceiver
Definition dl_path.h:17
static jmethodID g_mutators_stack_init_method
impeller::RoundingRadii DlRoundingRadii
static jfieldID g_jni_shell_holder_field
static void InvokePlatformMessageResponseCallback(JNIEnv *env, jobject jcaller, jlong shell_holder, jint responseId, jobject message, jint position)
static jmethodID g_request_dart_deferred_library_method
static jboolean GetIsSoftwareRendering(JNIEnv *env, jobject jcaller)
static bool IsSurfaceControlEnabled(JNIEnv *env, jobject jcaller, jlong shell_holder)
static void DispatchPointerDataPacket(JNIEnv *env, jobject jcaller, jlong shell_holder, jobject buffer, jint position)
bool RegisterApi(JNIEnv *env)
impeller::RoundRect DlRoundRect
static jmethodID g_mutators_stack_push_clippath_method
static jboolean FlutterTextUtilsIsEmojiModifier(JNIEnv *env, jobject obj, jint codePoint)
static fml::jni::ScopedJavaGlobalRef< jclass > * path_class
static fml::jni::ScopedJavaGlobalRef< jclass > * g_java_long_class
static void LoadLoadingUnitFailure(intptr_t loading_unit_id, const std::string &message, bool transient)
static void InvokePlatformMessageEmptyResponseCallback(JNIEnv *env, jobject jcaller, jlong shell_holder, jint responseId)
impeller::Matrix DlMatrix
impeller::Rect DlRect
impeller::ISize32 DlISize
static jmethodID g_acquire_latest_image_method
static jmethodID g_mutators_stack_push_transform_method
static fml::jni::ScopedJavaGlobalRef< jclass > * g_bitmap_class
std::nullptr_t JavaLocalRef
static void SurfaceDestroyed(JNIEnv *env, jobject jcaller, jlong shell_holder)
static jmethodID path_line_to_method
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
Definition switch_defs.h:52
static jmethodID path_quad_to_method
static jmethodID g_long_constructor
static void DestroyJNI(JNIEnv *env, jobject jcaller, jlong shell_holder)
static void DispatchSemanticsAction(JNIEnv *env, jobject jcaller, jlong shell_holder, jint id, jint action, jobject args, jint args_position)
static jmethodID g_jni_constructor
static void MarkTextureFrameAvailable(JNIEnv *env, jobject jcaller, jlong shell_holder, jlong texture_id)
static jmethodID g_attach_to_gl_context_method
static jfieldID g_path_fill_type_even_odd_field
static void SetSemanticsEnabled(JNIEnv *env, jobject jcaller, jlong shell_holder, jboolean enabled)
static void DeferredComponentInstallFailure(JNIEnv *env, jobject obj, jint jLoadingUnitId, jstring jError, jboolean jTransient)
static jobject SpawnJNI(JNIEnv *env, jobject jcaller, jlong shell_holder, jstring jEntrypoint, jstring jLibraryUrl, jstring jInitialRoute, jobject jEntrypointArgs, jlong engineId)
static jfieldID g_path_fill_type_winding_field
static fml::jni::ScopedJavaGlobalRef< jclass > * g_texture_wrapper_class
static void LoadDartDeferredLibrary(JNIEnv *env, jobject obj, jlong shell_holder, jint jLoadingUnitId, jobjectArray jSearchPaths)
static jmethodID g_java_weak_reference_get_method
static void NotifyLowMemoryWarning(JNIEnv *env, jobject obj, jlong shell_holder)
static jboolean FlutterTextUtilsIsVariationSelector(JNIEnv *env, jobject obj, jint codePoint)
static jmethodID g_image_get_hardware_buffer_method
static void CleanupMessageData(JNIEnv *env, jobject jcaller, jlong message_data)
static jmethodID g_mutators_stack_push_cliprect_method
static jmethodID g_overlay_surface_surface_method
static void DispatchPlatformMessage(JNIEnv *env, jobject jcaller, jlong shell_holder, jstring channel, jobject message, jint position, jint responseId)
static jmethodID g_overlay_surface_id_method
static jmethodID g_mutators_stack_push_cliprrect_method
static jmethodID g_get_transform_matrix_method
static jmethodID path_cubic_to_method
static jmethodID g_compute_platform_resolved_locale_method
static void SurfaceWindowChanged(JNIEnv *env, jobject jcaller, jlong shell_holder, jobject jsurface)
static jmethodID g_bitmap_copy_pixels_from_buffer_method
static void SetViewportMetrics(JNIEnv *env, jobject jcaller, jlong shell_holder, jfloat devicePixelRatio, jint physicalWidth, jint physicalHeight, jint physicalPaddingTop, jint physicalPaddingRight, jint physicalPaddingBottom, jint physicalPaddingLeft, jint physicalViewInsetTop, jint physicalViewInsetRight, jint physicalViewInsetBottom, jint physicalViewInsetLeft, jint systemGestureInsetTop, jint systemGestureInsetRight, jint systemGestureInsetBottom, jint systemGestureInsetLeft, jint physicalTouchSlop, jintArray javaDisplayFeaturesBounds, jintArray javaDisplayFeaturesType, jintArray javaDisplayFeaturesState)
static void RegisterImageTexture(JNIEnv *env, jobject jcaller, jlong shell_holder, jlong texture_id, jobject image_texture_entry, jboolean reset_on_background)
static fml::jni::ScopedJavaGlobalRef< jclass > * g_flutter_jni_class
static fml::jni::ScopedJavaGlobalRef< jclass > * g_bitmap_config_class
static jmethodID g_surface_texture_wrapper_should_update
static fml::jni::ScopedJavaGlobalRef< jclass > * g_image_class
static void SurfaceCreated(JNIEnv *env, jobject jcaller, jlong shell_holder, jobject jsurface)
static jmethodID g_flutter_callback_info_constructor
static jmethodID path_set_fill_type_method
static void DispatchEmptyPlatformMessage(JNIEnv *env, jobject jcaller, jlong shell_holder, jstring channel, jint responseId)
static fml::jni::ScopedJavaGlobalRef< jclass > * g_path_fill_type_class
static void ScheduleFrame(JNIEnv *env, jobject jcaller, jlong shell_holder)
static jmethodID path_move_to_method
static jlong AttachJNI(JNIEnv *env, jclass clazz, jobject flutterJNI)
static void SetAccessibilityFeatures(JNIEnv *env, jobject jcaller, jlong shell_holder, jint flags)
static jmethodID g_update_tex_image_method
static fml::jni::ScopedJavaGlobalRef< jclass > * g_java_weak_reference_class
static jmethodID g_image_close_method
static void UpdateDisplayMetrics(JNIEnv *env, jobject jcaller, jlong shell_holder)
static jmethodID g_mutators_stack_push_opacity_method
static void SurfaceChanged(JNIEnv *env, jobject jcaller, jlong shell_holder, jint width, jint height)
static jmethodID g_bitmap_config_value_of
static fml::jni::ScopedJavaGlobalRef< jclass > * g_image_consumer_texture_registry_interface
static void UpdateJavaAssetManager(JNIEnv *env, jobject obj, jlong shell_holder, jobject jAssetManager, jstring jAssetBundlePath)
static jobject GetBitmap(JNIEnv *env, jobject jcaller, jlong shell_holder)
static jmethodID path_constructor
static jmethodID g_bitmap_create_bitmap_method
static void UnregisterTexture(JNIEnv *env, jobject jcaller, jlong shell_holder, jlong texture_id)
static fml::jni::ScopedJavaGlobalRef< jclass > * g_flutter_callback_info_class
static fml::jni::ScopedJavaGlobalRef< jclass > * g_mutators_stack_class
static jmethodID path_close_method
static jboolean FlutterTextUtilsIsEmojiModifierBase(JNIEnv *env, jobject obj, jint codePoint)
static jobject LookupCallbackInformation(JNIEnv *env, jobject, jlong handle)
static jboolean FlutterTextUtilsIsRegionalIndicator(JNIEnv *env, jobject obj, jint codePoint)
static jmethodID g_detach_from_gl_context_method
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
static jmethodID path_conic_to_method
static fml::jni::ScopedJavaGlobalRef< jclass > * g_hardware_buffer_class
static jboolean FlutterTextUtilsIsEmoji(JNIEnv *env, jobject obj, jint codePoint)
static void RegisterTexture(JNIEnv *env, jobject jcaller, jlong shell_holder, jlong texture_id, jobject surface_texture)
JNIEnv * AttachCurrentThread()
Definition jni_util.cc:34
ScopedJavaLocalRef< jobjectArray > VectorToBufferArray(JNIEnv *env, const std::vector< std::vector< uint8_t > > &vector)
Definition jni_util.cc:164
std::string JavaStringToString(JNIEnv *env, jstring str)
Definition jni_util.cc:70
bool ClearException(JNIEnv *env, bool silent)
Definition jni_util.cc:188
bool CheckException(JNIEnv *env)
Definition jni_util.cc:199
ScopedJavaLocalRef< jobjectArray > VectorToStringArray(JNIEnv *env, const std::vector< std::string > &vector)
Definition jni_util.cc:147
std::vector< std::string > StringListToVector(JNIEnv *env, jobject list)
Definition jni_util.cc:118
std::vector< std::string > StringArrayToVector(JNIEnv *env, jobjectArray array)
Definition jni_util.cc:96
ScopedJavaLocalRef< jstring > StringToJavaString(JNIEnv *env, const std::string &u8_string)
Definition jni_util.cc:86
const ProcTable & GetProcTable()
Definition proc_table.cc:12
void MoveTo(PathBuilder *builder, Scalar x, Scalar y)
void LineTo(PathBuilder *builder, Scalar x, Scalar y)
void CubicTo(PathBuilder *builder, Scalar x1, Scalar y1, Scalar x2, Scalar y2, Scalar x3, Scalar y3)
void Close(PathBuilder *builder)
#define ANDROID_SHELL_HOLDER
#define FLUTTER_BIND_JNI(global_field, jni_name, jni_arg)
#define FLUTTER_DECLARE_JNI(global_field, jni_name, jni_arg)
#define FLUTTER_FOR_EACH_JNI_METHOD(V)
int32_t height
int32_t width
Type width
Definition size.h:28
Scalar font_size
std::shared_ptr< const fml::Mapping > data
int64_t texture_id

◆ FLUTTER_BIND_JNI

#define FLUTTER_BIND_JNI (   global_field,
  jni_name,
  jni_arg 
)
Value:
global_field = \
env->GetMethodID(g_flutter_jni_class->obj(), #jni_name, jni_arg); \
if (global_field == nullptr) { \
FML_LOG(ERROR) << "Could not locate " << #jni_name << " method."; \
return false; \
}

Definition at line 109 of file platform_view_android_jni_impl.cc.

112 { \
113 FML_LOG(ERROR) << "Could not locate " << #jni_name << " method."; \
114 return false; \
115 }

◆ FLUTTER_DECLARE_JNI

#define FLUTTER_DECLARE_JNI (   global_field,
  jni_name,
  jni_arg 
)     static jmethodID global_field = nullptr;

Definition at line 106 of file platform_view_android_jni_impl.cc.

◆ FLUTTER_FOR_EACH_JNI_METHOD

#define FLUTTER_FOR_EACH_JNI_METHOD (   V)

Definition at line 65 of file platform_view_android_jni_impl.cc.