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