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

Go to the source code of this file.

Namespaces

namespace  flutter
 

Macros

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

Functions

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

Variables

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

Macro Definition Documentation

◆ ANDROID_SHELL_HOLDER

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

Definition at line 31 of file platform_view_android_jni_impl.cc.

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

◆ FLUTTER_BIND_JNI

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

Definition at line 110 of file platform_view_android_jni_impl.cc.

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

◆ FLUTTER_DECLARE_JNI

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

*end#*‍/

Definition at line 107 of file platform_view_android_jni_impl.cc.

◆ FLUTTER_FOR_EACH_JNI_METHOD

#define FLUTTER_FOR_EACH_JNI_METHOD (   V)

Definition at line 65 of file platform_view_android_jni_impl.cc.