Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
platform_view_android_jni_impl.cc File Reference

Go to the source code of this file.

Namespaces

namespace  flutter
 

Macros

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

Functions

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

Variables

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

Macro Definition Documentation

◆ ANDROID_SHELL_HOLDER

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

Definition at line 31 of file platform_view_android_jni_impl.cc.

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

◆ FLUTTER_BIND_JNI

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

Definition at line 110 of file platform_view_android_jni_impl.cc.

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

◆ FLUTTER_DECLARE_JNI

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

*end#*‍/

Definition at line 107 of file platform_view_android_jni_impl.cc.

◆ FLUTTER_FOR_EACH_JNI_METHOD

#define FLUTTER_FOR_EACH_JNI_METHOD (   V)

Definition at line 65 of file platform_view_android_jni_impl.cc.