33 {
34
36 nullptr;
37
39
41 nullptr;
42
44
47
49
51
53
55
57
58
59
61
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
117
119
121
123
125
127
129
131
133
135
137
139
141
143
145
146
147
149
151
153
155
157
158
166
167
177
181
182
183static jlong
AttachJNI(JNIEnv* env, jclass clazz, jobject 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
202
203
204
205
206
207
208
209
210
212 jobject jcaller,
213 jlong shell_holder,
214 jstring jEntrypoint,
215 jstring jLibraryUrl,
216 jstring jInitialRoute,
217 jobject jEntrypointArgs,
218 jlong engineId) {
220 if (jni == nullptr) {
221 FML_LOG(ERROR) <<
"Could not create a FlutterJNI instance";
222 return nullptr;
223 }
224
226 std::shared_ptr<PlatformViewAndroidJNI> jni_facade =
227 std::make_shared<PlatformViewAndroidJNIImpl>(java_jni);
228
233
234 auto spawned_shell_holder =
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(
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
257 jobject jcaller,
258 jlong shell_holder,
259 jobject jsurface) {
260
261
262
264 auto window = fml::MakeRefCounted<AndroidNativeWindow>(
265 ANativeWindow_fromSurface(env, jsurface));
267}
268
270 jobject jcaller,
271 jlong shell_holder,
272 jobject jsurface) {
273
274
275
277 auto window = fml::MakeRefCounted<AndroidNativeWindow>(
278 ANativeWindow_fromSurface(env, jsurface));
281}
282
284 jobject jcaller,
285 jlong shell_holder,
290}
291
292static void SurfaceDestroyed(JNIEnv* env, jobject jcaller, jlong shell_holder) {
294}
295
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,
307 jAssetManager,
309 );
313
315 libraryUrl, entrypoint_args, engineId);
316}
317
319 jobject,
320 jlong handle) {
322 if (cbInfo == nullptr) {
323 return nullptr;
324 }
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
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
355
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
374 static_cast<double>(devicePixelRatio),
375 static_cast<double>(physicalWidth),
376 static_cast<double>(physicalHeight),
377 static_cast<double>(physicalWidth),
378 static_cast<double>(physicalWidth),
379 static_cast<double>(physicalHeight),
380 static_cast<double>(physicalHeight),
381 static_cast<double>(physicalPaddingTop),
382 static_cast<double>(physicalPaddingRight),
383 static_cast<double>(physicalPaddingBottom),
384 static_cast<double>(physicalPaddingLeft),
385 static_cast<double>(physicalViewInsetTop),
386 static_cast<double>(
387 physicalViewInsetRight),
388 static_cast<double>(
389 physicalViewInsetBottom),
390 static_cast<double>(physicalViewInsetLeft),
391 static_cast<double>(
392 systemGestureInsetTop),
393 static_cast<double>(
394 systemGestureInsetRight),
395 static_cast<double>(
396 systemGestureInsetBottom),
397 static_cast<double>(
398 systemGestureInsetLeft),
399 static_cast<double>(physicalTouchSlop),
400 displayFeaturesBounds,
401 displayFeaturesType,
402 displayFeaturesState,
403 0,
404 };
405
407 kFlutterImplicitViewId, metrics);
408}
409
411 jobject jcaller,
412 jlong shell_holder) {
414}
415
417 jobject jcaller,
418 jlong shell_holder) {
420}
421
422static jobject
GetBitmap(JNIEnv* env, jobject jcaller, jlong shell_holder) {
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(
436 if (bitmap_config == nullptr) {
437 return nullptr;
438 }
439
440 auto bitmap = env->CallStaticObjectMethod(
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,
451
452 return bitmap;
453}
454
456 jobject jcaller,
457 jlong shell_holder,
460 jint position,
461 jint responseId) {
463 env,
466 position,
467 responseId
468 );
469}
470
472 jobject jcaller,
473 jlong shell_holder,
475 jint responseId) {
477 env,
479 responseId
480 );
481}
482
484 jobject jcaller,
485 jlong message_data) {
486
487 free(reinterpret_cast<void*>(message_data));
488}
489
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);
498 std::move(packet));
499}
500
502 jobject jcaller,
503 jlong shell_holder,
504 jint id,
507 jint args_position) {
509 env,
510 id,
513 args_position
514 );
515}
516
518 jobject jcaller,
519 jlong shell_holder,
520 jboolean enabled) {
522}
523
525 jobject jcaller,
526 jlong shell_holder,
527 jint flags) {
529}
530
532 return FlutterMain::Get().GetSettings().enable_software_rendering;
533}
534
536 jobject jcaller,
537 jlong shell_holder,
539 jobject surface_texture) {
543 );
544}
545
547 jobject jcaller,
548 jlong shell_holder,
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
559 lifecycle
560 );
561}
562
564 jobject jcaller,
565 jlong shell_holder,
569}
570
572 jobject jcaller,
573 jlong shell_holder,
577}
578
579static void ScheduleFrame(JNIEnv* env, jobject jcaller, jlong shell_holder) {
581}
582
584 jobject jcaller,
585 jlong shell_holder,
586 jint responseId,
588 jint position) {
589 uint8_t* response_data =
590 static_cast<uint8_t*
>(env->GetDirectBufferAddress(
message));
592 auto mapping = std::make_unique<fml::MallocMapping>(
595 ->InvokePlatformMessageResponseCallback(responseId, std::move(mapping));
596}
597
599 jobject jcaller,
600 jlong shell_holder,
601 jint responseId) {
603 ->InvokePlatformMessageEmptyResponseCallback(responseId);
604}
605
607 jobject obj,
608 jlong shell_holder) {
610}
611
613 jobject obj,
614 jint codePoint) {
615 return u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI);
616}
617
619 jobject obj,
620 jint codePoint) {
621 return u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI_MODIFIER);
622}
623
625 jobject obj,
626 jint codePoint) {
627 return u_hasBinaryProperty(codePoint, UProperty::UCHAR_EMOJI_MODIFIER_BASE);
628}
629
631 jobject obj,
632 jint codePoint) {
633 return u_hasBinaryProperty(codePoint, UProperty::UCHAR_VARIATION_SELECTOR);
634}
635
637 jobject obj,
638 jint codePoint) {
639 return u_hasBinaryProperty(codePoint, UProperty::UCHAR_REGIONAL_INDICATOR);
640}
641
644 bool transient) {
645
646}
647
649 jobject obj,
650 jint jLoadingUnitId,
651 jstring jError,
652 jboolean jTransient) {
655 static_cast<bool>(jTransient));
656}
657
659 jobject obj,
660 jlong shell_holder,
661 jint jLoadingUnitId,
662 jobjectArray jSearchPaths) {
663
664 intptr_t loading_unit_id = static_cast<intptr_t>(jLoadingUnitId);
665 std::vector<std::string> search_paths =
667
668
669
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) {
678 "No lib .so found for provided search paths.", true);
679 return;
680 }
683
684
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
693 loading_unit_id, std::move(data_mapping),
694 std::move(instructions_mapping));
695}
696
698 jobject obj,
699 jlong shell_holder,
700 jobject jAssetManager,
701 jstring jAssetBundlePath) {
702 auto asset_resolver = std::make_unique<flutter::APKAssetProvider>(
703 env,
704 jAssetManager,
706
708 std::move(asset_resolver),
709 AssetResolver::AssetResolverType::kApkAssetProvider);
710}
711
713 static const JNINativeMethod flutter_jni_methods[] = {
714
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",
738 },
739 {
740 .name = "nativeDispatchEmptyPlatformMessage",
741 .signature = "(JLjava/lang/String;I)V",
743 },
744 {
745 .name = "nativeCleanupMessageData",
746 .signature = "(J)V",
748 },
749 {
750 .name = "nativeDispatchPlatformMessage",
751 .signature = "(JLjava/lang/String;Ljava/nio/ByteBuffer;II)V",
753 },
754 {
755 .name = "nativeInvokePlatformMessageResponseCallback",
756 .signature = "(JILjava/nio/ByteBuffer;I)V",
757 .fnPtr =
759 },
760 {
761 .name = "nativeInvokePlatformMessageEmptyResponseCallback",
762 .signature = "(JI)V",
763 .fnPtr = reinterpret_cast<void*>(
765 },
766 {
767 .name = "nativeNotifyLowMemoryWarning",
768 .signature = "(J)V",
770 },
771
772
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",
782 },
783 {
784 .name = "nativeSurfaceWindowChanged",
785 .signature = "(JLandroid/view/Surface;)V",
787 },
788 {
789 .name = "nativeSurfaceChanged",
790 .signature = "(JII)V",
792 },
793 {
794 .name = "nativeSurfaceDestroyed",
795 .signature = "(J)V",
797 },
798 {
799 .name = "nativeSetViewportMetrics",
800 .signature = "(JFIIIIIIIIIIIIIII[I[I[I)V",
802 },
803 {
804 .name = "nativeDispatchPointerDataPacket",
805 .signature = "(JLjava/nio/ByteBuffer;I)V",
807 },
808 {
809 .name = "nativeDispatchSemanticsAction",
810 .signature = "(JIILjava/nio/ByteBuffer;I)V",
812 },
813 {
814 .name = "nativeSetSemanticsEnabled",
815 .signature = "(JZ)V",
817 },
818 {
819 .name = "nativeSetAccessibilityFeatures",
820 .signature = "(JI)V",
822 },
823 {
824 .name = "nativeGetIsSoftwareRenderingEnabled",
825 .signature = "()Z",
827 },
828 {
829 .name = "nativeRegisterTexture",
830 .signature = "(JJLjava/lang/ref/"
831 "WeakReference;)V",
833 },
834 {
835 .name = "nativeRegisterImageTexture",
836 .signature = "(JJLjava/lang/ref/"
837 "WeakReference;Z)V",
839 },
840 {
841 .name = "nativeMarkTextureFrameAvailable",
842 .signature = "(JJ)V",
844 },
845 {
846 .name = "nativeScheduleFrame",
847 .signature = "(J)V",
849 },
850 {
851 .name = "nativeUnregisterTexture",
852 .signature = "(JJ)V",
854 },
855
856 {
857 .name = "nativeLookupCallbackInformation",
858 .signature = "(J)Lio/flutter/view/FlutterCallbackInformation;",
860 },
861
862
863 {
864 .name = "nativeFlutterTextUtilsIsEmoji",
865 .signature = "(I)Z",
867 },
868 {
869 .name = "nativeFlutterTextUtilsIsEmojiModifier",
870 .signature = "(I)Z",
872 },
873 {
874 .name = "nativeFlutterTextUtilsIsEmojiModifierBase",
875 .signature = "(I)Z",
876 .fnPtr =
878 },
879 {
880 .name = "nativeFlutterTextUtilsIsVariationSelector",
881 .signature = "(I)Z",
882 .fnPtr =
884 },
885 {
886 .name = "nativeFlutterTextUtilsIsRegionalIndicator",
887 .signature = "(I)Z",
888 .fnPtr =
890 },
891 {
892 .name = "nativeLoadDartDeferredLibrary",
893 .signature = "(JI[Ljava/lang/String;)V",
895 },
896 {
897 .name = "nativeUpdateJavaAssetManager",
898 .signature =
899 "(JLandroid/content/res/AssetManager;Ljava/lang/String;)V",
901 },
902 {
903 .name = "nativeDeferredComponentInstallFailure",
904 .signature = "(ILjava/lang/String;Z)V",
906 },
907 {
908 .name = "nativeUpdateDisplayMetrics",
909 .signature = "(J)V",
911 },
912 {
913 .name = "nativeIsSurfaceControlEnabled",
914 .signature = "(J)Z",
916 }};
917
919 std::size(flutter_jni_methods)) != 0) {
920 FML_LOG(ERROR) <<
"Failed to RegisterNatives with FlutterJNI";
921 return false;
922 }
923
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
934
935 if (g_jni_constructor == nullptr) {
936 FML_LOG(ERROR) <<
"Could not locate FlutterJNI's constructor";
937 return false;
938 }
939
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
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 }
962 overlay_surface_class.obj(), "getSurface", "()Landroid/view/Surface;");
963 if (g_overlay_surface_surface_method == nullptr) {
965 << "Could not locate FlutterOverlaySurface#getSurface() method";
966 return false;
967 }
968
970 env, env->FindClass("android/graphics/Bitmap"));
972 FML_LOG(ERROR) <<
"Could not locate Bitmap Class";
973 return false;
974 }
975
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"));
994 FML_LOG(ERROR) <<
"Could not locate Bitmap.Config Class";
995 return false;
996 }
997
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"));
1018 FML_LOG(ERROR) <<
"Could not locate FlutterCallbackInformation class";
1019 return false;
1020 }
1021
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"));
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
1048 if (g_mutators_stack_init_method == nullptr) {
1049 FML_LOG(ERROR) <<
"Could not locate FlutterMutatorsStack.init method";
1050 return false;
1051 }
1052
1055 if (g_mutators_stack_push_transform_method == nullptr) {
1057 << "Could not locate FlutterMutatorsStack.pushTransform method";
1058 return false;
1059 }
1060
1063 if (g_mutators_stack_push_cliprect_method == nullptr) {
1065 << "Could not locate FlutterMutatorsStack.pushClipRect method";
1066 return false;
1067 }
1068
1071 if (g_mutators_stack_push_cliprrect_method == nullptr) {
1073 << "Could not locate FlutterMutatorsStack.pushClipRRect method";
1074 return false;
1075 }
1076
1079 if (g_mutators_stack_push_opacity_method == nullptr) {
1081 << "Could not locate FlutterMutatorsStack.pushOpacity method";
1082 return false;
1083 }
1084
1087 "(Landroid/graphics/Path;)V");
1088 if (g_mutators_stack_push_clippath_method == nullptr) {
1090 << "Could not locate FlutterMutatorsStack.pushClipPath method";
1091 return false;
1092 }
1093
1095 env, env->FindClass("java/lang/ref/WeakReference"));
1097 FML_LOG(ERROR) <<
"Could not locate WeakReference class";
1098 return false;
1099 }
1100
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"));
1112 FML_LOG(ERROR) <<
"Could not locate SurfaceTextureWrapper class";
1113 return false;
1114 }
1115
1118
1119 if (g_attach_to_gl_context_method == nullptr) {
1120 FML_LOG(ERROR) <<
"Could not locate attachToGlContext method";
1121 return false;
1122 }
1123
1126
1127 if (g_surface_texture_wrapper_should_update == nullptr) {
1129 << "Could not locate SurfaceTextureWrapper.shouldUpdate method";
1130 return false;
1131 }
1132
1135
1136 if (g_update_tex_image_method == nullptr) {
1137 FML_LOG(ERROR) <<
"Could not locate updateTexImage method";
1138 return false;
1139 }
1140
1143
1144 if (g_get_transform_matrix_method == nullptr) {
1145 FML_LOG(ERROR) <<
"Could not locate getTransformMatrix method";
1146 return false;
1147 }
1148
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
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"));
1176 FML_LOG(ERROR) <<
"Could not locate Image class";
1177 return false;
1178 }
1179
1180
1182
1185 "()Landroid/hardware/HardwareBuffer;");
1186
1187 if (g_image_get_hardware_buffer_method == nullptr) {
1188
1190 }
1191
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
1202 env, env->FindClass("android/hardware/HardwareBuffer"));
1203
1207 if (g_hardware_buffer_close_method == nullptr) {
1208
1210 }
1211 } else {
1212
1214 }
1215
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
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"));
1236 FML_LOG(ERROR) <<
"Could not locate java.lang.Long class";
1237 return false;
1238 }
1239
1240
1242 env, env->FindClass("android/graphics/Path"));
1244 FML_LOG(ERROR) <<
"Could not locate android.graphics.Path class";
1245 return false;
1246 }
1247
1249 if (path_constructor == nullptr) {
1250 FML_LOG(ERROR) <<
"Could not locate android.graphics.Path constructor";
1251 return false;
1252 }
1253
1255 path_class->obj(),
"setFillType",
"(Landroid/graphics/Path$FillType;)V");
1256 if (path_set_fill_type_method == nullptr) {
1258 << "Could not locate android.graphics.Path.setFillType method";
1259 return false;
1260 }
1261
1263 if (path_move_to_method == nullptr) {
1264 FML_LOG(ERROR) <<
"Could not locate android.graphics.Path.moveTo method";
1265 return false;
1266 }
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
1286
1288 env->GetMethodID(
path_class->obj(),
"conicTo",
"(FFFFF)V");
1289 if (path_conic_to_method == nullptr) {
1290
1292 }
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"));
1302 FML_LOG(ERROR) <<
"Could not locate android.graphics.Path$FillType class";
1303 return false;
1304 }
1305
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
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
1323}
1324
1325PlatformViewAndroidJNIImpl::PlatformViewAndroidJNIImpl(
1327 : java_object_(java_object) {}
1328
1329PlatformViewAndroidJNIImpl::~PlatformViewAndroidJNIImpl() = default;
1330
1331void PlatformViewAndroidJNIImpl::FlutterViewHandlePlatformMessage(
1332 std::unique_ptr<flutter::PlatformMessage>
message,
1333 int responseId) {
1334
1336
1337 auto java_object = java_object_.get(env);
1338 if (java_object.is_null()) {
1339 return;
1340 }
1341
1344
1347 env, env->NewDirectByteBuffer(
1348 const_cast<uint8_t*
>(
message->data().GetMapping()),
1350
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) {
1366
1367 auto java_object = java_object_.get(env);
1368 if (java_object.is_null()) {
1369 return;
1370 }
1371
1374
1375 env->CallVoidMethod(java_object.obj(), g_set_application_locale_method,
1377
1379}
1380
1381void PlatformViewAndroidJNIImpl::FlutterViewHandlePlatformMessageResponse(
1382 int responseId,
1383 std::unique_ptr<fml::Mapping>
data) {
1384
1385
1387
1388 auto java_object = java_object_.get(env);
1389 if (java_object.is_null()) {
1390
1391
1392 return;
1393 }
1394 if (
data ==
nullptr) {
1395 env->CallVoidMethod(java_object.obj(),
1396 g_handle_platform_message_response_method, responseId,
1397 nullptr);
1398 } else {
1399
1401 env, env->NewDirectByteBuffer(
const_cast<uint8_t*
>(
data->GetMapping()),
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(
1414 int configuration_id) const {
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) {
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()));
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) {
1458
1459 auto java_object = java_object_.get(env);
1460 if (java_object.is_null()) {
1461 return;
1462 }
1463
1465 env,
1466 env->NewDirectByteBuffer(actions_buffer.data(), actions_buffer.size()));
1467
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() {
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() {
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) {
1508
1509 if (surface_texture.is_null()) {
1510 return;
1511 }
1512
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) {
1530
1531 if (surface_texture.is_null()) {
1532 return false;
1533 }
1534
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) {
1553
1554 if (surface_texture.is_null()) {
1555 return;
1556 }
1557
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) {
1574
1575 if (surface_texture.is_null()) {
1576 return {};
1577 }
1578
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
1601}
1602
1603void PlatformViewAndroidJNIImpl::SurfaceTextureDetachFromGLContext(
1604 JavaLocalRef surface_texture) {
1606
1607 if (surface_texture.is_null()) {
1608 return;
1609 }
1610
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) {
1628
1629 if (image_producer_texture_entry.is_null()) {
1630
1632 }
1633
1634
1635
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
1643 }
1644
1646 env, env->CallObjectMethod(image_producer_texture_entry_local_ref.obj(),
1647 g_acquire_latest_image_method));
1649 return r;
1650 }
1651
1653}
1654
1655JavaLocalRef PlatformViewAndroidJNIImpl::ImageGetHardwareBuffer(
1656 JavaLocalRef
image) {
1657 FML_CHECK(g_image_get_hardware_buffer_method !=
nullptr);
1659 if (
image.is_null()) {
1660
1662 }
1664 env,
1665 env->CallObjectMethod(
image.obj(), g_image_get_hardware_buffer_method));
1667 return r;
1668}
1669
1670void PlatformViewAndroidJNIImpl::ImageClose(JavaLocalRef
image) {
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);
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(
1696 int viewWidth,
1697 int viewHeight,
1698 MutatorsStack mutators_stack) {
1700 auto java_object = java_object_.get(env);
1701 if (java_object.is_null()) {
1702 return;
1703 }
1704
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();
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: {
1740 const DlRect& rect = rrect.GetBounds();
1742 SkScalar radiis[8] = {
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();
1764 SkScalar radiis[8] = {
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
1783
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,
1794 mutatorsStack);
1795
1797}
1798
1799void PlatformViewAndroidJNIImpl::FlutterViewDisplayOverlaySurface(
1800 int surface_id,
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,
1814
1816}
1817
1818void PlatformViewAndroidJNIImpl::FlutterViewBeginFrame() {
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() {
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() {
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() {
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) {
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 }
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);
1912 env,
static_cast<jstring
>(env->GetObjectArrayElement(result,
i))));
1913 }
1914 return out;
1915}
1916
1917double PlatformViewAndroidJNIImpl::GetDisplayRefreshRate() {
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() {
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() {
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() {
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) {
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
2006
2007ASurfaceTransaction* PlatformViewAndroidJNIImpl::createTransaction() {
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
2024 env, transaction.obj());
2025}
2026
2027void PlatformViewAndroidJNIImpl::swapTransaction() {
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() {
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() {
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() {
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 {
2100 public:
2101 explicit AndroidPathReceiver(JNIEnv* env)
2102 : env_(env),
2104
2105 void SetFillType(DlPathFillType
type) {
2106 jfieldID fill_type_field_id;
2108 case DlPathFillType::kOdd:
2110 break;
2111 case DlPathFillType::kNonZero:
2113 break;
2114 default:
2115
2116
2117 return;
2118 }
2119
2120
2121
2125 fill_type_field_id));
2128
2129
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}
2170
2171void PlatformViewAndroidJNIImpl::onDisplayPlatformView2(
2177 int32_t viewWidth,
2178 int32_t viewHeight,
2179 MutatorsStack mutators_stack) {
2181 auto java_object = java_object_.get(env);
2182 if (java_object.is_null()) {
2183 return;
2184 }
2185
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();
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: {
2221 const DlRect& rect = rrect.GetBounds();
2223 SkScalar radiis[8] = {
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();
2245 SkScalar radiis[8] = {
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
2272
2273
2274
2278
2279
2280 AndroidPathReceiver receiver(env);
2281 receiver.SetFillType(dlPath.GetFillType());
2282
2283
2284
2285
2286 dlPath.Dispatch(receiver);
2287
2288 env->CallVoidMethod(mutatorsStack,
2289 g_mutators_stack_push_clippath_method,
2290 receiver.TakePath());
2291 break;
2292 }
2293
2294
2295 case MutatorType::kBackdropFilter:
2296 break;
2297 }
2298 ++iter;
2299 }
2300
2301 env->CallVoidMethod(java_object.obj(), g_on_display_platform_view2_method,
2303 mutatorsStack);
2304
2306}
2307
2308void PlatformViewAndroidJNIImpl::hidePlatformView2(int32_t
view_id) {
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() {
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() {
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() {
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}
static std::unique_ptr< DartCallbackRepresentation > GetCallbackInformation(int64_t handle)
A Mapping like NonOwnedMapping, but uses Free as its release proc.
static MallocMapping Copy(const T *begin, const T *end)
static fml::RefPtr< NativeLibrary > CreateWithHandle(Handle handle, bool close_handle_when_done)
FlutterVulkanImage * image
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_BEGIN_DECLS GBytes * message
G_BEGIN_DECLS FlutterViewId view_id
#define FML_LOG(severity)
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
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
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::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
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
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()
ScopedJavaLocalRef< jobjectArray > VectorToBufferArray(JNIEnv *env, const std::vector< std::vector< uint8_t > > &vector)
std::string JavaStringToString(JNIEnv *env, jstring str)
bool ClearException(JNIEnv *env, bool silent)
bool CheckException(JNIEnv *env)
ScopedJavaLocalRef< jobjectArray > VectorToStringArray(JNIEnv *env, const std::vector< std::string > &vector)
std::vector< std::string > StringListToVector(JNIEnv *env, jobject list)
std::vector< std::string > StringArrayToVector(JNIEnv *env, jobjectArray array)
ScopedJavaLocalRef< jstring > StringToJavaString(JNIEnv *env, const std::string &u8_string)
const ProcTable & GetProcTable()
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)
std::shared_ptr< const fml::Mapping > data