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

◆ FLUTTER_BIND_JNI

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

Definition at line 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.