• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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