From 3ba1c4e51f4365cf2ea4cb05a5a3d3838f27324c Mon Sep 17 00:00:00 2001 From: cg021 Date: Sat, 6 Jun 2020 16:05:43 -0500 Subject: [PATCH 1/2] createOverlaySurface JNI --- .gradle/6.5/fileChanges/last-build.bin | Bin 0 -> 1 bytes .gradle/6.5/gc.properties | 0 .gradle/buildOutputCleanup/cache.properties | 2 + .gradle/vcs-1/gc.properties | 0 ci/licenses_golden/licenses_flutter | 3 + shell/platform/android/BUILD.gn | 1 + .../engine/FlutterOverlaySurface.java | 25 +++++++ .../platform/PlatformViewsController.java | 16 +++- .../android/platform_view_android_jni.h | 69 ++++++++++++++++++ .../android/platform_view_android_jni_impl.cc | 28 +++++++ 10 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 .gradle/6.5/fileChanges/last-build.bin create mode 100644 .gradle/6.5/gc.properties create mode 100644 .gradle/buildOutputCleanup/cache.properties create mode 100644 .gradle/vcs-1/gc.properties create mode 100644 shell/platform/android/io/flutter/embedding/engine/FlutterOverlaySurface.java create mode 100644 shell/platform/android/platform_view_android_jni.h diff --git a/.gradle/6.5/fileChanges/last-build.bin b/.gradle/6.5/fileChanges/last-build.bin new file mode 100644 index 0000000000000000000000000000000000000000..f76dd238ade08917e6712764a16a22005a50573d GIT binary patch literal 1 IcmZPo000310RR91 literal 0 HcmV?d00001 diff --git a/.gradle/6.5/gc.properties b/.gradle/6.5/gc.properties new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/.gradle/buildOutputCleanup/cache.properties b/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 0000000000000..114f6aa826de3 --- /dev/null +++ b/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Fri Jun 05 11:53:05 CDT 2020 +gradle.version=6.5 diff --git a/.gradle/vcs-1/gc.properties b/.gradle/vcs-1/gc.properties new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 2770d2953015b..7089ee1f7b333 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -11,6 +11,8 @@ LIBRARY: txt ORIGIN: ../../../flutter/LICENSE TYPE: LicenseType.bsd FILE: ../../../flutter/.clang-tidy +FILE: ../../../flutter/.gradle/6.5/fileChanges/last-build.bin +FILE: ../../../flutter/.gradle/buildOutputCleanup/cache.properties FILE: ../../../flutter/DEPS FILE: ../../../flutter/assets/asset_manager.cc FILE: ../../../flutter/assets/asset_manager.h @@ -702,6 +704,7 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/Flutte FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineCache.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEnginePluginRegistry.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterOverlaySurface.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterShellArgs.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/DartExecutor.java FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/DartMessenger.java diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index f68249194b751..9eb235907f232 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -150,6 +150,7 @@ android_java_sources = [ "io/flutter/embedding/engine/FlutterEngineCache.java", "io/flutter/embedding/engine/FlutterEnginePluginRegistry.java", "io/flutter/embedding/engine/FlutterJNI.java", + "io/flutter/embedding/engine/FlutterOverlaySurface.java", "io/flutter/embedding/engine/FlutterShellArgs.java", "io/flutter/embedding/engine/dart/DartExecutor.java", "io/flutter/embedding/engine/dart/DartMessenger.java", diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterOverlaySurface.java b/shell/platform/android/io/flutter/embedding/engine/FlutterOverlaySurface.java new file mode 100644 index 0000000000000..ecbdb6e9cee32 --- /dev/null +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterOverlaySurface.java @@ -0,0 +1,25 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.embedding.engine; + +import android.view.Surface; + +public class FlutterOverlaySurface { + private final Surface surface; + private final long id; + + public FlutterOverlaySurface(long id, Surface surface) { + this.id = id; + this.surface = surface; + } + + public long getId() { + return id; + } + + public Surface getSurface() { + return surface; + } +} diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java index 43568fe9de051..8fd6d8bb19960 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java @@ -19,6 +19,7 @@ import androidx.annotation.VisibleForTesting; import io.flutter.embedding.engine.dart.DartExecutor; import io.flutter.embedding.engine.systemchannels.PlatformViewsChannel; +import io.flutter.embedding.engine.FlutterOverlaySurface; import io.flutter.plugin.editing.TextInputPlugin; import io.flutter.view.AccessibilityBridge; import io.flutter.view.TextureRegistry; @@ -541,4 +542,17 @@ public void onDisplayPlatformView(int viewId, int x, int y, int width, int heigh public void onDisplayOverlaySurface(int id, int x, int y, int width, int height) { // TODO: Implement this method. https://github.com/flutter/flutter/issues/58288 } -} + + public void onBeginFrame() { + // TODO: Implement this method. https://github.com/flutter/flutter/issues/58288 + } + + public void onEndFrame() { + // TODO: Implement this method. https://github.com/flutter/flutter/issues/58288 + } + + public FlutterOverlaySurface createOverlaySurface() { + // TODO: Implement this method. https://github.com/flutter/flutter/issues/58288 + return null; + } +} \ No newline at end of file diff --git a/shell/platform/android/platform_view_android_jni.h b/shell/platform/android/platform_view_android_jni.h new file mode 100644 index 0000000000000..1ba25e0f05498 --- /dev/null +++ b/shell/platform/android/platform_view_android_jni.h @@ -0,0 +1,69 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_PLATFORM_VIEW_ANDROID_JNI_H_ +#define FLUTTER_SHELL_PLATFORM_ANDROID_PLATFORM_VIEW_ANDROID_JNI_H_ + +#include +#include "flutter/fml/macros.h" +#include "flutter/shell/platform/android/platform_view_android.h" + +namespace flutter { + +void FlutterViewHandlePlatformMessage(JNIEnv* env, + jobject obj, + jstring channel, + jobject message, + jint responseId); + +void FlutterViewHandlePlatformMessageResponse(JNIEnv* env, + jobject obj, + jint responseId, + jobject response); + +void FlutterViewUpdateSemantics(JNIEnv* env, + jobject obj, + jobject buffer, + jobjectArray strings); + +void FlutterViewUpdateCustomAccessibilityActions(JNIEnv* env, + jobject obj, + jobject buffer, + jobjectArray strings); + +void FlutterViewOnFirstFrame(JNIEnv* env, jobject obj); + +void FlutterViewOnPreEngineRestart(JNIEnv* env, jobject obj); + +class AndroidFlutterOverlaySurface { + public: + AndroidFlutterOverlaySurface(long id, fml::RefPtr window) + : id_(id), window_(std::move(window)){}; + + long GetId() { return id_; } + + fml::RefPtr GetWindow() { return window_; } + + private: + long id_; + fml::RefPtr window_; +}; + +std::unique_ptr FlutterViewCreateOverlaySurface( + JNIEnv* env, + jobject obj); + +void SurfaceTextureAttachToGLContext(JNIEnv* env, jobject obj, jint textureId); + +void SurfaceTextureUpdateTexImage(JNIEnv* env, jobject obj); + +void SurfaceTextureGetTransformMatrix(JNIEnv* env, + jobject obj, + jfloatArray result); + +void SurfaceTextureDetachFromGLContext(JNIEnv* env, jobject obj); + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_ANDROID_PLATFORM_VIEW_ANDROID_JNI_H_ diff --git a/shell/platform/android/platform_view_android_jni_impl.cc b/shell/platform/android/platform_view_android_jni_impl.cc index b791f120f7dcf..c1e83222b67ec 100644 --- a/shell/platform/android/platform_view_android_jni_impl.cc +++ b/shell/platform/android/platform_view_android_jni_impl.cc @@ -80,6 +80,26 @@ static jmethodID g_on_first_frame_method = nullptr; static jmethodID g_on_engine_restart_method = nullptr; +static jmethodID g_create_overlay_surface_method = nullptr; +static jmethodID g_flutter_overlay_layer_get_id_method = nullptr; +static jmethodID g_flutter_overlay_layer_get_surface_method = nullptr; + +std::unique_ptr FlutterViewCreateOverlaySurface( + JNIEnv* env, + jobject obj) { + jobject joverlay_layer = + env->CallObjectMethod(obj, g_create_overlay_surface_method); + jlong layer_id = env->CallLongMethod(joverlay_layer, + g_flutter_overlay_layer_get_id_method); + jobject surface = env->CallObjectMethod( + joverlay_layer, g_flutter_overlay_layer_get_surface_method); + + FML_CHECK(CheckException(env)); + return std::make_unique( + layer_id, fml::MakeRefCounted( + ANativeWindow_fromSurface(env, surface))); +} + static jmethodID g_attach_to_gl_context_method = nullptr; static jmethodID g_update_tex_image_method = nullptr; @@ -679,6 +699,10 @@ bool RegisterApi(JNIEnv* env) { return false; } + g_create_overlay_surface_method = + env->GetMethodID(g_flutter_jni_class->obj(), "createOverlaySurface", + "()Lio/flutter/embedding/engine/FlutterOverlaySurface;"); + return true; } @@ -703,6 +727,10 @@ bool PlatformViewAndroid::Register(JNIEnv* env) { return false; } + g_create_overlay_surface_method = + env->GetMethodID(g_flutter_jni_class->obj(), "createOverlaySurface", + "()Lio/flutter/embedding/engine/FlutterOverlaySurface;"); + g_flutter_jni_class = new fml::jni::ScopedJavaGlobalRef( env, env->FindClass("io/flutter/embedding/engine/FlutterJNI")); if (g_flutter_jni_class->is_null()) { From fe8a50336543b17bb1f84a171b534e9629afe0a1 Mon Sep 17 00:00:00 2001 From: cg021 Date: Sun, 14 Jun 2020 21:00:11 -0500 Subject: [PATCH 2/2] fix conflicts --- .../flutter/embedding/engine/FlutterJNI.java | 33 ++++++++ .../engine/FlutterOverlaySurface.java | 3 + .../platform/PlatformViewsController.java | 4 +- .../android/jni/platform_view_android_jni.h | 24 ++++++ .../android/platform_view_android_jni_impl.cc | 75 ++++++++++++++++++- .../android/platform_view_android_jni_impl.h | 6 ++ .../embedding/engine/FlutterJNITest.java | 46 ++++++++++++ 7 files changed, 188 insertions(+), 3 deletions(-) diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index c009574cabab4..a9f4a072ac37b 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -799,6 +799,39 @@ public void onDisplayOverlaySurface(int id, int x, int y, int width, int height) } platformViewsController.onDisplayOverlaySurface(id, x, y, width, height); } + + @SuppressWarnings("unused") + @UiThread + public void onBeginFrame() { + ensureRunningOnMainThread(); + if (platformViewsController == null) { + throw new RuntimeException( + "platformViewsController must be set before attempting to begin the frame"); + } + platformViewsController.onBeginFrame(); + } + + @SuppressWarnings("unused") + @UiThread + public void onEndFrame() { + ensureRunningOnMainThread(); + if (platformViewsController == null) { + throw new RuntimeException( + "platformViewsController must be set before attempting to end the frame"); + } + platformViewsController.onEndFrame(); + } + + @SuppressWarnings("unused") + @UiThread + public FlutterOverlaySurface createOverlaySurface() { + ensureRunningOnMainThread(); + if (platformViewsController == null) { + throw new RuntimeException( + "platformViewsController must be set before attempting to position an overlay surface"); + } + platformViewsController.onDisplayOverlaySurface(id, x, y, width, height); + } // ----- End Engine Lifecycle Support ---- // @SuppressWarnings("unused") diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterOverlaySurface.java b/shell/platform/android/io/flutter/embedding/engine/FlutterOverlaySurface.java index ecbdb6e9cee32..842cb1873c79d 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterOverlaySurface.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterOverlaySurface.java @@ -7,9 +7,12 @@ import android.view.Surface; public class FlutterOverlaySurface { + // @NonNull private final Surface surface; + private final long id; + // @Keep public FlutterOverlaySurface(long id, Surface surface) { this.id = id; this.surface = surface; diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java index 8fd6d8bb19960..706b31228a090 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java @@ -17,9 +17,9 @@ import androidx.annotation.NonNull; import androidx.annotation.UiThread; import androidx.annotation.VisibleForTesting; +import io.flutter.embedding.engine.FlutterOverlaySurface; import io.flutter.embedding.engine.dart.DartExecutor; import io.flutter.embedding.engine.systemchannels.PlatformViewsChannel; -import io.flutter.embedding.engine.FlutterOverlaySurface; import io.flutter.plugin.editing.TextInputPlugin; import io.flutter.view.AccessibilityBridge; import io.flutter.view.TextureRegistry; @@ -555,4 +555,4 @@ public FlutterOverlaySurface createOverlaySurface() { // TODO: Implement this method. https://github.com/flutter/flutter/issues/58288 return null; } -} \ No newline at end of file +} diff --git a/shell/platform/android/jni/platform_view_android_jni.h b/shell/platform/android/jni/platform_view_android_jni.h index eed89a1347845..1f16bc1e7660c 100644 --- a/shell/platform/android/jni/platform_view_android_jni.h +++ b/shell/platform/android/jni/platform_view_android_jni.h @@ -130,6 +130,30 @@ class PlatformViewAndroidJNI { int y, int width, int height) = 0; + + //---------------------------------------------------------------------------- + /// @brief Initiates a frame if using hybrid composition. + /// + /// + /// @note Must be called from the platform thread. + /// + virtual void FlutterViewBeginFrame() = 0; + + //---------------------------------------------------------------------------- + /// @brief Indicates that the current frame ended. + /// It's used to clean up state. + /// + /// @note Must be called from the platform thread. + /// + virtual void FlutterViewEndFrame() = 0; + + //---------------------------------------------------------------------------- + /// @brief Indicates that the current frame ended. + /// It's used to clean up state. + /// + /// @note Must be called from the platform thread. + /// + virtual FlutterOverlaySurface FlutterViewCreateOverlaySurface() = 0; }; } // namespace flutter diff --git a/shell/platform/android/platform_view_android_jni_impl.cc b/shell/platform/android/platform_view_android_jni_impl.cc index c1e83222b67ec..ba80a33f9007e 100644 --- a/shell/platform/android/platform_view_android_jni_impl.cc +++ b/shell/platform/android/platform_view_android_jni_impl.cc @@ -100,6 +100,16 @@ std::unique_ptr FlutterViewCreateOverlaySurface( ANativeWindow_fromSurface(env, surface))); } +static jmethodID g_on_begin_frame_method = nullptr; + +static jmethodID g_on_end_frame_method = nullptr; + +static jmethodID g_create_overlay_surface_method = nullptr; + +static jmethodID g_flutter_overlay_layer_get_id_method = nullptr; + +static jmethodID g_flutter_overlay_layer_get_surface_method = nullptr; + static jmethodID g_attach_to_gl_context_method = nullptr; static jmethodID g_update_tex_image_method = nullptr; @@ -746,6 +756,30 @@ bool PlatformViewAndroid::Register(JNIEnv* env) { return false; } + g_on_begin_frame_method = + env->GetMethodID(g_flutter_jni_class->obj(), "onBeginFrame", "()V"); + + if (g_on_begin_frame_method == nullptr) { + FML_LOG(ERROR) << "Could not locate onBeginFrame method"; + return false; + } + + g_on_end_frame_method = + env->GetMethodID(g_flutter_jni_class->obj(), "onEndFrame", "()V"); + + if (g_on_end_frame_method == nullptr) { + FML_LOG(ERROR) << "Could not locate onEndFrame method"; + return false; + } + + g_create_overlay_surface_method = env->GetMethodID( + g_flutter_jni_class->obj(), "createOverlaySurface", "()V"); + + if (g_create_overlay_surface_method == nullptr) { + FML_LOG(ERROR) << "Could not locate createOverlaySurface method"; + return false; + } + g_on_display_overlay_surface_method = env->GetMethodID( g_flutter_jni_class->obj(), "onDisplayOverlaySurface", "(IIIII)V"); @@ -1062,4 +1096,43 @@ void PlatformViewAndroidJNIImpl::FlutterViewDisplayOverlaySurface( FML_CHECK(CheckException(env)); } -} // namespace flutter +void PlatformViewAndroidJNIImpl::FlutterViewBeginFrame() { + JNIEnv* env = fml::jni::AttachCurrentThread(); + + auto java_object = java_object_.get(env); + if (java_object.is_null()) { + return; + } + + env->CallVoidMethod(java_object.obj(), g_on_begin_frame_method); + + FML_CHECK(CheckException(env)); +} + +void PlatformViewAndroidJNIImpl::FlutterViewEndFrame() { + JNIEnv* env = fml::jni::AttachCurrentThread(); + + auto java_object = java_object_.get(env); + if (java_object.is_null()) { + return; + } + + env->CallVoidMethod(java_object.obj(), g_on_end_frame_method); + + FML_CHECK(CheckException(env)); +} + +void PlatformViewAndroidJNIImpl::FlutterViewCreateOverlaySurface() { + JNIEnv* env = fml::jni::AttachCurrentThread(); + + auto java_object = java_object_.get(env); + if (java_object.is_null()) { + return; + } + + env->CallVoidMethod(java_object.obj(), g_create_overlay_surface_method); + + FML_CHECK(CheckException(env)); +} + +} // namespace flutter \ No newline at end of file diff --git a/shell/platform/android/platform_view_android_jni_impl.h b/shell/platform/android/platform_view_android_jni_impl.h index db0441036b6f1..25b62987ebf18 100644 --- a/shell/platform/android/platform_view_android_jni_impl.h +++ b/shell/platform/android/platform_view_android_jni_impl.h @@ -62,6 +62,12 @@ class PlatformViewAndroidJNIImpl final : public PlatformViewAndroidJNI { int width, int height) override; + void FlutterViewBeginFrame() override; + + void FlutterViewEndFrame() override; + + void FlutterViewCreateOverlaySurface() override; + private: // Reference to FlutterJNI object. const fml::jni::JavaObjectWeakGlobalRef java_object_; diff --git a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java index 3bb26ce7578d2..ac88420509bb4 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java @@ -81,4 +81,50 @@ public void onDisplayOverlaySurface__callsPlatformViewsController() { verify(platformViewsController, times(1)) .onDisplayOverlaySurface(/*id=*/ 1, /*x=*/ 10, /*y=*/ 20, /*width=*/ 100, /*height=*/ 200); } + + @Test + public void onBeginFrame__callsPlatformViewsController() { + PlatformViewsController platformViewsController = mock(PlatformViewsController.class); + + // --- Test Setup --- + FlutterJNI flutterJNI = new FlutterJNI(); + flutterJNI.setPlatformViewsController(platformViewsController); + + // --- Execute Test --- + flutterJNI.onBeginFrame(); + + // --- Verify Results --- + verify(platformViewsController, times(1)).onBeginFrame(); + } + + @Test + public void onEndFrame__callsPlatformViewsController() { + PlatformViewsController platformViewsController = mock(PlatformViewsController.class); + + // --- Test Setup --- + FlutterJNI flutterJNI = new FlutterJNI(); + flutterJNI.setPlatformViewsController(platformViewsController); + + // --- Execute Test --- + flutterJNI.onEndFrame(); + + // --- Verify Results --- + verify(platformViewsController, times(1)).onEndFrame(); + } + + @Test + public void createOverlaySurface__callsPlatformViewsController() { + PlatformViewsController platformViewsController = mock(PlatformViewsController.class); + + FlutterJNI flutterJNI = new FlutterJNI(); + flutterJNI.setPlatformViewsController(platformViewsController); + + // --- Execute Test --- + flutterJNI.onDisplayOverlaySurface( + /*id=*/ 1, /*x=*/ 10, /*y=*/ 20, /*width=*/ 100, /*height=*/ 200); + + // --- Verify Results --- + verify(platformViewsController, times(1)) + .onDisplayOverlaySurface(/*id=*/ 1, /*x=*/ 10, /*y=*/ 20, /*width=*/ 100, /*height=*/ 200); + } }