diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 4497a763ed419..d23154cafeb3e 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -702,6 +702,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 a14e3809d22d8..94ee1f77d8a33 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/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 397c99e41dcd2..3f6155f93f0b1 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -821,6 +821,17 @@ public void onEndFrame() { } 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"); + } + return platformViewsController.createOverlaySurface(); + } // ----- 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 new file mode 100644 index 0000000000000..05a3bdafb0c8c --- /dev/null +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterOverlaySurface.java @@ -0,0 +1,29 @@ +// 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; +import androidx.annotation.Keep; +import androidx.annotation.NonNull; + +public class FlutterOverlaySurface { + @NonNull private final Surface surface; + + private final long id; + + @Keep + public FlutterOverlaySurface(long id, @NonNull 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 8a394fa43fdc3..706b31228a090 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java @@ -17,6 +17,7 @@ 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.plugin.editing.TextInputPlugin; @@ -549,4 +550,9 @@ public void onBeginFrame() { 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; + } } diff --git a/shell/platform/android/jni/platform_view_android_jni.h b/shell/platform/android/jni/platform_view_android_jni.h index 5d00ef13b1fce..efbca69e5112f 100644 --- a/shell/platform/android/jni/platform_view_android_jni.h +++ b/shell/platform/android/jni/platform_view_android_jni.h @@ -130,6 +130,7 @@ class PlatformViewAndroidJNI { int y, int width, int height) = 0; + //---------------------------------------------------------------------------- /// @brief Initiates a frame if using hybrid composition. /// @@ -145,6 +146,13 @@ class PlatformViewAndroidJNI { /// @note Must be called from the platform thread. /// virtual void FlutterViewEndFrame() = 0; + + //---------------------------------------------------------------------------- + /// @brief Instantiates an overlay surface in hybrid composition. + /// + /// @note Must be called from the platform thread. + /// + virtual void 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 4e2d0db99b637..c23f5b48ba742 100644 --- a/shell/platform/android/platform_view_android_jni_impl.cc +++ b/shell/platform/android/platform_view_android_jni_impl.cc @@ -24,6 +24,7 @@ #include "flutter/shell/platform/android/android_shell_holder.h" #include "flutter/shell/platform/android/apk_asset_provider.h" #include "flutter/shell/platform/android/flutter_main.h" +#include "flutter/shell/platform/android/jni/platform_view_android_jni.h" #include "flutter/shell/platform/android/platform_view_android.h" #define ANDROID_SHELL_HOLDER \ @@ -80,6 +81,8 @@ 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_on_begin_frame_method = nullptr; static jmethodID g_on_end_frame_method = nullptr; @@ -683,6 +686,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; } @@ -707,6 +714,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()) { @@ -738,6 +749,14 @@ bool PlatformViewAndroid::Register(JNIEnv* env) { 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"); @@ -1080,4 +1099,17 @@ void PlatformViewAndroidJNIImpl::FlutterViewEndFrame() { 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 diff --git a/shell/platform/android/platform_view_android_jni_impl.h b/shell/platform/android/platform_view_android_jni_impl.h index 0ab94a28c685f..25b62987ebf18 100644 --- a/shell/platform/android/platform_view_android_jni_impl.h +++ b/shell/platform/android/platform_view_android_jni_impl.h @@ -66,6 +66,8 @@ class PlatformViewAndroidJNIImpl final : public PlatformViewAndroidJNI { 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 8918e4102aace..f63530a555ac7 100644 --- a/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java +++ b/shell/platform/android/test/io/flutter/embedding/engine/FlutterJNITest.java @@ -111,4 +111,18 @@ public void onEndFrame__callsPlatformViewsController() { // --- 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.createOverlaySurface(); + + // --- Verify Results --- + verify(platformViewsController, times(1)).createOverlaySurface(); + } }