1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "flutter/shell/platform/android/platform_view_android_jni.h"
6
7 #include <android/native_window_jni.h>
8
9 #include <utility>
10
11 #include "flutter/assets/directory_asset_bundle.h"
12 #include "flutter/common/settings.h"
13 #include "flutter/fml/file.h"
14 #include "flutter/fml/platform/android/jni_util.h"
15 #include "flutter/fml/platform/android/jni_weak_ref.h"
16 #include "flutter/fml/platform/android/scoped_java_ref.h"
17 #include "flutter/fml/size.h"
18 #include "flutter/lib/ui/plugins/callback_cache.h"
19 #include "flutter/runtime/dart_service_isolate.h"
20 #include "flutter/shell/common/run_configuration.h"
21 #include "flutter/shell/platform/android/android_external_texture_gl.h"
22 #include "flutter/shell/platform/android/android_shell_holder.h"
23 #include "flutter/shell/platform/android/apk_asset_provider.h"
24 #include "flutter/shell/platform/android/flutter_main.h"
25
26 #define ANDROID_SHELL_HOLDER \
27 (reinterpret_cast<AndroidShellHolder*>(shell_holder))
28
29 namespace flutter {
30
31 namespace {
32
CheckException(JNIEnv * env)33 bool CheckException(JNIEnv* env) {
34 if (env->ExceptionCheck() == JNI_FALSE)
35 return true;
36
37 jthrowable exception = env->ExceptionOccurred();
38 env->ExceptionClear();
39 FML_LOG(ERROR) << fml::jni::GetJavaExceptionInfo(env, exception);
40 env->DeleteLocalRef(exception);
41 return false;
42 }
43
44 } // anonymous namespace
45
46 static fml::jni::ScopedJavaGlobalRef<jclass>* g_flutter_callback_info_class =
47 nullptr;
48
49 static fml::jni::ScopedJavaGlobalRef<jclass>* g_flutter_jni_class = nullptr;
50
51 static fml::jni::ScopedJavaGlobalRef<jclass>* g_surface_texture_class = nullptr;
52
53 // Called By Native
54
55 static jmethodID g_flutter_callback_info_constructor = nullptr;
CreateFlutterCallbackInformation(JNIEnv * env,const std::string & callbackName,const std::string & callbackClassName,const std::string & callbackLibraryPath)56 jobject CreateFlutterCallbackInformation(
57 JNIEnv* env,
58 const std::string& callbackName,
59 const std::string& callbackClassName,
60 const std::string& callbackLibraryPath) {
61 return env->NewObject(g_flutter_callback_info_class->obj(),
62 g_flutter_callback_info_constructor,
63 env->NewStringUTF(callbackName.c_str()),
64 env->NewStringUTF(callbackClassName.c_str()),
65 env->NewStringUTF(callbackLibraryPath.c_str()));
66 }
67
68 static jmethodID g_handle_platform_message_method = nullptr;
FlutterViewHandlePlatformMessage(JNIEnv * env,jobject obj,jstring channel,jobject message,jint responseId)69 void FlutterViewHandlePlatformMessage(JNIEnv* env,
70 jobject obj,
71 jstring channel,
72 jobject message,
73 jint responseId) {
74 env->CallVoidMethod(obj, g_handle_platform_message_method, channel, message,
75 responseId);
76 FML_CHECK(CheckException(env));
77 }
78
79 static jmethodID g_handle_platform_message_response_method = nullptr;
FlutterViewHandlePlatformMessageResponse(JNIEnv * env,jobject obj,jint responseId,jobject response)80 void FlutterViewHandlePlatformMessageResponse(JNIEnv* env,
81 jobject obj,
82 jint responseId,
83 jobject response) {
84 env->CallVoidMethod(obj, g_handle_platform_message_response_method,
85 responseId, response);
86 FML_CHECK(CheckException(env));
87 }
88
89 static jmethodID g_update_semantics_method = nullptr;
FlutterViewUpdateSemantics(JNIEnv * env,jobject obj,jobject buffer,jobjectArray strings)90 void FlutterViewUpdateSemantics(JNIEnv* env,
91 jobject obj,
92 jobject buffer,
93 jobjectArray strings) {
94 env->CallVoidMethod(obj, g_update_semantics_method, buffer, strings);
95 FML_CHECK(CheckException(env));
96 }
97
98 static jmethodID g_update_custom_accessibility_actions_method = nullptr;
FlutterViewUpdateCustomAccessibilityActions(JNIEnv * env,jobject obj,jobject buffer,jobjectArray strings)99 void FlutterViewUpdateCustomAccessibilityActions(JNIEnv* env,
100 jobject obj,
101 jobject buffer,
102 jobjectArray strings) {
103 env->CallVoidMethod(obj, g_update_custom_accessibility_actions_method, buffer,
104 strings);
105 FML_CHECK(CheckException(env));
106 }
107
108 static jmethodID g_on_first_frame_method = nullptr;
FlutterViewOnFirstFrame(JNIEnv * env,jobject obj)109 void FlutterViewOnFirstFrame(JNIEnv* env, jobject obj) {
110 env->CallVoidMethod(obj, g_on_first_frame_method);
111 FML_CHECK(CheckException(env));
112 }
113
114 static jmethodID g_on_engine_restart_method = nullptr;
FlutterViewOnPreEngineRestart(JNIEnv * env,jobject obj)115 void FlutterViewOnPreEngineRestart(JNIEnv* env, jobject obj) {
116 env->CallVoidMethod(obj, g_on_engine_restart_method);
117 FML_CHECK(CheckException(env));
118 }
119
120 static jmethodID g_attach_to_gl_context_method = nullptr;
SurfaceTextureAttachToGLContext(JNIEnv * env,jobject obj,jint textureId)121 void SurfaceTextureAttachToGLContext(JNIEnv* env, jobject obj, jint textureId) {
122 env->CallVoidMethod(obj, g_attach_to_gl_context_method, textureId);
123 FML_CHECK(CheckException(env));
124 }
125
126 static jmethodID g_update_tex_image_method = nullptr;
SurfaceTextureUpdateTexImage(JNIEnv * env,jobject obj)127 void SurfaceTextureUpdateTexImage(JNIEnv* env, jobject obj) {
128 env->CallVoidMethod(obj, g_update_tex_image_method);
129 FML_CHECK(CheckException(env));
130 }
131
132 static jmethodID g_get_transform_matrix_method = nullptr;
SurfaceTextureGetTransformMatrix(JNIEnv * env,jobject obj,jfloatArray result)133 void SurfaceTextureGetTransformMatrix(JNIEnv* env,
134 jobject obj,
135 jfloatArray result) {
136 env->CallVoidMethod(obj, g_get_transform_matrix_method, result);
137 FML_CHECK(CheckException(env));
138 }
139
140 static jmethodID g_detach_from_gl_context_method = nullptr;
SurfaceTextureDetachFromGLContext(JNIEnv * env,jobject obj)141 void SurfaceTextureDetachFromGLContext(JNIEnv* env, jobject obj) {
142 env->CallVoidMethod(obj, g_detach_from_gl_context_method);
143 FML_CHECK(CheckException(env));
144 }
145
146 // Called By Java
147
AttachJNI(JNIEnv * env,jclass clazz,jobject flutterJNI,jboolean is_background_view)148 static jlong AttachJNI(JNIEnv* env,
149 jclass clazz,
150 jobject flutterJNI,
151 jboolean is_background_view) {
152 fml::jni::JavaObjectWeakGlobalRef java_object(env, flutterJNI);
153 auto shell_holder = std::make_unique<AndroidShellHolder>(
154 FlutterMain::Get().GetSettings(), java_object, is_background_view);
155 if (shell_holder->IsValid()) {
156 return reinterpret_cast<jlong>(shell_holder.release());
157 } else {
158 return 0;
159 }
160 }
161
DestroyJNI(JNIEnv * env,jobject jcaller,jlong shell_holder)162 static void DestroyJNI(JNIEnv* env, jobject jcaller, jlong shell_holder) {
163 delete ANDROID_SHELL_HOLDER;
164 }
165
SurfaceCreated(JNIEnv * env,jobject jcaller,jlong shell_holder,jobject jsurface)166 static void SurfaceCreated(JNIEnv* env,
167 jobject jcaller,
168 jlong shell_holder,
169 jobject jsurface) {
170 // Note: This frame ensures that any local references used by
171 // ANativeWindow_fromSurface are released immediately. This is needed as a
172 // workaround for https://code.google.com/p/android/issues/detail?id=68174
173 fml::jni::ScopedJavaLocalFrame scoped_local_reference_frame(env);
174 auto window = fml::MakeRefCounted<AndroidNativeWindow>(
175 ANativeWindow_fromSurface(env, jsurface));
176 ANDROID_SHELL_HOLDER->GetPlatformView()->NotifyCreated(std::move(window));
177 }
178
SurfaceChanged(JNIEnv * env,jobject jcaller,jlong shell_holder,jint width,jint height)179 static void SurfaceChanged(JNIEnv* env,
180 jobject jcaller,
181 jlong shell_holder,
182 jint width,
183 jint height) {
184 ANDROID_SHELL_HOLDER->GetPlatformView()->NotifyChanged(
185 SkISize::Make(width, height));
186 }
187
SurfaceDestroyed(JNIEnv * env,jobject jcaller,jlong shell_holder)188 static void SurfaceDestroyed(JNIEnv* env, jobject jcaller, jlong shell_holder) {
189 ANDROID_SHELL_HOLDER->GetPlatformView()->NotifyDestroyed();
190 }
191
RunBundleAndSnapshotFromLibrary(JNIEnv * env,jobject jcaller,jlong shell_holder,jstring jBundlePath,jstring jEntrypoint,jstring jLibraryUrl,jobject jAssetManager)192 static void RunBundleAndSnapshotFromLibrary(JNIEnv* env,
193 jobject jcaller,
194 jlong shell_holder,
195 jstring jBundlePath,
196 jstring jEntrypoint,
197 jstring jLibraryUrl,
198 jobject jAssetManager) {
199 auto asset_manager = std::make_shared<flutter::AssetManager>();
200
201 asset_manager->PushBack(std::make_unique<flutter::APKAssetProvider>(
202 env, // jni environment
203 jAssetManager, // asset manager
204 fml::jni::JavaStringToString(env, jBundlePath)) // apk asset dir
205 );
206
207 std::unique_ptr<IsolateConfiguration> isolate_configuration;
208 if (flutter::DartVM::IsRunningPrecompiledCode()) {
209 isolate_configuration = IsolateConfiguration::CreateForAppSnapshot();
210 } else {
211 std::unique_ptr<fml::Mapping> kernel_blob =
212 fml::FileMapping::CreateReadOnly(
213 ANDROID_SHELL_HOLDER->GetSettings().application_kernel_asset);
214 if (!kernel_blob) {
215 FML_DLOG(ERROR) << "Unable to load the kernel blob asset.";
216 return;
217 }
218 isolate_configuration =
219 IsolateConfiguration::CreateForKernel(std::move(kernel_blob));
220 }
221
222 RunConfiguration config(std::move(isolate_configuration),
223 std::move(asset_manager));
224
225 {
226 auto entrypoint = fml::jni::JavaStringToString(env, jEntrypoint);
227 auto libraryUrl = fml::jni::JavaStringToString(env, jLibraryUrl);
228
229 if ((entrypoint.size() > 0) && (libraryUrl.size() > 0)) {
230 config.SetEntrypointAndLibrary(std::move(entrypoint),
231 std::move(libraryUrl));
232 } else if (entrypoint.size() > 0) {
233 config.SetEntrypoint(std::move(entrypoint));
234 }
235 }
236
237 ANDROID_SHELL_HOLDER->Launch(std::move(config));
238 }
239
LookupCallbackInformation(JNIEnv * env,jobject,jlong handle)240 static jobject LookupCallbackInformation(JNIEnv* env,
241 /* unused */ jobject,
242 jlong handle) {
243 auto cbInfo = flutter::DartCallbackCache::GetCallbackInformation(handle);
244 if (cbInfo == nullptr) {
245 return nullptr;
246 }
247 return CreateFlutterCallbackInformation(env, cbInfo->name, cbInfo->class_name,
248 cbInfo->library_path);
249 }
250
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)251 static void SetViewportMetrics(JNIEnv* env,
252 jobject jcaller,
253 jlong shell_holder,
254 jfloat devicePixelRatio,
255 jint physicalWidth,
256 jint physicalHeight,
257 jint physicalPaddingTop,
258 jint physicalPaddingRight,
259 jint physicalPaddingBottom,
260 jint physicalPaddingLeft,
261 jint physicalViewInsetTop,
262 jint physicalViewInsetRight,
263 jint physicalViewInsetBottom,
264 jint physicalViewInsetLeft,
265 jint systemGestureInsetTop,
266 jint systemGestureInsetRight,
267 jint systemGestureInsetBottom,
268 jint systemGestureInsetLeft) {
269 const flutter::ViewportMetrics metrics{
270 static_cast<double>(devicePixelRatio),
271 static_cast<double>(physicalWidth),
272 static_cast<double>(physicalHeight),
273 static_cast<double>(physicalPaddingTop),
274 static_cast<double>(physicalPaddingRight),
275 static_cast<double>(physicalPaddingBottom),
276 static_cast<double>(physicalPaddingLeft),
277 static_cast<double>(physicalViewInsetTop),
278 static_cast<double>(physicalViewInsetRight),
279 static_cast<double>(physicalViewInsetBottom),
280 static_cast<double>(physicalViewInsetLeft),
281 static_cast<double>(systemGestureInsetTop),
282 static_cast<double>(systemGestureInsetRight),
283 static_cast<double>(systemGestureInsetBottom),
284 static_cast<double>(systemGestureInsetLeft),
285 };
286
287 ANDROID_SHELL_HOLDER->GetPlatformView()->SetViewportMetrics(metrics);
288 }
289
GetBitmap(JNIEnv * env,jobject jcaller,jlong shell_holder)290 static jobject GetBitmap(JNIEnv* env, jobject jcaller, jlong shell_holder) {
291 auto screenshot = ANDROID_SHELL_HOLDER->Screenshot(
292 Rasterizer::ScreenshotType::UncompressedImage, false);
293 if (screenshot.data == nullptr) {
294 return nullptr;
295 }
296
297 const SkISize& frame_size = screenshot.frame_size;
298 jsize pixels_size = frame_size.width() * frame_size.height();
299 jintArray pixels_array = env->NewIntArray(pixels_size);
300 if (pixels_array == nullptr) {
301 return nullptr;
302 }
303
304 jint* pixels = env->GetIntArrayElements(pixels_array, nullptr);
305 if (pixels == nullptr) {
306 return nullptr;
307 }
308
309 auto* pixels_src = static_cast<const int32_t*>(screenshot.data->data());
310
311 // Our configuration of Skia does not support rendering to the
312 // BitmapConfig.ARGB_8888 format expected by android.graphics.Bitmap.
313 // Convert from kRGBA_8888 to kBGRA_8888 (equivalent to ARGB_8888).
314 for (int i = 0; i < pixels_size; i++) {
315 int32_t src_pixel = pixels_src[i];
316 uint8_t* src_bytes = reinterpret_cast<uint8_t*>(&src_pixel);
317 std::swap(src_bytes[0], src_bytes[2]);
318 pixels[i] = src_pixel;
319 }
320
321 env->ReleaseIntArrayElements(pixels_array, pixels, 0);
322
323 jclass bitmap_class = env->FindClass("android/graphics/Bitmap");
324 if (bitmap_class == nullptr) {
325 return nullptr;
326 }
327
328 jmethodID create_bitmap = env->GetStaticMethodID(
329 bitmap_class, "createBitmap",
330 "([IIILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
331 if (create_bitmap == nullptr) {
332 return nullptr;
333 }
334
335 jclass bitmap_config_class = env->FindClass("android/graphics/Bitmap$Config");
336 if (bitmap_config_class == nullptr) {
337 return nullptr;
338 }
339
340 jmethodID bitmap_config_value_of = env->GetStaticMethodID(
341 bitmap_config_class, "valueOf",
342 "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");
343 if (bitmap_config_value_of == nullptr) {
344 return nullptr;
345 }
346
347 jstring argb = env->NewStringUTF("ARGB_8888");
348 if (argb == nullptr) {
349 return nullptr;
350 }
351
352 jobject bitmap_config = env->CallStaticObjectMethod(
353 bitmap_config_class, bitmap_config_value_of, argb);
354 if (bitmap_config == nullptr) {
355 return nullptr;
356 }
357
358 return env->CallStaticObjectMethod(bitmap_class, create_bitmap, pixels_array,
359 frame_size.width(), frame_size.height(),
360 bitmap_config);
361 }
362
DispatchPlatformMessage(JNIEnv * env,jobject jcaller,jlong shell_holder,jstring channel,jobject message,jint position,jint responseId)363 static void DispatchPlatformMessage(JNIEnv* env,
364 jobject jcaller,
365 jlong shell_holder,
366 jstring channel,
367 jobject message,
368 jint position,
369 jint responseId) {
370 ANDROID_SHELL_HOLDER->GetPlatformView()->DispatchPlatformMessage(
371 env, //
372 fml::jni::JavaStringToString(env, channel), //
373 message, //
374 position, //
375 responseId //
376 );
377 }
378
DispatchEmptyPlatformMessage(JNIEnv * env,jobject jcaller,jlong shell_holder,jstring channel,jint responseId)379 static void DispatchEmptyPlatformMessage(JNIEnv* env,
380 jobject jcaller,
381 jlong shell_holder,
382 jstring channel,
383 jint responseId) {
384 ANDROID_SHELL_HOLDER->GetPlatformView()->DispatchEmptyPlatformMessage(
385 env, //
386 fml::jni::JavaStringToString(env, channel), //
387 responseId //
388 );
389 }
390
DispatchPointerDataPacket(JNIEnv * env,jobject jcaller,jlong shell_holder,jobject buffer,jint position)391 static void DispatchPointerDataPacket(JNIEnv* env,
392 jobject jcaller,
393 jlong shell_holder,
394 jobject buffer,
395 jint position) {
396 uint8_t* data = static_cast<uint8_t*>(env->GetDirectBufferAddress(buffer));
397 auto packet = std::make_unique<flutter::PointerDataPacket>(data, position);
398 ANDROID_SHELL_HOLDER->GetPlatformView()->DispatchPointerDataPacket(
399 std::move(packet));
400 }
401
DispatchSemanticsAction(JNIEnv * env,jobject jcaller,jlong shell_holder,jint id,jint action,jobject args,jint args_position)402 static void DispatchSemanticsAction(JNIEnv* env,
403 jobject jcaller,
404 jlong shell_holder,
405 jint id,
406 jint action,
407 jobject args,
408 jint args_position) {
409 ANDROID_SHELL_HOLDER->GetPlatformView()->DispatchSemanticsAction(
410 env, //
411 id, //
412 action, //
413 args, //
414 args_position //
415 );
416 }
417
SetSemanticsEnabled(JNIEnv * env,jobject jcaller,jlong shell_holder,jboolean enabled)418 static void SetSemanticsEnabled(JNIEnv* env,
419 jobject jcaller,
420 jlong shell_holder,
421 jboolean enabled) {
422 ANDROID_SHELL_HOLDER->GetPlatformView()->SetSemanticsEnabled(enabled);
423 }
424
SetAccessibilityFeatures(JNIEnv * env,jobject jcaller,jlong shell_holder,jint flags)425 static void SetAccessibilityFeatures(JNIEnv* env,
426 jobject jcaller,
427 jlong shell_holder,
428 jint flags) {
429 ANDROID_SHELL_HOLDER->GetPlatformView()->SetAccessibilityFeatures(flags);
430 }
431
GetIsSoftwareRendering(JNIEnv * env,jobject jcaller)432 static jboolean GetIsSoftwareRendering(JNIEnv* env, jobject jcaller) {
433 return FlutterMain::Get().GetSettings().enable_software_rendering;
434 }
435
RegisterTexture(JNIEnv * env,jobject jcaller,jlong shell_holder,jlong texture_id,jobject surface_texture)436 static void RegisterTexture(JNIEnv* env,
437 jobject jcaller,
438 jlong shell_holder,
439 jlong texture_id,
440 jobject surface_texture) {
441 ANDROID_SHELL_HOLDER->GetPlatformView()->RegisterExternalTexture(
442 static_cast<int64_t>(texture_id), //
443 fml::jni::JavaObjectWeakGlobalRef(env, surface_texture) //
444 );
445 }
446
MarkTextureFrameAvailable(JNIEnv * env,jobject jcaller,jlong shell_holder,jlong texture_id)447 static void MarkTextureFrameAvailable(JNIEnv* env,
448 jobject jcaller,
449 jlong shell_holder,
450 jlong texture_id) {
451 ANDROID_SHELL_HOLDER->GetPlatformView()->MarkTextureFrameAvailable(
452 static_cast<int64_t>(texture_id));
453 }
454
UnregisterTexture(JNIEnv * env,jobject jcaller,jlong shell_holder,jlong texture_id)455 static void UnregisterTexture(JNIEnv* env,
456 jobject jcaller,
457 jlong shell_holder,
458 jlong texture_id) {
459 ANDROID_SHELL_HOLDER->GetPlatformView()->UnregisterTexture(
460 static_cast<int64_t>(texture_id));
461 }
462
InvokePlatformMessageResponseCallback(JNIEnv * env,jobject jcaller,jlong shell_holder,jint responseId,jobject message,jint position)463 static void InvokePlatformMessageResponseCallback(JNIEnv* env,
464 jobject jcaller,
465 jlong shell_holder,
466 jint responseId,
467 jobject message,
468 jint position) {
469 ANDROID_SHELL_HOLDER->GetPlatformView()
470 ->InvokePlatformMessageResponseCallback(env, //
471 responseId, //
472 message, //
473 position //
474 );
475 }
476
InvokePlatformMessageEmptyResponseCallback(JNIEnv * env,jobject jcaller,jlong shell_holder,jint responseId)477 static void InvokePlatformMessageEmptyResponseCallback(JNIEnv* env,
478 jobject jcaller,
479 jlong shell_holder,
480 jint responseId) {
481 ANDROID_SHELL_HOLDER->GetPlatformView()
482 ->InvokePlatformMessageEmptyResponseCallback(env, //
483 responseId //
484 );
485 }
486
RegisterApi(JNIEnv * env)487 bool RegisterApi(JNIEnv* env) {
488 static const JNINativeMethod flutter_jni_methods[] = {
489 // Start of methods from FlutterNativeView
490 {
491 .name = "nativeAttach",
492 .signature = "(Lio/flutter/embedding/engine/FlutterJNI;Z)J",
493 .fnPtr = reinterpret_cast<void*>(&AttachJNI),
494 },
495 {
496 .name = "nativeDestroy",
497 .signature = "(J)V",
498 .fnPtr = reinterpret_cast<void*>(&DestroyJNI),
499 },
500 {
501 .name = "nativeRunBundleAndSnapshotFromLibrary",
502 .signature = "(JLjava/lang/String;Ljava/lang/String;"
503 "Ljava/lang/String;Landroid/content/res/AssetManager;)V",
504 .fnPtr = reinterpret_cast<void*>(&RunBundleAndSnapshotFromLibrary),
505 },
506 {
507 .name = "nativeDispatchEmptyPlatformMessage",
508 .signature = "(JLjava/lang/String;I)V",
509 .fnPtr = reinterpret_cast<void*>(&DispatchEmptyPlatformMessage),
510 },
511 {
512 .name = "nativeDispatchPlatformMessage",
513 .signature = "(JLjava/lang/String;Ljava/nio/ByteBuffer;II)V",
514 .fnPtr = reinterpret_cast<void*>(&DispatchPlatformMessage),
515 },
516 {
517 .name = "nativeInvokePlatformMessageResponseCallback",
518 .signature = "(JILjava/nio/ByteBuffer;I)V",
519 .fnPtr =
520 reinterpret_cast<void*>(&InvokePlatformMessageResponseCallback),
521 },
522 {
523 .name = "nativeInvokePlatformMessageEmptyResponseCallback",
524 .signature = "(JI)V",
525 .fnPtr = reinterpret_cast<void*>(
526 &InvokePlatformMessageEmptyResponseCallback),
527 },
528
529 // Start of methods from FlutterView
530 {
531 .name = "nativeGetBitmap",
532 .signature = "(J)Landroid/graphics/Bitmap;",
533 .fnPtr = reinterpret_cast<void*>(&GetBitmap),
534 },
535 {
536 .name = "nativeSurfaceCreated",
537 .signature = "(JLandroid/view/Surface;)V",
538 .fnPtr = reinterpret_cast<void*>(&SurfaceCreated),
539 },
540 {
541 .name = "nativeSurfaceChanged",
542 .signature = "(JII)V",
543 .fnPtr = reinterpret_cast<void*>(&SurfaceChanged),
544 },
545 {
546 .name = "nativeSurfaceDestroyed",
547 .signature = "(J)V",
548 .fnPtr = reinterpret_cast<void*>(&SurfaceDestroyed),
549 },
550 {
551 .name = "nativeSetViewportMetrics",
552 .signature = "(JFIIIIIIIIIIIIII)V",
553 .fnPtr = reinterpret_cast<void*>(&SetViewportMetrics),
554 },
555 {
556 .name = "nativeDispatchPointerDataPacket",
557 .signature = "(JLjava/nio/ByteBuffer;I)V",
558 .fnPtr = reinterpret_cast<void*>(&DispatchPointerDataPacket),
559 },
560 {
561 .name = "nativeDispatchSemanticsAction",
562 .signature = "(JIILjava/nio/ByteBuffer;I)V",
563 .fnPtr = reinterpret_cast<void*>(&DispatchSemanticsAction),
564 },
565 {
566 .name = "nativeSetSemanticsEnabled",
567 .signature = "(JZ)V",
568 .fnPtr = reinterpret_cast<void*>(&SetSemanticsEnabled),
569 },
570 {
571 .name = "nativeSetAccessibilityFeatures",
572 .signature = "(JI)V",
573 .fnPtr = reinterpret_cast<void*>(&SetAccessibilityFeatures),
574 },
575 {
576 .name = "nativeGetIsSoftwareRenderingEnabled",
577 .signature = "()Z",
578 .fnPtr = reinterpret_cast<void*>(&GetIsSoftwareRendering),
579 },
580 {
581 .name = "nativeRegisterTexture",
582 .signature = "(JJLandroid/graphics/SurfaceTexture;)V",
583 .fnPtr = reinterpret_cast<void*>(&RegisterTexture),
584 },
585 {
586 .name = "nativeMarkTextureFrameAvailable",
587 .signature = "(JJ)V",
588 .fnPtr = reinterpret_cast<void*>(&MarkTextureFrameAvailable),
589 },
590 {
591 .name = "nativeUnregisterTexture",
592 .signature = "(JJ)V",
593 .fnPtr = reinterpret_cast<void*>(&UnregisterTexture),
594 },
595
596 // Methods for Dart callback functionality.
597 {
598 .name = "nativeLookupCallbackInformation",
599 .signature = "(J)Lio/flutter/view/FlutterCallbackInformation;",
600 .fnPtr = reinterpret_cast<void*>(&LookupCallbackInformation),
601 },
602 };
603
604 if (env->RegisterNatives(g_flutter_jni_class->obj(), flutter_jni_methods,
605 fml::size(flutter_jni_methods)) != 0) {
606 FML_LOG(ERROR) << "Failed to RegisterNatives with FlutterJNI";
607 return false;
608 }
609
610 g_handle_platform_message_method =
611 env->GetMethodID(g_flutter_jni_class->obj(), "handlePlatformMessage",
612 "(Ljava/lang/String;[BI)V");
613
614 if (g_handle_platform_message_method == nullptr) {
615 FML_LOG(ERROR) << "Could not locate handlePlatformMessage method";
616 return false;
617 }
618
619 g_handle_platform_message_response_method = env->GetMethodID(
620 g_flutter_jni_class->obj(), "handlePlatformMessageResponse", "(I[B)V");
621
622 if (g_handle_platform_message_response_method == nullptr) {
623 FML_LOG(ERROR) << "Could not locate handlePlatformMessageResponse method";
624 return false;
625 }
626
627 g_update_semantics_method =
628 env->GetMethodID(g_flutter_jni_class->obj(), "updateSemantics",
629 "(Ljava/nio/ByteBuffer;[Ljava/lang/String;)V");
630
631 if (g_update_semantics_method == nullptr) {
632 FML_LOG(ERROR) << "Could not locate updateSemantics method";
633 return false;
634 }
635
636 g_update_custom_accessibility_actions_method = env->GetMethodID(
637 g_flutter_jni_class->obj(), "updateCustomAccessibilityActions",
638 "(Ljava/nio/ByteBuffer;[Ljava/lang/String;)V");
639
640 if (g_update_custom_accessibility_actions_method == nullptr) {
641 FML_LOG(ERROR)
642 << "Could not locate updateCustomAccessibilityActions method";
643 return false;
644 }
645
646 g_on_first_frame_method =
647 env->GetMethodID(g_flutter_jni_class->obj(), "onFirstFrame", "()V");
648
649 if (g_on_first_frame_method == nullptr) {
650 FML_LOG(ERROR) << "Could not locate onFirstFrame method";
651 return false;
652 }
653
654 g_on_engine_restart_method =
655 env->GetMethodID(g_flutter_jni_class->obj(), "onPreEngineRestart", "()V");
656
657 if (g_on_engine_restart_method == nullptr) {
658 FML_LOG(ERROR) << "Could not locate onEngineRestart method";
659 return false;
660 }
661
662 return true;
663 }
664
Register(JNIEnv * env)665 bool PlatformViewAndroid::Register(JNIEnv* env) {
666 if (env == nullptr) {
667 FML_LOG(ERROR) << "No JNIEnv provided";
668 return false;
669 }
670
671 g_flutter_callback_info_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
672 env, env->FindClass("io/flutter/view/FlutterCallbackInformation"));
673 if (g_flutter_callback_info_class->is_null()) {
674 FML_LOG(ERROR) << "Could not locate FlutterCallbackInformation class";
675 return false;
676 }
677
678 g_flutter_callback_info_constructor = env->GetMethodID(
679 g_flutter_callback_info_class->obj(), "<init>",
680 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
681 if (g_flutter_callback_info_constructor == nullptr) {
682 FML_LOG(ERROR) << "Could not locate FlutterCallbackInformation constructor";
683 return false;
684 }
685
686 g_flutter_jni_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
687 env, env->FindClass("io/flutter/embedding/engine/FlutterJNI"));
688 if (g_flutter_jni_class->is_null()) {
689 FML_LOG(ERROR) << "Failed to find FlutterJNI Class.";
690 return false;
691 }
692
693 g_surface_texture_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
694 env, env->FindClass("android/graphics/SurfaceTexture"));
695 if (g_surface_texture_class->is_null()) {
696 FML_LOG(ERROR) << "Could not locate SurfaceTexture class";
697 return false;
698 }
699
700 g_attach_to_gl_context_method = env->GetMethodID(
701 g_surface_texture_class->obj(), "attachToGLContext", "(I)V");
702
703 if (g_attach_to_gl_context_method == nullptr) {
704 FML_LOG(ERROR) << "Could not locate attachToGlContext method";
705 return false;
706 }
707
708 g_update_tex_image_method =
709 env->GetMethodID(g_surface_texture_class->obj(), "updateTexImage", "()V");
710
711 if (g_update_tex_image_method == nullptr) {
712 FML_LOG(ERROR) << "Could not locate updateTexImage method";
713 return false;
714 }
715
716 g_get_transform_matrix_method = env->GetMethodID(
717 g_surface_texture_class->obj(), "getTransformMatrix", "([F)V");
718
719 if (g_get_transform_matrix_method == nullptr) {
720 FML_LOG(ERROR) << "Could not locate getTransformMatrix method";
721 return false;
722 }
723
724 g_detach_from_gl_context_method = env->GetMethodID(
725 g_surface_texture_class->obj(), "detachFromGLContext", "()V");
726
727 if (g_detach_from_gl_context_method == nullptr) {
728 FML_LOG(ERROR) << "Could not locate detachFromGlContext method";
729 return false;
730 }
731
732 return RegisterApi(env);
733 }
734
735 } // namespace flutter
736